Cython has moved to github.
cython-devel
view Cython/Compiler/Nodes.py @ 4256:b816b03ff502
Make __new__ -> __cinit__ into an error, fix compiler crash.
| author | Robert Bradshaw <robertwb@math.washington.edu> |
|---|---|
| date | Tue Dec 21 02:09:22 2010 -0800 (17 months ago) |
| parents | 1dadfbd04642 |
| children |
line source
2 #
3 # Pyrex - Parse tree nodes
4 #
6 import cython
7 from cython import set
8 cython.declare(sys=object, os=object, time=object, copy=object,
9 Builtin=object, error=object, warning=object, Naming=object, PyrexTypes=object,
10 py_object_type=object, ModuleScope=object, LocalScope=object, ClosureScope=object, \
11 StructOrUnionScope=object, PyClassScope=object, CClassScope=object,
12 CppClassScope=object, UtilityCode=object, EncodedString=object,
13 absolute_path_length=cython.Py_ssize_t)
15 import sys, os, time, copy
17 import Builtin
18 from Errors import error, warning, InternalError
19 import Naming
20 import PyrexTypes
21 import TypeSlots
22 from PyrexTypes import py_object_type, error_type, CFuncType
23 from Symtab import ModuleScope, LocalScope, ClosureScope, \
24 StructOrUnionScope, PyClassScope, CClassScope, CppClassScope
25 from Cython.Utils import open_new_file, replace_suffix
26 from Code import UtilityCode
27 from StringEncoding import EncodedString, escape_byte_string, split_string_literal
28 import Options
29 import ControlFlow
30 import DebugFlags
32 absolute_path_length = 0
34 def relative_position(pos):
35 """
36 We embed the relative filename in the generated C file, since we
37 don't want to have to regnerate and compile all the source code
38 whenever the Python install directory moves (which could happen,
39 e.g,. when distributing binaries.)
41 INPUT:
42 a position tuple -- (absolute filename, line number column position)
44 OUTPUT:
45 relative filename
46 line number
48 AUTHOR: William Stein
49 """
50 global absolute_path_length
51 if absolute_path_length==0:
52 absolute_path_length = len(os.path.abspath(os.getcwd()))
53 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
55 def embed_position(pos, docstring):
56 if not Options.embed_pos_in_docstring:
57 return docstring
58 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
59 if docstring is None:
60 # unicode string
61 return EncodedString(pos_line)
63 # make sure we can encode the filename in the docstring encoding
64 # otherwise make the docstring a unicode string
65 encoding = docstring.encoding
66 if encoding is not None:
67 try:
68 encoded_bytes = pos_line.encode(encoding)
69 except UnicodeEncodeError:
70 encoding = None
72 if not docstring:
73 # reuse the string encoding of the original docstring
74 doc = EncodedString(pos_line)
75 else:
76 doc = EncodedString(pos_line + u'\n' + docstring)
77 doc.encoding = encoding
78 return doc
81 from Code import CCodeWriter
82 from types import FunctionType
84 def write_func_call(func):
85 def f(*args, **kwds):
86 if len(args) > 1 and isinstance(args[1], CCodeWriter):
87 # here we annotate the code with this function call
88 # but only if new code is generated
89 node, code = args[:2]
90 marker = ' /* %s -> %s.%s %s */' % (
91 ' ' * code.call_level,
92 node.__class__.__name__,
93 func.__name__,
94 node.pos[1:])
95 pristine = code.buffer.stream.tell()
96 code.putln(marker)
97 start = code.buffer.stream.tell()
98 code.call_level += 4
99 res = func(*args, **kwds)
100 code.call_level -= 4
101 if start == code.buffer.stream.tell():
102 code.buffer.stream.seek(pristine)
103 else:
104 marker = marker.replace('->', '<-')
105 code.putln(marker)
106 return res
107 else:
108 return func(*args, **kwds)
109 return f
111 class VerboseCodeWriter(type):
112 # Set this as a metaclass to trace function calls in code.
113 # This slows down code generation and makes much larger files.
114 def __new__(cls, name, bases, attrs):
115 attrs = dict(attrs)
116 for mname, m in attrs.items():
117 if isinstance(m, FunctionType):
118 attrs[mname] = write_func_call(m)
119 return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
122 class Node(object):
123 # pos (string, int, int) Source file position
124 # is_name boolean Is a NameNode
125 # is_literal boolean Is a ConstNode
127 if DebugFlags.debug_trace_code_generation:
128 __metaclass__ = VerboseCodeWriter
130 is_name = 0
131 is_literal = 0
132 temps = None
134 # All descandants should set child_attrs to a list of the attributes
135 # containing nodes considered "children" in the tree. Each such attribute
136 # can either contain a single node or a list of nodes. See Visitor.py.
137 child_attrs = None
139 def __init__(self, pos, **kw):
140 self.pos = pos
141 self.__dict__.update(kw)
143 gil_message = "Operation"
145 nogil_check = None
147 def gil_error(self, env=None):
148 error(self.pos, "%s not allowed without gil" % self.gil_message)
150 cpp_message = "Operation"
152 def cpp_check(self, env):
153 if not env.is_cpp():
154 self.cpp_error()
156 def cpp_error(self):
157 error(self.pos, "%s only allowed in c++" % self.cpp_message)
159 def clone_node(self):
160 """Clone the node. This is defined as a shallow copy, except for member lists
161 amongst the child attributes (from get_child_accessors) which are also
162 copied. Lists containing child nodes are thus seen as a way for the node
163 to hold multiple children directly; the list is not treated as a seperate
164 level in the tree."""
165 result = copy.copy(self)
166 for attrname in result.child_attrs:
167 value = getattr(result, attrname)
168 if isinstance(value, list):
169 setattr(result, attrname, [x for x in value])
170 return result
173 #
174 # There are 4 phases of parse tree processing, applied in order to
175 # all the statements in a given scope-block:
176 #
177 # (0) analyse_control_flow
178 # Create the control flow tree into which state can be asserted and
179 # queried.
180 #
181 # (1) analyse_declarations
182 # Make symbol table entries for all declarations at the current
183 # level, both explicit (def, cdef, etc.) and implicit (assignment
184 # to an otherwise undeclared name).
185 #
186 # (2) analyse_expressions
187 # Determine the result types of expressions and fill in the
188 # 'type' attribute of each ExprNode. Insert coercion nodes into the
189 # tree where needed to convert to and from Python objects.
190 # Allocate temporary locals for intermediate results. Fill
191 # in the 'result_code' attribute of each ExprNode with a C code
192 # fragment.
193 #
194 # (3) generate_code
195 # Emit C code for all declarations, statements and expressions.
196 # Recursively applies the 3 processing phases to the bodies of
197 # functions.
198 #
200 def analyse_control_flow(self, env):
201 pass
203 def analyse_declarations(self, env):
204 pass
206 def analyse_expressions(self, env):
207 raise InternalError("analyse_expressions not implemented for %s" % \
208 self.__class__.__name__)
210 def generate_code(self, code):
211 raise InternalError("generate_code not implemented for %s" % \
212 self.__class__.__name__)
214 def annotate(self, code):
215 # mro does the wrong thing
216 if isinstance(self, BlockNode):
217 self.body.annotate(code)
219 def end_pos(self):
220 try:
221 return self._end_pos
222 except AttributeError:
223 pos = self.pos
224 if not self.child_attrs:
225 self._end_pos = pos
226 return pos
227 for attr in self.child_attrs:
228 child = getattr(self, attr)
229 # Sometimes lists, sometimes nodes
230 if child is None:
231 pass
232 elif isinstance(child, list):
233 for c in child:
234 pos = max(pos, c.end_pos())
235 else:
236 pos = max(pos, child.end_pos())
237 self._end_pos = pos
238 return pos
240 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
241 if cutoff == 0:
242 return "<...nesting level cutoff...>"
243 if encountered is None:
244 encountered = set()
245 if id(self) in encountered:
246 return "<%s (0x%x) -- already output>" % (self.__class__.__name__, id(self))
247 encountered.add(id(self))
249 def dump_child(x, level):
250 if isinstance(x, Node):
251 return x.dump(level, filter_out, cutoff-1, encountered)
252 elif isinstance(x, list):
253 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
254 else:
255 return repr(x)
258 attrs = [(key, value) for key, value in self.__dict__.items() if key not in filter_out]
259 if len(attrs) == 0:
260 return "<%s (0x%x)>" % (self.__class__.__name__, id(self))
261 else:
262 indent = " " * level
263 res = "<%s (0x%x)\n" % (self.__class__.__name__, id(self))
264 for key, value in attrs:
265 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
266 res += "%s>" % indent
267 return res
269 class CompilerDirectivesNode(Node):
270 """
271 Sets compiler directives for the children nodes
272 """
273 # directives {string:value} A dictionary holding the right value for
274 # *all* possible directives.
275 # body Node
276 child_attrs = ["body"]
278 def analyse_control_flow(self, env):
279 old = env.directives
280 env.directives = self.directives
281 self.body.analyse_control_flow(env)
282 env.directives = old
284 def analyse_declarations(self, env):
285 old = env.directives
286 env.directives = self.directives
287 self.body.analyse_declarations(env)
288 env.directives = old
290 def analyse_expressions(self, env):
291 old = env.directives
292 env.directives = self.directives
293 self.body.analyse_expressions(env)
294 env.directives = old
296 def generate_function_definitions(self, env, code):
297 env_old = env.directives
298 code_old = code.globalstate.directives
299 code.globalstate.directives = self.directives
300 self.body.generate_function_definitions(env, code)
301 env.directives = env_old
302 code.globalstate.directives = code_old
304 def generate_execution_code(self, code):
305 old = code.globalstate.directives
306 code.globalstate.directives = self.directives
307 self.body.generate_execution_code(code)
308 code.globalstate.directives = old
310 def annotate(self, code):
311 old = code.globalstate.directives
312 code.globalstate.directives = self.directives
313 self.body.annotate(code)
314 code.globalstate.directives = old
316 class BlockNode(object):
317 # Mixin class for nodes representing a declaration block.
319 def generate_cached_builtins_decls(self, env, code):
320 entries = env.global_scope().undeclared_cached_builtins
321 for entry in entries:
322 code.globalstate.add_cached_builtin_decl(entry)
323 del entries[:]
325 def generate_lambda_definitions(self, env, code):
326 for node in env.lambda_defs:
327 node.generate_function_definitions(env, code)
329 class StatListNode(Node):
330 # stats a list of StatNode
332 child_attrs = ["stats"]
334 def create_analysed(pos, env, *args, **kw):
335 node = StatListNode(pos, *args, **kw)
336 return node # No node-specific analysis necesarry
337 create_analysed = staticmethod(create_analysed)
339 def analyse_control_flow(self, env):
340 for stat in self.stats:
341 stat.analyse_control_flow(env)
343 def analyse_declarations(self, env):
344 #print "StatListNode.analyse_declarations" ###
345 for stat in self.stats:
346 stat.analyse_declarations(env)
348 def analyse_expressions(self, env):
349 #print "StatListNode.analyse_expressions" ###
350 for stat in self.stats:
351 stat.analyse_expressions(env)
353 def generate_function_definitions(self, env, code):
354 #print "StatListNode.generate_function_definitions" ###
355 for stat in self.stats:
356 stat.generate_function_definitions(env, code)
358 def generate_execution_code(self, code):
359 #print "StatListNode.generate_execution_code" ###
360 for stat in self.stats:
361 code.mark_pos(stat.pos)
362 stat.generate_execution_code(code)
364 def annotate(self, code):
365 for stat in self.stats:
366 stat.annotate(code)
369 class StatNode(Node):
370 #
371 # Code generation for statements is split into the following subphases:
372 #
373 # (1) generate_function_definitions
374 # Emit C code for the definitions of any structs,
375 # unions, enums and functions defined in the current
376 # scope-block.
377 #
378 # (2) generate_execution_code
379 # Emit C code for executable statements.
380 #
382 def generate_function_definitions(self, env, code):
383 pass
385 def generate_execution_code(self, code):
386 raise InternalError("generate_execution_code not implemented for %s" % \
387 self.__class__.__name__)
390 class CDefExternNode(StatNode):
391 # include_file string or None
392 # body StatNode
394 child_attrs = ["body"]
396 def analyse_declarations(self, env):
397 if self.include_file:
398 env.add_include_file(self.include_file)
399 old_cinclude_flag = env.in_cinclude
400 env.in_cinclude = 1
401 self.body.analyse_declarations(env)
402 env.in_cinclude = old_cinclude_flag
404 def analyse_expressions(self, env):
405 pass
407 def generate_execution_code(self, code):
408 pass
410 def annotate(self, code):
411 self.body.annotate(code)
414 class CDeclaratorNode(Node):
415 # Part of a C declaration.
416 #
417 # Processing during analyse_declarations phase:
418 #
419 # analyse
420 # Returns (name, type) pair where name is the
421 # CNameDeclaratorNode of the name being declared
422 # and type is the type it is being declared as.
423 #
424 # calling_convention string Calling convention of CFuncDeclaratorNode
425 # for which this is a base
427 child_attrs = []
429 calling_convention = ""
432 class CNameDeclaratorNode(CDeclaratorNode):
433 # name string The Pyrex name being declared
434 # cname string or None C name, if specified
435 # default ExprNode or None the value assigned on declaration
437 child_attrs = ['default']
439 default = None
441 def analyse(self, base_type, env, nonempty = 0):
442 if nonempty and self.name == '':
443 # May have mistaken the name for the type.
444 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
445 error(self.pos, "Missing argument name")
446 elif base_type.is_void:
447 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
448 else:
449 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
450 base_type = py_object_type
451 self.type = base_type
452 return self, base_type
454 class CPtrDeclaratorNode(CDeclaratorNode):
455 # base CDeclaratorNode
457 child_attrs = ["base"]
459 def analyse(self, base_type, env, nonempty = 0):
460 if base_type.is_pyobject:
461 error(self.pos,
462 "Pointer base type cannot be a Python object")
463 ptr_type = PyrexTypes.c_ptr_type(base_type)
464 return self.base.analyse(ptr_type, env, nonempty = nonempty)
466 class CReferenceDeclaratorNode(CDeclaratorNode):
467 # base CDeclaratorNode
469 child_attrs = ["base"]
471 def analyse(self, base_type, env, nonempty = 0):
472 if base_type.is_pyobject:
473 error(self.pos,
474 "Reference base type cannot be a Python object")
475 ref_type = PyrexTypes.c_ref_type(base_type)
476 return self.base.analyse(ref_type, env, nonempty = nonempty)
478 class CArrayDeclaratorNode(CDeclaratorNode):
479 # base CDeclaratorNode
480 # dimension ExprNode
482 child_attrs = ["base", "dimension"]
484 def analyse(self, base_type, env, nonempty = 0):
485 if base_type.is_cpp_class:
486 from ExprNodes import TupleNode
487 if isinstance(self.dimension, TupleNode):
488 args = self.dimension.args
489 else:
490 args = self.dimension,
491 values = [v.analyse_as_type(env) for v in args]
492 if None in values:
493 ix = values.index(None)
494 error(args[ix].pos, "Template parameter not a type.")
495 return error_type
496 base_type = base_type.specialize_here(self.pos, values)
497 return self.base.analyse(base_type, env, nonempty = nonempty)
498 if self.dimension:
499 self.dimension.analyse_const_expression(env)
500 if not self.dimension.type.is_int:
501 error(self.dimension.pos, "Array dimension not integer")
502 size = self.dimension.get_constant_c_result_code()
503 if size is not None:
504 try:
505 size = int(size)
506 except ValueError:
507 # runtime constant?
508 pass
509 else:
510 size = None
511 if not base_type.is_complete():
512 error(self.pos,
513 "Array element type '%s' is incomplete" % base_type)
514 if base_type.is_pyobject:
515 error(self.pos,
516 "Array element cannot be a Python object")
517 if base_type.is_cfunction:
518 error(self.pos,
519 "Array element cannot be a function")
520 array_type = PyrexTypes.c_array_type(base_type, size)
521 return self.base.analyse(array_type, env, nonempty = nonempty)
524 class CFuncDeclaratorNode(CDeclaratorNode):
525 # base CDeclaratorNode
526 # args [CArgDeclNode]
527 # has_varargs boolean
528 # exception_value ConstNode
529 # exception_check boolean True if PyErr_Occurred check needed
530 # nogil boolean Can be called without gil
531 # with_gil boolean Acquire gil around function body
533 child_attrs = ["base", "args", "exception_value"]
535 overridable = 0
536 optional_arg_count = 0
538 def analyse(self, return_type, env, nonempty = 0):
539 if nonempty:
540 nonempty -= 1
541 func_type_args = []
542 for i, arg_node in enumerate(self.args):
543 name_declarator, type = arg_node.analyse(env, nonempty = nonempty,
544 is_self_arg = (i == 0 and env.is_c_class_scope))
545 name = name_declarator.name
546 if name_declarator.cname:
547 error(self.pos,
548 "Function argument cannot have C name specification")
549 # Turn *[] argument into **
550 if type.is_array:
551 type = PyrexTypes.c_ptr_type(type.base_type)
552 # Catch attempted C-style func(void) decl
553 if type.is_void:
554 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
555 func_type_args.append(
556 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
557 if arg_node.default:
558 self.optional_arg_count += 1
559 elif self.optional_arg_count:
560 error(self.pos, "Non-default argument follows default argument")
562 if self.optional_arg_count:
563 scope = StructOrUnionScope()
564 arg_count_member = '%sn' % Naming.pyrex_prefix
565 scope.declare_var(arg_count_member, PyrexTypes.c_int_type, self.pos)
566 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
567 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
568 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
569 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
570 kind = 'struct',
571 scope = scope,
572 typedef_flag = 0,
573 pos = self.pos,
574 cname = struct_cname)
575 self.op_args_struct.defined_in_pxd = 1
576 self.op_args_struct.used = 1
578 exc_val = None
579 exc_check = 0
580 if self.exception_check == '+':
581 env.add_include_file('stdexcept')
582 if return_type.is_pyobject \
583 and (self.exception_value or self.exception_check) \
584 and self.exception_check != '+':
585 error(self.pos,
586 "Exception clause not allowed for function returning Python object")
587 else:
588 if self.exception_value:
589 self.exception_value.analyse_const_expression(env)
590 if self.exception_check == '+':
591 self.exception_value.analyse_types(env)
592 exc_val_type = self.exception_value.type
593 if not exc_val_type.is_error and \
594 not exc_val_type.is_pyobject and \
595 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
596 error(self.exception_value.pos,
597 "Exception value must be a Python exception or cdef function with no arguments.")
598 exc_val = self.exception_value
599 else:
600 self.exception_value = self.exception_value.coerce_to(return_type, env)
601 if self.exception_value.analyse_const_expression(env):
602 exc_val = self.exception_value.get_constant_c_result_code()
603 if exc_val is None:
604 raise InternalError("get_constant_c_result_code not implemented for %s" %
605 self.exception_value.__class__.__name__)
606 if not return_type.assignable_from(self.exception_value.type):
607 error(self.exception_value.pos,
608 "Exception value incompatible with function return type")
609 exc_check = self.exception_check
610 if return_type.is_array:
611 error(self.pos,
612 "Function cannot return an array")
613 if return_type.is_cfunction:
614 error(self.pos,
615 "Function cannot return a function")
616 func_type = PyrexTypes.CFuncType(
617 return_type, func_type_args, self.has_varargs,
618 optional_arg_count = self.optional_arg_count,
619 exception_value = exc_val, exception_check = exc_check,
620 calling_convention = self.base.calling_convention,
621 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
622 if self.optional_arg_count:
623 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
624 callspec = env.directives['callspec']
625 if callspec:
626 current = func_type.calling_convention
627 if current and current != callspec:
628 error(self.pos, "cannot have both '%s' and '%s' "
629 "calling conventions" % (current, callspec))
630 func_type.calling_convention = callspec
631 return self.base.analyse(func_type, env)
634 class CArgDeclNode(Node):
635 # Item in a function declaration argument list.
636 #
637 # base_type CBaseTypeNode
638 # declarator CDeclaratorNode
639 # not_none boolean Tagged with 'not None'
640 # or_none boolean Tagged with 'or None'
641 # accept_none boolean Resolved boolean for not_none/or_none
642 # default ExprNode or None
643 # default_value PyObjectConst constant for default value
644 # annotation ExprNode or None Py3 function arg annotation
645 # is_self_arg boolean Is the "self" arg of an extension type method
646 # is_type_arg boolean Is the "class" arg of an extension type classmethod
647 # is_kw_only boolean Is a keyword-only argument
649 child_attrs = ["base_type", "declarator", "default"]
651 is_self_arg = 0
652 is_type_arg = 0
653 is_generic = 1
654 type = None
655 name_declarator = None
656 default_value = None
657 annotation = None
659 def analyse(self, env, nonempty = 0, is_self_arg = False):
660 if is_self_arg:
661 self.base_type.is_self_arg = self.is_self_arg = True
662 if self.type is None:
663 # The parser may missinterpret names as types...
664 # We fix that here.
665 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
666 if nonempty:
667 self.declarator.name = self.base_type.name
668 self.base_type.name = None
669 self.base_type.is_basic_c_type = False
670 could_be_name = True
671 else:
672 could_be_name = False
673 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
674 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
675 self.declarator.name = self.base_type.arg_name
676 # The parser is unable to resolve the ambiguity of [] as part of the
677 # type (e.g. in buffers) or empty declarator (as with arrays).
678 # This is only arises for empty multi-dimensional arrays.
679 if (base_type.is_array
680 and isinstance(self.base_type, TemplatedTypeNode)
681 and isinstance(self.declarator, CArrayDeclaratorNode)):
682 declarator = self.declarator
683 while isinstance(declarator.base, CArrayDeclaratorNode):
684 declarator = declarator.base
685 declarator.base = self.base_type.array_declarator
686 base_type = base_type.base_type
687 return self.declarator.analyse(base_type, env, nonempty = nonempty)
688 else:
689 return self.name_declarator, self.type
691 def calculate_default_value_code(self, code):
692 if self.default_value is None:
693 if self.default:
694 if self.default.is_literal:
695 # will not output any code, just assign the result_code
696 self.default.generate_evaluation_code(code)
697 return self.type.cast_code(self.default.result())
698 self.default_value = code.get_argument_default_const(self.type)
699 return self.default_value
701 def annotate(self, code):
702 if self.default:
703 self.default.annotate(code)
706 class CBaseTypeNode(Node):
707 # Abstract base class for C base type nodes.
708 #
709 # Processing during analyse_declarations phase:
710 #
711 # analyse
712 # Returns the type.
714 pass
716 def analyse_as_type(self, env):
717 return self.analyse(env)
719 class CAnalysedBaseTypeNode(Node):
720 # type type
722 child_attrs = []
724 def analyse(self, env, could_be_name = False):
725 return self.type
727 class CSimpleBaseTypeNode(CBaseTypeNode):
728 # name string
729 # module_path [string] Qualifying name components
730 # is_basic_c_type boolean
731 # signed boolean
732 # longness integer
733 # complex boolean
734 # is_self_arg boolean Is self argument of C method
735 # ##is_type_arg boolean Is type argument of class method
737 child_attrs = []
738 arg_name = None # in case the argument name was interpreted as a type
740 def analyse(self, env, could_be_name = False):
741 # Return type descriptor.
742 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
743 type = None
744 if self.is_basic_c_type:
745 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
746 if not type:
747 error(self.pos, "Unrecognised type modifier combination")
748 elif self.name == "object" and not self.module_path:
749 type = py_object_type
750 elif self.name is None:
751 if self.is_self_arg and env.is_c_class_scope:
752 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
753 type = env.parent_type
754 ## elif self.is_type_arg and env.is_c_class_scope:
755 ## type = Builtin.type_type
756 else:
757 type = py_object_type
758 else:
759 if self.module_path:
760 scope = env.find_imported_module(self.module_path, self.pos)
761 else:
762 scope = env
763 if scope:
764 if scope.is_c_class_scope:
765 scope = scope.global_scope()
766 entry = scope.lookup(self.name)
767 if entry and entry.is_type:
768 type = entry.type
769 elif could_be_name:
770 if self.is_self_arg and env.is_c_class_scope:
771 type = env.parent_type
772 ## elif self.is_type_arg and env.is_c_class_scope:
773 ## type = Builtin.type_type
774 else:
775 type = py_object_type
776 self.arg_name = self.name
777 else:
778 if self.templates:
779 if not self.name in self.templates:
780 error(self.pos, "'%s' is not a type identifier" % self.name)
781 type = PyrexTypes.TemplatePlaceholderType(self.name)
782 else:
783 error(self.pos, "'%s' is not a type identifier" % self.name)
784 if self.complex:
785 if not type.is_numeric or type.is_complex:
786 error(self.pos, "can only complexify c numeric types")
787 type = PyrexTypes.CComplexType(type)
788 type.create_declaration_utility_code(env)
789 elif type is Builtin.complex_type:
790 # Special case: optimise builtin complex type into C's
791 # double complex. The parser cannot do this (as for the
792 # normal scalar types) as the user may have redeclared the
793 # 'complex' type. Testing for the exact type here works.
794 type = PyrexTypes.c_double_complex_type
795 type.create_declaration_utility_code(env)
796 self.complex = True
797 if type:
798 return type
799 else:
800 return PyrexTypes.error_type
802 class CNestedBaseTypeNode(CBaseTypeNode):
803 # For C++ classes that live inside other C++ classes.
805 # name string
806 # base_type CBaseTypeNode
808 child_attrs = ['base_type']
810 def analyse(self, env, could_be_name = None):
811 base_type = self.base_type.analyse(env)
812 if base_type is PyrexTypes.error_type:
813 return PyrexTypes.error_type
814 if not base_type.is_cpp_class:
815 error(self.pos, "'%s' is not a valid type scope" % base_type)
816 return PyrexTypes.error_type
817 type_entry = base_type.scope.lookup_here(self.name)
818 if not type_entry or not type_entry.is_type:
819 error(self.pos, "'%s.%s' is not a type identifier" % (base_type, self.name))
820 return PyrexTypes.error_type
821 return type_entry.type
823 class TemplatedTypeNode(CBaseTypeNode):
824 # After parsing:
825 # positional_args [ExprNode] List of positional arguments
826 # keyword_args DictNode Keyword arguments
827 # base_type_node CBaseTypeNode
829 # After analysis:
830 # type PyrexTypes.BufferType or PyrexTypes.CppClassType ...containing the right options
833 child_attrs = ["base_type_node", "positional_args",
834 "keyword_args", "dtype_node"]
836 dtype_node = None
838 name = None
840 def analyse(self, env, could_be_name = False, base_type = None):
841 if base_type is None:
842 base_type = self.base_type_node.analyse(env)
843 if base_type.is_error: return base_type
845 if base_type.is_cpp_class:
846 # Templated class
847 if self.keyword_args and self.keyword_args.key_value_pairs:
848 error(self.pos, "c++ templates cannot take keyword arguments");
849 self.type = PyrexTypes.error_type
850 else:
851 template_types = []
852 for template_node in self.positional_args:
853 type = template_node.analyse_as_type(env)
854 if type is None:
855 error(template_node.pos, "unknown type in template argument")
856 return error_type
857 template_types.append(type)
858 self.type = base_type.specialize_here(self.pos, template_types)
860 elif base_type.is_pyobject:
861 # Buffer
862 import Buffer
864 options = Buffer.analyse_buffer_options(
865 self.pos,
866 env,
867 self.positional_args,
868 self.keyword_args,
869 base_type.buffer_defaults)
871 if sys.version_info[0] < 3:
872 # Py 2.x enforces byte strings as keyword arguments ...
873 options = dict([ (name.encode('ASCII'), value)
874 for name, value in options.items() ])
876 self.type = PyrexTypes.BufferType(base_type, **options)
878 else:
879 # Array
880 empty_declarator = CNameDeclaratorNode(self.pos, name="", cname=None)
881 if len(self.positional_args) > 1 or self.keyword_args.key_value_pairs:
882 error(self.pos, "invalid array declaration")
883 self.type = PyrexTypes.error_type
884 else:
885 # It would be nice to merge this class with CArrayDeclaratorNode,
886 # but arrays are part of the declaration, not the type...
887 if not self.positional_args:
888 dimension = None
889 else:
890 dimension = self.positional_args[0]
891 self.array_declarator = CArrayDeclaratorNode(self.pos,
892 base = empty_declarator,
893 dimension = dimension)
894 self.type = self.array_declarator.analyse(base_type, env)[1]
896 return self.type
898 class CComplexBaseTypeNode(CBaseTypeNode):
899 # base_type CBaseTypeNode
900 # declarator CDeclaratorNode
902 child_attrs = ["base_type", "declarator"]
904 def analyse(self, env, could_be_name = False):
905 base = self.base_type.analyse(env, could_be_name)
906 _, type = self.declarator.analyse(base, env)
907 return type
910 class CVarDefNode(StatNode):
911 # C variable definition or forward/extern function declaration.
912 #
913 # visibility 'private' or 'public' or 'extern'
914 # base_type CBaseTypeNode
915 # declarators [CDeclaratorNode]
916 # in_pxd boolean
917 # api boolean
919 # decorators [cython.locals(...)] or None
920 # directive_locals { string : NameNode } locals defined by cython.locals(...)
922 child_attrs = ["base_type", "declarators"]
924 decorators = None
925 directive_locals = {}
927 def analyse_declarations(self, env, dest_scope = None):
928 if not dest_scope:
929 dest_scope = env
930 self.dest_scope = dest_scope
931 base_type = self.base_type.analyse(env)
933 # If the field is an external typedef, we cannot be sure about the type,
934 # so do conversion ourself rather than rely on the CPython mechanism (through
935 # a property; made in AnalyseDeclarationsTransform).
936 if (dest_scope.is_c_class_scope
937 and self.visibility in ('public', 'readonly')):
938 need_property = True
939 else:
940 need_property = False
941 visibility = self.visibility
943 for declarator in self.declarators:
944 name_declarator, type = declarator.analyse(base_type, env)
945 if not type.is_complete():
946 if not (self.visibility == 'extern' and type.is_array):
947 error(declarator.pos,
948 "Variable type '%s' is incomplete" % type)
949 if self.visibility == 'extern' and type.is_pyobject:
950 error(declarator.pos,
951 "Python object cannot be declared extern")
952 name = name_declarator.name
953 cname = name_declarator.cname
954 if name == '':
955 error(declarator.pos, "Missing name in declaration.")
956 return
957 if type.is_cfunction:
958 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
959 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
960 api = self.api)
961 if entry is not None:
962 entry.directive_locals = self.directive_locals
963 else:
964 if self.directive_locals:
965 error(self.pos, "Decorators can only be followed by functions")
966 if self.in_pxd and self.visibility != 'extern':
967 error(self.pos,
968 "Only 'extern' C variable declaration allowed in .pxd file")
969 entry = dest_scope.declare_var(name, type, declarator.pos,
970 cname = cname, visibility = visibility, is_cdef = 1)
971 entry.needs_property = need_property
974 class CStructOrUnionDefNode(StatNode):
975 # name string
976 # cname string or None
977 # kind "struct" or "union"
978 # typedef_flag boolean
979 # visibility "public" or "private"
980 # in_pxd boolean
981 # attributes [CVarDefNode] or None
982 # entry Entry
983 # packed boolean
985 child_attrs = ["attributes"]
987 def analyse_declarations(self, env):
988 scope = None
989 if self.visibility == 'extern' and self.packed:
990 error(self.pos, "Cannot declare extern struct as 'packed'")
991 if self.attributes is not None:
992 scope = StructOrUnionScope(self.name)
993 self.entry = env.declare_struct_or_union(
994 self.name, self.kind, scope, self.typedef_flag, self.pos,
995 self.cname, visibility = self.visibility, packed = self.packed)
996 if self.attributes is not None:
997 if self.in_pxd and not env.in_cinclude:
998 self.entry.defined_in_pxd = 1
999 for attr in self.attributes:
1000 attr.analyse_declarations(env, scope)
1001 if self.visibility != 'extern':
1002 need_typedef_indirection = False
1003 for attr in scope.var_entries:
1004 type = attr.type
1005 while type.is_array:
1006 type = type.base_type
1007 if type == self.entry.type:
1008 error(attr.pos, "Struct cannot contain itself as a member.")
1009 if self.typedef_flag:
1010 while type.is_ptr:
1011 type = type.base_type
1012 if type == self.entry.type:
1013 need_typedef_indirection = True
1014 if need_typedef_indirection:
1015 # C can't handle typedef structs that refer to themselves.
1016 struct_entry = self.entry
1017 self.entry = env.declare_typedef(
1018 self.name, struct_entry.type, self.pos,
1019 cname = self.cname, visibility='ignore')
1020 struct_entry.type.typedef_flag = False
1021 # FIXME: this might be considered a hack ;-)
1022 struct_entry.cname = struct_entry.type.cname = \
1023 '_' + self.entry.type.typedef_cname
1025 def analyse_expressions(self, env):
1026 pass
1028 def generate_execution_code(self, code):
1029 pass
1032 class CppClassNode(CStructOrUnionDefNode):
1034 # name string
1035 # cname string or None
1036 # visibility "extern"
1037 # in_pxd boolean
1038 # attributes [CVarDefNode] or None
1039 # entry Entry
1040 # base_classes [string]
1041 # templates [string] or None
1043 def analyse_declarations(self, env):
1044 scope = None
1045 if self.attributes is not None:
1046 scope = CppClassScope(self.name, env)
1047 base_class_types = []
1048 for base_class_name in self.base_classes:
1049 base_class_entry = env.lookup(base_class_name)
1050 if base_class_entry is None:
1051 error(self.pos, "'%s' not found" % base_class_name)
1052 elif not base_class_entry.is_type or not base_class_entry.type.is_cpp_class:
1053 error(self.pos, "'%s' is not a cpp class type" % base_class_name)
1054 else:
1055 base_class_types.append(base_class_entry.type)
1056 if self.templates is None:
1057 template_types = None
1058 else:
1059 template_types = [PyrexTypes.TemplatePlaceholderType(template_name) for template_name in self.templates]
1060 self.entry = env.declare_cpp_class(
1061 self.name, scope, self.pos,
1062 self.cname, base_class_types, visibility = self.visibility, templates = template_types)
1063 self.entry.is_cpp_class = 1
1064 if self.attributes is not None:
1065 if self.in_pxd and not env.in_cinclude:
1066 self.entry.defined_in_pxd = 1
1067 for attr in self.attributes:
1068 attr.analyse_declarations(scope)
1070 class CEnumDefNode(StatNode):
1071 # name string or None
1072 # cname string or None
1073 # items [CEnumDefItemNode]
1074 # typedef_flag boolean
1075 # visibility "public" or "private"
1076 # in_pxd boolean
1077 # entry Entry
1079 child_attrs = ["items"]
1081 def analyse_declarations(self, env):
1082 self.entry = env.declare_enum(self.name, self.pos,
1083 cname = self.cname, typedef_flag = self.typedef_flag,
1084 visibility = self.visibility)
1085 if self.items is not None:
1086 if self.in_pxd and not env.in_cinclude:
1087 self.entry.defined_in_pxd = 1
1088 for item in self.items:
1089 item.analyse_declarations(env, self.entry)
1091 def analyse_expressions(self, env):
1092 pass
1094 def generate_execution_code(self, code):
1095 if self.visibility == 'public':
1096 temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
1097 for item in self.entry.enum_values:
1098 code.putln("%s = PyInt_FromLong(%s); %s" % (
1099 temp,
1100 item.cname,
1101 code.error_goto_if_null(temp, item.pos)))
1102 code.put_gotref(temp)
1103 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
1104 Naming.module_cname,
1105 item.name,
1106 temp,
1107 code.error_goto(item.pos)))
1108 code.put_decref_clear(temp, PyrexTypes.py_object_type)
1109 code.funcstate.release_temp(temp)
1112 class CEnumDefItemNode(StatNode):
1113 # name string
1114 # cname string or None
1115 # value ExprNode or None
1117 child_attrs = ["value"]
1119 def analyse_declarations(self, env, enum_entry):
1120 if self.value:
1121 self.value.analyse_const_expression(env)
1122 if not self.value.type.is_int:
1123 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
1124 self.value.analyse_const_expression(env)
1125 entry = env.declare_const(self.name, enum_entry.type,
1126 self.value, self.pos, cname = self.cname,
1127 visibility = enum_entry.visibility)
1128 enum_entry.enum_values.append(entry)
1131 class CTypeDefNode(StatNode):
1132 # base_type CBaseTypeNode
1133 # declarator CDeclaratorNode
1134 # visibility "public" or "private"
1135 # in_pxd boolean
1137 child_attrs = ["base_type", "declarator"]
1139 def analyse_declarations(self, env):
1140 base = self.base_type.analyse(env)
1141 name_declarator, type = self.declarator.analyse(base, env)
1142 name = name_declarator.name
1143 cname = name_declarator.cname
1144 entry = env.declare_typedef(name, type, self.pos,
1145 cname = cname, visibility = self.visibility)
1146 if self.in_pxd and not env.in_cinclude:
1147 entry.defined_in_pxd = 1
1149 def analyse_expressions(self, env):
1150 pass
1151 def generate_execution_code(self, code):
1152 pass
1155 class FuncDefNode(StatNode, BlockNode):
1156 # Base class for function definition nodes.
1157 #
1158 # return_type PyrexType
1159 # #filename string C name of filename string const
1160 # entry Symtab.Entry
1161 # needs_closure boolean Whether or not this function has inner functions/classes/yield
1162 # needs_outer_scope boolean Whether or not this function requires outer scope
1163 # directive_locals { string : NameNode } locals defined by cython.locals(...)
1165 py_func = None
1166 assmt = None
1167 needs_closure = False
1168 needs_outer_scope = False
1169 modifiers = []
1171 def analyse_default_values(self, env):
1172 genv = env.global_scope()
1173 default_seen = 0
1174 for arg in self.args:
1175 if arg.default:
1176 default_seen = 1
1177 if arg.is_generic:
1178 arg.default.analyse_types(env)
1179 arg.default = arg.default.coerce_to(arg.type, genv)
1180 else:
1181 error(arg.pos,
1182 "This argument cannot have a default value")
1183 arg.default = None
1184 elif arg.kw_only:
1185 default_seen = 1
1186 elif default_seen:
1187 error(arg.pos, "Non-default argument following default argument")
1189 def need_gil_acquisition(self, lenv):
1190 return 0
1192 def create_local_scope(self, env):
1193 genv = env
1194 while genv.is_py_class_scope or genv.is_c_class_scope:
1195 genv = genv.outer_scope
1196 if self.needs_closure:
1197 lenv = ClosureScope(name=self.entry.name,
1198 outer_scope = genv,
1199 scope_name=self.entry.cname)
1200 else:
1201 lenv = LocalScope(name=self.entry.name,
1202 outer_scope=genv,
1203 parent_scope=env)
1204 lenv.return_type = self.return_type
1205 type = self.entry.type
1206 if type.is_cfunction:
1207 lenv.nogil = type.nogil and not type.with_gil
1208 self.local_scope = lenv
1209 lenv.directives = env.directives
1210 return lenv
1212 def generate_function_definitions(self, env, code):
1213 import Buffer
1215 lenv = self.local_scope
1216 if lenv.is_closure_scope and not lenv.is_passthrough:
1217 outer_scope_cname = "%s->%s" % (Naming.cur_scope_cname,
1218 Naming.outer_scope_cname)
1219 else:
1220 outer_scope_cname = Naming.outer_scope_cname
1221 lenv.mangle_closure_cnames(outer_scope_cname)
1222 # Generate closure function definitions
1223 self.body.generate_function_definitions(lenv, code)
1224 # generate lambda function definitions
1225 self.generate_lambda_definitions(lenv, code)
1227 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1228 self.entry.scope.is_c_class_scope)
1229 is_releasebuffer_slot = (self.entry.name == "__releasebuffer__" and
1230 self.entry.scope.is_c_class_scope)
1231 is_buffer_slot = is_getbuffer_slot or is_releasebuffer_slot
1232 if is_buffer_slot:
1233 if 'cython_unused' not in self.modifiers:
1234 self.modifiers = self.modifiers + ['cython_unused']
1236 preprocessor_guard = None
1237 if self.entry.is_special and not is_buffer_slot:
1238 slot = TypeSlots.method_name_to_slot.get(self.entry.name)
1239 if slot:
1240 preprocessor_guard = slot.preprocessor_guard_code()
1241 if (self.entry.name == '__long__' and
1242 not self.entry.scope.lookup_here('__int__')):
1243 preprocessor_guard = None
1245 profile = code.globalstate.directives['profile']
1246 if profile:
1247 if lenv.nogil:
1248 error(self.pos, "Cannot profile nogil function.")
1249 code.globalstate.use_utility_code(profile_utility_code)
1251 # Generate C code for header and body of function
1252 code.enter_cfunc_scope()
1253 code.return_from_error_cleanup_label = code.new_label()
1255 # ----- Top-level constants used by this function
1256 code.mark_pos(self.pos)
1257 self.generate_cached_builtins_decls(lenv, code)
1258 # ----- Function header
1259 code.putln("")
1261 if preprocessor_guard:
1262 code.putln(preprocessor_guard)
1264 with_pymethdef = self.needs_assignment_synthesis(env, code)
1265 if self.py_func:
1266 self.py_func.generate_function_header(code,
1267 with_pymethdef = with_pymethdef,
1268 proto_only=True)
1269 self.generate_function_header(code,
1270 with_pymethdef = with_pymethdef)
1271 # ----- Local variable declarations
1272 # Find function scope
1273 cenv = env
1274 while cenv.is_py_class_scope or cenv.is_c_class_scope:
1275 cenv = cenv.outer_scope
1276 if self.needs_closure:
1277 code.put(lenv.scope_class.type.declaration_code(Naming.cur_scope_cname))
1278 code.putln(";")
1279 elif self.needs_outer_scope:
1280 if lenv.is_passthrough:
1281 code.put(lenv.scope_class.type.declaration_code(Naming.cur_scope_cname))
1282 code.putln(";")
1283 code.put(cenv.scope_class.type.declaration_code(Naming.outer_scope_cname))
1284 code.putln(";")
1285 self.generate_argument_declarations(lenv, code)
1286 for entry in lenv.var_entries:
1287 if not entry.in_closure:
1288 code.put_var_declaration(entry)
1289 init = ""
1290 if not self.return_type.is_void:
1291 if self.return_type.is_pyobject:
1292 init = " = NULL"
1293 code.putln(
1294 "%s%s;" %
1295 (self.return_type.declaration_code(Naming.retval_cname),
1296 init))
1297 tempvardecl_code = code.insertion_point()
1298 self.generate_keyword_list(code)
1299 if profile:
1300 code.put_trace_declarations()
1301 # ----- Extern library function declarations
1302 lenv.generate_library_function_declarations(code)
1303 # ----- GIL acquisition
1304 acquire_gil = self.acquire_gil
1305 if acquire_gil:
1306 env.use_utility_code(force_init_threads_utility_code)
1307 code.putln("#ifdef WITH_THREAD")
1308 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1309 code.putln("#endif")
1310 # ----- set up refnanny
1311 if not lenv.nogil:
1312 code.put_setup_refcount_context(self.entry.name)
1313 # ----- Automatic lead-ins for certain special functions
1314 if is_getbuffer_slot:
1315 self.getbuffer_init(code)
1316 # ----- Create closure scope object
1317 if self.needs_closure:
1318 code.putln("%s = (%s)%s->tp_new(%s, %s, NULL);" % (
1319 Naming.cur_scope_cname,
1320 lenv.scope_class.type.declaration_code(''),
1321 lenv.scope_class.type.typeptr_cname,
1322 lenv.scope_class.type.typeptr_cname,
1323 Naming.empty_tuple))
1324 code.putln("if (unlikely(!%s)) {" % Naming.cur_scope_cname)
1325 if is_getbuffer_slot:
1326 self.getbuffer_error_cleanup(code)
1327 if not lenv.nogil:
1328 code.put_finish_refcount_context()
1329 # FIXME: what if the error return value is a Python value?
1330 code.putln("return %s;" % self.error_value())
1331 code.putln("}")
1332 code.put_gotref(Naming.cur_scope_cname)
1333 # Note that it is unsafe to decref the scope at this point.
1334 if self.needs_outer_scope:
1335 code.putln("%s = (%s)%s;" % (
1336 outer_scope_cname,
1337 cenv.scope_class.type.declaration_code(''),
1338 Naming.self_cname))
1339 if lenv.is_passthrough:
1340 code.putln("%s = %s;" % (Naming.cur_scope_cname, outer_scope_cname));
1341 elif self.needs_closure:
1342 # inner closures own a reference to their outer parent
1343 code.put_incref(outer_scope_cname, cenv.scope_class.type)
1344 code.put_giveref(outer_scope_cname)
1345 # ----- Trace function call
1346 if profile:
1347 # this looks a bit late, but if we don't get here due to a
1348 # fatal error before hand, it's not really worth tracing
1349 code.put_trace_call(self.entry.name, self.pos)
1350 # ----- Fetch arguments
1351 self.generate_argument_parsing_code(env, code)
1352 # If an argument is assigned to in the body, we must
1353 # incref it to properly keep track of refcounts.
1354 for entry in lenv.arg_entries:
1355 if entry.type.is_pyobject:
1356 if entry.assignments and not entry.in_closure:
1357 code.put_var_incref(entry)
1358 # ----- Initialise local variables
1359 for entry in lenv.var_entries:
1360 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1361 code.put_init_var_to_py_none(entry)
1362 # ----- Initialise local buffer auxiliary variables
1363 for entry in lenv.var_entries + lenv.arg_entries:
1364 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1365 code.putln("%s.buf = NULL;" %
1366 entry.buffer_aux.buffer_info_var.cname)
1367 # ----- Check and convert arguments
1368 self.generate_argument_type_tests(code)
1369 # ----- Acquire buffer arguments
1370 for entry in lenv.arg_entries:
1371 if entry.type.is_buffer:
1372 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1374 # -------------------------
1375 # ----- Function body -----
1376 # -------------------------
1377 self.body.generate_execution_code(code)
1379 # ----- Default return value
1380 code.putln("")
1381 if self.return_type.is_pyobject:
1382 #if self.return_type.is_extension_type:
1383 # lhs = "(PyObject *)%s" % Naming.retval_cname
1384 #else:
1385 lhs = Naming.retval_cname
1386 code.put_init_to_py_none(lhs, self.return_type)
1387 else:
1388 val = self.return_type.default_value
1389 if val:
1390 code.putln("%s = %s;" % (Naming.retval_cname, val))
1391 # ----- Error cleanup
1392 if code.error_label in code.labels_used:
1393 code.put_goto(code.return_label)
1394 code.put_label(code.error_label)
1395 for cname, type in code.funcstate.all_managed_temps():
1396 code.put_xdecref(cname, type)
1398 # Clean up buffers -- this calls a Python function
1399 # so need to save and restore error state
1400 buffers_present = len(lenv.buffer_entries) > 0
1401 if buffers_present:
1402 code.globalstate.use_utility_code(restore_exception_utility_code)
1403 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1404 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1405 for entry in lenv.buffer_entries:
1406 Buffer.put_release_buffer_code(code, entry)
1407 #code.putln("%s = 0;" % entry.cname)
1408 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1410 err_val = self.error_value()
1411 exc_check = self.caller_will_check_exceptions()
1412 if err_val is not None or exc_check:
1413 # TODO: Fix exception tracing (though currently unused by cProfile).
1414 # code.globalstate.use_utility_code(get_exception_tuple_utility_code)
1415 # code.put_trace_exception()
1416 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1417 else:
1418 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1419 % self.entry.qualified_name, 0)
1420 code.putln(
1421 '__Pyx_WriteUnraisable("%s");' %
1422 self.entry.qualified_name)
1423 env.use_utility_code(unraisable_exception_utility_code)
1424 env.use_utility_code(restore_exception_utility_code)
1425 default_retval = self.return_type.default_value
1426 if err_val is None and default_retval:
1427 err_val = default_retval
1428 if err_val is not None:
1429 code.putln("%s = %s;" % (Naming.retval_cname, err_val))
1431 if is_getbuffer_slot:
1432 self.getbuffer_error_cleanup(code)
1434 # If we are using the non-error cleanup section we should
1435 # jump past it if we have an error. The if-test below determine
1436 # whether this section is used.
1437 if buffers_present or is_getbuffer_slot:
1438 code.put_goto(code.return_from_error_cleanup_label)
1441 # ----- Non-error return cleanup
1442 code.put_label(code.return_label)
1443 for entry in lenv.buffer_entries:
1444 if entry.used:
1445 Buffer.put_release_buffer_code(code, entry)
1446 if is_getbuffer_slot:
1447 self.getbuffer_normal_cleanup(code)
1448 # ----- Return cleanup for both error and no-error return
1449 code.put_label(code.return_from_error_cleanup_label)
1450 if not Options.init_local_none:
1451 for entry in lenv.var_entries:
1452 if lenv.control_flow.get_state((entry.name, 'initialized')) is not True:
1453 entry.xdecref_cleanup = 1
1455 for entry in lenv.var_entries:
1456 if entry.type.is_pyobject:
1457 if entry.used and not entry.in_closure:
1458 code.put_var_decref(entry)
1459 elif entry.in_closure and self.needs_closure:
1460 code.put_giveref(entry.cname)
1461 # Decref any increfed args
1462 for entry in lenv.arg_entries:
1463 if entry.type.is_pyobject:
1464 if entry.in_closure:
1465 code.put_var_giveref(entry)
1466 elif entry.assignments:
1467 code.put_var_decref(entry)
1468 if self.needs_closure:
1469 code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type)
1471 # ----- Return
1472 # This code is duplicated in ModuleNode.generate_module_init_func
1473 if not lenv.nogil:
1474 default_retval = self.return_type.default_value
1475 err_val = self.error_value()
1476 if err_val is None and default_retval:
1477 err_val = default_retval
1478 if self.return_type.is_pyobject:
1479 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1481 if self.entry.is_special and self.entry.name == "__hash__":
1482 # Returning -1 for __hash__ is supposed to signal an error
1483 # We do as Python instances and coerce -1 into -2.
1484 code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (
1485 Naming.retval_cname, Naming.retval_cname))
1487 if profile:
1488 if self.return_type.is_pyobject:
1489 code.put_trace_return(Naming.retval_cname)
1490 else:
1491 code.put_trace_return("Py_None")
1492 if not lenv.nogil:
1493 code.put_finish_refcount_context()
1495 if acquire_gil:
1496 code.putln("#ifdef WITH_THREAD")
1497 code.putln("PyGILState_Release(_save);")
1498 code.putln("#endif")
1500 if not self.return_type.is_void:
1501 code.putln("return %s;" % Naming.retval_cname)
1503 code.putln("}")
1505 if preprocessor_guard:
1506 code.putln("#endif /*!(%s)*/" % preprocessor_guard)
1508 # ----- Go back and insert temp variable declarations
1509 tempvardecl_code.put_temp_declarations(code.funcstate)
1510 # ----- Python version
1511 code.exit_cfunc_scope()
1512 if self.py_func:
1513 self.py_func.generate_function_definitions(env, code)
1514 self.generate_wrapper_functions(code)
1516 def declare_argument(self, env, arg):
1517 if arg.type.is_void:
1518 error(arg.pos, "Invalid use of 'void'")
1519 elif not arg.type.is_complete() and not arg.type.is_array:
1520 error(arg.pos,
1521 "Argument type '%s' is incomplete" % arg.type)
1522 return env.declare_arg(arg.name, arg.type, arg.pos)
1524 def generate_arg_type_test(self, arg, code):
1525 # Generate type test for one argument.
1526 if arg.type.typeobj_is_available():
1527 code.globalstate.use_utility_code(arg_type_test_utility_code)
1528 typeptr_cname = arg.type.typeptr_cname
1529 arg_code = "((PyObject *)%s)" % arg.entry.cname
1530 code.putln(
1531 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1532 arg_code,
1533 typeptr_cname,
1534 arg.accept_none,
1535 arg.name,
1536 arg.type.is_builtin_type,
1537 code.error_goto(arg.pos)))
1538 else:
1539 error(arg.pos, "Cannot test type of extern C class "
1540 "without type object name specification")
1542 def generate_arg_none_check(self, arg, code):
1543 # Generate None check for one argument.
1544 code.globalstate.use_utility_code(arg_type_test_utility_code)
1545 code.putln('if (unlikely(((PyObject *)%s) == Py_None)) {' % arg.entry.cname)
1546 code.putln('''PyErr_Format(PyExc_TypeError, "Argument '%s' must not be None"); %s''' % (
1547 arg.name,
1548 code.error_goto(arg.pos)))
1549 code.putln('}')
1551 def generate_wrapper_functions(self, code):
1552 pass
1554 def generate_execution_code(self, code):
1555 # Evaluate and store argument default values
1556 for arg in self.args:
1557 default = arg.default
1558 if default:
1559 if not default.is_literal:
1560 default.generate_evaluation_code(code)
1561 default.make_owned_reference(code)
1562 result = default.result_as(arg.type)
1563 code.putln(
1564 "%s = %s;" % (
1565 arg.calculate_default_value_code(code),
1566 result))
1567 if arg.type.is_pyobject:
1568 code.put_giveref(default.result())
1569 default.generate_post_assignment_code(code)
1570 default.free_temps(code)
1571 # For Python class methods, create and store function object
1572 if self.assmt:
1573 self.assmt.generate_execution_code(code)
1575 #
1576 # Special code for the __getbuffer__ function
1577 #
1578 def getbuffer_init(self, code):
1579 info = self.local_scope.arg_entries[1].cname
1580 # Python 3.0 betas have a bug in memoryview which makes it call
1581 # getbuffer with a NULL parameter. For now we work around this;
1582 # the following line should be removed when this bug is fixed.
1583 code.putln("if (%s == NULL) return 0;" % info)
1584 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1585 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1587 def getbuffer_error_cleanup(self, code):
1588 info = self.local_scope.arg_entries[1].cname
1589 code.put_gotref("%s->obj" % info)
1590 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1591 (info, info))
1593 def getbuffer_normal_cleanup(self, code):
1594 info = self.local_scope.arg_entries[1].cname
1595 code.putln("if (%s->obj == Py_None) {" % info)
1596 code.put_gotref("Py_None")
1597 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1598 code.putln("}")
1600 class CFuncDefNode(FuncDefNode):
1601 # C function definition.
1602 #
1603 # modifiers ['inline']
1604 # visibility 'private' or 'public' or 'extern'
1605 # base_type CBaseTypeNode
1606 # declarator CDeclaratorNode
1607 # body StatListNode
1608 # api boolean
1609 # decorators [DecoratorNode] list of decorators
1610 #
1611 # with_gil boolean Acquire GIL around body
1612 # type CFuncType
1613 # py_func wrapper for calling from Python
1614 # overridable whether or not this is a cpdef function
1615 # inline_in_pxd whether this is an inline function in a pxd file
1617 child_attrs = ["base_type", "declarator", "body", "py_func"]
1619 inline_in_pxd = False
1620 decorators = None
1621 directive_locals = {}
1623 def unqualified_name(self):
1624 return self.entry.name
1626 def analyse_declarations(self, env):
1627 self.directive_locals.update(env.directives['locals'])
1628 base_type = self.base_type.analyse(env)
1629 # The 2 here is because we need both function and argument names.
1630 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1631 if not type.is_cfunction:
1632 error(self.pos,
1633 "Suite attached to non-function declaration")
1634 # Remember the actual type according to the function header
1635 # written here, because the type in the symbol table entry
1636 # may be different if we're overriding a C method inherited
1637 # from the base type of an extension type.
1638 self.type = type
1639 type.is_overridable = self.overridable
1640 declarator = self.declarator
1641 while not hasattr(declarator, 'args'):
1642 declarator = declarator.base
1643 self.args = declarator.args
1644 for formal_arg, type_arg in zip(self.args, type.args):
1645 formal_arg.type = type_arg.type
1646 formal_arg.name = type_arg.name
1647 formal_arg.cname = type_arg.cname
1648 name = name_declarator.name
1649 cname = name_declarator.cname
1650 self.entry = env.declare_cfunction(
1651 name, type, self.pos,
1652 cname = cname, visibility = self.visibility,
1653 defining = self.body is not None,
1654 api = self.api, modifiers = self.modifiers)
1655 self.entry.inline_func_in_pxd = self.inline_in_pxd
1656 self.return_type = type.return_type
1658 if self.overridable and not env.is_module_scope:
1659 if len(self.args) < 1 or not self.args[0].type.is_pyobject:
1660 # An error will be produced in the cdef function
1661 self.overridable = False
1663 if self.overridable:
1664 import ExprNodes
1665 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1666 self.py_func = DefNode(pos = self.pos,
1667 name = self.entry.name,
1668 args = self.args,
1669 star_arg = None,
1670 starstar_arg = None,
1671 doc = self.doc,
1672 body = py_func_body,
1673 is_wrapper = 1)
1674 self.py_func.is_module_scope = env.is_module_scope
1675 self.py_func.analyse_declarations(env)
1676 self.entry.as_variable = self.py_func.entry
1677 # Reset scope entry the above cfunction
1678 env.entries[name] = self.entry
1679 if not env.is_module_scope or Options.lookup_module_cpdef:
1680 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1681 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1682 self.create_local_scope(env)
1684 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1685 import ExprNodes
1686 args = self.type.args
1687 if omit_optional_args:
1688 args = args[:len(args) - self.type.optional_arg_count]
1689 arg_names = [arg.name for arg in args]
1690 if is_module_scope:
1691 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1692 else:
1693 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1694 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1695 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1696 c_call = ExprNodes.SimpleCallNode(self.pos, function=cfunc, args=[ExprNodes.NameNode(self.pos, name=n) for n in arg_names[1-is_module_scope:]], wrapper_call=skip_dispatch)
1697 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1699 def declare_arguments(self, env):
1700 for arg in self.type.args:
1701 if not arg.name:
1702 error(arg.pos, "Missing argument name")
1703 self.declare_argument(env, arg)
1705 def need_gil_acquisition(self, lenv):
1706 return self.type.with_gil
1708 def nogil_check(self, env):
1709 type = self.type
1710 with_gil = type.with_gil
1711 if type.nogil and not with_gil:
1712 if type.return_type.is_pyobject:
1713 error(self.pos,
1714 "Function with Python return type cannot be declared nogil")
1715 for entry in self.local_scope.var_entries:
1716 if entry.type.is_pyobject:
1717 error(self.pos, "Function declared nogil has Python locals or temporaries")
1719 def analyse_expressions(self, env):
1720 self.local_scope.directives = env.directives
1721 if self.py_func is not None:
1722 # this will also analyse the default values
1723 self.py_func.analyse_expressions(env)
1724 else:
1725 self.analyse_default_values(env)
1726 self.acquire_gil = self.need_gil_acquisition(self.local_scope)
1728 def needs_assignment_synthesis(self, env, code=None):
1729 return False
1731 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1732 arg_decls = []
1733 type = self.type
1734 visibility = self.entry.visibility
1735 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1736 arg_decls.append(arg.declaration_code())
1737 if with_dispatch and self.overridable:
1738 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1739 if type.optional_arg_count and with_opt_args:
1740 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1741 if type.has_varargs:
1742 arg_decls.append("...")
1743 if not arg_decls:
1744 arg_decls = ["void"]
1745 if cname is None:
1746 cname = self.entry.func_cname
1747 entity = type.function_header_code(cname, ', '.join(arg_decls))
1748 if visibility == 'public':
1749 dll_linkage = "DL_EXPORT"
1750 else:
1751 dll_linkage = None
1752 header = self.return_type.declaration_code(entity,
1753 dll_linkage = dll_linkage)
1754 if visibility == 'extern':
1755 storage_class = "%s " % Naming.extern_c_macro
1756 elif visibility == 'public':
1757 storage_class = ""
1758 else:
1759 storage_class = "static "
1760 if 'inline' in self.modifiers:
1761 self.modifiers[self.modifiers.index('inline')] = 'cython_inline'
1762 code.putln("%s%s %s {" % (
1763 storage_class,
1764 ' '.join(self.modifiers).upper(), # macro forms
1765 header))
1767 def generate_argument_declarations(self, env, code):
1768 for arg in self.args:
1769 if arg.default:
1770 result = arg.calculate_default_value_code(code)
1771 code.putln('%s = %s;' % (
1772 arg.type.declaration_code(arg.cname), result))
1774 def generate_keyword_list(self, code):
1775 pass
1777 def generate_argument_parsing_code(self, env, code):
1778 i = 0
1779 if self.type.optional_arg_count:
1780 code.putln('if (%s) {' % Naming.optional_args_cname)
1781 for arg in self.args:
1782 if arg.default:
1783 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1784 declarator = arg.declarator
1785 while not hasattr(declarator, 'name'):
1786 declarator = declarator.base
1787 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, self.type.opt_arg_cname(declarator.name)))
1788 i += 1
1789 for _ in range(self.type.optional_arg_count):
1790 code.putln('}')
1791 code.putln('}')
1793 def generate_argument_conversion_code(self, code):
1794 pass
1796 def generate_argument_type_tests(self, code):
1797 # Generate type tests for args whose type in a parent
1798 # class is a supertype of the declared type.
1799 for arg in self.type.args:
1800 if arg.needs_type_test:
1801 self.generate_arg_type_test(arg, code)
1802 elif arg.type.is_pyobject and not arg.accept_none:
1803 self.generate_arg_none_check(arg, code)
1805 def error_value(self):
1806 if self.return_type.is_pyobject:
1807 return "0"
1808 else:
1809 #return None
1810 return self.entry.type.exception_value
1812 def caller_will_check_exceptions(self):
1813 return self.entry.type.exception_check
1815 def generate_wrapper_functions(self, code):
1816 # If the C signature of a function has changed, we need to generate
1817 # wrappers to put in the slots here.
1818 k = 0
1819 entry = self.entry
1820 func_type = entry.type
1821 while entry.prev_entry is not None:
1822 k += 1
1823 entry = entry.prev_entry
1824 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1825 code.putln()
1826 self.generate_function_header(code,
1827 0,
1828 with_dispatch = entry.type.is_overridable,
1829 with_opt_args = entry.type.optional_arg_count,
1830 cname = entry.func_cname)
1831 if not self.return_type.is_void:
1832 code.put('return ')
1833 args = self.type.args
1834 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1835 if entry.type.is_overridable:
1836 arglist.append(Naming.skip_dispatch_cname)
1837 elif func_type.is_overridable:
1838 arglist.append('0')
1839 if entry.type.optional_arg_count:
1840 arglist.append(Naming.optional_args_cname)
1841 elif func_type.optional_arg_count:
1842 arglist.append('NULL')
1843 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1844 code.putln('}')
1847 class PyArgDeclNode(Node):
1848 # Argument which must be a Python object (used
1849 # for * and ** arguments).
1850 #
1851 # name string
1852 # entry Symtab.Entry
1853 # annotation ExprNode or None Py3 argument annotation
1854 child_attrs = []
1856 def generate_function_definitions(self, env, code):
1857 self.entry.generate_function_definitions(env, code)
1859 class DecoratorNode(Node):
1860 # A decorator
1861 #
1862 # decorator NameNode or CallNode or AttributeNode
1863 child_attrs = ['decorator']
1866 class DefNode(FuncDefNode):
1867 # A Python function definition.
1868 #
1869 # name string the Python name of the function
1870 # lambda_name string the internal name of a lambda 'function'
1871 # decorators [DecoratorNode] list of decorators
1872 # args [CArgDeclNode] formal arguments
1873 # star_arg PyArgDeclNode or None * argument
1874 # starstar_arg PyArgDeclNode or None ** argument
1875 # doc EncodedString or None
1876 # body StatListNode
1877 # return_type_annotation
1878 # ExprNode or None the Py3 return type annotation
1879 #
1880 # The following subnode is constructed internally
1881 # when the def statement is inside a Python class definition.
1882 #
1883 # assmt AssignmentNode Function construction/assignment
1885 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1887 lambda_name = None
1888 assmt = None
1889 num_kwonly_args = 0
1890 num_required_kw_args = 0
1891 reqd_kw_flags_cname = "0"
1892 is_wrapper = 0
1893 decorators = None
1894 return_type_annotation = None
1895 entry = None
1896 acquire_gil = 0
1897 self_in_stararg = 0
1899 def __init__(self, pos, **kwds):
1900 FuncDefNode.__init__(self, pos, **kwds)
1901 k = rk = r = 0
1902 for arg in self.args:
1903 if arg.kw_only:
1904 k += 1
1905 if not arg.default:
1906 rk += 1
1907 if not arg.default:
1908 r += 1
1909 self.num_kwonly_args = k
1910 self.num_required_kw_args = rk
1911 self.num_required_args = r
1913 def as_cfunction(self, cfunc=None, scope=None):
1914 if self.star_arg:
1915 error(self.star_arg.pos, "cdef function cannot have star argument")
1916 if self.starstar_arg:
1917 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1918 if cfunc is None:
1919 cfunc_args = []
1920 for formal_arg in self.args:
1921 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1922 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1923 cname = None,
1924 type = py_object_type,
1925 pos = formal_arg.pos))
1926 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1927 args = cfunc_args,
1928 has_varargs = False,
1929 exception_value = None,
1930 exception_check = False,
1931 nogil = False,
1932 with_gil = False,
1933 is_overridable = True)
1934 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1935 else:
1936 if scope is None:
1937 scope = cfunc.scope
1938 cfunc_type = cfunc.type
1939 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1940 error(self.pos, "wrong number of arguments")
1941 error(cfunc.pos, "previous declaration here")
1942 for i, (formal_arg, type_arg) in enumerate(zip(self.args, cfunc_type.args)):
1943 name_declarator, type = formal_arg.analyse(scope, nonempty=1,
1944 is_self_arg = (i == 0 and scope.is_c_class_scope))
1945 if type is None or type is PyrexTypes.py_object_type:
1946 formal_arg.type = type_arg.type
1947 formal_arg.name_declarator = name_declarator
1948 import ExprNodes
1949 if cfunc_type.exception_value is None:
1950 exception_value = None
1951 else:
1952 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1953 declarator = CFuncDeclaratorNode(self.pos,
1954 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1955 args = self.args,
1956 has_varargs = False,
1957 exception_check = cfunc_type.exception_check,
1958 exception_value = exception_value,
1959 with_gil = cfunc_type.with_gil,
1960 nogil = cfunc_type.nogil)
1961 return CFuncDefNode(self.pos,
1962 modifiers = [],
1963 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1964 declarator = declarator,
1965 body = self.body,
1966 doc = self.doc,
1967 overridable = cfunc_type.is_overridable,
1968 type = cfunc_type,
1969 with_gil = cfunc_type.with_gil,
1970 nogil = cfunc_type.nogil,
1971 visibility = 'private',
1972 api = False,
1973 directive_locals = getattr(cfunc, 'directive_locals', {}))
1975 def analyse_declarations(self, env):
1976 self.is_classmethod = self.is_staticmethod = False
1977 if self.decorators:
1978 for decorator in self.decorators:
1979 func = decorator.decorator
1980 if func.is_name:
1981 self.is_classmethod |= func.name == 'classmethod'
1982 self.is_staticmethod |= func.name == 'staticmethod'
1984 if self.is_classmethod and env.lookup_here('classmethod'):
1985 # classmethod() was overridden - not much we can do here ...
1986 self.is_classmethod = False
1987 if self.is_staticmethod and env.lookup_here('staticmethod'):
1988 # staticmethod() was overridden - not much we can do here ...
1989 self.is_staticmethod = False
1991 if self.name == '__new__' and env.is_py_class_scope:
1992 self.is_staticmethod = 1
1994 self.analyse_argument_types(env)
1995 if self.name == '<lambda>':
1996 self.declare_lambda_function(env)
1997 else:
1998 self.declare_pyfunction(env)
1999 self.analyse_signature(env)
2000 self.return_type = self.entry.signature.return_type()
2001 self.create_local_scope(env)
2003 def analyse_argument_types(self, env):
2004 directive_locals = self.directive_locals = env.directives['locals']
2005 allow_none_for_extension_args = env.directives['allow_none_for_extension_args']
2006 for arg in self.args:
2007 if hasattr(arg, 'name'):
2008 type = arg.type
2009 name_declarator = None
2010 else:
2011 base_type = arg.base_type.analyse(env)
2012 name_declarator, type = \
2013 arg.declarator.analyse(base_type, env)
2014 arg.name = name_declarator.name
2015 if arg.name in directive_locals:
2016 type_node = directive_locals[arg.name]
2017 other_type = type_node.analyse_as_type(env)
2018 if other_type is None:
2019 error(type_node.pos, "Not a type")
2020 elif (type is not PyrexTypes.py_object_type
2021 and not type.same_as(other_type)):
2022 error(arg.base_type.pos, "Signature does not agree with previous declaration")
2023 error(type_node.pos, "Previous declaration here")
2024 else:
2025 type = other_type
2026 if name_declarator and name_declarator.cname:
2027 error(self.pos,
2028 "Python function argument cannot have C name specification")
2029 arg.type = type.as_argument_type()
2030 arg.hdr_type = None
2031 arg.needs_conversion = 0
2032 arg.needs_type_test = 0
2033 arg.is_generic = 1
2034 if arg.type.is_pyobject:
2035 if arg.or_none:
2036 arg.accept_none = True
2037 elif arg.not_none:
2038 arg.accept_none = False
2039 elif arg.type.is_extension_type or arg.type.is_builtin_type:
2040 if arg.default and arg.default.constant_result is None:
2041 # special case: def func(MyType obj = None)
2042 arg.accept_none = True
2043 else:
2044 # default depends on compiler directive
2045 arg.accept_none = allow_none_for_extension_args
2046 else:
2047 # probably just a plain 'object'
2048 arg.accept_none = True
2049 else:
2050 arg.accept_none = True # won't be used, but must be there
2051 if arg.not_none:
2052 error(arg.pos, "Only Python type arguments can have 'not None'")
2053 if arg.or_none:
2054 error(arg.pos, "Only Python type arguments can have 'or None'")
2056 def analyse_signature(self, env):
2057 if self.entry.is_special:
2058 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
2059 elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
2060 # Use the simpler calling signature for zero- and one-argument functions.
2061 if self.entry.signature is TypeSlots.pyfunction_signature:
2062 if len(self.args) == 0:
2063 self.entry.signature = TypeSlots.pyfunction_noargs
2064 elif len(self.args) == 1:
2065 if self.args[0].default is None and not self.args[0].kw_only:
2066 self.entry.signature = TypeSlots.pyfunction_onearg
2067 elif self.entry.signature is TypeSlots.pymethod_signature:
2068 if len(self.args) == 1:
2069 self.entry.signature = TypeSlots.unaryfunc
2070 elif len(self.args) == 2:
2071 if self.args[1].default is None and not self.args[1].kw_only:
2072 self.entry.signature = TypeSlots.ibinaryfunc
2074 sig = self.entry.signature
2075 nfixed = sig.num_fixed_args()
2076 if sig is TypeSlots.pymethod_signature and nfixed == 1 \
2077 and len(self.args) == 0 and self.star_arg:
2078 # this is the only case where a diverging number of
2079 # arguments is not an error - when we have no explicit
2080 # 'self' parameter as in method(*args)
2081 sig = self.entry.signature = TypeSlots.pyfunction_signature # self is not 'really' used
2082 self.self_in_stararg = 1
2083 nfixed = 0
2085 for i in range(min(nfixed, len(self.args))):
2086 arg = self.args[i]
2087 arg.is_generic = 0
2088 if sig.is_self_arg(i) and not self.is_staticmethod:
2089 if self.is_classmethod:
2090 arg.is_type_arg = 1
2091 arg.hdr_type = arg.type = Builtin.type_type
2092 else:
2093 arg.is_self_arg = 1
2094 arg.hdr_type = arg.type = env.parent_type
2095 arg.needs_conversion = 0
2096 else:
2097 arg.hdr_type = sig.fixed_arg_type(i)
2098 if not arg.type.same_as(arg.hdr_type):
2099 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
2100 arg.needs_type_test = 1
2101 else:
2102 arg.needs_conversion = 1
2103 if arg.needs_conversion:
2104 arg.hdr_cname = Naming.arg_prefix + arg.name
2105 else:
2106 arg.hdr_cname = Naming.var_prefix + arg.name
2108 if nfixed > len(self.args):
2109 self.bad_signature()
2110 return
2111 elif nfixed < len(self.args):
2112 if not sig.has_generic_args:
2113 self.bad_signature()
2114 for arg in self.args:
2115 if arg.is_generic and \
2116 (arg.type.is_extension_type or arg.type.is_builtin_type):
2117 arg.needs_type_test = 1
2119 def bad_signature(self):
2120 sig = self.entry.signature
2121 expected_str = "%d" % sig.num_fixed_args()
2122 if sig.has_generic_args:
2123 expected_str = expected_str + " or more"
2124 name = self.name
2125 if name.startswith("__") and name.endswith("__"):
2126 desc = "Special method"
2127 else:
2128 desc = "Method"
2129 error(self.pos,
2130 "%s %s has wrong number of arguments "
2131 "(%d declared, %s expected)" % (
2132 desc, self.name, len(self.args), expected_str))
2134 def signature_has_nongeneric_args(self):
2135 argcount = len(self.args)
2136 if argcount == 0 or (
2137 argcount == 1 and (self.args[0].is_self_arg or
2138 self.args[0].is_type_arg)):
2139 return 0
2140 return 1
2142 def signature_has_generic_args(self):
2143 return self.entry.signature.has_generic_args
2145 def declare_pyfunction(self, env):
2146 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
2147 name = self.name
2148 entry = env.lookup_here(name)
2149 if entry and entry.type.is_cfunction and not self.is_wrapper:
2150 warning(self.pos, "Overriding cdef method with def method.", 5)
2151 entry = env.declare_pyfunction(name, self.pos, allow_redefine=not self.is_wrapper)
2152 self.entry = entry
2153 prefix = env.next_id(env.scope_prefix)
2155 entry.func_cname = \
2156 Naming.pyfunc_prefix + prefix + name
2157 entry.pymethdef_cname = \
2158 Naming.pymethdef_prefix + prefix + name
2159 if Options.docstrings:
2160 entry.doc = embed_position(self.pos, self.doc)
2161 entry.doc_cname = \
2162 Naming.funcdoc_prefix + prefix + name
2163 if entry.is_special:
2164 if entry.name in TypeSlots.invisible or not entry.doc or (entry.name in '__getattr__' and env.directives['fast_getattr']):
2165 entry.wrapperbase_cname = None
2166 else:
2167 entry.wrapperbase_cname = Naming.wrapperbase_prefix + prefix + name
2168 else:
2169 entry.doc = None
2171 def declare_lambda_function(self, env):
2172 name = self.name
2173 prefix = env.scope_prefix
2174 func_cname = \
2175 Naming.lambda_func_prefix + u'funcdef' + prefix + self.lambda_name
2176 entry = env.declare_lambda_function(func_cname, self.pos)
2177 entry.pymethdef_cname = \
2178 Naming.lambda_func_prefix + u'methdef' + prefix + self.lambda_name
2179 entry.qualified_name = env.qualify_name(self.lambda_name)
2180 entry.doc = None
2181 self.entry = entry
2183 def declare_arguments(self, env):
2184 for arg in self.args:
2185 if not arg.name:
2186 error(arg.pos, "Missing argument name")
2187 else:
2188 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
2189 env.control_flow.set_state((), (arg.name, 'initialized'), True)
2190 if arg.needs_conversion:
2191 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
2192 if arg.type.is_pyobject:
2193 arg.entry.init = "0"
2194 arg.entry.init_to_none = 0
2195 else:
2196 arg.entry = self.declare_argument(env, arg)
2197 arg.entry.used = 1
2198 arg.entry.is_self_arg = arg.is_self_arg
2199 if arg.hdr_type:
2200 if arg.is_self_arg or arg.is_type_arg or \
2201 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
2202 arg.entry.is_declared_generic = 1
2203 self.declare_python_arg(env, self.star_arg)
2204 self.declare_python_arg(env, self.starstar_arg)
2206 def declare_python_arg(self, env, arg):
2207 if arg:
2208 if env.directives['infer_types'] != False:
2209 type = PyrexTypes.unspecified_type
2210 else:
2211 type = py_object_type
2212 entry = env.declare_var(arg.name, type, arg.pos)
2213 entry.used = 1
2214 entry.init = "0"
2215 entry.init_to_none = 0
2216 entry.xdecref_cleanup = 1
2217 arg.entry = entry
2218 env.control_flow.set_state((), (arg.name, 'initialized'), True)
2220 def analyse_expressions(self, env):
2221 self.local_scope.directives = env.directives
2222 self.analyse_default_values(env)
2223 if self.needs_assignment_synthesis(env):
2224 # Shouldn't we be doing this at the module level too?
2225 self.synthesize_assignment_node(env)
2227 def needs_assignment_synthesis(self, env, code=None):
2228 # Should enable for module level as well, that will require more testing...
2229 if self.entry.is_anonymous:
2230 return True
2231 if env.is_module_scope:
2232 if code is None:
2233 return env.directives['binding']
2234 else:
2235 return code.globalstate.directives['binding']
2236 return env.is_py_class_scope or env.is_closure_scope
2238 def synthesize_assignment_node(self, env):
2239 import ExprNodes
2240 genv = env
2241 while genv.is_py_class_scope or genv.is_c_class_scope:
2242 genv = genv.outer_scope
2244 if genv.is_closure_scope:
2245 rhs = ExprNodes.InnerFunctionNode(
2246 self.pos, pymethdef_cname = self.entry.pymethdef_cname)
2247 else:
2248 rhs = ExprNodes.PyCFunctionNode(
2249 self.pos, pymethdef_cname = self.entry.pymethdef_cname, binding = env.directives['binding'])
2251 if env.is_py_class_scope:
2252 if not self.is_staticmethod and not self.is_classmethod:
2253 rhs.binding = True
2255 self.assmt = SingleAssignmentNode(self.pos,
2256 lhs = ExprNodes.NameNode(self.pos, name = self.name),
2257 rhs = rhs)
2258 self.assmt.analyse_declarations(env)
2259 self.assmt.analyse_expressions(env)
2261 def generate_function_header(self, code, with_pymethdef, proto_only=0):
2262 arg_code_list = []
2263 sig = self.entry.signature
2264 if sig.has_dummy_arg or self.self_in_stararg:
2265 arg_code_list.append(
2266 "PyObject *%s" % Naming.self_cname)
2267 for arg in self.args:
2268 if not arg.is_generic:
2269 if arg.is_self_arg or arg.is_type_arg:
2270 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
2271 else:
2272 arg_code_list.append(
2273 arg.hdr_type.declaration_code(arg.hdr_cname))
2274 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
2275 arg_code_list.append("CYTHON_UNUSED PyObject *unused")
2276 if sig.has_generic_args:
2277 arg_code_list.append(
2278 "PyObject *%s, PyObject *%s"
2279 % (Naming.args_cname, Naming.kwds_cname))
2280 arg_code = ", ".join(arg_code_list)
2281 dc = self.return_type.declaration_code(self.entry.func_cname)
2282 mf = " ".join(self.modifiers).upper()
2283 if mf: mf += " "
2284 header = "static %s%s(%s)" % (mf, dc, arg_code)
2285 code.putln("%s; /*proto*/" % header)
2286 if proto_only:
2287 return
2288 if (Options.docstrings and self.entry.doc and
2289 not self.entry.scope.is_property_scope and
2290 (not self.entry.is_special or self.entry.wrapperbase_cname)):
2291 docstr = self.entry.doc
2292 if docstr.is_unicode:
2293 docstr = docstr.utf8encode()
2294 code.putln(
2295 'static char %s[] = "%s";' % (
2296 self.entry.doc_cname,
2297 split_string_literal(escape_byte_string(docstr))))
2298 if self.entry.is_special:
2299 code.putln(
2300 "struct wrapperbase %s;" % self.entry.wrapperbase_cname)
2301 if with_pymethdef:
2302 code.put(
2303 "static PyMethodDef %s = " %
2304 self.entry.pymethdef_cname)
2305 code.put_pymethoddef(self.entry, ";", allow_skip=False)
2306 code.putln("%s {" % header)
2308 def generate_argument_declarations(self, env, code):
2309 for arg in self.args:
2310 if arg.is_generic: # or arg.needs_conversion:
2311 if arg.needs_conversion:
2312 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
2313 elif not arg.entry.in_closure:
2314 code.put_var_declaration(arg.entry)
2316 def generate_keyword_list(self, code):
2317 if self.signature_has_generic_args() and \
2318 self.signature_has_nongeneric_args():
2319 code.put(
2320 "static PyObject **%s[] = {" %
2321 Naming.pykwdlist_cname)
2322 for arg in self.args:
2323 if arg.is_generic:
2324 pystring_cname = code.intern_identifier(arg.name)
2325 code.put('&%s,' % pystring_cname)
2326 code.putln("0};")
2328 def generate_argument_parsing_code(self, env, code):
2329 # Generate PyArg_ParseTuple call for generic
2330 # arguments, if any.
2331 if self.entry.signature.has_dummy_arg and not self.self_in_stararg:
2332 # get rid of unused argument warning
2333 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
2335 old_error_label = code.new_error_label()
2336 our_error_label = code.error_label
2337 end_label = code.new_label("argument_unpacking_done")
2339 has_kwonly_args = self.num_kwonly_args > 0
2340 has_star_or_kw_args = self.star_arg is not None \
2341 or self.starstar_arg is not None or has_kwonly_args
2343 for arg in self.args:
2344 if not arg.type.is_pyobject:
2345 done = arg.type.create_from_py_utility_code(env)
2346 if not done: pass # will fail later
2348 if not self.signature_has_generic_args():
2349 if has_star_or_kw_args:
2350 error(self.pos, "This method cannot have * or keyword arguments")
2351 self.generate_argument_conversion_code(code)
2353 elif not self.signature_has_nongeneric_args():
2354 # func(*args) or func(**kw) or func(*args, **kw)
2355 self.generate_stararg_copy_code(code)
2357 else:
2358 positional_args = []
2359 kw_only_args = []
2360 for arg in self.args:
2361 arg_entry = arg.entry
2362 if arg.is_generic:
2363 if arg.default:
2364 if not arg.is_self_arg and not arg.is_type_arg:
2365 if arg.kw_only:
2366 kw_only_args.append(arg)
2367 else:
2368 positional_args.append(arg)
2369 elif arg.kw_only:
2370 kw_only_args.append(arg)
2371 elif not arg.is_self_arg and not arg.is_type_arg:
2372 positional_args.append(arg)
2374 self.generate_tuple_and_keyword_parsing_code(
2375 positional_args, kw_only_args, end_label, code)
2377 code.error_label = old_error_label
2378 if code.label_used(our_error_label):
2379 if not code.label_used(end_label):
2380 code.put_goto(end_label)
2381 code.put_label(our_error_label)
2382 if has_star_or_kw_args:
2383 self.generate_arg_decref(self.star_arg, code)
2384 if self.starstar_arg:
2385 if self.starstar_arg.entry.xdecref_cleanup:
2386 code.put_var_xdecref(self.starstar_arg.entry)
2387 else:
2388 code.put_var_decref(self.starstar_arg.entry)
2389 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
2390 # The arguments are put into the closure one after the
2391 # other, so when type errors are found, all references in
2392 # the closure instance must be properly ref-counted to
2393 # facilitate generic closure instance deallocation. In
2394 # the case of an argument type error, it's best to just
2395 # DECREF+clear the already handled references, as this
2396 # frees their references as early as possible.
2397 for arg in self.args:
2398 if arg.type.is_pyobject and arg.entry.in_closure:
2399 code.put_var_xdecref_clear(arg.entry)
2400 if self.needs_closure:
2401 code.put_decref(Naming.cur_scope_cname, self.local_scope.scope_class.type)
2402 code.put_finish_refcount_context()
2403 code.putln("return %s;" % self.error_value())
2404 if code.label_used(end_label):
2405 code.put_label(end_label)
2407 def generate_arg_assignment(self, arg, item, code):
2408 if arg.type.is_pyobject:
2409 if arg.is_generic:
2410 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
2411 entry = arg.entry
2412 code.putln("%s = %s;" % (entry.cname, item))
2413 if entry.in_closure:
2414 code.put_var_incref(entry)
2415 else:
2416 func = arg.type.from_py_function
2417 if func:
2418 code.putln("%s = %s(%s); %s" % (
2419 arg.entry.cname,
2420 func,
2421 item,
2422 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
2423 else:
2424 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
2426 def generate_arg_xdecref(self, arg, code):
2427 if arg:
2428 code.put_var_xdecref(arg.entry)
2430 def generate_arg_decref(self, arg, code):
2431 if arg:
2432 code.put_var_decref(arg.entry)
2434 def generate_stararg_copy_code(self, code):
2435 if not self.star_arg:
2436 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2437 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
2438 Naming.args_cname)
2439 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2440 self.name, Naming.args_cname, self.error_value()))
2441 code.putln("}")
2443 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2445 if self.starstar_arg:
2446 if self.star_arg:
2447 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2448 else:
2449 kwarg_check = "%s" % Naming.kwds_cname
2450 else:
2451 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2452 Naming.kwds_cname, Naming.kwds_cname)
2453 code.putln(
2454 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2455 kwarg_check, Naming.kwds_cname, self.name,
2456 bool(self.starstar_arg), self.error_value()))
2458 if self.starstar_arg:
2459 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2460 self.starstar_arg.entry.cname,
2461 Naming.kwds_cname,
2462 Naming.kwds_cname))
2463 code.putln("if (unlikely(!%s)) return %s;" % (
2464 self.starstar_arg.entry.cname, self.error_value()))
2465 self.starstar_arg.entry.xdecref_cleanup = 0
2466 code.put_gotref(self.starstar_arg.entry.cname)
2468 if self.self_in_stararg:
2469 # need to create a new tuple with 'self' inserted as first item
2470 code.put("%s = PyTuple_New(PyTuple_GET_SIZE(%s)+1); if (unlikely(!%s)) " % (
2471 self.star_arg.entry.cname,
2472 Naming.args_cname,
2473 self.star_arg.entry.cname))
2474 if self.starstar_arg:
2475 code.putln("{")
2476 code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type)
2477 code.putln("return %s;" % self.error_value())
2478 code.putln("}")
2479 else:
2480 code.putln("return %s;" % self.error_value())
2481 code.put_gotref(self.star_arg.entry.cname)
2482 code.put_incref(Naming.self_cname, py_object_type)
2483 code.put_giveref(Naming.self_cname)
2484 code.putln("PyTuple_SET_ITEM(%s, 0, %s);" % (
2485 self.star_arg.entry.cname, Naming.self_cname))
2486 temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False)
2487 code.putln("for (%s=0; %s < PyTuple_GET_SIZE(%s); %s++) {" % (
2488 temp, temp, Naming.args_cname, temp))
2489 code.putln("PyObject* item = PyTuple_GET_ITEM(%s, %s);" % (
2490 Naming.args_cname, temp))
2491 code.put_incref("item", py_object_type)
2492 code.put_giveref("item")
2493 code.putln("PyTuple_SET_ITEM(%s, %s+1, item);" % (
2494 self.star_arg.entry.cname, temp))
2495 code.putln("}")
2496 code.funcstate.release_temp(temp)
2497 self.star_arg.entry.xdecref_cleanup = 0
2498 elif self.star_arg:
2499 code.put_incref(Naming.args_cname, py_object_type)
2500 code.putln("%s = %s;" % (
2501 self.star_arg.entry.cname,
2502 Naming.args_cname))
2503 self.star_arg.entry.xdecref_cleanup = 0
2505 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2506 kw_only_args, success_label, code):
2507 argtuple_error_label = code.new_label("argtuple_error")
2509 min_positional_args = self.num_required_args - self.num_required_kw_args
2510 if len(self.args) > 0 and (self.args[0].is_self_arg or self.args[0].is_type_arg):
2511 min_positional_args -= 1
2512 max_positional_args = len(positional_args)
2513 has_fixed_positional_count = not self.star_arg and \
2514 min_positional_args == max_positional_args
2516 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2517 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2518 if self.num_required_kw_args:
2519 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2521 if self.starstar_arg or self.star_arg:
2522 self.generate_stararg_init_code(max_positional_args, code)
2524 # --- optimised code when we receive keyword arguments
2525 if self.num_required_kw_args:
2526 likely_hint = "likely"
2527 else:
2528 likely_hint = "unlikely"
2529 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2530 self.generate_keyword_unpacking_code(
2531 min_positional_args, max_positional_args,
2532 has_fixed_positional_count,
2533 positional_args, kw_only_args, argtuple_error_label, code)
2535 # --- optimised code when we do not receive any keyword arguments
2536 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2537 # Python raises arg tuple related errors first, so we must
2538 # check the length here
2539 if min_positional_args == max_positional_args and not self.star_arg:
2540 compare = '!='
2541 else:
2542 compare = '<'
2543 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2544 Naming.args_cname, compare, min_positional_args))
2545 code.put_goto(argtuple_error_label)
2547 if self.num_required_kw_args:
2548 # pure error case: keywords required but not passed
2549 if max_positional_args > min_positional_args and not self.star_arg:
2550 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2551 Naming.args_cname, max_positional_args))
2552 code.put_goto(argtuple_error_label)
2553 code.putln('} else {')
2554 for i, arg in enumerate(kw_only_args):
2555 if not arg.default:
2556 pystring_cname = code.intern_identifier(arg.name)
2557 # required keyword-only argument missing
2558 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2559 self.name,
2560 pystring_cname))
2561 code.putln(code.error_goto(self.pos))
2562 break
2564 elif min_positional_args == max_positional_args:
2565 # parse the exact number of positional arguments from the
2566 # args tuple
2567 code.putln('} else {')
2568 for i, arg in enumerate(positional_args):
2569 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2570 self.generate_arg_assignment(arg, item, code)
2571 self.generate_arg_default_assignments(code)
2573 else:
2574 # parse the positional arguments from the variable length
2575 # args tuple
2576 code.putln('} else {')
2577 self.generate_arg_default_assignments(code)
2578 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2579 if self.star_arg:
2580 code.putln('default:')
2581 reversed_args = list(enumerate(positional_args))[::-1]
2582 for i, arg in reversed_args:
2583 if i >= min_positional_args-1:
2584 if min_positional_args > 1:
2585 code.putln('case %2d:' % (i+1)) # pure code beautification
2586 else:
2587 code.put('case %2d: ' % (i+1))
2588 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2589 self.generate_arg_assignment(arg, item, code)
2590 if min_positional_args == 0:
2591 code.put('case 0: ')
2592 code.putln('break;')
2593 if self.star_arg:
2594 if min_positional_args:
2595 for i in range(min_positional_args-1, -1, -1):
2596 code.putln('case %2d:' % i)
2597 code.put_goto(argtuple_error_label)
2598 else:
2599 code.put('default: ')
2600 code.put_goto(argtuple_error_label)
2601 code.putln('}')
2603 code.putln('}')
2605 if code.label_used(argtuple_error_label):
2606 code.put_goto(success_label)
2607 code.put_label(argtuple_error_label)
2608 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2609 self.name, has_fixed_positional_count,
2610 min_positional_args, max_positional_args,
2611 Naming.args_cname))
2612 code.putln(code.error_goto(self.pos))
2614 def generate_arg_default_assignments(self, code):
2615 for arg in self.args:
2616 if arg.is_generic and arg.default:
2617 code.putln(
2618 "%s = %s;" % (
2619 arg.entry.cname,
2620 arg.calculate_default_value_code(code)))
2622 def generate_stararg_init_code(self, max_positional_args, code):
2623 if self.starstar_arg:
2624 self.starstar_arg.entry.xdecref_cleanup = 0
2625 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2626 self.starstar_arg.entry.cname,
2627 self.starstar_arg.entry.cname,
2628 self.error_value()))
2629 code.put_gotref(self.starstar_arg.entry.cname)
2630 if self.star_arg:
2631 self.star_arg.entry.xdecref_cleanup = 0
2632 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2633 Naming.args_cname,
2634 max_positional_args))
2635 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2636 self.star_arg.entry.cname, Naming.args_cname,
2637 max_positional_args, Naming.args_cname))
2638 code.put_gotref(self.star_arg.entry.cname)
2639 if self.starstar_arg:
2640 code.putln("")
2641 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2642 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2643 code.putln('return %s;' % self.error_value())
2644 code.putln('}')
2645 else:
2646 code.putln("if (unlikely(!%s)) return %s;" % (
2647 self.star_arg.entry.cname, self.error_value()))
2648 code.putln('} else {')
2649 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2650 code.put_incref(Naming.empty_tuple, py_object_type)
2651 code.putln('}')
2653 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2654 has_fixed_positional_count, positional_args,
2655 kw_only_args, argtuple_error_label, code):
2656 all_args = tuple(positional_args) + tuple(kw_only_args)
2657 max_args = len(all_args)
2659 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2660 Naming.kwds_cname)
2661 # the 'values' array collects borrowed references to arguments
2662 # before doing any type coercion etc.
2663 code.putln("PyObject* values[%d] = {%s};" % (
2664 max_args, ','.join('0'*max_args)))
2666 # assign borrowed Python default values to the values array,
2667 # so that they can be overwritten by received arguments below
2668 for i, arg in enumerate(all_args):
2669 if arg.default and arg.type.is_pyobject:
2670 default_value = arg.calculate_default_value_code(code)
2671 code.putln('values[%d] = %s;' % (i, arg.type.as_pyobject(default_value)))
2673 # parse the args tuple and check that it's not too long
2674 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2675 if self.star_arg:
2676 code.putln('default:')
2677 for i in range(max_positional_args-1, -1, -1):
2678 code.put('case %2d: ' % (i+1))
2679 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2680 i, Naming.args_cname, i))
2681 code.putln('case 0: break;')
2682 if not self.star_arg:
2683 code.put('default: ') # more arguments than allowed
2684 code.put_goto(argtuple_error_label)
2685 code.putln('}')
2687 # now fill up the positional/required arguments with values
2688 # from the kw dict
2689 if self.num_required_args or max_positional_args > 0:
2690 last_required_arg = -1
2691 for i, arg in enumerate(all_args):
2692 if not arg.default:
2693 last_required_arg = i
2694 if last_required_arg < max_positional_args:
2695 last_required_arg = max_positional_args-1
2696 num_required_args = self.num_required_args
2697 if max_positional_args > 0:
2698 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2699 for i, arg in enumerate(all_args[:last_required_arg+1]):
2700 if max_positional_args > 0 and i <= max_positional_args:
2701 if self.star_arg and i == max_positional_args:
2702 code.putln('default:')
2703 else:
2704 code.putln('case %2d:' % i)
2705 pystring_cname = code.intern_identifier(arg.name)
2706 if arg.default:
2707 if arg.kw_only:
2708 # handled separately below
2709 continue
2710 code.putln('if (kw_args > 0) {')
2711 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2712 Naming.kwds_cname, pystring_cname))
2713 code.putln('if (value) { values[%d] = value; kw_args--; }' % i)
2714 code.putln('}')
2715 else:
2716 num_required_args -= 1
2717 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2718 i, Naming.kwds_cname, pystring_cname))
2719 code.putln('if (likely(values[%d])) kw_args--;' % i);
2720 if i < min_positional_args:
2721 if i == 0:
2722 # special case: we know arg 0 is missing
2723 code.put('else ')
2724 code.put_goto(argtuple_error_label)
2725 else:
2726 # print the correct number of values (args or
2727 # kwargs) that were passed into positional
2728 # arguments up to this point
2729 code.putln('else {')
2730 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2731 self.name, has_fixed_positional_count,
2732 min_positional_args, max_positional_args, i))
2733 code.putln(code.error_goto(self.pos))
2734 code.putln('}')
2735 elif arg.kw_only:
2736 code.putln('else {')
2737 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2738 self.name, pystring_cname))
2739 code.putln(code.error_goto(self.pos))
2740 code.putln('}')
2741 if max_positional_args > 0:
2742 code.putln('}')
2744 if kw_only_args and not self.starstar_arg:
2745 # unpack optional keyword-only arguments
2746 # checking for interned strings in a dict is faster than iterating
2747 # but it's too likely that we must iterate if we expect **kwargs
2748 optional_args = []
2749 for i, arg in enumerate(all_args[max_positional_args:]):
2750 if not arg.kw_only or not arg.default:
2751 continue
2752 optional_args.append((i+max_positional_args, arg))
2753 if optional_args:
2754 # this mimics an unrolled loop so that we can "break" out of it
2755 code.putln('while (kw_args > 0) {')
2756 code.putln('PyObject* value;')
2757 for i, arg in optional_args:
2758 pystring_cname = code.intern_identifier(arg.name)
2759 code.putln(
2760 'value = PyDict_GetItem(%s, %s);' % (
2761 Naming.kwds_cname, pystring_cname))
2762 code.putln(
2763 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2764 code.putln('break;')
2765 code.putln('}')
2767 code.putln('if (unlikely(kw_args > 0)) {')
2768 # non-positional/-required kw args left in dict: default args,
2769 # kw-only args, **kwargs or error
2770 #
2771 # This is sort of a catch-all: except for checking required
2772 # arguments, this will always do the right thing for unpacking
2773 # keyword arguments, so that we can concentrate on optimising
2774 # common cases above.
2775 if max_positional_args == 0:
2776 pos_arg_count = "0"
2777 elif self.star_arg:
2778 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2779 Naming.args_cname, max_positional_args,
2780 Naming.args_cname, max_positional_args))
2781 pos_arg_count = "used_pos_args"
2782 else:
2783 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2784 code.globalstate.use_utility_code(parse_keywords_utility_code)
2785 code.put(
2786 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2787 Naming.kwds_cname,
2788 Naming.pykwdlist_cname,
2789 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2790 pos_arg_count,
2791 self.name))
2792 code.putln(code.error_goto(self.pos))
2793 code.putln('}')
2795 # convert arg values to their final type and assign them
2796 for i, arg in enumerate(all_args):
2797 if arg.default and not arg.type.is_pyobject:
2798 code.putln("if (values[%d]) {" % i)
2799 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2800 if arg.default and not arg.type.is_pyobject:
2801 code.putln('} else {')
2802 code.putln(
2803 "%s = %s;" % (
2804 arg.entry.cname,
2805 arg.calculate_default_value_code(code)))
2806 code.putln('}')
2808 def generate_argument_conversion_code(self, code):
2809 # Generate code to convert arguments from signature type to
2810 # declared type, if needed. Also copies signature arguments
2811 # into closure fields.
2812 for arg in self.args:
2813 if arg.needs_conversion:
2814 self.generate_arg_conversion(arg, code)
2815 elif arg.entry.in_closure:
2816 code.putln('%s = %s;' % (arg.entry.cname, arg.hdr_cname))
2817 if arg.type.is_pyobject:
2818 code.put_var_incref(arg.entry)
2820 def generate_arg_conversion(self, arg, code):
2821 # Generate conversion code for one argument.
2822 old_type = arg.hdr_type
2823 new_type = arg.type
2824 if old_type.is_pyobject:
2825 if arg.default:
2826 code.putln("if (%s) {" % arg.hdr_cname)
2827 else:
2828 code.putln("assert(%s); {" % arg.hdr_cname)
2829 self.generate_arg_conversion_from_pyobject(arg, code)
2830 code.putln("}")
2831 elif new_type.is_pyobject:
2832 self.generate_arg_conversion_to_pyobject(arg, code)
2833 else:
2834 if new_type.assignable_from(old_type):
2835 code.putln(
2836 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2837 else:
2838 error(arg.pos,
2839 "Cannot convert 1 argument from '%s' to '%s'" %
2840 (old_type, new_type))
2842 def generate_arg_conversion_from_pyobject(self, arg, code):
2843 new_type = arg.type
2844 func = new_type.from_py_function
2845 # copied from CoerceFromPyTypeNode
2846 if func:
2847 lhs = arg.entry.cname
2848 rhs = "%s(%s)" % (func, arg.hdr_cname)
2849 if new_type.is_enum:
2850 rhs = PyrexTypes.typecast(new_type, PyrexTypes.c_long_type, rhs)
2851 code.putln("%s = %s; %s" % (
2852 lhs,
2853 rhs,
2854 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2855 else:
2856 error(arg.pos,
2857 "Cannot convert Python object argument to type '%s'"
2858 % new_type)
2860 def generate_arg_conversion_to_pyobject(self, arg, code):
2861 old_type = arg.hdr_type
2862 func = old_type.to_py_function
2863 if func:
2864 code.putln("%s = %s(%s); %s" % (
2865 arg.entry.cname,
2866 func,
2867 arg.hdr_cname,
2868 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2869 code.put_var_gotref(arg.entry)
2870 else:
2871 error(arg.pos,
2872 "Cannot convert argument of type '%s' to Python object"
2873 % old_type)
2875 def generate_argument_type_tests(self, code):
2876 # Generate type tests for args whose signature
2877 # type is PyObject * and whose declared type is
2878 # a subtype thereof.
2879 for arg in self.args:
2880 if arg.needs_type_test:
2881 self.generate_arg_type_test(arg, code)
2882 elif not arg.accept_none and arg.type.is_pyobject:
2883 self.generate_arg_none_check(arg, code)
2885 def error_value(self):
2886 return self.entry.signature.error_value
2888 def caller_will_check_exceptions(self):
2889 return 1
2891 class OverrideCheckNode(StatNode):
2892 # A Node for dispatching to the def method if it
2893 # is overriden.
2894 #
2895 # py_func
2896 #
2897 # args
2898 # func_temp
2899 # body
2901 child_attrs = ['body']
2903 body = None
2905 def analyse_expressions(self, env):
2906 self.args = env.arg_entries
2907 if self.py_func.is_module_scope:
2908 first_arg = 0
2909 else:
2910 first_arg = 1
2911 import ExprNodes
2912 self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
2913 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2914 call_node = ExprNodes.SimpleCallNode(self.pos,
2915 function=self.func_node,
2916 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2917 self.body = ReturnStatNode(self.pos, value=call_node)
2918 self.body.analyse_expressions(env)
2920 def generate_execution_code(self, code):
2921 interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
2922 # Check to see if we are an extension type
2923 if self.py_func.is_module_scope:
2924 self_arg = "((PyObject *)%s)" % Naming.module_cname
2925 else:
2926 self_arg = "((PyObject *)%s)" % self.args[0].cname
2927 code.putln("/* Check if called by wrapper */")
2928 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2929 code.putln("/* Check if overriden in Python */")
2930 if self.py_func.is_module_scope:
2931 code.putln("else {")
2932 else:
2933 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2934 func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
2935 self.func_node.set_cname(func_node_temp)
2936 # need to get attribute manually--scope would return cdef method
2937 err = code.error_goto_if_null(func_node_temp, self.pos)
2938 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
2939 func_node_temp, self_arg, interned_attr_cname, err))
2940 code.put_gotref(func_node_temp)
2941 is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
2942 is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)" % (
2943 func_node_temp, self.py_func.entry.func_cname)
2944 code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
2945 self.body.generate_execution_code(code)
2946 code.putln("}")
2947 code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
2948 code.funcstate.release_temp(func_node_temp)
2949 code.putln("}")
2951 class ClassDefNode(StatNode, BlockNode):
2952 pass
2954 class PyClassDefNode(ClassDefNode):
2955 # A Python class definition.
2956 #
2957 # name EncodedString Name of the class
2958 # doc string or None
2959 # body StatNode Attribute definition code
2960 # entry Symtab.Entry
2961 # scope PyClassScope
2962 # decorators [DecoratorNode] list of decorators or None
2963 #
2964 # The following subnodes are constructed internally:
2965 #
2966 # dict DictNode Class dictionary or Py3 namespace
2967 # classobj ClassNode Class object
2968 # target NameNode Variable to assign class object to
2970 child_attrs = ["body", "dict", "metaclass", "mkw", "bases", "classobj", "target"]
2971 decorators = None
2972 py3_style_class = False # Python3 style class (bases+kwargs)
2974 def __init__(self, pos, name, bases, doc, body, decorators = None,
2975 keyword_args = None, starstar_arg = None):
2976 StatNode.__init__(self, pos)
2977 self.name = name
2978 self.doc = doc
2979 self.body = body
2980 self.decorators = decorators
2981 import ExprNodes
2982 if self.doc and Options.docstrings:
2983 doc = embed_position(self.pos, self.doc)
2984 doc_node = ExprNodes.StringNode(pos, value = doc)
2985 else:
2986 doc_node = None
2987 if keyword_args or starstar_arg:
2988 self.py3_style_class = True
2989 self.bases = bases
2990 self.metaclass = None
2991 if keyword_args and not starstar_arg:
2992 for i, item in list(enumerate(keyword_args.key_value_pairs))[::-1]:
2993 if item.key.value == 'metaclass':
2994 if self.metaclass is not None:
2995 error(item.pos, "keyword argument 'metaclass' passed multiple times")
2996 # special case: we already know the metaclass,
2997 # so we don't need to do the "build kwargs,
2998 # find metaclass" dance at runtime
2999 self.metaclass = item.value
3000 del keyword_args.key_value_pairs[i]
3001 if starstar_arg or (keyword_args and keyword_args.key_value_pairs):
3002 self.mkw = ExprNodes.KeywordArgsNode(
3003 pos, keyword_args = keyword_args, starstar_arg = starstar_arg)
3004 else:
3005 self.mkw = ExprNodes.NullNode(pos)
3006 if self.metaclass is None:
3007 self.metaclass = ExprNodes.PyClassMetaclassNode(
3008 pos, mkw = self.mkw, bases = self.bases)
3009 self.dict = ExprNodes.PyClassNamespaceNode(pos, name = name,
3010 doc = doc_node, metaclass = self.metaclass, bases = self.bases,
3011 mkw = self.mkw)
3012 self.classobj = ExprNodes.Py3ClassNode(pos, name = name,
3013 bases = self.bases, dict = self.dict, doc = doc_node,
3014 metaclass = self.metaclass, mkw = self.mkw)
3015 else:
3016 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
3017 self.metaclass = None
3018 self.mkw = None
3019 self.bases = None
3020 self.classobj = ExprNodes.ClassNode(pos, name = name,
3021 bases = bases, dict = self.dict, doc = doc_node)
3022 self.target = ExprNodes.NameNode(pos, name = name)
3024 def as_cclass(self):
3025 """
3026 Return this node as if it were declared as an extension class
3027 """
3028 if self.py3_style_class:
3029 error(self.classobj.pos, "Python3 style class could not be represented as C class")
3030 return
3031 bases = self.classobj.bases.args
3032 if len(bases) == 0:
3033 base_class_name = None
3034 base_class_module = None
3035 elif len(bases) == 1:
3036 base = bases[0]
3037 path = []
3038 from ExprNodes import AttributeNode, NameNode
3039 while isinstance(base, AttributeNode):
3040 path.insert(0, base.attribute)
3041 base = base.obj
3042 if isinstance(base, NameNode):
3043 path.insert(0, base.name)
3044 base_class_name = path[-1]
3045 if len(path) > 1:
3046 base_class_module = u'.'.join(path[:-1])
3047 else:
3048 base_class_module = None
3049 else:
3050 error(self.classobj.bases.args.pos, "Invalid base class")
3051 else:
3052 error(self.classobj.bases.args.pos, "C class may only have one base class")
3053 return None
3055 return CClassDefNode(self.pos,
3056 visibility = 'private',
3057 module_name = None,
3058 class_name = self.name,
3059 base_class_module = base_class_module,
3060 base_class_name = base_class_name,
3061 decorators = self.decorators,
3062 body = self.body,
3063 in_pxd = False,
3064 doc = self.doc)
3066 def create_scope(self, env):
3067 genv = env
3068 while genv.is_py_class_scope or genv.is_c_class_scope:
3069 genv = genv.outer_scope
3070 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
3071 return cenv
3073 def analyse_declarations(self, env):
3074 self.target.analyse_target_declaration(env)
3075 cenv = self.create_scope(env)
3076 cenv.directives = env.directives
3077 cenv.class_obj_cname = self.target.entry.cname
3078 self.body.analyse_declarations(cenv)
3080 def analyse_expressions(self, env):
3081 if self.py3_style_class:
3082 self.bases.analyse_expressions(env)
3083 self.metaclass.analyse_expressions(env)
3084 self.mkw.analyse_expressions(env)
3085 self.dict.analyse_expressions(env)
3086 self.classobj.analyse_expressions(env)
3087 genv = env.global_scope()
3088 cenv = self.scope
3089 self.body.analyse_expressions(cenv)
3090 self.target.analyse_target_expression(env, self.classobj)
3092 def generate_function_definitions(self, env, code):
3093 self.generate_lambda_definitions(self.scope, code)
3094 self.body.generate_function_definitions(self.scope, code)
3096 def generate_execution_code(self, code):
3097 code.pyclass_stack.append(self)
3098 cenv = self.scope
3099 if self.py3_style_class:
3100 self.bases.generate_evaluation_code(code)
3101 self.mkw.generate_evaluation_code(code)
3102 self.metaclass.generate_evaluation_code(code)
3103 self.dict.generate_evaluation_code(code)
3104 cenv.namespace_cname = cenv.class_obj_cname = self.dict.result()
3105 self.body.generate_execution_code(code)
3106 self.classobj.generate_evaluation_code(code)
3107 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
3108 self.target.generate_assignment_code(self.classobj, code)
3109 self.dict.generate_disposal_code(code)
3110 self.dict.free_temps(code)
3111 if self.py3_style_class:
3112 self.mkw.generate_disposal_code(code)
3113 self.mkw.free_temps(code)
3114 self.metaclass.generate_disposal_code(code)
3115 self.metaclass.free_temps(code)
3116 self.bases.generate_disposal_code(code)
3117 self.bases.free_temps(code)
3118 code.pyclass_stack.pop()
3120 class CClassDefNode(ClassDefNode):
3121 # An extension type definition.
3122 #
3123 # visibility 'private' or 'public' or 'extern'
3124 # typedef_flag boolean
3125 # api boolean
3126 # module_name string or None For import of extern type objects
3127 # class_name string Unqualified name of class
3128 # as_name string or None Name to declare as in this scope
3129 # base_class_module string or None Module containing the base class
3130 # base_class_name string or None Name of the base class
3131 # objstruct_name string or None Specified C name of object struct
3132 # typeobj_name string or None Specified C name of type object
3133 # in_pxd boolean Is in a .pxd file
3134 # decorators [DecoratorNode] list of decorators or None
3135 # doc string or None
3136 # body StatNode or None
3137 # entry Symtab.Entry
3138 # base_type PyExtensionType or None
3139 # buffer_defaults_node DictNode or None Declares defaults for a buffer
3140 # buffer_defaults_pos
3142 child_attrs = ["body"]
3143 buffer_defaults_node = None
3144 buffer_defaults_pos = None
3145 typedef_flag = False
3146 api = False
3147 objstruct_name = None
3148 typeobj_name = None
3149 decorators = None
3151 def analyse_declarations(self, env):
3152 #print "CClassDefNode.analyse_declarations:", self.class_name
3153 #print "...visibility =", self.visibility
3154 #print "...module_name =", self.module_name
3156 import Buffer
3157 if self.buffer_defaults_node:
3158 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
3159 env, [], self.buffer_defaults_node,
3160 need_complete=False)
3161 else:
3162 buffer_defaults = None
3164 if env.in_cinclude and not self.objstruct_name:
3165 error(self.pos, "Object struct name specification required for "
3166 "C class defined in 'extern from' block")
3167 self.base_type = None
3168 # Now that module imports are cached, we need to
3169 # import the modules for extern classes.
3170 if self.module_name:
3171 self.module = None
3172 for module in env.cimported_modules:
3173 if module.name == self.module_name:
3174 self.module = module
3175 if self.module is None:
3176 self.module = ModuleScope(self.module_name, None, env.context)
3177 self.module.has_extern_class = 1
3178 env.add_imported_module(self.module)
3180 if self.base_class_name:
3181 if self.base_class_module:
3182 base_class_scope = env.find_module(self.base_class_module, self.pos)
3183 else:
3184 base_class_scope = env
3185 if self.base_class_name == 'object':
3186 # extension classes are special and don't need to inherit from object
3187 if base_class_scope is None or base_class_scope.lookup('object') is None:
3188 self.base_class_name = None
3189 self.base_class_module = None
3190 base_class_scope = None
3191 if base_class_scope:
3192 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
3193 if base_class_entry:
3194 if not base_class_entry.is_type:
3195 error(self.pos, "'%s' is not a type name" % self.base_class_name)
3196 elif not base_class_entry.type.is_extension_type and \
3197 not (base_class_entry.type.is_builtin_type and \
3198 base_class_entry.type.objstruct_cname):
3199 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
3200 elif not base_class_entry.type.is_complete():
3201 error(self.pos, "Base class '%s' of type '%s' is incomplete" % (
3202 self.base_class_name, self.class_name))
3203 elif base_class_entry.type.scope and base_class_entry.type.scope.directives and \
3204 base_class_entry.type.scope.directives['final']:
3205 error(self.pos, "Base class '%s' of type '%s' is final" % (
3206 self.base_class_name, self.class_name))
3207 elif base_class_entry.type.is_builtin_type and \
3208 base_class_entry.type.name in ('tuple', 'str', 'bytes'):
3209 error(self.pos, "inheritance from PyVarObject types like '%s' is not currently supported"
3210 % base_class_entry.type.name)
3211 else:
3212 self.base_type = base_class_entry.type
3213 has_body = self.body is not None
3214 if self.module_name and self.visibility != 'extern':
3215 module_path = self.module_name.split(".")
3216 home_scope = env.find_imported_module(module_path, self.pos)
3217 if not home_scope:
3218 return
3219 else:
3220 home_scope = env
3222 if self.visibility == 'extern':
3223 if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
3224 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
3226 self.entry = home_scope.declare_c_class(
3227 name = self.class_name,
3228 pos = self.pos,
3229 defining = has_body and self.in_pxd,
3230 implementing = has_body and not self.in_pxd,
3231 module_name = self.module_name,
3232 base_type = self.base_type,
3233 objstruct_cname = self.objstruct_name,
3234 typeobj_cname = self.typeobj_name,
3235 visibility = self.visibility,
3236 typedef_flag = self.typedef_flag,
3237 api = self.api,
3238 buffer_defaults = buffer_defaults)
3239 if home_scope is not env and self.visibility == 'extern':
3240 env.add_imported_entry(self.class_name, self.entry, self.pos)
3241 self.scope = scope = self.entry.type.scope
3242 if scope is not None:
3243 scope.directives = env.directives
3245 if self.doc and Options.docstrings:
3246 scope.doc = embed_position(self.pos, self.doc)
3248 if has_body:
3249 self.body.analyse_declarations(scope)
3250 if self.in_pxd:
3251 scope.defined = 1
3252 else:
3253 scope.implemented = 1
3254 env.allocate_vtable_names(self.entry)
3256 def analyse_expressions(self, env):
3257 if self.body:
3258 scope = self.entry.type.scope
3259 self.body.analyse_expressions(scope)
3261 def generate_function_definitions(self, env, code):
3262 if self.body:
3263 self.generate_lambda_definitions(self.scope, code)
3264 self.body.generate_function_definitions(self.scope, code)
3266 def generate_execution_code(self, code):
3267 # This is needed to generate evaluation code for
3268 # default values of method arguments.
3269 if self.body:
3270 self.body.generate_execution_code(code)
3272 def annotate(self, code):
3273 if self.body:
3274 self.body.annotate(code)
3277 class PropertyNode(StatNode):
3278 # Definition of a property in an extension type.
3279 #
3280 # name string
3281 # doc EncodedString or None Doc string
3282 # body StatListNode
3284 child_attrs = ["body"]
3286 def analyse_declarations(self, env):
3287 entry = env.declare_property(self.name, self.doc, self.pos)
3288 if entry:
3289 entry.scope.directives = env.directives
3290 self.body.analyse_declarations(entry.scope)
3292 def analyse_expressions(self, env):
3293 self.body.analyse_expressions(env)
3295 def generate_function_definitions(self, env, code):
3296 self.body.generate_function_definitions(env, code)
3298 def generate_execution_code(self, code):
3299 pass
3301 def annotate(self, code):
3302 self.body.annotate(code)
3305 class GlobalNode(StatNode):
3306 # Global variable declaration.
3307 #
3308 # names [string]
3310 child_attrs = []
3312 def analyse_declarations(self, env):
3313 for name in self.names:
3314 env.declare_global(name, self.pos)
3316 def analyse_expressions(self, env):
3317 pass
3319 def generate_execution_code(self, code):
3320 pass
3323 class ExprStatNode(StatNode):
3324 # Expression used as a statement.
3325 #
3326 # expr ExprNode
3328 child_attrs = ["expr"]
3330 def analyse_declarations(self, env):
3331 import ExprNodes
3332 if isinstance(self.expr, ExprNodes.GeneralCallNode):
3333 func = self.expr.function.as_cython_attribute()
3334 if func == u'declare':
3335 args, kwds = self.expr.explicit_args_kwds()
3336 if len(args):
3337 error(self.expr.pos, "Variable names must be specified.")
3338 for var, type_node in kwds.key_value_pairs:
3339 type = type_node.analyse_as_type(env)
3340 if type is None:
3341 error(type_node.pos, "Unknown type")
3342 else:
3343 env.declare_var(var.value, type, var.pos, is_cdef = True)
3344 self.__class__ = PassStatNode
3346 def analyse_expressions(self, env):
3347 self.expr.analyse_expressions(env)
3349 def generate_execution_code(self, code):
3350 self.expr.generate_evaluation_code(code)
3351 if not self.expr.is_temp and self.expr.result():
3352 code.putln("%s;" % self.expr.result())
3353 self.expr.generate_disposal_code(code)
3354 self.expr.free_temps(code)
3356 def generate_function_definitions(self, env, code):
3357 self.expr.generate_function_definitions(env, code)
3359 def annotate(self, code):
3360 self.expr.annotate(code)
3363 class AssignmentNode(StatNode):
3364 # Abstract base class for assignment nodes.
3365 #
3366 # The analyse_expressions and generate_execution_code
3367 # phases of assignments are split into two sub-phases
3368 # each, to enable all the right hand sides of a
3369 # parallel assignment to be evaluated before assigning
3370 # to any of the left hand sides.
3372 def analyse_expressions(self, env):
3373 self.analyse_types(env)
3375 # def analyse_expressions(self, env):
3376 # self.analyse_expressions_1(env)
3377 # self.analyse_expressions_2(env)
3379 def generate_execution_code(self, code):
3380 self.generate_rhs_evaluation_code(code)
3381 self.generate_assignment_code(code)
3384 class SingleAssignmentNode(AssignmentNode):
3385 # The simplest case:
3386 #
3387 # a = b
3388 #
3389 # lhs ExprNode Left hand side
3390 # rhs ExprNode Right hand side
3391 # first bool Is this guaranteed the first assignment to lhs?
3393 child_attrs = ["lhs", "rhs"]
3394 first = False
3395 declaration_only = False
3397 def analyse_declarations(self, env):
3398 import ExprNodes
3400 # handle declarations of the form x = cython.foo()
3401 if isinstance(self.rhs, ExprNodes.CallNode):
3402 func_name = self.rhs.function.as_cython_attribute()
3403 if func_name:
3404 args, kwds = self.rhs.explicit_args_kwds()
3406 if func_name in ['declare', 'typedef']:
3407 if len(args) > 2 or kwds is not None:
3408 error(self.rhs.pos, "Can only declare one type at a time.")
3409 return
3410 type = args[0].analyse_as_type(env)
3411 if type is None:
3412 error(args[0].pos, "Unknown type")
3413 return
3414 lhs = self.lhs
3415 if func_name == 'declare':
3416 if isinstance(lhs, ExprNodes.NameNode):
3417 vars = [(lhs.name, lhs.pos)]
3418 elif isinstance(lhs, ExprNodes.TupleNode):
3419 vars = [(var.name, var.pos) for var in lhs.args]
3420 else:
3421 error(lhs.pos, "Invalid declaration")
3422 return
3423 for var, pos in vars:
3424 env.declare_var(var, type, pos, is_cdef = True)
3425 if len(args) == 2:
3426 # we have a value
3427 self.rhs = args[1]
3428 else:
3429 self.declaration_only = True
3430 else:
3431 self.declaration_only = True
3432 if not isinstance(lhs, ExprNodes.NameNode):
3433 error(lhs.pos, "Invalid declaration.")
3434 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
3436 elif func_name in ['struct', 'union']:
3437 self.declaration_only = True
3438 if len(args) > 0 or kwds is None:
3439 error(self.rhs.pos, "Struct or union members must be given by name.")
3440 return
3441 members = []
3442 for member, type_node in kwds.key_value_pairs:
3443 type = type_node.analyse_as_type(env)
3444 if type is None:
3445 error(type_node.pos, "Unknown type")
3446 else:
3447 members.append((member.value, type, member.pos))
3448 if len(members) < len(kwds.key_value_pairs):
3449 return
3450 if not isinstance(self.lhs, ExprNodes.NameNode):
3451 error(self.lhs.pos, "Invalid declaration.")
3452 name = self.lhs.name
3453 scope = StructOrUnionScope(name)
3454 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
3455 for member, type, pos in members:
3456 scope.declare_var(member, type, pos)
3458 if self.declaration_only:
3459 return
3460 else:
3461 self.lhs.analyse_target_declaration(env)
3463 def analyse_types(self, env, use_temp = 0):
3464 self.rhs.analyse_types(env)
3465 self.lhs.analyse_target_types(env)
3466 self.lhs.gil_assignment_check(env)
3467 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3468 if use_temp:
3469 self.rhs = self.rhs.coerce_to_temp(env)
3471 def generate_rhs_evaluation_code(self, code):
3472 self.rhs.generate_evaluation_code(code)
3474 def generate_assignment_code(self, code):
3475 self.lhs.generate_assignment_code(self.rhs, code)
3477 def generate_function_definitions(self, env, code):
3478 self.rhs.generate_function_definitions(env, code)
3480 def annotate(self, code):
3481 self.lhs.annotate(code)
3482 self.rhs.annotate(code)
3485 class CascadedAssignmentNode(AssignmentNode):
3486 # An assignment with multiple left hand sides:
3487 #
3488 # a = b = c
3489 #
3490 # lhs_list [ExprNode] Left hand sides
3491 # rhs ExprNode Right hand sides
3492 #
3493 # Used internally:
3494 #
3495 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
3497 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
3498 coerced_rhs_list = None
3500 def analyse_declarations(self, env):
3501 for lhs in self.lhs_list:
3502 lhs.analyse_target_declaration(env)
3504 def analyse_types(self, env, use_temp = 0):
3505 self.rhs.analyse_types(env)
3506 if not self.rhs.is_simple():
3507 if use_temp:
3508 self.rhs = self.rhs.coerce_to_temp(env)
3509 else:
3510 self.rhs = self.rhs.coerce_to_simple(env)
3511 from ExprNodes import CloneNode
3512 self.coerced_rhs_list = []
3513 for lhs in self.lhs_list:
3514 lhs.analyse_target_types(env)
3515 lhs.gil_assignment_check(env)
3516 rhs = CloneNode(self.rhs)
3517 rhs = rhs.coerce_to(lhs.type, env)
3518 self.coerced_rhs_list.append(rhs)
3520 def generate_rhs_evaluation_code(self, code):
3521 self.rhs.generate_evaluation_code(code)
3523 def generate_assignment_code(self, code):
3524 for i in range(len(self.lhs_list)):
3525 lhs = self.lhs_list[i]
3526 rhs = self.coerced_rhs_list[i]
3527 rhs.generate_evaluation_code(code)
3528 lhs.generate_assignment_code(rhs, code)
3529 # Assignment has disposed of the cloned RHS
3530 self.rhs.generate_disposal_code(code)
3531 self.rhs.free_temps(code)
3533 def generate_function_definitions(self, env, code):
3534 self.rhs.generate_function_definitions(env, code)
3536 def annotate(self, code):
3537 for i in range(len(self.lhs_list)):
3538 lhs = self.lhs_list[i].annotate(code)
3539 rhs = self.coerced_rhs_list[i].annotate(code)
3540 self.rhs.annotate(code)
3543 class ParallelAssignmentNode(AssignmentNode):
3544 # A combined packing/unpacking assignment:
3545 #
3546 # a, b, c = d, e, f
3547 #
3548 # This has been rearranged by the parser into
3549 #
3550 # a = d ; b = e ; c = f
3551 #
3552 # but we must evaluate all the right hand sides
3553 # before assigning to any of the left hand sides.
3554 #
3555 # stats [AssignmentNode] The constituent assignments
3557 child_attrs = ["stats"]
3559 def analyse_declarations(self, env):
3560 for stat in self.stats:
3561 stat.analyse_declarations(env)
3563 def analyse_expressions(self, env):
3564 for stat in self.stats:
3565 stat.analyse_types(env, use_temp = 1)
3567 # def analyse_expressions(self, env):
3568 # for stat in self.stats:
3569 # stat.analyse_expressions_1(env, use_temp = 1)
3570 # for stat in self.stats:
3571 # stat.analyse_expressions_2(env)
3573 def generate_execution_code(self, code):
3574 for stat in self.stats:
3575 stat.generate_rhs_evaluation_code(code)
3576 for stat in self.stats:
3577 stat.generate_assignment_code(code)
3579 def generate_function_definitions(self, env, code):
3580 for stat in self.stats:
3581 stat.generate_function_definitions(env, code)
3583 def annotate(self, code):
3584 for stat in self.stats:
3585 stat.annotate(code)
3588 class InPlaceAssignmentNode(AssignmentNode):
3589 # An in place arithmetic operand:
3590 #
3591 # a += b
3592 # a -= b
3593 # ...
3594 #
3595 # lhs ExprNode Left hand side
3596 # rhs ExprNode Right hand side
3597 # op char one of "+-*/%^&|"
3598 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3599 #
3600 # This code is a bit tricky because in order to obey Python
3601 # semantics the sub-expressions (e.g. indices) of the lhs must
3602 # not be evaluated twice. So we must re-use the values calculated
3603 # in evaluation phase for the assignment phase as well.
3604 # Fortunately, the type of the lhs node is fairly constrained
3605 # (it must be a NameNode, AttributeNode, or IndexNode).
3607 child_attrs = ["lhs", "rhs"]
3609 def analyse_declarations(self, env):
3610 self.lhs.analyse_target_declaration(env)
3612 def analyse_types(self, env):
3613 self.rhs.analyse_types(env)
3614 self.lhs.analyse_target_types(env)
3616 def generate_execution_code(self, code):
3617 import ExprNodes
3618 self.rhs.generate_evaluation_code(code)
3619 self.lhs.generate_subexpr_evaluation_code(code)
3620 c_op = self.operator
3621 if c_op == "//":
3622 c_op = "/"
3623 elif c_op == "**":
3624 error(self.pos, "No C inplace power operator")
3625 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3626 if self.lhs.type.is_pyobject:
3627 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3628 if c_op in ('/', '%') and self.lhs.type.is_int and not code.directives['cdivision']:
3629 error(self.pos, "In-place non-c divide operators not allowed on int buffers.")
3630 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3631 else:
3632 # C++
3633 # TODO: make sure overload is declared
3634 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()))
3635 self.lhs.generate_subexpr_disposal_code(code)
3636 self.lhs.free_subexpr_temps(code)
3637 self.rhs.generate_disposal_code(code)
3638 self.rhs.free_temps(code)
3640 def annotate(self, code):
3641 self.lhs.annotate(code)
3642 self.rhs.annotate(code)
3644 def create_binop_node(self):
3645 import ExprNodes
3646 return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
3649 class PrintStatNode(StatNode):
3650 # print statement
3651 #
3652 # arg_tuple TupleNode
3653 # stream ExprNode or None (stdout)
3654 # append_newline boolean
3656 child_attrs = ["arg_tuple", "stream"]
3658 def analyse_expressions(self, env):
3659 if self.stream:
3660 self.stream.analyse_expressions(env)
3661 self.stream = self.stream.coerce_to_pyobject(env)
3662 self.arg_tuple.analyse_expressions(env)
3663 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3664 env.use_utility_code(printing_utility_code)
3665 if len(self.arg_tuple.args) == 1 and self.append_newline:
3666 env.use_utility_code(printing_one_utility_code)
3668 nogil_check = Node.gil_error
3669 gil_message = "Python print statement"
3671 def generate_execution_code(self, code):
3672 if self.stream:
3673 self.stream.generate_evaluation_code(code)
3674 stream_result = self.stream.py_result()
3675 else:
3676 stream_result = '0'
3677 if len(self.arg_tuple.args) == 1 and self.append_newline:
3678 arg = self.arg_tuple.args[0]
3679 arg.generate_evaluation_code(code)
3681 code.putln(
3682 "if (__Pyx_PrintOne(%s, %s) < 0) %s" % (
3683 stream_result,
3684 arg.py_result(),
3685 code.error_goto(self.pos)))
3686 arg.generate_disposal_code(code)
3687 arg.free_temps(code)
3688 else:
3689 self.arg_tuple.generate_evaluation_code(code)
3690 code.putln(
3691 "if (__Pyx_Print(%s, %s, %d) < 0) %s" % (
3692 stream_result,
3693 self.arg_tuple.py_result(),
3694 self.append_newline,
3695 code.error_goto(self.pos)))
3696 self.arg_tuple.generate_disposal_code(code)
3697 self.arg_tuple.free_temps(code)
3699 if self.stream:
3700 self.stream.generate_disposal_code(code)
3701 self.stream.free_temps(code)
3703 def generate_function_definitions(self, env, code):
3704 if self.stream:
3705 self.stream.generate_function_definitions(env, code)
3706 self.arg_tuple.generate_function_definitions(env, code)
3708 def annotate(self, code):
3709 if self.stream:
3710 self.stream.annotate(code)
3711 self.arg_tuple.annotate(code)
3714 class ExecStatNode(StatNode):
3715 # exec statement
3716 #
3717 # args [ExprNode]
3719 child_attrs = ["args"]
3721 def analyse_expressions(self, env):
3722 for i, arg in enumerate(self.args):
3723 arg.analyse_expressions(env)
3724 arg = arg.coerce_to_pyobject(env)
3725 self.args[i] = arg
3726 env.use_utility_code(Builtin.pyexec_utility_code)
3728 nogil_check = Node.gil_error
3729 gil_message = "Python exec statement"
3731 def generate_execution_code(self, code):
3732 args = []
3733 for arg in self.args:
3734 arg.generate_evaluation_code(code)
3735 args.append( arg.py_result() )
3736 args = tuple(args + ['0', '0'][:3-len(args)])
3737 temp_result = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
3738 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3739 (temp_result,) + args))
3740 for arg in self.args:
3741 arg.generate_disposal_code(code)
3742 arg.free_temps(code)
3743 code.putln(
3744 code.error_goto_if_null(temp_result, self.pos))
3745 code.put_gotref(temp_result)
3746 code.put_decref_clear(temp_result, py_object_type)
3747 code.funcstate.release_temp(temp_result)
3749 def annotate(self, code):
3750 for arg in self.args:
3751 arg.annotate(code)
3754 class DelStatNode(StatNode):
3755 # del statement
3756 #
3757 # args [ExprNode]
3759 child_attrs = ["args"]
3761 def analyse_declarations(self, env):
3762 for arg in self.args:
3763 arg.analyse_target_declaration(env)
3765 def analyse_expressions(self, env):
3766 for arg in self.args:
3767 arg.analyse_target_expression(env, None)
3768 if arg.type.is_pyobject:
3769 pass
3770 elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
3771 self.cpp_check(env)
3772 elif arg.type.is_cpp_class:
3773 error(arg.pos, "Deletion of non-heap C++ object")
3774 else:
3775 error(arg.pos, "Deletion of non-Python, non-C++ object")
3776 #arg.release_target_temp(env)
3778 def nogil_check(self, env):
3779 for arg in self.args:
3780 if arg.type.is_pyobject:
3781 self.gil_error()
3783 gil_message = "Deleting Python object"
3785 def generate_execution_code(self, code):
3786 for arg in self.args:
3787 if arg.type.is_pyobject:
3788 arg.generate_deletion_code(code)
3789 elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
3790 arg.generate_result_code(code)
3791 code.putln("delete %s;" % arg.result())
3792 # else error reported earlier
3794 def annotate(self, code):
3795 for arg in self.args:
3796 arg.annotate(code)
3799 class PassStatNode(StatNode):
3800 # pass statement
3802 child_attrs = []
3804 def analyse_expressions(self, env):
3805 pass
3807 def generate_execution_code(self, code):
3808 pass
3811 class BreakStatNode(StatNode):
3813 child_attrs = []
3815 def analyse_expressions(self, env):
3816 pass
3818 def generate_execution_code(self, code):
3819 if not code.break_label:
3820 error(self.pos, "break statement not inside loop")
3821 else:
3822 code.put_goto(code.break_label)
3825 class ContinueStatNode(StatNode):
3827 child_attrs = []
3829 def analyse_expressions(self, env):
3830 pass
3832 def generate_execution_code(self, code):
3833 if code.funcstate.in_try_finally:
3834 error(self.pos, "continue statement inside try of try...finally")
3835 elif not code.continue_label:
3836 error(self.pos, "continue statement not inside loop")
3837 else:
3838 code.put_goto(code.continue_label)
3841 class ReturnStatNode(StatNode):
3842 # return statement
3843 #
3844 # value ExprNode or None
3845 # return_type PyrexType
3847 child_attrs = ["value"]
3849 def analyse_expressions(self, env):
3850 return_type = env.return_type
3851 self.return_type = return_type
3852 if not return_type:
3853 error(self.pos, "Return not inside a function body")
3854 return
3855 if self.value:
3856 self.value.analyse_types(env)
3857 if return_type.is_void or return_type.is_returncode:
3858 error(self.value.pos,
3859 "Return with value in void function")
3860 else:
3861 self.value = self.value.coerce_to(env.return_type, env)
3862 else:
3863 if (not return_type.is_void
3864 and not return_type.is_pyobject
3865 and not return_type.is_returncode):
3866 error(self.pos, "Return value required")
3868 def nogil_check(self, env):
3869 if self.return_type.is_pyobject:
3870 self.gil_error()
3872 gil_message = "Returning Python object"
3874 def generate_execution_code(self, code):
3875 code.mark_pos(self.pos)
3876 if not self.return_type:
3877 # error reported earlier
3878 return
3879 if self.return_type.is_pyobject:
3880 code.put_xdecref(Naming.retval_cname,
3881 self.return_type)
3882 if self.value:
3883 self.value.generate_evaluation_code(code)
3884 self.value.make_owned_reference(code)
3885 code.putln(
3886 "%s = %s;" % (
3887 Naming.retval_cname,
3888 self.value.result_as(self.return_type)))
3889 self.value.generate_post_assignment_code(code)
3890 self.value.free_temps(code)
3891 else:
3892 if self.return_type.is_pyobject:
3893 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3894 elif self.return_type.is_returncode:
3895 code.putln(
3896 "%s = %s;" % (
3897 Naming.retval_cname,
3898 self.return_type.default_value))
3899 for cname, type in code.funcstate.temps_holding_reference():
3900 code.put_decref_clear(cname, type)
3901 code.put_goto(code.return_label)
3903 def generate_function_definitions(self, env, code):
3904 if self.value is not None:
3905 self.value.generate_function_definitions(env, code)
3907 def annotate(self, code):
3908 if self.value:
3909 self.value.annotate(code)
3912 class RaiseStatNode(StatNode):
3913 # raise statement
3914 #
3915 # exc_type ExprNode or None
3916 # exc_value ExprNode or None
3917 # exc_tb ExprNode or None
3919 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3921 def analyse_expressions(self, env):
3922 if self.exc_type:
3923 self.exc_type.analyse_types(env)
3924 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3925 if self.exc_value:
3926 self.exc_value.analyse_types(env)
3927 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3928 if self.exc_tb:
3929 self.exc_tb.analyse_types(env)
3930 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3931 env.use_utility_code(raise_utility_code)
3933 nogil_check = Node.gil_error
3934 gil_message = "Raising exception"
3936 def generate_execution_code(self, code):
3937 if self.exc_type:
3938 self.exc_type.generate_evaluation_code(code)
3939 type_code = self.exc_type.py_result()
3940 else:
3941 type_code = "0"
3942 if self.exc_value:
3943 self.exc_value.generate_evaluation_code(code)
3944 value_code = self.exc_value.py_result()
3945 else:
3946 value_code = "0"
3947 if self.exc_tb:
3948 self.exc_tb.generate_evaluation_code(code)
3949 tb_code = self.exc_tb.py_result()
3950 else:
3951 tb_code = "0"
3952 code.putln(
3953 "__Pyx_Raise(%s, %s, %s);" % (
3954 type_code,
3955 value_code,
3956 tb_code))
3957 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3958 if obj:
3959 obj.generate_disposal_code(code)
3960 obj.free_temps(code)
3961 code.putln(
3962 code.error_goto(self.pos))
3964 def generate_function_definitions(self, env, code):
3965 if self.exc_type is not None:
3966 self.exc_type.generate_function_definitions(env, code)
3967 if self.exc_value is not None:
3968 self.exc_value.generate_function_definitions(env, code)
3969 if self.exc_tb is not None:
3970 self.exc_tb.generate_function_definitions(env, code)
3972 def annotate(self, code):
3973 if self.exc_type:
3974 self.exc_type.annotate(code)
3975 if self.exc_value:
3976 self.exc_value.annotate(code)
3977 if self.exc_tb:
3978 self.exc_tb.annotate(code)
3981 class ReraiseStatNode(StatNode):
3983 child_attrs = []
3985 def analyse_expressions(self, env):
3986 env.use_utility_code(restore_exception_utility_code)
3988 nogil_check = Node.gil_error
3989 gil_message = "Raising exception"
3991 def generate_execution_code(self, code):
3992 vars = code.funcstate.exc_vars
3993 if vars:
3994 for varname in vars:
3995 code.put_giveref(varname)
3996 code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars))
3997 for varname in vars:
3998 code.put("%s = 0; " % varname)
3999 code.putln()
4000 code.putln(code.error_goto(self.pos))
4001 else:
4002 error(self.pos, "Reraise not inside except clause")
4005 class AssertStatNode(StatNode):
4006 # assert statement
4007 #
4008 # cond ExprNode
4009 # value ExprNode or None
4011 child_attrs = ["cond", "value"]
4013 def analyse_expressions(self, env):
4014 self.cond = self.cond.analyse_boolean_expression(env)
4015 if self.value:
4016 self.value.analyse_types(env)
4017 self.value = self.value.coerce_to_pyobject(env)
4019 nogil_check = Node.gil_error
4020 gil_message = "Raising exception"
4022 def generate_execution_code(self, code):
4023 code.putln("#ifndef CYTHON_WITHOUT_ASSERTIONS")
4024 self.cond.generate_evaluation_code(code)
4025 code.putln(
4026 "if (unlikely(!%s)) {" %
4027 self.cond.result())
4028 if self.value:
4029 self.value.generate_evaluation_code(code)
4030 code.putln(
4031 "PyErr_SetObject(PyExc_AssertionError, %s);" %
4032 self.value.py_result())
4033 self.value.generate_disposal_code(code)
4034 self.value.free_temps(code)
4035 else:
4036 code.putln(
4037 "PyErr_SetNone(PyExc_AssertionError);")
4038 code.putln(
4039 code.error_goto(self.pos))
4040 code.putln(
4041 "}")
4042 self.cond.generate_disposal_code(code)
4043 self.cond.free_temps(code)
4044 code.putln("#endif")
4046 def generate_function_definitions(self, env, code):
4047 self.cond.generate_function_definitions(env, code)
4048 if self.value is not None:
4049 self.value.generate_function_definitions(env, code)
4051 def annotate(self, code):
4052 self.cond.annotate(code)
4053 if self.value:
4054 self.value.annotate(code)
4057 class IfStatNode(StatNode):
4058 # if statement
4059 #
4060 # if_clauses [IfClauseNode]
4061 # else_clause StatNode or None
4063 child_attrs = ["if_clauses", "else_clause"]
4065 def analyse_control_flow(self, env):
4066 env.start_branching(self.pos)
4067 for if_clause in self.if_clauses:
4068 if_clause.analyse_control_flow(env)
4069 env.next_branch(if_clause.end_pos())
4070 if self.else_clause:
4071 self.else_clause.analyse_control_flow(env)
4072 env.finish_branching(self.end_pos())
4074 def analyse_declarations(self, env):
4075 for if_clause in self.if_clauses:
4076 if_clause.analyse_declarations(env)
4077 if self.else_clause:
4078 self.else_clause.analyse_declarations(env)
4080 def analyse_expressions(self, env):
4081 for if_clause in self.if_clauses:
4082 if_clause.analyse_expressions(env)
4083 if self.else_clause:
4084 self.else_clause.analyse_expressions(env)
4086 def generate_execution_code(self, code):
4087 code.mark_pos(self.pos)
4088 end_label = code.new_label()
4089 for if_clause in self.if_clauses:
4090 if_clause.generate_execution_code(code, end_label)
4091 if self.else_clause:
4092 code.putln("/*else*/ {")
4093 self.else_clause.generate_execution_code(code)
4094 code.putln("}")
4095 code.put_label(end_label)
4097 def generate_function_definitions(self, env, code):
4098 for clause in self.if_clauses:
4099 clause.generate_function_definitions(env, code)
4100 if self.else_clause is not None:
4101 self.else_clause.generate_function_definitions(env, code)
4103 def annotate(self, code):
4104 for if_clause in self.if_clauses:
4105 if_clause.annotate(code)
4106 if self.else_clause:
4107 self.else_clause.annotate(code)
4110 class IfClauseNode(Node):
4111 # if or elif clause in an if statement
4112 #
4113 # condition ExprNode
4114 # body StatNode
4116 child_attrs = ["condition", "body"]
4118 def analyse_control_flow(self, env):
4119 self.body.analyse_control_flow(env)
4121 def analyse_declarations(self, env):
4122 self.body.analyse_declarations(env)
4124 def analyse_expressions(self, env):
4125 self.condition = \
4126 self.condition.analyse_temp_boolean_expression(env)
4127 self.body.analyse_expressions(env)
4129 def get_constant_condition_result(self):
4130 if self.condition.has_constant_result():
4131 return bool(self.condition.constant_result)
4132 else:
4133 return None
4135 def generate_execution_code(self, code, end_label):
4136 self.condition.generate_evaluation_code(code)
4137 code.putln(
4138 "if (%s) {" %
4139 self.condition.result())
4140 self.condition.generate_disposal_code(code)
4141 self.condition.free_temps(code)
4142 self.body.generate_execution_code(code)
4143 code.put_goto(end_label)
4144 code.putln("}")
4146 def generate_function_definitions(self, env, code):
4147 self.condition.generate_function_definitions(env, code)
4148 self.body.generate_function_definitions(env, code)
4150 def annotate(self, code):
4151 self.condition.annotate(code)
4152 self.body.annotate(code)
4155 class SwitchCaseNode(StatNode):
4156 # Generated in the optimization of an if-elif-else node
4157 #
4158 # conditions [ExprNode]
4159 # body StatNode
4161 child_attrs = ['conditions', 'body']
4163 def generate_execution_code(self, code):
4164 for cond in self.conditions:
4165 code.mark_pos(cond.pos)
4166 cond.generate_evaluation_code(code)
4167 code.putln("case %s:" % cond.result())
4168 self.body.generate_execution_code(code)
4169 code.putln("break;")
4171 def generate_function_definitions(self, env, code):
4172 for cond in self.conditions:
4173 cond.generate_function_definitions(env, code)
4174 self.body.generate_function_definitions(env, code)
4176 def annotate(self, code):
4177 for cond in self.conditions:
4178 cond.annotate(code)
4179 self.body.annotate(code)
4181 class SwitchStatNode(StatNode):
4182 # Generated in the optimization of an if-elif-else node
4183 #
4184 # test ExprNode
4185 # cases [SwitchCaseNode]
4186 # else_clause StatNode or None
4188 child_attrs = ['test', 'cases', 'else_clause']
4190 def generate_execution_code(self, code):
4191 self.test.generate_evaluation_code(code)
4192 code.putln("switch (%s) {" % self.test.result())
4193 for case in self.cases:
4194 case.generate_execution_code(code)
4195 if self.else_clause is not None:
4196 code.putln("default:")
4197 self.else_clause.generate_execution_code(code)
4198 code.putln("break;")
4199 code.putln("}")
4201 def generate_function_definitions(self, env, code):
4202 self.test.generate_function_definitions(env, code)
4203 for case in self.cases:
4204 case.generate_function_definitions(env, code)
4205 if self.else_clause is not None:
4206 self.else_clause.generate_function_definitions(env, code)
4208 def annotate(self, code):
4209 self.test.annotate(code)
4210 for case in self.cases:
4211 case.annotate(code)
4212 if self.else_clause is not None:
4213 self.else_clause.annotate(code)
4215 class LoopNode(object):
4217 def analyse_control_flow(self, env):
4218 env.start_branching(self.pos)
4219 self.body.analyse_control_flow(env)
4220 env.next_branch(self.body.end_pos())
4221 if self.else_clause:
4222 self.else_clause.analyse_control_flow(env)
4223 env.finish_branching(self.end_pos())
4226 class WhileStatNode(LoopNode, StatNode):
4227 # while statement
4228 #
4229 # condition ExprNode
4230 # body StatNode
4231 # else_clause StatNode
4233 child_attrs = ["condition", "body", "else_clause"]
4235 def analyse_declarations(self, env):
4236 self.body.analyse_declarations(env)
4237 if self.else_clause:
4238 self.else_clause.analyse_declarations(env)
4240 def analyse_expressions(self, env):
4241 self.condition = \
4242 self.condition.analyse_temp_boolean_expression(env)
4243 self.body.analyse_expressions(env)
4244 if self.else_clause:
4245 self.else_clause.analyse_expressions(env)
4247 def generate_execution_code(self, code):
4248 old_loop_labels = code.new_loop_labels()
4249 code.putln(
4250 "while (1) {")
4251 self.condition.generate_evaluation_code(code)
4252 self.condition.generate_disposal_code(code)
4253 code.putln(
4254 "if (!%s) break;" %
4255 self.condition.result())
4256 self.condition.free_temps(code)
4257 self.body.generate_execution_code(code)
4258 code.put_label(code.continue_label)
4259 code.putln("}")
4260 break_label = code.break_label
4261 code.set_loop_labels(old_loop_labels)
4262 if self.else_clause:
4263 code.putln("/*else*/ {")
4264 self.else_clause.generate_execution_code(code)
4265 code.putln("}")
4266 code.put_label(break_label)
4268 def generate_function_definitions(self, env, code):
4269 self.condition.generate_function_definitions(env, code)
4270 self.body.generate_function_definitions(env, code)
4271 if self.else_clause is not None:
4272 self.else_clause.generate_function_definitions(env, code)
4274 def annotate(self, code):
4275 self.condition.annotate(code)
4276 self.body.annotate(code)
4277 if self.else_clause:
4278 self.else_clause.annotate(code)
4281 def ForStatNode(pos, **kw):
4282 if 'iterator' in kw:
4283 return ForInStatNode(pos, **kw)
4284 else:
4285 return ForFromStatNode(pos, **kw)
4287 class ForInStatNode(LoopNode, StatNode):
4288 # for statement
4289 #
4290 # target ExprNode
4291 # iterator IteratorNode
4292 # body StatNode
4293 # else_clause StatNode
4294 # item NextNode used internally
4296 child_attrs = ["target", "iterator", "body", "else_clause"]
4297 item = None
4299 def analyse_declarations(self, env):
4300 self.target.analyse_target_declaration(env)
4301 self.body.analyse_declarations(env)
4302 if self.else_clause:
4303 self.else_clause.analyse_declarations(env)
4305 def analyse_expressions(self, env):
4306 import ExprNodes
4307 self.target.analyse_target_types(env)
4308 self.iterator.analyse_expressions(env)
4309 self.item = ExprNodes.NextNode(self.iterator, env)
4310 self.item = self.item.coerce_to(self.target.type, env)
4311 self.body.analyse_expressions(env)
4312 if self.else_clause:
4313 self.else_clause.analyse_expressions(env)
4315 def generate_execution_code(self, code):
4316 old_loop_labels = code.new_loop_labels()
4317 self.iterator.allocate_counter_temp(code)
4318 self.iterator.generate_evaluation_code(code)
4319 code.putln(
4320 "for (;;) {")
4321 self.item.generate_evaluation_code(code)
4322 self.target.generate_assignment_code(self.item, code)
4323 self.body.generate_execution_code(code)
4324 code.put_label(code.continue_label)
4325 code.putln(
4326 "}")
4327 break_label = code.break_label
4328 code.set_loop_labels(old_loop_labels)
4330 if self.else_clause:
4331 # in nested loops, the 'else' block can contain a
4332 # 'continue' statement for the outer loop, but we may need
4333 # to generate cleanup code before taking that path, so we
4334 # intercept it here
4335 orig_continue_label = code.continue_label
4336 code.continue_label = code.new_label('outer_continue')
4338 code.putln("/*else*/ {")
4339 self.else_clause.generate_execution_code(code)
4340 code.putln("}")
4342 if code.label_used(code.continue_label):
4343 code.put_goto(break_label)
4344 code.put_label(code.continue_label)
4345 self.iterator.generate_disposal_code(code)
4346 code.put_goto(orig_continue_label)
4347 code.set_loop_labels(old_loop_labels)
4349 if code.label_used(break_label):
4350 code.put_label(break_label)
4351 self.iterator.release_counter_temp(code)
4352 self.iterator.generate_disposal_code(code)
4353 self.iterator.free_temps(code)
4355 def generate_function_definitions(self, env, code):
4356 self.target.generate_function_definitions(env, code)
4357 self.iterator.generate_function_definitions(env, code)
4358 self.body.generate_function_definitions(env, code)
4359 if self.else_clause is not None:
4360 self.else_clause.generate_function_definitions(env, code)
4362 def annotate(self, code):
4363 self.target.annotate(code)
4364 self.iterator.annotate(code)
4365 self.body.annotate(code)
4366 if self.else_clause:
4367 self.else_clause.annotate(code)
4368 self.item.annotate(code)
4371 class ForFromStatNode(LoopNode, StatNode):
4372 # for name from expr rel name rel expr
4373 #
4374 # target NameNode
4375 # bound1 ExprNode
4376 # relation1 string
4377 # relation2 string
4378 # bound2 ExprNode
4379 # step ExprNode or None
4380 # body StatNode
4381 # else_clause StatNode or None
4382 #
4383 # Used internally:
4384 #
4385 # from_range bool
4386 # is_py_target bool
4387 # loopvar_node ExprNode (usually a NameNode or temp node)
4388 # py_loopvar_node PyTempNode or None
4389 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
4391 is_py_target = False
4392 loopvar_node = None
4393 py_loopvar_node = None
4394 from_range = False
4396 gil_message = "For-loop using object bounds or target"
4398 def nogil_check(self, env):
4399 for x in (self.target, self.bound1, self.bound2):
4400 if x.type.is_pyobject:
4401 self.gil_error()
4403 def analyse_declarations(self, env):
4404 self.target.analyse_target_declaration(env)
4405 self.body.analyse_declarations(env)
4406 if self.else_clause:
4407 self.else_clause.analyse_declarations(env)
4409 def analyse_expressions(self, env):
4410 import ExprNodes
4411 self.target.analyse_target_types(env)
4412 self.bound1.analyse_types(env)
4413 self.bound2.analyse_types(env)
4414 if self.step is not None:
4415 if isinstance(self.step, ExprNodes.UnaryMinusNode):
4416 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
4417 self.step.analyse_types(env)
4419 target_type = self.target.type
4420 if self.target.type.is_numeric:
4421 loop_type = self.target.type
4422 else:
4423 loop_type = PyrexTypes.c_int_type
4424 if not self.bound1.type.is_pyobject:
4425 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
4426 if not self.bound2.type.is_pyobject:
4427 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
4428 if self.step is not None and not self.step.type.is_pyobject:
4429 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
4430 self.bound1 = self.bound1.coerce_to(loop_type, env)
4431 self.bound2 = self.bound2.coerce_to(loop_type, env)
4432 if not self.bound2.is_literal:
4433 self.bound2 = self.bound2.coerce_to_temp(env)
4434 if self.step is not None:
4435 self.step = self.step.coerce_to(loop_type, env)
4436 if not self.step.is_literal:
4437 self.step = self.step.coerce_to_temp(env)
4439 target_type = self.target.type
4440 if not (target_type.is_pyobject or target_type.is_numeric):
4441 error(self.target.pos,
4442 "for-from loop variable must be c numeric type or Python object")
4443 if target_type.is_numeric:
4444 self.is_py_target = False
4445 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
4446 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
4447 self.loopvar_node = self.target
4448 self.py_loopvar_node = None
4449 else:
4450 self.is_py_target = True
4451 c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
4452 self.loopvar_node = c_loopvar_node
4453 self.py_loopvar_node = \
4454 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
4455 self.body.analyse_expressions(env)
4456 if self.else_clause:
4457 self.else_clause.analyse_expressions(env)
4459 def generate_execution_code(self, code):
4460 old_loop_labels = code.new_loop_labels()
4461 from_range = self.from_range
4462 self.bound1.generate_evaluation_code(code)
4463 self.bound2.generate_evaluation_code(code)
4464 offset, incop = self.relation_table[self.relation1]
4465 if self.step is not None:
4466 self.step.generate_evaluation_code(code)
4467 step = self.step.result()
4468 incop = "%s=%s" % (incop[0], step)
4469 import ExprNodes
4470 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4471 self.loopvar_node.allocate(code)
4472 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4473 self.py_loopvar_node.allocate(code)
4474 if from_range:
4475 loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
4476 else:
4477 loopvar_name = self.loopvar_node.result()
4478 code.putln(
4479 "for (%s = %s%s; %s %s %s; %s%s) {" % (
4480 loopvar_name,
4481 self.bound1.result(), offset,
4482 loopvar_name, self.relation2, self.bound2.result(),
4483 loopvar_name, incop))
4484 if self.py_loopvar_node:
4485 self.py_loopvar_node.generate_evaluation_code(code)
4486 self.target.generate_assignment_code(self.py_loopvar_node, code)
4487 elif from_range:
4488 code.putln("%s = %s;" % (
4489 self.target.result(), loopvar_name))
4490 self.body.generate_execution_code(code)
4491 code.put_label(code.continue_label)
4492 if self.py_loopvar_node:
4493 # This mess is to make for..from loops with python targets behave
4494 # exactly like those with C targets with regards to re-assignment
4495 # of the loop variable.
4496 import ExprNodes
4497 if self.target.entry.is_pyglobal:
4498 # We know target is a NameNode, this is the only ugly case.
4499 target_node = ExprNodes.PyTempNode(self.target.pos, None)
4500 target_node.allocate(code)
4501 interned_cname = code.intern_identifier(self.target.entry.name)
4502 code.globalstate.use_utility_code(ExprNodes.get_name_interned_utility_code)
4503 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
4504 target_node.result(),
4505 Naming.module_cname,
4506 interned_cname,
4507 code.error_goto_if_null(target_node.result(), self.target.pos)))
4508 code.put_gotref(target_node.result())
4509 else:
4510 target_node = self.target
4511 from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
4512 from_py_node.temp_code = loopvar_name
4513 from_py_node.generate_result_code(code)
4514 if self.target.entry.is_pyglobal:
4515 code.put_decref(target_node.result(), target_node.type)
4516 target_node.release(code)
4517 code.putln("}")
4518 if self.py_loopvar_node:
4519 # This is potentially wasteful, but we don't want the semantics to
4520 # depend on whether or not the loop is a python type.
4521 self.py_loopvar_node.generate_evaluation_code(code)
4522 self.target.generate_assignment_code(self.py_loopvar_node, code)
4523 if from_range:
4524 code.funcstate.release_temp(loopvar_name)
4525 break_label = code.break_label
4526 code.set_loop_labels(old_loop_labels)
4527 if self.else_clause:
4528 code.putln("/*else*/ {")
4529 self.else_clause.generate_execution_code(code)
4530 code.putln("}")
4531 code.put_label(break_label)
4532 self.bound1.generate_disposal_code(code)
4533 self.bound1.free_temps(code)
4534 self.bound2.generate_disposal_code(code)
4535 self.bound2.free_temps(code)
4536 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4537 self.loopvar_node.release(code)
4538 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4539 self.py_loopvar_node.release(code)
4540 if self.step is not None:
4541 self.step.generate_disposal_code(code)
4542 self.step.free_temps(code)
4544 relation_table = {
4545 # {relop : (initial offset, increment op)}
4546 '<=': ("", "++"),
4547 '<' : ("+1", "++"),
4548 '>=': ("", "--"),
4549 '>' : ("-1", "--")
4550 }
4552 def generate_function_definitions(self, env, code):
4553 self.target.generate_function_definitions(env, code)
4554 self.bound1.generate_function_definitions(env, code)
4555 self.bound2.generate_function_definitions(env, code)
4556 if self.step is not None:
4557 self.step.generate_function_definitions(env, code)
4558 self.body.generate_function_definitions(env, code)
4559 if self.else_clause is not None:
4560 self.else_clause.generate_function_definitions(env, code)
4562 def annotate(self, code):
4563 self.target.annotate(code)
4564 self.bound1.annotate(code)
4565 self.bound2.annotate(code)
4566 if self.step:
4567 self.step.annotate(code)
4568 self.body.annotate(code)
4569 if self.else_clause:
4570 self.else_clause.annotate(code)
4573 class WithStatNode(StatNode):
4574 """
4575 Represents a Python with statement.
4577 This is only used at parse tree level; and is not present in
4578 analysis or generation phases.
4579 """
4580 # manager The with statement manager object
4581 # target Node (lhs expression)
4582 # body StatNode
4583 child_attrs = ["manager", "target", "body"]
4585 class TryExceptStatNode(StatNode):
4586 # try .. except statement
4587 #
4588 # body StatNode
4589 # except_clauses [ExceptClauseNode]
4590 # else_clause StatNode or None
4592 child_attrs = ["body", "except_clauses", "else_clause"]
4594 def analyse_control_flow(self, env):
4595 env.start_branching(self.pos)
4596 self.body.analyse_control_flow(env)
4597 successful_try = env.control_flow # grab this for later
4598 env.next_branch(self.body.end_pos())
4599 env.finish_branching(self.body.end_pos())
4601 env.start_branching(self.except_clauses[0].pos)
4602 for except_clause in self.except_clauses:
4603 except_clause.analyse_control_flow(env)
4604 env.next_branch(except_clause.end_pos())
4606 # the else cause it executed only when the try clause finishes
4607 env.control_flow.incoming = successful_try
4608 if self.else_clause:
4609 self.else_clause.analyse_control_flow(env)
4610 env.finish_branching(self.end_pos())
4612 def analyse_declarations(self, env):
4613 self.body.analyse_declarations(env)
4614 for except_clause in self.except_clauses:
4615 except_clause.analyse_declarations(env)
4616 if self.else_clause:
4617 self.else_clause.analyse_declarations(env)
4618 env.use_utility_code(reset_exception_utility_code)
4620 def analyse_expressions(self, env):
4621 self.body.analyse_expressions(env)
4622 default_clause_seen = 0
4623 for except_clause in self.except_clauses:
4624 except_clause.analyse_expressions(env)
4625 if default_clause_seen:
4626 error(except_clause.pos, "default 'except:' must be last")
4627 if not except_clause.pattern:
4628 default_clause_seen = 1
4629 self.has_default_clause = default_clause_seen
4630 if self.else_clause:
4631 self.else_clause.analyse_expressions(env)
4633 nogil_check = Node.gil_error
4634 gil_message = "Try-except statement"
4636 def generate_execution_code(self, code):
4637 old_return_label = code.return_label
4638 old_break_label = code.break_label
4639 old_continue_label = code.continue_label
4640 old_error_label = code.new_error_label()
4641 our_error_label = code.error_label
4642 except_end_label = code.new_label('exception_handled')
4643 except_error_label = code.new_label('except_error')
4644 except_return_label = code.new_label('except_return')
4645 try_return_label = code.new_label('try_return')
4646 try_break_label = code.new_label('try_break')
4647 try_continue_label = code.new_label('try_continue')
4648 try_end_label = code.new_label('try_end')
4650 code.putln("{")
4651 code.putln("PyObject %s;" %
4652 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4653 code.putln("__Pyx_ExceptionSave(%s);" %
4654 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4655 for var in Naming.exc_save_vars:
4656 code.put_xgotref(var)
4657 code.putln(
4658 "/*try:*/ {")
4659 code.return_label = try_return_label
4660 code.break_label = try_break_label
4661 code.continue_label = try_continue_label
4662 self.body.generate_execution_code(code)
4663 code.putln(
4664 "}")
4665 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4666 code.error_label = except_error_label
4667 code.return_label = except_return_label
4668 if self.else_clause:
4669 code.putln(
4670 "/*else:*/ {")
4671 self.else_clause.generate_execution_code(code)
4672 code.putln(
4673 "}")
4674 for var in Naming.exc_save_vars:
4675 code.put_xdecref_clear(var, py_object_type)
4676 code.put_goto(try_end_label)
4677 if code.label_used(try_return_label):
4678 code.put_label(try_return_label)
4679 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4680 code.putln("__Pyx_ExceptionReset(%s);" %
4681 ', '.join(Naming.exc_save_vars))
4682 code.put_goto(old_return_label)
4683 code.put_label(our_error_label)
4684 for temp_name, type in temps_to_clean_up:
4685 code.put_xdecref_clear(temp_name, type)
4686 for except_clause in self.except_clauses:
4687 except_clause.generate_handling_code(code, except_end_label)
4689 error_label_used = code.label_used(except_error_label)
4690 if error_label_used or not self.has_default_clause:
4691 if error_label_used:
4692 code.put_label(except_error_label)
4693 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4694 code.putln("__Pyx_ExceptionReset(%s);" %
4695 ', '.join(Naming.exc_save_vars))
4696 code.put_goto(old_error_label)
4698 for exit_label, old_label in zip(
4699 [try_break_label, try_continue_label, except_return_label],
4700 [old_break_label, old_continue_label, old_return_label]):
4702 if code.label_used(exit_label):
4703 code.put_label(exit_label)
4704 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4705 code.putln("__Pyx_ExceptionReset(%s);" %
4706 ', '.join(Naming.exc_save_vars))
4707 code.put_goto(old_label)
4709 if code.label_used(except_end_label):
4710 code.put_label(except_end_label)
4711 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4712 code.putln("__Pyx_ExceptionReset(%s);" %
4713 ', '.join(Naming.exc_save_vars))
4714 code.put_label(try_end_label)
4715 code.putln("}")
4717 code.return_label = old_return_label
4718 code.break_label = old_break_label
4719 code.continue_label = old_continue_label
4720 code.error_label = old_error_label
4722 def generate_function_definitions(self, env, code):
4723 self.body.generate_function_definitions(env, code)
4724 for except_clause in self.except_clauses:
4725 except_clause.generate_function_definitions(env, code)
4726 if self.else_clause is not None:
4727 self.else_clause.generate_function_definitions(env, code)
4729 def annotate(self, code):
4730 self.body.annotate(code)
4731 for except_node in self.except_clauses:
4732 except_node.annotate(code)
4733 if self.else_clause:
4734 self.else_clause.annotate(code)
4737 class ExceptClauseNode(Node):
4738 # Part of try ... except statement.
4739 #
4740 # pattern [ExprNode]
4741 # target ExprNode or None
4742 # body StatNode
4743 # excinfo_target NameNode or None optional target for exception info
4744 # match_flag string result of exception match
4745 # exc_value ExcValueNode used internally
4746 # function_name string qualified name of enclosing function
4747 # exc_vars (string * 3) local exception variables
4749 # excinfo_target is never set by the parser, but can be set by a transform
4750 # in order to extract more extensive information about the exception as a
4751 # sys.exc_info()-style tuple into a target variable
4753 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4755 exc_value = None
4756 excinfo_target = None
4758 def analyse_declarations(self, env):
4759 if self.target:
4760 self.target.analyse_target_declaration(env)
4761 if self.excinfo_target is not None:
4762 self.excinfo_target.analyse_target_declaration(env)
4763 self.body.analyse_declarations(env)
4765 def analyse_expressions(self, env):
4766 import ExprNodes
4767 genv = env.global_scope()
4768 self.function_name = env.qualified_name
4769 if self.pattern:
4770 # normalise/unpack self.pattern into a list
4771 for i, pattern in enumerate(self.pattern):
4772 pattern.analyse_expressions(env)
4773 self.pattern[i] = pattern.coerce_to_pyobject(env)
4775 if self.target:
4776 self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
4777 self.target.analyse_target_expression(env, self.exc_value)
4778 if self.excinfo_target is not None:
4779 import ExprNodes
4780 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4781 ExprNodes.ExcValueNode(pos=self.pos, env=env) for x in range(3)])
4782 self.excinfo_tuple.analyse_expressions(env)
4783 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4785 self.body.analyse_expressions(env)
4787 def generate_handling_code(self, code, end_label):
4788 code.mark_pos(self.pos)
4789 if self.pattern:
4790 exc_tests = []
4791 for pattern in self.pattern:
4792 pattern.generate_evaluation_code(code)
4793 exc_tests.append("PyErr_ExceptionMatches(%s)" % pattern.py_result())
4795 match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
4796 code.putln(
4797 "%s = %s;" % (match_flag, ' || '.join(exc_tests)))
4798 for pattern in self.pattern:
4799 pattern.generate_disposal_code(code)
4800 pattern.free_temps(code)
4801 code.putln(
4802 "if (%s) {" %
4803 match_flag)
4804 code.funcstate.release_temp(match_flag)
4805 else:
4806 code.putln("/*except:*/ {")
4808 if not getattr(self.body, 'stats', True) and \
4809 self.excinfo_target is None and self.target is None:
4810 # most simple case: no exception variable, empty body (pass)
4811 # => reset the exception state, done
4812 code.putln("PyErr_Restore(0,0,0);")
4813 code.put_goto(end_label)
4814 code.putln("}")
4815 return
4817 exc_vars = [code.funcstate.allocate_temp(py_object_type,
4818 manage_ref=True)
4819 for i in xrange(3)]
4820 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4821 # We always have to fetch the exception value even if
4822 # there is no target, because this also normalises the
4823 # exception and stores it in the thread state.
4824 code.globalstate.use_utility_code(get_exception_utility_code)
4825 exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4826 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4827 code.error_goto(self.pos)))
4828 for x in exc_vars:
4829 code.put_gotref(x)
4830 if self.target:
4831 self.exc_value.set_var(exc_vars[1])
4832 self.exc_value.generate_evaluation_code(code)
4833 self.target.generate_assignment_code(self.exc_value, code)
4834 if self.excinfo_target is not None:
4835 for tempvar, node in zip(exc_vars, self.excinfo_tuple.args):
4836 node.set_var(tempvar)
4837 self.excinfo_tuple.generate_evaluation_code(code)
4838 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4840 old_break_label, old_continue_label = code.break_label, code.continue_label
4841 code.break_label = code.new_label('except_break')
4842 code.continue_label = code.new_label('except_continue')
4844 old_exc_vars = code.funcstate.exc_vars
4845 code.funcstate.exc_vars = exc_vars
4846 self.body.generate_execution_code(code)
4847 code.funcstate.exc_vars = old_exc_vars
4848 for var in exc_vars:
4849 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4850 code.put_goto(end_label)
4852 if code.label_used(code.break_label):
4853 code.put_label(code.break_label)
4854 for var in exc_vars:
4855 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4856 code.put_goto(old_break_label)
4857 code.break_label = old_break_label
4859 if code.label_used(code.continue_label):
4860 code.put_label(code.continue_label)
4861 for var in exc_vars:
4862 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4863 code.put_goto(old_continue_label)
4864 code.continue_label = old_continue_label
4866 for temp in exc_vars:
4867 code.funcstate.release_temp(temp)
4869 code.putln(
4870 "}")
4872 def generate_function_definitions(self, env, code):
4873 if self.target is not None:
4874 self.target.generate_function_definitions(env, code)
4875 self.body.generate_function_definitions(env, code)
4877 def annotate(self, code):
4878 if self.pattern:
4879 for pattern in self.pattern:
4880 pattern.annotate(code)
4881 if self.target:
4882 self.target.annotate(code)
4883 self.body.annotate(code)
4886 class TryFinallyStatNode(StatNode):
4887 # try ... finally statement
4888 #
4889 # body StatNode
4890 # finally_clause StatNode
4891 #
4892 # The plan is that we funnel all continue, break
4893 # return and error gotos into the beginning of the
4894 # finally block, setting a variable to remember which
4895 # one we're doing. At the end of the finally block, we
4896 # switch on the variable to figure out where to go.
4897 # In addition, if we're doing an error, we save the
4898 # exception on entry to the finally block and restore
4899 # it on exit.
4901 child_attrs = ["body", "finally_clause"]
4903 preserve_exception = 1
4905 disallow_continue_in_try_finally = 0
4906 # There doesn't seem to be any point in disallowing
4907 # continue in the try block, since we have no problem
4908 # handling it.
4910 def create_analysed(pos, env, body, finally_clause):
4911 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4912 return node
4913 create_analysed = staticmethod(create_analysed)
4915 def analyse_control_flow(self, env):
4916 env.start_branching(self.pos)
4917 self.body.analyse_control_flow(env)
4918 env.next_branch(self.body.end_pos())
4919 env.finish_branching(self.body.end_pos())
4920 self.finally_clause.analyse_control_flow(env)
4922 def analyse_declarations(self, env):
4923 self.body.analyse_declarations(env)
4924 self.finally_clause.analyse_declarations(env)
4926 def analyse_expressions(self, env):
4927 self.body.analyse_expressions(env)
4928 self.finally_clause.analyse_expressions(env)
4930 nogil_check = Node.gil_error
4931 gil_message = "Try-finally statement"
4933 def generate_execution_code(self, code):
4934 old_error_label = code.error_label
4935 old_labels = code.all_new_labels()
4936 new_labels = code.get_all_labels()
4937 new_error_label = code.error_label
4938 catch_label = code.new_label()
4939 code.putln(
4940 "/*try:*/ {")
4941 if self.disallow_continue_in_try_finally:
4942 was_in_try_finally = code.funcstate.in_try_finally
4943 code.funcstate.in_try_finally = 1
4944 self.body.generate_execution_code(code)
4945 if self.disallow_continue_in_try_finally:
4946 code.funcstate.in_try_finally = was_in_try_finally
4947 code.putln(
4948 "}")
4949 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4950 code.mark_pos(self.finally_clause.pos)
4951 code.putln(
4952 "/*finally:*/ {")
4953 cases_used = []
4954 error_label_used = 0
4955 for i, new_label in enumerate(new_labels):
4956 if new_label in code.labels_used:
4957 cases_used.append(i)
4958 if new_label == new_error_label:
4959 error_label_used = 1
4960 error_label_case = i
4961 if cases_used:
4962 code.putln(
4963 "int __pyx_why;")
4964 if error_label_used and self.preserve_exception:
4965 code.putln(
4966 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4967 code.putln(
4968 "int %s;" % Naming.exc_lineno_name)
4969 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4970 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4971 code.putln(exc_var_init_zero)
4972 else:
4973 exc_var_init_zero = None
4974 code.use_label(catch_label)
4975 code.putln(
4976 "__pyx_why = 0; goto %s;" % catch_label)
4977 for i in cases_used:
4978 new_label = new_labels[i]
4979 #if new_label and new_label != "<try>":
4980 if new_label == new_error_label and self.preserve_exception:
4981 self.put_error_catcher(code,
4982 new_error_label, i+1, catch_label, temps_to_clean_up)
4983 else:
4984 code.put('%s: ' % new_label)
4985 if exc_var_init_zero:
4986 code.putln(exc_var_init_zero)
4987 code.putln("__pyx_why = %s; goto %s;" % (
4988 i+1,
4989 catch_label))
4990 code.put_label(catch_label)
4991 code.set_all_labels(old_labels)
4992 if error_label_used:
4993 code.new_error_label()
4994 finally_error_label = code.error_label
4995 self.finally_clause.generate_execution_code(code)
4996 if error_label_used:
4997 if finally_error_label in code.labels_used and self.preserve_exception:
4998 over_label = code.new_label()
4999 code.put_goto(over_label);
5000 code.put_label(finally_error_label)
5001 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
5002 for var in Naming.exc_vars:
5003 code.putln("Py_XDECREF(%s);" % var)
5004 code.putln("}")
5005 code.put_goto(old_error_label)
5006 code.put_label(over_label)
5007 code.error_label = old_error_label
5008 if cases_used:
5009 code.putln(
5010 "switch (__pyx_why) {")
5011 for i in cases_used:
5012 old_label = old_labels[i]
5013 if old_label == old_error_label and self.preserve_exception:
5014 self.put_error_uncatcher(code, i+1, old_error_label)
5015 else:
5016 code.use_label(old_label)
5017 code.putln(
5018 "case %s: goto %s;" % (
5019 i+1,
5020 old_label))
5021 code.putln(
5022 "}")
5023 code.putln(
5024 "}")
5026 def generate_function_definitions(self, env, code):
5027 self.body.generate_function_definitions(env, code)
5028 self.finally_clause.generate_function_definitions(env, code)
5030 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
5031 code.globalstate.use_utility_code(restore_exception_utility_code)
5032 code.putln(
5033 "%s: {" %
5034 error_label)
5035 code.putln(
5036 "__pyx_why = %s;" %
5037 i)
5038 for temp_name, type in temps_to_clean_up:
5039 code.put_xdecref_clear(temp_name, type)
5040 code.putln(
5041 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
5042 Naming.exc_vars)
5043 code.putln(
5044 "%s = %s;" % (
5045 Naming.exc_lineno_name, Naming.lineno_cname))
5046 code.put_goto(catch_label)
5047 code.putln("}")
5049 def put_error_uncatcher(self, code, i, error_label):
5050 code.globalstate.use_utility_code(restore_exception_utility_code)
5051 code.putln(
5052 "case %s: {" %
5053 i)
5054 code.putln(
5055 "__Pyx_ErrRestore(%s, %s, %s);" %
5056 Naming.exc_vars)
5057 code.putln(
5058 "%s = %s;" % (
5059 Naming.lineno_cname, Naming.exc_lineno_name))
5060 for var in Naming.exc_vars:
5061 code.putln(
5062 "%s = 0;" %
5063 var)
5064 code.put_goto(error_label)
5065 code.putln(
5066 "}")
5068 def annotate(self, code):
5069 self.body.annotate(code)
5070 self.finally_clause.annotate(code)
5073 class GILStatNode(TryFinallyStatNode):
5074 # 'with gil' or 'with nogil' statement
5075 #
5076 # state string 'gil' or 'nogil'
5078 # child_attrs = []
5080 preserve_exception = 0
5082 def __init__(self, pos, state, body):
5083 self.state = state
5084 TryFinallyStatNode.__init__(self, pos,
5085 body = body,
5086 finally_clause = GILExitNode(pos, state = state))
5088 def analyse_expressions(self, env):
5089 env.use_utility_code(force_init_threads_utility_code)
5090 was_nogil = env.nogil
5091 env.nogil = 1
5092 TryFinallyStatNode.analyse_expressions(self, env)
5093 env.nogil = was_nogil
5095 nogil_check = None
5097 def generate_execution_code(self, code):
5098 code.mark_pos(self.pos)
5099 code.putln("{")
5100 if self.state == 'gil':
5101 code.putln("#ifdef WITH_THREAD")
5102 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
5103 code.putln("#endif")
5104 else:
5105 code.putln("#ifdef WITH_THREAD")
5106 code.putln("PyThreadState *_save;")
5107 code.putln("#endif")
5108 code.putln("Py_UNBLOCK_THREADS")
5109 TryFinallyStatNode.generate_execution_code(self, code)
5110 code.putln("}")
5113 class GILExitNode(StatNode):
5114 # Used as the 'finally' block in a GILStatNode
5115 #
5116 # state string 'gil' or 'nogil'
5118 child_attrs = []
5120 def analyse_expressions(self, env):
5121 pass
5123 def generate_execution_code(self, code):
5124 if self.state == 'gil':
5125 code.putln("#ifdef WITH_THREAD")
5126 code.putln("PyGILState_Release(_save);")
5127 code.putln("#endif")
5128 else:
5129 code.putln("Py_BLOCK_THREADS")
5132 class CImportStatNode(StatNode):
5133 # cimport statement
5134 #
5135 # module_name string Qualified name of module being imported
5136 # as_name string or None Name specified in "as" clause, if any
5138 child_attrs = []
5140 def analyse_declarations(self, env):
5141 if not env.is_module_scope:
5142 error(self.pos, "cimport only allowed at module level")
5143 return
5144 module_scope = env.find_module(self.module_name, self.pos)
5145 if "." in self.module_name:
5146 names = [EncodedString(name) for name in self.module_name.split(".")]
5147 top_name = names[0]
5148 top_module_scope = env.context.find_submodule(top_name)
5149 module_scope = top_module_scope
5150 for name in names[1:]:
5151 submodule_scope = module_scope.find_submodule(name)
5152 module_scope.declare_module(name, submodule_scope, self.pos)
5153 module_scope = submodule_scope
5154 if self.as_name:
5155 env.declare_module(self.as_name, module_scope, self.pos)
5156 else:
5157 env.declare_module(top_name, top_module_scope, self.pos)
5158 else:
5159 name = self.as_name or self.module_name
5160 env.declare_module(name, module_scope, self.pos)
5162 def analyse_expressions(self, env):
5163 pass
5165 def generate_execution_code(self, code):
5166 pass
5169 class FromCImportStatNode(StatNode):
5170 # from ... cimport statement
5171 #
5172 # module_name string Qualified name of module
5173 # imported_names [(pos, name, as_name, kind)] Names to be imported
5175 child_attrs = []
5177 def analyse_declarations(self, env):
5178 if not env.is_module_scope:
5179 error(self.pos, "cimport only allowed at module level")
5180 return
5181 module_scope = env.find_module(self.module_name, self.pos)
5182 env.add_imported_module(module_scope)
5183 for pos, name, as_name, kind in self.imported_names:
5184 if name == "*":
5185 for local_name, entry in module_scope.entries.items():
5186 env.add_imported_entry(local_name, entry, pos)
5187 else:
5188 entry = module_scope.lookup(name)
5189 if entry:
5190 if kind and not self.declaration_matches(entry, kind):
5191 entry.redeclared(pos)
5192 else:
5193 if kind == 'struct' or kind == 'union':
5194 entry = module_scope.declare_struct_or_union(name,
5195 kind = kind, scope = None, typedef_flag = 0, pos = pos)
5196 elif kind == 'class':
5197 entry = module_scope.declare_c_class(name, pos = pos,
5198 module_name = self.module_name)
5199 else:
5200 submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
5201 if submodule_scope.parent_module is module_scope:
5202 env.declare_module(as_name or name, submodule_scope, self.pos)
5203 else:
5204 error(pos, "Name '%s' not declared in module '%s'"
5205 % (name, self.module_name))
5207 if entry:
5208 local_name = as_name or name
5209 env.add_imported_entry(local_name, entry, pos)
5211 def declaration_matches(self, entry, kind):
5212 if not entry.is_type:
5213 return 0
5214 type = entry.type
5215 if kind == 'class':
5216 if not type.is_extension_type:
5217 return 0
5218 else:
5219 if not type.is_struct_or_union:
5220 return 0
5221 if kind != type.kind:
5222 return 0
5223 return 1
5225 def analyse_expressions(self, env):
5226 pass
5228 def generate_execution_code(self, code):
5229 pass
5232 class FromImportStatNode(StatNode):
5233 # from ... import statement
5234 #
5235 # module ImportNode
5236 # items [(string, NameNode)]
5237 # interned_items [(string, NameNode, ExprNode)]
5238 # item PyTempNode used internally
5239 # import_star boolean used internally
5241 child_attrs = ["module"]
5242 import_star = 0
5244 def analyse_declarations(self, env):
5245 for name, target in self.items:
5246 if name == "*":
5247 if not env.is_module_scope:
5248 error(self.pos, "import * only allowed at module level")
5249 return
5250 env.has_import_star = 1
5251 self.import_star = 1
5252 else:
5253 target.analyse_target_declaration(env)
5255 def analyse_expressions(self, env):
5256 import ExprNodes
5257 self.module.analyse_expressions(env)
5258 self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
5259 self.interned_items = []
5260 for name, target in self.items:
5261 if name == '*':
5262 for _, entry in env.entries.items():
5263 if not entry.is_type and entry.type.is_extension_type:
5264 env.use_utility_code(ExprNodes.type_test_utility_code)
5265 break
5266 else:
5267 entry = env.lookup(target.name)
5268 # check whether or not entry is already cimported
5269 if (entry.is_type and entry.type.name == name
5270 and hasattr(entry.type, 'module_name')):
5271 if entry.type.module_name == self.module.module_name.value:
5272 # cimported with absolute name
5273 continue
5274 try:
5275 # cimported with relative name
5276 module = env.find_module(self.module.module_name.value,
5277 pos=None)
5278 if entry.type.module_name == module.qualified_name:
5279 continue
5280 except AttributeError:
5281 pass
5282 target.analyse_target_expression(env, None)
5283 if target.type is py_object_type:
5284 coerced_item = None
5285 else:
5286 coerced_item = self.item.coerce_to(target.type, env)
5287 self.interned_items.append((name, target, coerced_item))
5289 def generate_execution_code(self, code):
5290 self.module.generate_evaluation_code(code)
5291 if self.import_star:
5292 code.putln(
5293 'if (%s(%s) < 0) %s;' % (
5294 Naming.import_star,
5295 self.module.py_result(),
5296 code.error_goto(self.pos)))
5297 item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
5298 self.item.set_cname(item_temp)
5299 for name, target, coerced_item in self.interned_items:
5300 cname = code.intern_identifier(name)
5301 code.putln(
5302 '%s = PyObject_GetAttr(%s, %s); %s' % (
5303 item_temp,
5304 self.module.py_result(),
5305 cname,
5306 code.error_goto_if_null(item_temp, self.pos)))
5307 code.put_gotref(item_temp)
5308 if coerced_item is None:
5309 target.generate_assignment_code(self.item, code)
5310 else:
5311 coerced_item.allocate_temp_result(code)
5312 coerced_item.generate_result_code(code)
5313 target.generate_assignment_code(coerced_item, code)
5314 code.put_decref_clear(item_temp, py_object_type)
5315 code.funcstate.release_temp(item_temp)
5316 self.module.generate_disposal_code(code)
5317 self.module.free_temps(code)
5321 #------------------------------------------------------------------------------------
5322 #
5323 # Runtime support code
5324 #
5325 #------------------------------------------------------------------------------------
5327 utility_function_predeclarations = \
5328 """
5329 /* inline attribute */
5330 #ifndef CYTHON_INLINE
5331 #if defined(__GNUC__)
5332 #define CYTHON_INLINE __inline__
5333 #elif defined(_MSC_VER)
5334 #define CYTHON_INLINE __inline
5335 #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
5336 #define CYTHON_INLINE inline
5337 #else
5338 #define CYTHON_INLINE
5339 #endif
5340 #endif
5342 /* unused attribute */
5343 #ifndef CYTHON_UNUSED
5344 # if defined(__GNUC__)
5345 # if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
5346 # define CYTHON_UNUSED __attribute__ ((__unused__))
5347 # else
5348 # define CYTHON_UNUSED
5349 # endif
5350 # elif defined(__ICC) || defined(__INTEL_COMPILER)
5351 # define CYTHON_UNUSED __attribute__ ((__unused__))
5352 # else
5353 # define CYTHON_UNUSED
5354 # endif
5355 #endif
5357 typedef struct {PyObject **p; char *s; const long n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; /*proto*/
5359 """
5361 if Options.gcc_branch_hints:
5362 branch_prediction_macros = \
5363 """
5364 #ifdef __GNUC__
5365 /* Test for GCC > 2.95 */
5366 #if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
5367 #define likely(x) __builtin_expect(!!(x), 1)
5368 #define unlikely(x) __builtin_expect(!!(x), 0)
5369 #else /* __GNUC__ > 2 ... */
5370 #define likely(x) (x)
5371 #define unlikely(x) (x)
5372 #endif /* __GNUC__ > 2 ... */
5373 #else /* __GNUC__ */
5374 #define likely(x) (x)
5375 #define unlikely(x) (x)
5376 #endif /* __GNUC__ */
5377 """
5378 else:
5379 branch_prediction_macros = \
5380 """
5381 #define likely(x) (x)
5382 #define unlikely(x) (x)
5383 """
5385 #get_name_predeclaration = \
5386 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
5388 #get_name_interned_predeclaration = \
5389 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
5391 #------------------------------------------------------------------------------------
5393 printing_utility_code = UtilityCode(
5394 proto = """
5395 static int __Pyx_Print(PyObject*, PyObject *, int); /*proto*/
5396 #if PY_MAJOR_VERSION >= 3
5397 static PyObject* %s = 0;
5398 static PyObject* %s = 0;
5399 #endif
5400 """ % (Naming.print_function, Naming.print_function_kwargs),
5401 cleanup = """
5402 #if PY_MAJOR_VERSION >= 3
5403 Py_CLEAR(%s);
5404 Py_CLEAR(%s);
5405 #endif
5406 """ % (Naming.print_function, Naming.print_function_kwargs),
5407 impl = r"""
5408 #if PY_MAJOR_VERSION < 3
5409 static PyObject *__Pyx_GetStdout(void) {
5410 PyObject *f = PySys_GetObject((char *)"stdout");
5411 if (!f) {
5412 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
5413 }
5414 return f;
5415 }
5417 static int __Pyx_Print(PyObject* f, PyObject *arg_tuple, int newline) {
5418 PyObject* v;
5419 int i;
5421 if (!f) {
5422 if (!(f = __Pyx_GetStdout()))
5423 return -1;
5424 }
5425 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
5426 if (PyFile_SoftSpace(f, 1)) {
5427 if (PyFile_WriteString(" ", f) < 0)
5428 return -1;
5429 }
5430 v = PyTuple_GET_ITEM(arg_tuple, i);
5431 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
5432 return -1;
5433 if (PyString_Check(v)) {
5434 char *s = PyString_AsString(v);
5435 Py_ssize_t len = PyString_Size(v);
5436 if (len > 0 &&
5437 isspace(Py_CHARMASK(s[len-1])) &&
5438 s[len-1] != ' ')
5439 PyFile_SoftSpace(f, 0);
5440 }
5441 }
5442 if (newline) {
5443 if (PyFile_WriteString("\n", f) < 0)
5444 return -1;
5445 PyFile_SoftSpace(f, 0);
5446 }
5447 return 0;
5448 }
5450 #else /* Python 3 has a print function */
5452 static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) {
5453 PyObject* kwargs = 0;
5454 PyObject* result = 0;
5455 PyObject* end_string;
5456 if (unlikely(!%(PRINT_FUNCTION)s)) {
5457 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
5458 if (!%(PRINT_FUNCTION)s)
5459 return -1;
5460 }
5461 if (stream) {
5462 kwargs = PyDict_New();
5463 if (unlikely(!kwargs))
5464 return -1;
5465 if (unlikely(PyDict_SetItemString(kwargs, "file", stream) < 0))
5466 goto bad;
5467 if (!newline) {
5468 end_string = PyUnicode_FromStringAndSize(" ", 1);
5469 if (unlikely(!end_string))
5470 goto bad;
5471 if (PyDict_SetItemString(kwargs, "end", end_string) < 0) {
5472 Py_DECREF(end_string);
5473 goto bad;
5474 }
5475 Py_DECREF(end_string);
5476 }
5477 } else if (!newline) {
5478 if (unlikely(!%(PRINT_KWARGS)s)) {
5479 %(PRINT_KWARGS)s = PyDict_New();
5480 if (unlikely(!%(PRINT_KWARGS)s))
5481 return -1;
5482 end_string = PyUnicode_FromStringAndSize(" ", 1);
5483 if (unlikely(!end_string))
5484 return -1;
5485 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
5486 Py_DECREF(end_string);
5487 return -1;
5488 }
5489 Py_DECREF(end_string);
5490 }
5491 kwargs = %(PRINT_KWARGS)s;
5492 }
5493 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
5494 if (unlikely(kwargs) && (kwargs != %(PRINT_KWARGS)s))
5495 Py_DECREF(kwargs);
5496 if (!result)
5497 return -1;
5498 Py_DECREF(result);
5499 return 0;
5500 bad:
5501 if (kwargs != %(PRINT_KWARGS)s)
5502 Py_XDECREF(kwargs);
5503 return -1;
5504 }
5506 #endif
5507 """ % {'BUILTINS' : Naming.builtins_cname,
5508 'PRINT_FUNCTION' : Naming.print_function,
5509 'PRINT_KWARGS' : Naming.print_function_kwargs}
5510 )
5513 printing_one_utility_code = UtilityCode(
5514 proto = """
5515 static int __Pyx_PrintOne(PyObject* stream, PyObject *o); /*proto*/
5516 """,
5517 impl = r"""
5518 #if PY_MAJOR_VERSION < 3
5520 static int __Pyx_PrintOne(PyObject* f, PyObject *o) {
5521 if (!f) {
5522 if (!(f = __Pyx_GetStdout()))
5523 return -1;
5524 }
5525 if (PyFile_SoftSpace(f, 0)) {
5526 if (PyFile_WriteString(" ", f) < 0)
5527 return -1;
5528 }
5529 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
5530 return -1;
5531 if (PyFile_WriteString("\n", f) < 0)
5532 return -1;
5533 return 0;
5534 /* the line below is just to avoid compiler
5535 * compiler warnings about unused functions */
5536 return __Pyx_Print(f, NULL, 0);
5537 }
5539 #else /* Python 3 has a print function */
5541 static int __Pyx_PrintOne(PyObject* stream, PyObject *o) {
5542 int res;
5543 PyObject* arg_tuple = PyTuple_New(1);
5544 if (unlikely(!arg_tuple))
5545 return -1;
5546 Py_INCREF(o);
5547 PyTuple_SET_ITEM(arg_tuple, 0, o);
5548 res = __Pyx_Print(stream, arg_tuple, 1);
5549 Py_DECREF(arg_tuple);
5550 return res;
5551 }
5553 #endif
5554 """,
5555 requires=[printing_utility_code])
5559 #------------------------------------------------------------------------------------
5561 # Exception raising code
5562 #
5563 # Exceptions are raised by __Pyx_Raise() and stored as plain
5564 # type/value/tb in PyThreadState->curexc_*. When being caught by an
5565 # 'except' statement, curexc_* is moved over to exc_* by
5566 # __Pyx_GetException()
5568 restore_exception_utility_code = UtilityCode(
5569 proto = """
5570 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5571 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5572 """,
5573 impl = """
5574 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5575 PyObject *tmp_type, *tmp_value, *tmp_tb;
5576 PyThreadState *tstate = PyThreadState_GET();
5578 tmp_type = tstate->curexc_type;
5579 tmp_value = tstate->curexc_value;
5580 tmp_tb = tstate->curexc_traceback;
5581 tstate->curexc_type = type;
5582 tstate->curexc_value = value;
5583 tstate->curexc_traceback = tb;
5584 Py_XDECREF(tmp_type);
5585 Py_XDECREF(tmp_value);
5586 Py_XDECREF(tmp_tb);
5587 }
5589 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5590 PyThreadState *tstate = PyThreadState_GET();
5591 *type = tstate->curexc_type;
5592 *value = tstate->curexc_value;
5593 *tb = tstate->curexc_traceback;
5595 tstate->curexc_type = 0;
5596 tstate->curexc_value = 0;
5597 tstate->curexc_traceback = 0;
5598 }
5600 """)
5602 # The following function is based on do_raise() from ceval.c. There
5603 # are separate versions for Python2 and Python3 as exception handling
5604 # has changed quite a lot between the two versions.
5606 raise_utility_code = UtilityCode(
5607 proto = """
5608 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5609 """,
5610 impl = """
5611 #if PY_MAJOR_VERSION < 3
5612 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5613 Py_XINCREF(type);
5614 Py_XINCREF(value);
5615 Py_XINCREF(tb);
5616 /* First, check the traceback argument, replacing None with NULL. */
5617 if (tb == Py_None) {
5618 Py_DECREF(tb);
5619 tb = 0;
5620 }
5621 else if (tb != NULL && !PyTraceBack_Check(tb)) {
5622 PyErr_SetString(PyExc_TypeError,
5623 "raise: arg 3 must be a traceback or None");
5624 goto raise_error;
5625 }
5626 /* Next, replace a missing value with None */
5627 if (value == NULL) {
5628 value = Py_None;
5629 Py_INCREF(value);
5630 }
5631 #if PY_VERSION_HEX < 0x02050000
5632 if (!PyClass_Check(type))
5633 #else
5634 if (!PyType_Check(type))
5635 #endif
5636 {
5637 /* Raising an instance. The value should be a dummy. */
5638 if (value != Py_None) {
5639 PyErr_SetString(PyExc_TypeError,
5640 "instance exception may not have a separate value");
5641 goto raise_error;
5642 }
5643 /* Normalize to raise <class>, <instance> */
5644 Py_DECREF(value);
5645 value = type;
5646 #if PY_VERSION_HEX < 0x02050000
5647 if (PyInstance_Check(type)) {
5648 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
5649 Py_INCREF(type);
5650 }
5651 else {
5652 type = 0;
5653 PyErr_SetString(PyExc_TypeError,
5654 "raise: exception must be an old-style class or instance");
5655 goto raise_error;
5656 }
5657 #else
5658 type = (PyObject*) Py_TYPE(type);
5659 Py_INCREF(type);
5660 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
5661 PyErr_SetString(PyExc_TypeError,
5662 "raise: exception class must be a subclass of BaseException");
5663 goto raise_error;
5664 }
5665 #endif
5666 }
5668 __Pyx_ErrRestore(type, value, tb);
5669 return;
5670 raise_error:
5671 Py_XDECREF(value);
5672 Py_XDECREF(type);
5673 Py_XDECREF(tb);
5674 return;
5675 }
5677 #else /* Python 3+ */
5679 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5680 if (tb == Py_None) {
5681 tb = 0;
5682 } else if (tb && !PyTraceBack_Check(tb)) {
5683 PyErr_SetString(PyExc_TypeError,
5684 "raise: arg 3 must be a traceback or None");
5685 goto bad;
5686 }
5687 if (value == Py_None)
5688 value = 0;
5690 if (PyExceptionInstance_Check(type)) {
5691 if (value) {
5692 PyErr_SetString(PyExc_TypeError,
5693 "instance exception may not have a separate value");
5694 goto bad;
5695 }
5696 value = type;
5697 type = (PyObject*) Py_TYPE(value);
5698 } else if (!PyExceptionClass_Check(type)) {
5699 PyErr_SetString(PyExc_TypeError,
5700 "raise: exception class must be a subclass of BaseException");
5701 goto bad;
5702 }
5704 PyErr_SetObject(type, value);
5706 if (tb) {
5707 PyThreadState *tstate = PyThreadState_GET();
5708 PyObject* tmp_tb = tstate->curexc_traceback;
5709 if (tb != tmp_tb) {
5710 Py_INCREF(tb);
5711 tstate->curexc_traceback = tb;
5712 Py_XDECREF(tmp_tb);
5713 }
5714 }
5716 bad:
5717 return;
5718 }
5719 #endif
5720 """,
5721 requires=[restore_exception_utility_code])
5723 #------------------------------------------------------------------------------------
5725 get_exception_utility_code = UtilityCode(
5726 proto = """
5727 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5728 """,
5729 impl = """
5730 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5731 PyObject *local_type, *local_value, *local_tb;
5732 PyObject *tmp_type, *tmp_value, *tmp_tb;
5733 PyThreadState *tstate = PyThreadState_GET();
5734 local_type = tstate->curexc_type;
5735 local_value = tstate->curexc_value;
5736 local_tb = tstate->curexc_traceback;
5737 tstate->curexc_type = 0;
5738 tstate->curexc_value = 0;
5739 tstate->curexc_traceback = 0;
5740 PyErr_NormalizeException(&local_type, &local_value, &local_tb);
5741 if (unlikely(tstate->curexc_type))
5742 goto bad;
5743 #if PY_MAJOR_VERSION >= 3
5744 if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
5745 goto bad;
5746 #endif
5747 *type = local_type;
5748 *value = local_value;
5749 *tb = local_tb;
5750 Py_INCREF(local_type);
5751 Py_INCREF(local_value);
5752 Py_INCREF(local_tb);
5753 tmp_type = tstate->exc_type;
5754 tmp_value = tstate->exc_value;
5755 tmp_tb = tstate->exc_traceback;
5756 tstate->exc_type = local_type;
5757 tstate->exc_value = local_value;
5758 tstate->exc_traceback = local_tb;
5759 /* Make sure tstate is in a consistent state when we XDECREF
5760 these objects (XDECREF may run arbitrary code). */
5761 Py_XDECREF(tmp_type);
5762 Py_XDECREF(tmp_value);
5763 Py_XDECREF(tmp_tb);
5764 return 0;
5765 bad:
5766 *type = 0;
5767 *value = 0;
5768 *tb = 0;
5769 Py_XDECREF(local_type);
5770 Py_XDECREF(local_value);
5771 Py_XDECREF(local_tb);
5772 return -1;
5773 }
5775 """)
5777 #------------------------------------------------------------------------------------
5779 get_exception_tuple_utility_code = UtilityCode(proto="""
5780 static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
5781 """,
5782 # I doubt that calling __Pyx_GetException() here is correct as it moves
5783 # the exception from tstate->curexc_* to tstate->exc_*, which prevents
5784 # exception handlers later on from receiving it.
5785 impl = """
5786 static PyObject *__Pyx_GetExceptionTuple(void) {
5787 PyObject *type = NULL, *value = NULL, *tb = NULL;
5788 if (__Pyx_GetException(&type, &value, &tb) == 0) {
5789 PyObject* exc_info = PyTuple_New(3);
5790 if (exc_info) {
5791 Py_INCREF(type);
5792 Py_INCREF(value);
5793 Py_INCREF(tb);
5794 PyTuple_SET_ITEM(exc_info, 0, type);
5795 PyTuple_SET_ITEM(exc_info, 1, value);
5796 PyTuple_SET_ITEM(exc_info, 2, tb);
5797 return exc_info;
5798 }
5799 }
5800 return NULL;
5801 }
5802 """,
5803 requires=[get_exception_utility_code])
5805 #------------------------------------------------------------------------------------
5807 reset_exception_utility_code = UtilityCode(
5808 proto = """
5809 static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5810 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5811 """,
5812 impl = """
5813 static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5814 PyThreadState *tstate = PyThreadState_GET();
5815 *type = tstate->exc_type;
5816 *value = tstate->exc_value;
5817 *tb = tstate->exc_traceback;
5818 Py_XINCREF(*type);
5819 Py_XINCREF(*value);
5820 Py_XINCREF(*tb);
5821 }
5823 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5824 PyObject *tmp_type, *tmp_value, *tmp_tb;
5825 PyThreadState *tstate = PyThreadState_GET();
5826 tmp_type = tstate->exc_type;
5827 tmp_value = tstate->exc_value;
5828 tmp_tb = tstate->exc_traceback;
5829 tstate->exc_type = type;
5830 tstate->exc_value = value;
5831 tstate->exc_traceback = tb;
5832 Py_XDECREF(tmp_type);
5833 Py_XDECREF(tmp_value);
5834 Py_XDECREF(tmp_tb);
5835 }
5836 """)
5838 #------------------------------------------------------------------------------------
5840 arg_type_test_utility_code = UtilityCode(
5841 proto = """
5842 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5843 const char *name, int exact); /*proto*/
5844 """,
5845 impl = """
5846 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5847 const char *name, int exact)
5848 {
5849 if (!type) {
5850 PyErr_Format(PyExc_SystemError, "Missing type object");
5851 return 0;
5852 }
5853 if (none_allowed && obj == Py_None) return 1;
5854 else if (exact) {
5855 if (Py_TYPE(obj) == type) return 1;
5856 }
5857 else {
5858 if (PyObject_TypeCheck(obj, type)) return 1;
5859 }
5860 PyErr_Format(PyExc_TypeError,
5861 "Argument '%s' has incorrect type (expected %s, got %s)",
5862 name, type->tp_name, Py_TYPE(obj)->tp_name);
5863 return 0;
5864 }
5865 """)
5867 #------------------------------------------------------------------------------------
5868 #
5869 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5870 # many or too few positional arguments were found. This handles
5871 # Py_ssize_t formatting correctly.
5873 raise_argtuple_invalid_utility_code = UtilityCode(
5874 proto = """
5875 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5876 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5877 """,
5878 impl = """
5879 static void __Pyx_RaiseArgtupleInvalid(
5880 const char* func_name,
5881 int exact,
5882 Py_ssize_t num_min,
5883 Py_ssize_t num_max,
5884 Py_ssize_t num_found)
5885 {
5886 Py_ssize_t num_expected;
5887 const char *number, *more_or_less;
5889 if (num_found < num_min) {
5890 num_expected = num_min;
5891 more_or_less = "at least";
5892 } else {
5893 num_expected = num_max;
5894 more_or_less = "at most";
5895 }
5896 if (exact) {
5897 more_or_less = "exactly";
5898 }
5899 number = (num_expected == 1) ? "" : "s";
5900 PyErr_Format(PyExc_TypeError,
5901 #if PY_VERSION_HEX < 0x02050000
5902 "%s() takes %s %d positional argument%s (%d given)",
5903 #else
5904 "%s() takes %s %zd positional argument%s (%zd given)",
5905 #endif
5906 func_name, more_or_less, num_expected, number, num_found);
5907 }
5908 """)
5910 raise_keyword_required_utility_code = UtilityCode(
5911 proto = """
5912 static CYTHON_INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5913 """,
5914 impl = """
5915 static CYTHON_INLINE void __Pyx_RaiseKeywordRequired(
5916 const char* func_name,
5917 PyObject* kw_name)
5918 {
5919 PyErr_Format(PyExc_TypeError,
5920 #if PY_MAJOR_VERSION >= 3
5921 "%s() needs keyword-only argument %U", func_name, kw_name);
5922 #else
5923 "%s() needs keyword-only argument %s", func_name,
5924 PyString_AS_STRING(kw_name));
5925 #endif
5926 }
5927 """)
5929 raise_double_keywords_utility_code = UtilityCode(
5930 proto = """
5931 static void __Pyx_RaiseDoubleKeywordsError(
5932 const char* func_name, PyObject* kw_name); /*proto*/
5933 """,
5934 impl = """
5935 static void __Pyx_RaiseDoubleKeywordsError(
5936 const char* func_name,
5937 PyObject* kw_name)
5938 {
5939 PyErr_Format(PyExc_TypeError,
5940 #if PY_MAJOR_VERSION >= 3
5941 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5942 #else
5943 "%s() got multiple values for keyword argument '%s'", func_name,
5944 PyString_AS_STRING(kw_name));
5945 #endif
5946 }
5947 """)
5949 #------------------------------------------------------------------------------------
5950 #
5951 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5952 # were passed to a function, or if any keywords were passed to a
5953 # function that does not accept them.
5955 keyword_string_check_utility_code = UtilityCode(
5956 proto = """
5957 static CYTHON_INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5958 const char* function_name, int kw_allowed); /*proto*/
5959 """,
5960 impl = """
5961 static CYTHON_INLINE int __Pyx_CheckKeywordStrings(
5962 PyObject *kwdict,
5963 const char* function_name,
5964 int kw_allowed)
5965 {
5966 PyObject* key = 0;
5967 Py_ssize_t pos = 0;
5968 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5969 #if PY_MAJOR_VERSION < 3
5970 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5971 #else
5972 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5973 #endif
5974 goto invalid_keyword_type;
5975 }
5976 if ((!kw_allowed) && unlikely(key))
5977 goto invalid_keyword;
5978 return 1;
5979 invalid_keyword_type:
5980 PyErr_Format(PyExc_TypeError,
5981 "%s() keywords must be strings", function_name);
5982 return 0;
5983 invalid_keyword:
5984 PyErr_Format(PyExc_TypeError,
5985 #if PY_MAJOR_VERSION < 3
5986 "%s() got an unexpected keyword argument '%s'",
5987 function_name, PyString_AsString(key));
5988 #else
5989 "%s() got an unexpected keyword argument '%U'",
5990 function_name, key);
5991 #endif
5992 return 0;
5993 }
5994 """)
5996 #------------------------------------------------------------------------------------
5997 #
5998 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5999 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
6000 # keywords will raise an invalid keyword error.
6001 #
6002 # Three kinds of errors are checked: 1) non-string keywords, 2)
6003 # unexpected keywords and 3) overlap with positional arguments.
6004 #
6005 # If num_posargs is greater 0, it denotes the number of positional
6006 # arguments that were passed and that must therefore not appear
6007 # amongst the keywords as well.
6008 #
6009 # This method does not check for required keyword arguments.
6010 #
6012 parse_keywords_utility_code = UtilityCode(
6013 proto = """
6014 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
6015 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
6016 const char* function_name); /*proto*/
6017 """,
6018 impl = """
6019 static int __Pyx_ParseOptionalKeywords(
6020 PyObject *kwds,
6021 PyObject **argnames[],
6022 PyObject *kwds2,
6023 PyObject *values[],
6024 Py_ssize_t num_pos_args,
6025 const char* function_name)
6026 {
6027 PyObject *key = 0, *value = 0;
6028 Py_ssize_t pos = 0;
6029 PyObject*** name;
6030 PyObject*** first_kw_arg = argnames + num_pos_args;
6032 while (PyDict_Next(kwds, &pos, &key, &value)) {
6033 name = first_kw_arg;
6034 while (*name && (**name != key)) name++;
6035 if (*name) {
6036 values[name-argnames] = value;
6037 } else {
6038 #if PY_MAJOR_VERSION < 3
6039 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
6040 #else
6041 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
6042 #endif
6043 goto invalid_keyword_type;
6044 } else {
6045 for (name = first_kw_arg; *name; name++) {
6046 #if PY_MAJOR_VERSION >= 3
6047 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
6048 PyUnicode_Compare(**name, key) == 0) break;
6049 #else
6050 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
6051 _PyString_Eq(**name, key)) break;
6052 #endif
6053 }
6054 if (*name) {
6055 values[name-argnames] = value;
6056 } else {
6057 /* unexpected keyword found */
6058 for (name=argnames; name != first_kw_arg; name++) {
6059 if (**name == key) goto arg_passed_twice;
6060 #if PY_MAJOR_VERSION >= 3
6061 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
6062 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
6063 #else
6064 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
6065 _PyString_Eq(**name, key)) goto arg_passed_twice;
6066 #endif
6067 }
6068 if (kwds2) {
6069 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
6070 } else {
6071 goto invalid_keyword;
6072 }
6073 }
6074 }
6075 }
6076 }
6077 return 0;
6078 arg_passed_twice:
6079 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
6080 goto bad;
6081 invalid_keyword_type:
6082 PyErr_Format(PyExc_TypeError,
6083 "%s() keywords must be strings", function_name);
6084 goto bad;
6085 invalid_keyword:
6086 PyErr_Format(PyExc_TypeError,
6087 #if PY_MAJOR_VERSION < 3
6088 "%s() got an unexpected keyword argument '%s'",
6089 function_name, PyString_AsString(key));
6090 #else
6091 "%s() got an unexpected keyword argument '%U'",
6092 function_name, key);
6093 #endif
6094 bad:
6095 return -1;
6096 }
6097 """)
6099 #------------------------------------------------------------------------------------
6101 traceback_utility_code = UtilityCode(
6102 proto = """
6103 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
6104 """,
6105 impl = """
6106 #include "compile.h"
6107 #include "frameobject.h"
6108 #include "traceback.h"
6110 static void __Pyx_AddTraceback(const char *funcname) {
6111 PyObject *py_srcfile = 0;
6112 PyObject *py_funcname = 0;
6113 PyObject *py_globals = 0;
6114 PyCodeObject *py_code = 0;
6115 PyFrameObject *py_frame = 0;
6117 #if PY_MAJOR_VERSION < 3
6118 py_srcfile = PyString_FromString(%(FILENAME)s);
6119 #else
6120 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
6121 #endif
6122 if (!py_srcfile) goto bad;
6123 if (%(CLINENO)s) {
6124 #if PY_MAJOR_VERSION < 3
6125 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
6126 #else
6127 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
6128 #endif
6129 }
6130 else {
6131 #if PY_MAJOR_VERSION < 3
6132 py_funcname = PyString_FromString(funcname);
6133 #else
6134 py_funcname = PyUnicode_FromString(funcname);
6135 #endif
6136 }
6137 if (!py_funcname) goto bad;
6138 py_globals = PyModule_GetDict(%(GLOBALS)s);
6139 if (!py_globals) goto bad;
6140 py_code = PyCode_New(
6141 0, /*int argcount,*/
6142 #if PY_MAJOR_VERSION >= 3
6143 0, /*int kwonlyargcount,*/
6144 #endif
6145 0, /*int nlocals,*/
6146 0, /*int stacksize,*/
6147 0, /*int flags,*/
6148 %(EMPTY_BYTES)s, /*PyObject *code,*/
6149 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
6150 %(EMPTY_TUPLE)s, /*PyObject *names,*/
6151 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
6152 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
6153 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
6154 py_srcfile, /*PyObject *filename,*/
6155 py_funcname, /*PyObject *name,*/
6156 %(LINENO)s, /*int firstlineno,*/
6157 %(EMPTY_BYTES)s /*PyObject *lnotab*/
6158 );
6159 if (!py_code) goto bad;
6160 py_frame = PyFrame_New(
6161 PyThreadState_GET(), /*PyThreadState *tstate,*/
6162 py_code, /*PyCodeObject *code,*/
6163 py_globals, /*PyObject *globals,*/
6164 0 /*PyObject *locals*/
6165 );
6166 if (!py_frame) goto bad;
6167 py_frame->f_lineno = %(LINENO)s;
6168 PyTraceBack_Here(py_frame);
6169 bad:
6170 Py_XDECREF(py_srcfile);
6171 Py_XDECREF(py_funcname);
6172 Py_XDECREF(py_code);
6173 Py_XDECREF(py_frame);
6174 }
6175 """ % {
6176 'FILENAME': Naming.filename_cname,
6177 'LINENO': Naming.lineno_cname,
6178 'CFILENAME': Naming.cfilenm_cname,
6179 'CLINENO': Naming.clineno_cname,
6180 'GLOBALS': Naming.module_cname,
6181 'EMPTY_TUPLE' : Naming.empty_tuple,
6182 'EMPTY_BYTES' : Naming.empty_bytes,
6183 })
6185 #------------------------------------------------------------------------------------
6187 unraisable_exception_utility_code = UtilityCode(
6188 proto = """
6189 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
6190 """,
6191 impl = """
6192 static void __Pyx_WriteUnraisable(const char *name) {
6193 PyObject *old_exc, *old_val, *old_tb;
6194 PyObject *ctx;
6195 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
6196 #if PY_MAJOR_VERSION < 3
6197 ctx = PyString_FromString(name);
6198 #else
6199 ctx = PyUnicode_FromString(name);
6200 #endif
6201 __Pyx_ErrRestore(old_exc, old_val, old_tb);
6202 if (!ctx) {
6203 PyErr_WriteUnraisable(Py_None);
6204 } else {
6205 PyErr_WriteUnraisable(ctx);
6206 Py_DECREF(ctx);
6207 }
6208 }
6209 """,
6210 requires=[restore_exception_utility_code])
6212 #------------------------------------------------------------------------------------
6214 set_vtable_utility_code = UtilityCode(
6215 proto = """
6216 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
6217 """,
6218 impl = """
6219 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
6220 #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
6221 PyObject *ob = PyCapsule_New(vtable, 0, 0);
6222 #else
6223 PyObject *ob = PyCObject_FromVoidPtr(vtable, 0);
6224 #endif
6225 if (!ob)
6226 goto bad;
6227 if (PyDict_SetItemString(dict, "__pyx_vtable__", ob) < 0)
6228 goto bad;
6229 Py_DECREF(ob);
6230 return 0;
6231 bad:
6232 Py_XDECREF(ob);
6233 return -1;
6234 }
6235 """)
6237 #------------------------------------------------------------------------------------
6239 get_vtable_utility_code = UtilityCode(
6240 proto = """
6241 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
6242 """,
6243 impl = r"""
6244 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
6245 PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
6246 if (!ob)
6247 goto bad;
6248 #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
6249 *(void **)vtabptr = PyCapsule_GetPointer(ob, 0);
6250 #else
6251 *(void **)vtabptr = PyCObject_AsVoidPtr(ob);
6252 #endif
6253 if (!*(void **)vtabptr)
6254 goto bad;
6255 Py_DECREF(ob);
6256 return 0;
6257 bad:
6258 Py_XDECREF(ob);
6259 return -1;
6260 }
6261 """)
6263 #------------------------------------------------------------------------------------
6265 init_string_tab_utility_code = UtilityCode(
6266 proto = """
6267 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
6268 """,
6269 impl = """
6270 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
6271 while (t->p) {
6272 #if PY_MAJOR_VERSION < 3
6273 if (t->is_unicode) {
6274 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
6275 } else if (t->intern) {
6276 *t->p = PyString_InternFromString(t->s);
6277 } else {
6278 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
6279 }
6280 #else /* Python 3+ has unicode identifiers */
6281 if (t->is_unicode | t->is_str) {
6282 if (t->intern) {
6283 *t->p = PyUnicode_InternFromString(t->s);
6284 } else if (t->encoding) {
6285 *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
6286 } else {
6287 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
6288 }
6289 } else {
6290 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
6291 }
6292 #endif
6293 if (!*t->p)
6294 return -1;
6295 ++t;
6296 }
6297 return 0;
6298 }
6299 """)
6301 #------------------------------------------------------------------------------------
6303 force_init_threads_utility_code = UtilityCode(
6304 proto="""
6305 #ifndef __PYX_FORCE_INIT_THREADS
6306 #if PY_VERSION_HEX < 0x02040200
6307 #define __PYX_FORCE_INIT_THREADS 1
6308 #else
6309 #define __PYX_FORCE_INIT_THREADS 0
6310 #endif
6311 #endif
6312 """)
6314 #------------------------------------------------------------------------------------
6316 # Note that cPython ignores PyTrace_EXCEPTION,
6317 # but maybe some other profilers don't.
6319 profile_utility_code = UtilityCode(proto="""
6320 #ifndef CYTHON_PROFILE
6321 #define CYTHON_PROFILE 1
6322 #endif
6324 #ifndef CYTHON_PROFILE_REUSE_FRAME
6325 #define CYTHON_PROFILE_REUSE_FRAME 0
6326 #endif
6328 #if CYTHON_PROFILE
6330 #include "compile.h"
6331 #include "frameobject.h"
6332 #include "traceback.h"
6334 #if CYTHON_PROFILE_REUSE_FRAME
6335 #define CYTHON_FRAME_MODIFIER static
6336 #define CYTHON_FRAME_DEL
6337 #else
6338 #define CYTHON_FRAME_MODIFIER
6339 #define CYTHON_FRAME_DEL Py_DECREF(%(FRAME)s)
6340 #endif
6342 #define __Pyx_TraceDeclarations \\
6343 static PyCodeObject *%(FRAME_CODE)s = NULL; \\
6344 CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL; \\
6345 int __Pyx_use_tracing = 0;
6347 #define __Pyx_TraceCall(funcname, srcfile, firstlineno) \\
6348 if (unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc)) { \\
6349 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&%(FRAME_CODE)s, &%(FRAME)s, funcname, srcfile, firstlineno); \\
6350 }
6352 #define __Pyx_TraceException() \\
6353 if (unlikely(__Pyx_use_tracing( && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
6354 PyObject *exc_info = __Pyx_GetExceptionTuple(); \\
6355 if (exc_info) { \\
6356 PyThreadState_GET()->c_profilefunc( \\
6357 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_EXCEPTION, exc_info); \\
6358 Py_DECREF(exc_info); \\
6359 } \\
6360 }
6362 #define __Pyx_TraceReturn(result) \\
6363 if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
6364 PyThreadState_GET()->c_profilefunc( \\
6365 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_RETURN, (PyObject*)result); \\
6366 CYTHON_FRAME_DEL; \\
6367 }
6369 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
6370 static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
6372 #else
6374 #define __Pyx_TraceDeclarations
6375 #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
6376 #define __Pyx_TraceException()
6377 #define __Pyx_TraceReturn(result)
6379 #endif /* CYTHON_PROFILE */
6380 """
6381 % {
6382 "FRAME": Naming.frame_cname,
6383 "FRAME_CODE": Naming.frame_code_cname,
6384 },
6385 impl = """
6387 #if CYTHON_PROFILE
6389 static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
6390 PyFrameObject** frame,
6391 const char *funcname,
6392 const char *srcfile,
6393 int firstlineno) {
6394 if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) {
6395 if (*code == NULL) {
6396 *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
6397 if (*code == NULL) return 0;
6398 }
6399 *frame = PyFrame_New(
6400 PyThreadState_GET(), /*PyThreadState *tstate*/
6401 *code, /*PyCodeObject *code*/
6402 PyModule_GetDict(%(MODULE)s), /*PyObject *globals*/
6403 0 /*PyObject *locals*/
6404 );
6405 if (*frame == NULL) return 0;
6406 }
6407 else {
6408 (*frame)->f_tstate = PyThreadState_GET();
6409 }
6410 return PyThreadState_GET()->c_profilefunc(PyThreadState_GET()->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
6411 }
6413 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
6414 PyObject *py_srcfile = 0;
6415 PyObject *py_funcname = 0;
6416 PyCodeObject *py_code = 0;
6418 #if PY_MAJOR_VERSION < 3
6419 py_funcname = PyString_FromString(funcname);
6420 py_srcfile = PyString_FromString(srcfile);
6421 #else
6422 py_funcname = PyUnicode_FromString(funcname);
6423 py_srcfile = PyUnicode_FromString(srcfile);
6424 #endif
6425 if (!py_funcname | !py_srcfile) goto bad;
6427 py_code = PyCode_New(
6428 0, /*int argcount,*/
6429 #if PY_MAJOR_VERSION >= 3
6430 0, /*int kwonlyargcount,*/
6431 #endif
6432 0, /*int nlocals,*/
6433 0, /*int stacksize,*/
6434 0, /*int flags,*/
6435 %(EMPTY_BYTES)s, /*PyObject *code,*/
6436 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
6437 %(EMPTY_TUPLE)s, /*PyObject *names,*/
6438 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
6439 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
6440 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
6441 py_srcfile, /*PyObject *filename,*/
6442 py_funcname, /*PyObject *name,*/
6443 firstlineno, /*int firstlineno,*/
6444 %(EMPTY_BYTES)s /*PyObject *lnotab*/
6445 );
6447 bad:
6448 Py_XDECREF(py_srcfile);
6449 Py_XDECREF(py_funcname);
6451 return py_code;
6452 }
6454 #endif /* CYTHON_PROFILE */
6455 """ % {
6456 'EMPTY_TUPLE' : Naming.empty_tuple,
6457 'EMPTY_BYTES' : Naming.empty_bytes,
6458 "MODULE": Naming.module_cname,
6459 })
