Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 1673:5730e9a933ef

Fix for #196
author Magnus Lie Hetland
date Fri Jan 30 15:53:16 2009 +0100 (3 years ago)
parents 41ac022ba25c
children 61fa04659c77
line source
1 #
2 # Pyrex - Parse tree nodes
3 #
5 import string, sys, os, time, copy
7 import Code
8 import Builtin
9 from Errors import error, warning, InternalError
10 import Naming
11 import PyrexTypes
12 import TypeSlots
13 from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType
14 from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
15 StructOrUnionScope, PyClassScope, CClassScope
16 from Cython.Utils import open_new_file, replace_suffix, UtilityCode
17 from StringEncoding import EncodedString, escape_byte_string, split_docstring
18 import Options
19 import ControlFlow
20 import DebugFlags
22 from DebugFlags import debug_disposal_code
24 absolute_path_length = 0
26 def relative_position(pos):
27 """
28 We embed the relative filename in the generated C file, since we
29 don't want to have to regnerate and compile all the source code
30 whenever the Python install directory moves (which could happen,
31 e.g,. when distributing binaries.)
33 INPUT:
34 a position tuple -- (absolute filename, line number column position)
36 OUTPUT:
37 relative filename
38 line number
40 AUTHOR: William Stein
41 """
42 global absolute_path_length
43 if absolute_path_length==0:
44 absolute_path_length = len(os.path.abspath(os.getcwd()))
45 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
47 def embed_position(pos, docstring):
48 if not Options.embed_pos_in_docstring:
49 return docstring
50 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
51 if docstring is None:
52 # unicode string
53 return EncodedString(pos_line)
55 # make sure we can encode the filename in the docstring encoding
56 # otherwise make the docstring a unicode string
57 encoding = docstring.encoding
58 if encoding is not None:
59 try:
60 encoded_bytes = pos_line.encode(encoding)
61 except UnicodeEncodeError:
62 encoding = None
64 if not docstring:
65 # reuse the string encoding of the original docstring
66 doc = EncodedString(pos_line)
67 else:
68 doc = EncodedString(pos_line + u'\n' + docstring)
69 doc.encoding = encoding
70 return doc
73 from Code import CCodeWriter
74 from types import FunctionType
76 def write_func_call(func):
77 def f(*args, **kwds):
78 if len(args) > 1 and isinstance(args[1], CCodeWriter):
79 # here we annotate the code with this function call
80 # but only if new code is generated
81 node, code = args[:2]
82 marker = ' /* %s -> %s.%s %s */' % (
83 ' ' * code.call_level,
84 node.__class__.__name__,
85 func.__name__,
86 node.pos[1:])
87 pristine = code.buffer.stream.tell()
88 code.putln(marker)
89 start = code.buffer.stream.tell()
90 code.call_level += 4
91 res = func(*args, **kwds)
92 code.call_level -= 4
93 if start == code.buffer.stream.tell():
94 code.buffer.stream.seek(pristine)
95 else:
96 marker = marker.replace('->', '<-')
97 code.putln(marker)
98 return res
99 else:
100 return func(*args, **kwds)
101 return f
103 class VerboseCodeWriter(type):
104 # Set this as a metaclass to trace function calls in code.
105 # This slows down code generation and makes much larger files.
106 def __new__(cls, name, bases, attrs):
107 attrs = dict(attrs)
108 for mname, m in attrs.items():
109 if isinstance(m, FunctionType):
110 attrs[mname] = write_func_call(m)
111 return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
114 class Node(object):
115 # pos (string, int, int) Source file position
116 # is_name boolean Is a NameNode
117 # is_literal boolean Is a ConstNode
119 # Uncomment this for debugging.
120 # __metaclass__ = VerboseCodeWriter
122 is_name = 0
123 is_literal = 0
124 temps = None
126 # All descandants should set child_attrs to a list of the attributes
127 # containing nodes considered "children" in the tree. Each such attribute
128 # can either contain a single node or a list of nodes. See Visitor.py.
129 child_attrs = None
131 def __init__(self, pos, **kw):
132 self.pos = pos
133 self.__dict__.update(kw)
135 gil_message = "Operation"
137 def gil_check(self, env):
138 if env.nogil:
139 self.gil_error()
141 def gil_error(self):
142 error(self.pos, "%s not allowed without gil" % self.gil_message)
144 def clone_node(self):
145 """Clone the node. This is defined as a shallow copy, except for member lists
146 amongst the child attributes (from get_child_accessors) which are also
147 copied. Lists containing child nodes are thus seen as a way for the node
148 to hold multiple children directly; the list is not treated as a seperate
149 level in the tree."""
150 result = copy.copy(self)
151 for attrname in result.child_attrs:
152 value = getattr(result, attrname)
153 if isinstance(value, list):
154 setattr(result, attrname, [x for x in value])
155 return result
158 #
159 # There are 4 phases of parse tree processing, applied in order to
160 # all the statements in a given scope-block:
161 #
162 # (0) analyse_control_flow
163 # Create the control flow tree into which state can be asserted and
164 # queried.
165 #
166 # (1) analyse_declarations
167 # Make symbol table entries for all declarations at the current
168 # level, both explicit (def, cdef, etc.) and implicit (assignment
169 # to an otherwise undeclared name).
170 #
171 # (2) analyse_expressions
172 # Determine the result types of expressions and fill in the
173 # 'type' attribute of each ExprNode. Insert coercion nodes into the
174 # tree where needed to convert to and from Python objects.
175 # Allocate temporary locals for intermediate results. Fill
176 # in the 'result_code' attribute of each ExprNode with a C code
177 # fragment.
178 #
179 # (3) generate_code
180 # Emit C code for all declarations, statements and expressions.
181 # Recursively applies the 3 processing phases to the bodies of
182 # functions.
183 #
185 def analyse_control_flow(self, env):
186 pass
188 def analyse_declarations(self, env):
189 pass
191 def analyse_expressions(self, env):
192 raise InternalError("analyse_expressions not implemented for %s" % \
193 self.__class__.__name__)
195 def generate_code(self, code):
196 raise InternalError("generate_code not implemented for %s" % \
197 self.__class__.__name__)
199 def annotate(self, code):
200 # mro does the wrong thing
201 if isinstance(self, BlockNode):
202 self.body.annotate(code)
204 def end_pos(self):
205 try:
206 return self._end_pos
207 except AttributeError:
208 pos = self.pos
209 if not self.child_attrs:
210 self._end_pos = pos
211 return pos
212 for attr in self.child_attrs:
213 child = getattr(self, attr)
214 # Sometimes lists, sometimes nodes
215 if child is None:
216 pass
217 elif isinstance(child, list):
218 for c in child:
219 pos = max(pos, c.end_pos())
220 else:
221 pos = max(pos, child.end_pos())
222 self._end_pos = pos
223 return pos
225 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
226 if cutoff == 0:
227 return "<...nesting level cutoff...>"
228 if encountered is None:
229 encountered = set()
230 if id(self) in encountered:
231 return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
232 encountered.add(id(self))
234 def dump_child(x, level):
235 if isinstance(x, Node):
236 return x.dump(level, filter_out, cutoff-1, encountered)
237 elif isinstance(x, list):
238 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
239 else:
240 return repr(x)
243 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
244 if len(attrs) == 0:
245 return "<%s (%d)>" % (self.__class__.__name__, id(self))
246 else:
247 indent = " " * level
248 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
249 for key, value in attrs:
250 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
251 res += "%s>" % indent
252 return res
254 class CompilerDirectivesNode(Node):
255 """
256 Sets compiler directives for the children nodes
257 """
258 # directives {string:value} A dictionary holding the right value for
259 # *all* possible directives.
260 # body Node
261 child_attrs = ["body"]
263 def analyse_control_flow(self, env):
264 old = env.directives
265 env.directives = self.directives
266 self.body.analyse_control_flow(env)
267 env.directives = old
269 def analyse_declarations(self, env):
270 old = env.directives
271 env.directives = self.directives
272 self.body.analyse_declarations(env)
273 env.directives = old
275 def analyse_expressions(self, env):
276 old = env.directives
277 env.directives = self.directives
278 self.body.analyse_expressions(env)
279 env.directives = old
281 def generate_function_definitions(self, env, code):
282 env_old = env.directives
283 code_old = code.globalstate.directives
284 code.globalstate.directives = self.directives
285 self.body.generate_function_definitions(env, code)
286 env.directives = env_old
287 code.globalstate.directives = code_old
289 def generate_execution_code(self, code):
290 old = code.globalstate.directives
291 code.globalstate.directives = self.directives
292 self.body.generate_execution_code(code)
293 code.globalstate.directives = old
295 def annotate(self, code):
296 old = code.globalstate.directives
297 code.globalstate.directives = self.directives
298 self.body.annotate(code)
299 code.globalstate.directives = old
301 class BlockNode(object):
302 # Mixin class for nodes representing a declaration block.
304 def generate_const_definitions(self, env, code):
305 if env.const_entries:
306 for entry in env.const_entries:
307 if not entry.is_interned:
308 code.globalstate.add_const_definition(entry)
310 def generate_interned_string_decls(self, env, code):
311 entries = env.global_scope().new_interned_string_entries
312 if entries:
313 for entry in entries:
314 code.globalstate.add_interned_string_decl(entry)
315 del entries[:]
317 def generate_py_string_decls(self, env, code):
318 if env is None:
319 return # earlier error
320 entries = env.pystring_entries
321 if entries:
322 for entry in entries:
323 if not entry.is_interned:
324 code.globalstate.add_py_string_decl(entry)
326 def generate_interned_num_decls(self, env, code):
327 # Flush accumulated interned nums from the global scope
328 # and generate declarations for them.
329 genv = env.global_scope()
330 entries = genv.interned_nums
331 if entries:
332 for entry in entries:
333 code.globalstate.add_interned_num_decl(entry)
334 del entries[:]
336 def generate_cached_builtins_decls(self, env, code):
337 entries = env.global_scope().undeclared_cached_builtins
338 for entry in entries:
339 code.globalstate.add_cached_builtin_decl(entry)
340 del entries[:]
343 class StatListNode(Node):
344 # stats a list of StatNode
346 child_attrs = ["stats"]
348 def create_analysed(pos, env, *args, **kw):
349 node = StatListNode(pos, *args, **kw)
350 return node # No node-specific analysis necesarry
351 create_analysed = staticmethod(create_analysed)
353 def analyse_control_flow(self, env):
354 for stat in self.stats:
355 stat.analyse_control_flow(env)
357 def analyse_declarations(self, env):
358 #print "StatListNode.analyse_declarations" ###
359 for stat in self.stats:
360 stat.analyse_declarations(env)
362 def analyse_expressions(self, env):
363 #print "StatListNode.analyse_expressions" ###
364 for stat in self.stats:
365 stat.analyse_expressions(env)
367 def generate_function_definitions(self, env, code):
368 #print "StatListNode.generate_function_definitions" ###
369 for stat in self.stats:
370 stat.generate_function_definitions(env, code)
372 def generate_execution_code(self, code):
373 #print "StatListNode.generate_execution_code" ###
374 for stat in self.stats:
375 code.mark_pos(stat.pos)
376 stat.generate_execution_code(code)
378 def annotate(self, code):
379 for stat in self.stats:
380 stat.annotate(code)
383 class StatNode(Node):
384 #
385 # Code generation for statements is split into the following subphases:
386 #
387 # (1) generate_function_definitions
388 # Emit C code for the definitions of any structs,
389 # unions, enums and functions defined in the current
390 # scope-block.
391 #
392 # (2) generate_execution_code
393 # Emit C code for executable statements.
394 #
396 def generate_function_definitions(self, env, code):
397 pass
399 def generate_execution_code(self, code):
400 raise InternalError("generate_execution_code not implemented for %s" % \
401 self.__class__.__name__)
404 class CDefExternNode(StatNode):
405 # include_file string or None
406 # body StatNode
408 child_attrs = ["body"]
410 def analyse_declarations(self, env):
411 if self.include_file:
412 env.add_include_file(self.include_file)
413 old_cinclude_flag = env.in_cinclude
414 env.in_cinclude = 1
415 self.body.analyse_declarations(env)
416 env.in_cinclude = old_cinclude_flag
418 def analyse_expressions(self, env):
419 pass
421 def generate_execution_code(self, code):
422 pass
424 def annotate(self, code):
425 self.body.annotate(code)
428 class CDeclaratorNode(Node):
429 # Part of a C declaration.
430 #
431 # Processing during analyse_declarations phase:
432 #
433 # analyse
434 # Returns (name, type) pair where name is the
435 # CNameDeclaratorNode of the name being declared
436 # and type is the type it is being declared as.
437 #
438 # calling_convention string Calling convention of CFuncDeclaratorNode
439 # for which this is a base
441 child_attrs = []
443 calling_convention = ""
446 class CNameDeclaratorNode(CDeclaratorNode):
447 # name string The Pyrex name being declared
448 # cname string or None C name, if specified
449 # default ExprNode or None the value assigned on declaration
451 child_attrs = ['default']
453 default = None
455 def analyse(self, base_type, env, nonempty = 0):
456 if nonempty and self.name == '':
457 # May have mistaken the name for the type.
458 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
459 error(self.pos, "Missing argument name")
460 elif base_type.is_void:
461 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
462 else:
463 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
464 base_type = py_object_type
465 self.type = base_type
466 return self, base_type
468 class CPtrDeclaratorNode(CDeclaratorNode):
469 # base CDeclaratorNode
471 child_attrs = ["base"]
473 def analyse(self, base_type, env, nonempty = 0):
474 if base_type.is_pyobject:
475 error(self.pos,
476 "Pointer base type cannot be a Python object")
477 ptr_type = PyrexTypes.c_ptr_type(base_type)
478 return self.base.analyse(ptr_type, env, nonempty = nonempty)
480 class CArrayDeclaratorNode(CDeclaratorNode):
481 # base CDeclaratorNode
482 # dimension ExprNode
484 child_attrs = ["base", "dimension"]
486 def analyse(self, base_type, env, nonempty = 0):
487 if self.dimension:
488 self.dimension.analyse_const_expression(env)
489 if not self.dimension.type.is_int:
490 error(self.dimension.pos, "Array dimension not integer")
491 size = self.dimension.result()
492 try:
493 size = int(size)
494 except ValueError:
495 # runtime constant?
496 pass
497 else:
498 size = None
499 if not base_type.is_complete():
500 error(self.pos,
501 "Array element type '%s' is incomplete" % base_type)
502 if base_type.is_pyobject:
503 error(self.pos,
504 "Array element cannot be a Python object")
505 if base_type.is_cfunction:
506 error(self.pos,
507 "Array element cannot be a function")
508 array_type = PyrexTypes.c_array_type(base_type, size)
509 return self.base.analyse(array_type, env, nonempty = nonempty)
512 class CFuncDeclaratorNode(CDeclaratorNode):
513 # base CDeclaratorNode
514 # args [CArgDeclNode]
515 # has_varargs boolean
516 # exception_value ConstNode
517 # exception_check boolean True if PyErr_Occurred check needed
518 # nogil boolean Can be called without gil
519 # with_gil boolean Acquire gil around function body
521 child_attrs = ["base", "args", "exception_value"]
523 overridable = 0
524 optional_arg_count = 0
526 def analyse(self, return_type, env, nonempty = 0):
527 if nonempty:
528 nonempty -= 1
529 func_type_args = []
530 for arg_node in self.args:
531 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
532 name = name_declarator.name
533 if name_declarator.cname:
534 error(self.pos,
535 "Function argument cannot have C name specification")
536 # Turn *[] argument into **
537 if type.is_array:
538 type = PyrexTypes.c_ptr_type(type.base_type)
539 # Catch attempted C-style func(void) decl
540 if type.is_void:
541 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
542 # if type.is_pyobject and self.nogil:
543 # error(self.pos,
544 # "Function with Python argument cannot be declared nogil")
545 func_type_args.append(
546 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
547 if arg_node.default:
548 self.optional_arg_count += 1
549 elif self.optional_arg_count:
550 error(self.pos, "Non-default argument follows default argument")
552 if self.optional_arg_count:
553 scope = StructOrUnionScope()
554 scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
555 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
556 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
557 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
558 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
559 kind = 'struct',
560 scope = scope,
561 typedef_flag = 0,
562 pos = self.pos,
563 cname = struct_cname)
564 self.op_args_struct.defined_in_pxd = 1
565 self.op_args_struct.used = 1
567 exc_val = None
568 exc_check = 0
569 if return_type.is_pyobject \
570 and (self.exception_value or self.exception_check) \
571 and self.exception_check != '+':
572 error(self.pos,
573 "Exception clause not allowed for function returning Python object")
574 else:
575 if self.exception_value:
576 self.exception_value.analyse_const_expression(env)
577 if self.exception_check == '+':
578 exc_val_type = self.exception_value.type
579 if not exc_val_type.is_error and \
580 not exc_val_type.is_pyobject and \
581 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
582 error(self.exception_value.pos,
583 "Exception value must be a Python exception or cdef function with no arguments.")
584 exc_val = self.exception_value
585 else:
586 exc_val = self.exception_value.result()
587 if not return_type.assignable_from(self.exception_value.type):
588 error(self.exception_value.pos,
589 "Exception value incompatible with function return type")
590 exc_check = self.exception_check
591 if return_type.is_array:
592 error(self.pos,
593 "Function cannot return an array")
594 if return_type.is_cfunction:
595 error(self.pos,
596 "Function cannot return a function")
597 func_type = PyrexTypes.CFuncType(
598 return_type, func_type_args, self.has_varargs,
599 optional_arg_count = self.optional_arg_count,
600 exception_value = exc_val, exception_check = exc_check,
601 calling_convention = self.base.calling_convention,
602 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
603 if self.optional_arg_count:
604 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
605 return self.base.analyse(func_type, env)
608 class CArgDeclNode(Node):
609 # Item in a function declaration argument list.
610 #
611 # base_type CBaseTypeNode
612 # declarator CDeclaratorNode
613 # not_none boolean Tagged with 'not None'
614 # default ExprNode or None
615 # default_entry Symtab.Entry Entry for the variable holding the default value
616 # default_result_code string cname or code fragment for default value
617 # is_self_arg boolean Is the "self" arg of an extension type method
618 # is_kw_only boolean Is a keyword-only argument
620 child_attrs = ["base_type", "declarator", "default"]
622 is_self_arg = 0
623 is_generic = 1
624 type = None
625 name_declarator = None
627 def analyse(self, env, nonempty = 0):
628 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
629 if self.type is None:
630 # The parser may missinterpret names as types...
631 # We fix that here.
632 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
633 if nonempty:
634 self.declarator.name = self.base_type.name
635 self.base_type.name = None
636 self.base_type.is_basic_c_type = False
637 could_be_name = True
638 else:
639 could_be_name = False
640 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
641 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
642 self.declarator.name = self.base_type.arg_name
643 return self.declarator.analyse(base_type, env, nonempty = nonempty)
644 else:
645 return self.name_declarator, self.type
647 def annotate(self, code):
648 if self.default:
649 self.default.annotate(code)
652 class CBaseTypeNode(Node):
653 # Abstract base class for C base type nodes.
654 #
655 # Processing during analyse_declarations phase:
656 #
657 # analyse
658 # Returns the type.
660 pass
662 class CAnalysedBaseTypeNode(Node):
663 # type type
665 child_attrs = []
667 def analyse(self, env, could_be_name = False):
668 return self.type
670 class CSimpleBaseTypeNode(CBaseTypeNode):
671 # name string
672 # module_path [string] Qualifying name components
673 # is_basic_c_type boolean
674 # signed boolean
675 # longness integer
676 # is_self_arg boolean Is self argument of C method
678 child_attrs = []
679 arg_name = None # in case the argument name was interpreted as a type
681 def analyse(self, env, could_be_name = False):
682 # Return type descriptor.
683 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
684 type = None
685 if self.is_basic_c_type:
686 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
687 if not type:
688 error(self.pos, "Unrecognised type modifier combination")
689 elif self.name == "object" and not self.module_path:
690 type = py_object_type
691 elif self.name is None:
692 if self.is_self_arg and env.is_c_class_scope:
693 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
694 type = env.parent_type
695 else:
696 type = py_object_type
697 else:
698 if self.module_path:
699 scope = env.find_imported_module(self.module_path, self.pos)
700 else:
701 scope = env
702 if scope:
703 if scope.is_c_class_scope:
704 scope = scope.global_scope()
705 entry = scope.lookup(self.name)
706 if entry and entry.is_type:
707 type = entry.type
708 elif could_be_name:
709 if self.is_self_arg and env.is_c_class_scope:
710 type = env.parent_type
711 else:
712 type = py_object_type
713 self.arg_name = self.name
714 else:
715 error(self.pos, "'%s' is not a type identifier" % self.name)
716 if type:
717 return type
718 else:
719 return PyrexTypes.error_type
721 class CBufferAccessTypeNode(CBaseTypeNode):
722 # After parsing:
723 # positional_args [ExprNode] List of positional arguments
724 # keyword_args DictNode Keyword arguments
725 # base_type_node CBaseTypeNode
727 # After analysis:
728 # type PyrexType.BufferType ...containing the right options
731 child_attrs = ["base_type_node", "positional_args",
732 "keyword_args", "dtype_node"]
734 dtype_node = None
736 name = None
738 def analyse(self, env, could_be_name = False):
739 base_type = self.base_type_node.analyse(env)
740 if base_type.is_error: return base_type
741 import Buffer
743 options = Buffer.analyse_buffer_options(
744 self.pos,
745 env,
746 self.positional_args,
747 self.keyword_args,
748 base_type.buffer_defaults)
750 self.type = PyrexTypes.BufferType(base_type, **options)
751 return self.type
753 class CComplexBaseTypeNode(CBaseTypeNode):
754 # base_type CBaseTypeNode
755 # declarator CDeclaratorNode
757 child_attrs = ["base_type", "declarator"]
759 def analyse(self, env, could_be_name = False):
760 base = self.base_type.analyse(env, could_be_name)
761 _, type = self.declarator.analyse(base, env)
762 return type
765 class CVarDefNode(StatNode):
766 # C variable definition or forward/extern function declaration.
767 #
768 # visibility 'private' or 'public' or 'extern'
769 # base_type CBaseTypeNode
770 # declarators [CDeclaratorNode]
771 # in_pxd boolean
772 # api boolean
773 # need_properties [entry]
774 # pxd_locals [CVarDefNode] (used for functions declared in pxd)
776 child_attrs = ["base_type", "declarators"]
777 need_properties = ()
778 pxd_locals = []
780 def analyse_declarations(self, env, dest_scope = None):
781 if not dest_scope:
782 dest_scope = env
783 self.dest_scope = dest_scope
784 base_type = self.base_type.analyse(env)
785 if (dest_scope.is_c_class_scope
786 and self.visibility == 'public'
787 and base_type.is_pyobject
788 and (base_type.is_builtin_type or base_type.is_extension_type)):
789 self.need_properties = []
790 need_property = True
791 visibility = 'private'
792 else:
793 need_property = False
794 visibility = self.visibility
796 for declarator in self.declarators:
797 name_declarator, type = declarator.analyse(base_type, env)
798 if not type.is_complete():
799 if not (self.visibility == 'extern' and type.is_array):
800 error(declarator.pos,
801 "Variable type '%s' is incomplete" % type)
802 if self.visibility == 'extern' and type.is_pyobject:
803 error(declarator.pos,
804 "Python object cannot be declared extern")
805 name = name_declarator.name
806 cname = name_declarator.cname
807 if name == '':
808 error(declarator.pos, "Missing name in declaration.")
809 return
810 if type.is_cfunction:
811 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
812 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
813 api = self.api)
814 if entry is not None:
815 entry.pxd_locals = self.pxd_locals
816 else:
817 if self.in_pxd and self.visibility != 'extern':
818 error(self.pos,
819 "Only 'extern' C variable declaration allowed in .pxd file")
820 entry = dest_scope.declare_var(name, type, declarator.pos,
821 cname = cname, visibility = visibility, is_cdef = 1)
822 if need_property:
823 self.need_properties.append(entry)
824 entry.needs_property = 1
827 class CStructOrUnionDefNode(StatNode):
828 # name string
829 # cname string or None
830 # kind "struct" or "union"
831 # typedef_flag boolean
832 # visibility "public" or "private"
833 # in_pxd boolean
834 # attributes [CVarDefNode] or None
835 # entry Entry
837 child_attrs = ["attributes"]
839 def analyse_declarations(self, env):
840 scope = None
841 if self.attributes is not None:
842 scope = StructOrUnionScope(self.name)
843 self.entry = env.declare_struct_or_union(
844 self.name, self.kind, scope, self.typedef_flag, self.pos,
845 self.cname, visibility = self.visibility)
846 if self.attributes is not None:
847 if self.in_pxd and not env.in_cinclude:
848 self.entry.defined_in_pxd = 1
849 for attr in self.attributes:
850 attr.analyse_declarations(env, scope)
851 if self.visibility != 'extern':
852 need_typedef_indirection = False
853 for attr in scope.var_entries:
854 type = attr.type
855 while type.is_array:
856 type = type.base_type
857 if type == self.entry.type:
858 error(attr.pos, "Struct cannot contain itself as a member.")
859 if self.typedef_flag:
860 while type.is_ptr:
861 type = type.base_type
862 if type == self.entry.type:
863 need_typedef_indirection = True
864 if need_typedef_indirection:
865 # C can't handle typedef structs that refer to themselves.
866 struct_entry = self.entry
867 cname = env.new_const_cname()
868 self.entry = env.declare_typedef(self.name, struct_entry.type, self.pos, cname = self.cname, visibility='ignore')
869 struct_entry.type.typedef_flag = False
870 struct_entry.cname = struct_entry.type.cname = env.new_const_cname()
872 def analyse_expressions(self, env):
873 pass
875 def generate_execution_code(self, code):
876 pass
879 class CEnumDefNode(StatNode):
880 # name string or None
881 # cname string or None
882 # items [CEnumDefItemNode]
883 # typedef_flag boolean
884 # visibility "public" or "private"
885 # in_pxd boolean
886 # entry Entry
888 child_attrs = ["items"]
890 def analyse_declarations(self, env):
891 self.entry = env.declare_enum(self.name, self.pos,
892 cname = self.cname, typedef_flag = self.typedef_flag,
893 visibility = self.visibility)
894 if self.items is not None:
895 if self.in_pxd and not env.in_cinclude:
896 self.entry.defined_in_pxd = 1
897 for item in self.items:
898 item.analyse_declarations(env, self.entry)
900 def analyse_expressions(self, env):
901 if self.visibility == 'public':
902 self.temp = env.allocate_temp_pyobject()
903 env.release_temp(self.temp)
905 def generate_execution_code(self, code):
906 if self.visibility == 'public':
907 for item in self.entry.enum_values:
908 code.putln("%s = PyInt_FromLong(%s); %s" % (
909 self.temp,
910 item.cname,
911 code.error_goto_if_null(self.temp, item.pos)))
912 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
913 Naming.module_cname,
914 item.name,
915 self.temp,
916 code.error_goto(item.pos)))
917 code.putln("%s = 0;" % self.temp)
920 class CEnumDefItemNode(StatNode):
921 # name string
922 # cname string or None
923 # value ExprNode or None
925 child_attrs = ["value"]
927 def analyse_declarations(self, env, enum_entry):
928 if self.value:
929 self.value.analyse_const_expression(env)
930 if not self.value.type.is_int:
931 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
932 self.value.analyse_const_expression(env)
933 value = self.value.result()
934 else:
935 value = self.name
936 entry = env.declare_const(self.name, enum_entry.type,
937 value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
938 enum_entry.enum_values.append(entry)
941 class CTypeDefNode(StatNode):
942 # base_type CBaseTypeNode
943 # declarator CDeclaratorNode
944 # visibility "public" or "private"
945 # in_pxd boolean
947 child_attrs = ["base_type", "declarator"]
949 def analyse_declarations(self, env):
950 base = self.base_type.analyse(env)
951 name_declarator, type = self.declarator.analyse(base, env)
952 name = name_declarator.name
953 cname = name_declarator.cname
954 entry = env.declare_typedef(name, type, self.pos,
955 cname = cname, visibility = self.visibility)
956 if self.in_pxd and not env.in_cinclude:
957 entry.defined_in_pxd = 1
959 def analyse_expressions(self, env):
960 pass
961 def generate_execution_code(self, code):
962 pass
965 class FuncDefNode(StatNode, BlockNode):
966 # Base class for function definition nodes.
967 #
968 # return_type PyrexType
969 # #filename string C name of filename string const
970 # entry Symtab.Entry
971 # needs_closure boolean Whether or not this function has inner functions/classes/yield
972 # pxd_locals [CVarDefNode] locals defined in the pxd
974 py_func = None
975 assmt = None
976 needs_closure = False
977 pxd_locals = []
979 def analyse_default_values(self, env):
980 genv = env.global_scope()
981 for arg in self.args:
982 if arg.default:
983 if arg.is_generic:
984 if not hasattr(arg, 'default_entry'):
985 arg.default.analyse_types(env)
986 arg.default = arg.default.coerce_to(arg.type, genv)
987 if arg.default.is_literal:
988 arg.default_entry = arg.default
989 arg.default_result_code = arg.default.calculate_result_code()
990 if arg.default.type != arg.type and not arg.type.is_int:
991 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
992 else:
993 arg.default.allocate_temps(genv)
994 arg.default_entry = genv.add_default_value(arg.type)
995 arg.default_entry.used = 1
996 arg.default_result_code = arg.default_entry.cname
997 else:
998 error(arg.pos,
999 "This argument cannot have a default value")
1000 arg.default = None
1002 def need_gil_acquisition(self, lenv):
1003 return 0
1005 def create_local_scope(self, env):
1006 genv = env
1007 while env.is_py_class_scope or env.is_c_class_scope:
1008 env = env.outer_scope
1009 if self.needs_closure:
1010 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
1011 else:
1012 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
1013 lenv.return_type = self.return_type
1014 type = self.entry.type
1015 if type.is_cfunction:
1016 lenv.nogil = type.nogil and not type.with_gil
1017 self.local_scope = lenv
1018 return lenv
1020 def generate_function_definitions(self, env, code):
1021 import Buffer
1023 lenv = self.local_scope
1025 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1026 self.entry.scope.is_c_class_scope)
1028 # Generate C code for header and body of function
1029 code.enter_cfunc_scope()
1030 code.return_from_error_cleanup_label = code.new_label()
1032 # ----- Top-level constants used by this function
1033 code.mark_pos(self.pos)
1034 self.generate_interned_num_decls(lenv, code)
1035 self.generate_interned_string_decls(lenv, code)
1036 self.generate_py_string_decls(lenv, code)
1037 self.generate_cached_builtins_decls(lenv, code)
1038 #code.putln("")
1039 #code.put_var_declarations(lenv.const_entries, static = 1)
1040 self.generate_const_definitions(lenv, code)
1041 # ----- Function header
1042 code.putln("")
1043 if self.py_func:
1044 self.py_func.generate_function_header(code,
1045 with_pymethdef = env.is_py_class_scope,
1046 proto_only=True)
1047 self.generate_function_header(code,
1048 with_pymethdef = env.is_py_class_scope)
1049 # ----- Local variable declarations
1050 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
1051 self.generate_argument_declarations(lenv, code)
1052 if self.needs_closure:
1053 code.putln("/* TODO: declare and create scope object */")
1054 code.put_var_declarations(lenv.var_entries)
1055 init = ""
1056 if not self.return_type.is_void:
1057 code.putln(
1058 "%s%s;" %
1059 (self.return_type.declaration_code(
1060 Naming.retval_cname),
1061 init))
1062 tempvardecl_code = code.insertion_point()
1063 self.generate_keyword_list(code)
1064 # ----- Extern library function declarations
1065 lenv.generate_library_function_declarations(code)
1066 # ----- GIL acquisition
1067 acquire_gil = self.need_gil_acquisition(lenv)
1068 if acquire_gil:
1069 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1070 # ----- Automatic lead-ins for certain special functions
1071 if not lenv.nogil:
1072 code.put_setup_refcount_context(self.entry.name)
1073 if is_getbuffer_slot:
1074 self.getbuffer_init(code)
1075 # ----- Fetch arguments
1076 self.generate_argument_parsing_code(env, code)
1077 # If an argument is assigned to in the body, we must
1078 # incref it to properly keep track of refcounts.
1079 for entry in lenv.arg_entries:
1080 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1081 code.put_var_incref(entry)
1082 # ----- Initialise local variables
1083 for entry in lenv.var_entries:
1084 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1085 code.put_init_var_to_py_none(entry)
1086 # ----- Initialise local buffer auxiliary variables
1087 for entry in lenv.var_entries + lenv.arg_entries:
1088 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1089 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1090 # ----- Check and convert arguments
1091 self.generate_argument_type_tests(code)
1092 # ----- Acquire buffer arguments
1093 for entry in lenv.arg_entries:
1094 if entry.type.is_buffer:
1095 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1096 # ----- Function body
1097 self.body.generate_execution_code(code)
1098 # ----- Default return value
1099 code.putln("")
1100 if self.return_type.is_pyobject:
1101 #if self.return_type.is_extension_type:
1102 # lhs = "(PyObject *)%s" % Naming.retval_cname
1103 #else:
1104 lhs = Naming.retval_cname
1105 code.put_init_to_py_none(lhs, self.return_type)
1106 else:
1107 val = self.return_type.default_value
1108 if val:
1109 code.putln("%s = %s;" % (Naming.retval_cname, val))
1110 # ----- Error cleanup
1111 if code.error_label in code.labels_used:
1112 code.put_goto(code.return_label)
1113 code.put_label(code.error_label)
1114 # cleanup temps the old way
1115 code.put_var_xdecrefs(lenv.temp_entries)
1116 # cleanup temps the new way
1117 for cname, type in code.funcstate.all_managed_temps():
1118 code.put_xdecref(cname, type)
1120 # Clean up buffers -- this calls a Python function
1121 # so need to save and restore error state
1122 buffers_present = len(lenv.buffer_entries) > 0
1123 if buffers_present:
1124 code.globalstate.use_utility_code(restore_exception_utility_code)
1125 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1126 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1127 for entry in lenv.buffer_entries:
1128 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1129 #code.putln("%s = 0;" % entry.cname)
1130 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1132 err_val = self.error_value()
1133 exc_check = self.caller_will_check_exceptions()
1134 if err_val is not None or exc_check:
1135 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1136 else:
1137 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1138 % self.entry.qualified_name, 0)
1139 code.putln(
1140 '__Pyx_WriteUnraisable("%s");' %
1141 self.entry.qualified_name)
1142 env.use_utility_code(unraisable_exception_utility_code)
1143 env.use_utility_code(restore_exception_utility_code)
1144 default_retval = self.return_type.default_value
1145 if err_val is None and default_retval:
1146 err_val = default_retval
1147 if err_val is not None:
1148 code.putln(
1149 "%s = %s;" % (
1150 Naming.retval_cname,
1151 err_val))
1153 if is_getbuffer_slot:
1154 self.getbuffer_error_cleanup(code)
1156 # If we are using the non-error cleanup section we should
1157 # jump past it if we have an error. The if-test below determine
1158 # whether this section is used.
1159 if buffers_present or is_getbuffer_slot:
1160 code.put_goto(code.return_from_error_cleanup_label)
1163 # ----- Non-error return cleanup
1164 # If you add anything here, remember to add a condition to the
1165 # if-test above in the error block (so that it can jump past this
1166 # block).
1167 code.put_label(code.return_label)
1168 for entry in lenv.buffer_entries:
1169 if entry.used:
1170 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1171 if is_getbuffer_slot:
1172 self.getbuffer_normal_cleanup(code)
1173 # ----- Return cleanup for both error and no-error return
1174 code.put_label(code.return_from_error_cleanup_label)
1175 if not Options.init_local_none:
1176 for entry in lenv.var_entries:
1177 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1178 entry.xdecref_cleanup = 1
1179 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1180 # Decref any increfed args
1181 for entry in lenv.arg_entries:
1182 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1183 code.put_var_decref(entry)
1184 if acquire_gil:
1185 code.putln("PyGILState_Release(_save);")
1186 # code.putln("/* TODO: decref scope object */")
1187 # ----- Return
1188 # This code is duplicated in ModuleNode.generate_module_init_func
1189 if not lenv.nogil:
1190 default_retval = self.return_type.default_value
1191 err_val = self.error_value()
1192 if err_val is None and default_retval:
1193 err_val = default_retval
1194 if self.return_type.is_pyobject:
1195 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1197 code.put_finish_refcount_context(self.pos,
1198 self.entry.qualified_name,
1199 Naming.retval_cname,
1200 err_val)
1202 if not self.return_type.is_void:
1203 code.putln("return %s;" % Naming.retval_cname)
1205 code.putln("}")
1206 # ----- Go back and insert temp variable declarations
1207 tempvardecl_code.put_var_declarations(lenv.temp_entries)
1208 tempvardecl_code.put_temp_declarations(code.funcstate)
1209 # ----- Python version
1210 code.exit_cfunc_scope()
1211 if self.py_func:
1212 self.py_func.generate_function_definitions(env, code)
1213 self.generate_wrapper_functions(code)
1215 def declare_argument(self, env, arg):
1216 if arg.type.is_void:
1217 error(arg.pos, "Invalid use of 'void'")
1218 elif not arg.type.is_complete() and not arg.type.is_array:
1219 error(arg.pos,
1220 "Argument type '%s' is incomplete" % arg.type)
1221 return env.declare_arg(arg.name, arg.type, arg.pos)
1223 def generate_wrapper_functions(self, code):
1224 pass
1226 def generate_execution_code(self, code):
1227 # Evaluate and store argument default values
1228 for arg in self.args:
1229 default = arg.default
1230 if default:
1231 if not default.is_literal:
1232 default.generate_evaluation_code(code)
1233 default.make_owned_reference(code)
1234 code.putln(
1235 "%s = %s;" % (
1236 arg.default_entry.cname,
1237 default.result_as(arg.default_entry.type)))
1238 if default.is_temp and default.type.is_pyobject:
1239 code.putln(
1240 "%s = 0;" %
1241 default.result())
1242 default.free_temps(code)
1243 # For Python class methods, create and store function object
1244 if self.assmt:
1245 self.assmt.generate_execution_code(code)
1248 # Special code for the __getbuffer__ function
1250 def getbuffer_init(self, code):
1251 info = self.local_scope.arg_entries[1].cname
1252 # Python 3.0 betas have a bug in memoryview which makes it call
1253 # getbuffer with a NULL parameter. For now we work around this;
1254 # the following line should be removed when this bug is fixed.
1255 code.putln("if (%s == NULL) return 0;" % info)
1256 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1257 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1259 def getbuffer_error_cleanup(self, code):
1260 info = self.local_scope.arg_entries[1].cname
1261 code.put_gotref("%s->obj" % info)
1262 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1263 (info, info))
1265 def getbuffer_normal_cleanup(self, code):
1266 info = self.local_scope.arg_entries[1].cname
1267 code.putln("if (%s->obj == Py_None) {" % info)
1268 code.put_gotref("Py_None")
1269 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1270 code.putln("}")
1272 class CFuncDefNode(FuncDefNode):
1273 # C function definition.
1275 # modifiers ['inline']
1276 # visibility 'private' or 'public' or 'extern'
1277 # base_type CBaseTypeNode
1278 # declarator CDeclaratorNode
1279 # body StatListNode
1280 # api boolean
1282 # with_gil boolean Acquire GIL around body
1283 # type CFuncType
1284 # py_func wrapper for calling from Python
1285 # overridable whether or not this is a cpdef function
1286 # inline_in_pxd whether this is an inline function in a pxd file
1288 child_attrs = ["base_type", "declarator", "body", "py_func"]
1290 inline_in_pxd = False
1292 def unqualified_name(self):
1293 return self.entry.name
1295 def analyse_declarations(self, env):
1296 if 'locals' in env.directives:
1297 directive_locals = env.directives['locals']
1298 else:
1299 directive_locals = {}
1300 self.directive_locals = directive_locals
1301 base_type = self.base_type.analyse(env)
1302 # The 2 here is because we need both function and argument names.
1303 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1304 if not type.is_cfunction:
1305 error(self.pos,
1306 "Suite attached to non-function declaration")
1307 # Remember the actual type according to the function header
1308 # written here, because the type in the symbol table entry
1309 # may be different if we're overriding a C method inherited
1310 # from the base type of an extension type.
1311 self.type = type
1312 type.is_overridable = self.overridable
1313 declarator = self.declarator
1314 while not hasattr(declarator, 'args'):
1315 declarator = declarator.base
1316 self.args = declarator.args
1317 for formal_arg, type_arg in zip(self.args, type.args):
1318 formal_arg.type = type_arg.type
1319 formal_arg.name = type_arg.name
1320 formal_arg.cname = type_arg.cname
1321 name = name_declarator.name
1322 cname = name_declarator.cname
1323 self.entry = env.declare_cfunction(
1324 name, type, self.pos,
1325 cname = cname, visibility = self.visibility,
1326 defining = self.body is not None,
1327 api = self.api, modifiers = self.modifiers)
1328 self.entry.inline_func_in_pxd = self.inline_in_pxd
1329 self.return_type = type.return_type
1331 if self.overridable:
1332 import ExprNodes
1333 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1334 self.py_func = DefNode(pos = self.pos,
1335 name = self.entry.name,
1336 args = self.args,
1337 star_arg = None,
1338 starstar_arg = None,
1339 doc = self.doc,
1340 body = py_func_body,
1341 is_wrapper = 1)
1342 self.py_func.is_module_scope = env.is_module_scope
1343 self.py_func.analyse_declarations(env)
1344 self.entry.as_variable = self.py_func.entry
1345 # Reset scope entry the above cfunction
1346 env.entries[name] = self.entry
1347 self.py_func.interned_attr_cname = env.intern_identifier(
1348 self.py_func.entry.name)
1349 if not env.is_module_scope or Options.lookup_module_cpdef:
1350 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1351 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1353 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1354 import ExprNodes
1355 args = self.type.args
1356 if omit_optional_args:
1357 args = args[:len(args) - self.type.optional_arg_count]
1358 arg_names = [arg.name for arg in args]
1359 if is_module_scope:
1360 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1361 else:
1362 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1363 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1364 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1365 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)
1366 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1368 def declare_arguments(self, env):
1369 for arg in self.type.args:
1370 if not arg.name:
1371 error(arg.pos, "Missing argument name")
1372 self.declare_argument(env, arg)
1374 def need_gil_acquisition(self, lenv):
1375 type = self.type
1376 with_gil = self.type.with_gil
1377 if type.nogil and not with_gil:
1378 if type.return_type.is_pyobject:
1379 error(self.pos,
1380 "Function with Python return type cannot be declared nogil")
1381 for entry in lenv.var_entries + lenv.temp_entries:
1382 if entry.type.is_pyobject:
1383 error(self.pos, "Function declared nogil has Python locals or temporaries")
1384 return with_gil
1386 def analyse_expressions(self, env):
1387 self.analyse_default_values(env)
1388 if self.overridable:
1389 self.py_func.analyse_expressions(env)
1391 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1392 arg_decls = []
1393 type = self.type
1394 visibility = self.entry.visibility
1395 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1396 arg_decls.append(arg.declaration_code())
1397 if with_dispatch and self.overridable:
1398 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1399 if type.optional_arg_count and with_opt_args:
1400 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1401 if type.has_varargs:
1402 arg_decls.append("...")
1403 if not arg_decls:
1404 arg_decls = ["void"]
1405 if cname is None:
1406 cname = self.entry.func_cname
1407 entity = type.function_header_code(cname, string.join(arg_decls, ", "))
1408 if visibility == 'public':
1409 dll_linkage = "DL_EXPORT"
1410 else:
1411 dll_linkage = None
1412 header = self.return_type.declaration_code(entity,
1413 dll_linkage = dll_linkage)
1414 if visibility == 'extern':
1415 storage_class = "%s " % Naming.extern_c_macro
1416 elif visibility == 'public':
1417 storage_class = ""
1418 else:
1419 storage_class = "static "
1420 code.putln("%s%s %s {" % (
1421 storage_class,
1422 ' '.join(self.modifiers).upper(), # macro forms
1423 header))
1425 def generate_argument_declarations(self, env, code):
1426 for arg in self.args:
1427 if arg.default:
1428 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1430 def generate_keyword_list(self, code):
1431 pass
1433 def generate_argument_parsing_code(self, env, code):
1434 i = 0
1435 if self.type.optional_arg_count:
1436 code.putln('if (%s) {' % Naming.optional_args_cname)
1437 for arg in self.args:
1438 if arg.default:
1439 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1440 declarator = arg.declarator
1441 while not hasattr(declarator, 'name'):
1442 declarator = declarator.base
1443 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1444 i += 1
1445 for _ in range(self.type.optional_arg_count):
1446 code.putln('}')
1447 code.putln('}')
1449 def generate_argument_conversion_code(self, code):
1450 pass
1452 def generate_argument_type_tests(self, code):
1453 # Generate type tests for args whose type in a parent
1454 # class is a supertype of the declared type.
1455 for arg in self.type.args:
1456 if arg.needs_type_test:
1457 self.generate_arg_type_test(arg, code)
1459 def generate_arg_type_test(self, arg, code):
1460 # Generate type test for one argument.
1461 if arg.type.typeobj_is_available():
1462 typeptr_cname = arg.type.typeptr_cname
1463 arg_code = "((PyObject *)%s)" % arg.cname
1464 code.putln(
1465 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1466 arg_code,
1467 typeptr_cname,
1468 not arg.not_none,
1469 arg.name,
1470 type.is_builtin_type,
1471 code.error_goto(arg.pos)))
1472 else:
1473 error(arg.pos, "Cannot test type of extern C class "
1474 "without type object name specification")
1476 def error_value(self):
1477 if self.return_type.is_pyobject:
1478 return "0"
1479 else:
1480 #return None
1481 return self.entry.type.exception_value
1483 def caller_will_check_exceptions(self):
1484 return self.entry.type.exception_check
1486 def generate_wrapper_functions(self, code):
1487 # If the C signature of a function has changed, we need to generate
1488 # wrappers to put in the slots here.
1489 k = 0
1490 entry = self.entry
1491 func_type = entry.type
1492 while entry.prev_entry is not None:
1493 k += 1
1494 entry = entry.prev_entry
1495 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1496 code.putln()
1497 self.generate_function_header(code,
1498 0,
1499 with_dispatch = entry.type.is_overridable,
1500 with_opt_args = entry.type.optional_arg_count,
1501 cname = entry.func_cname)
1502 if not self.return_type.is_void:
1503 code.put('return ')
1504 args = self.type.args
1505 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1506 if entry.type.is_overridable:
1507 arglist.append(Naming.skip_dispatch_cname)
1508 elif func_type.is_overridable:
1509 arglist.append('0')
1510 if entry.type.optional_arg_count:
1511 arglist.append(Naming.optional_args_cname)
1512 elif func_type.optional_arg_count:
1513 arglist.append('NULL')
1514 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1515 code.putln('}')
1518 class PyArgDeclNode(Node):
1519 # Argument which must be a Python object (used
1520 # for * and ** arguments).
1522 # name string
1523 # entry Symtab.Entry
1524 child_attrs = []
1527 class DecoratorNode(Node):
1528 # A decorator
1530 # decorator NameNode or CallNode
1531 child_attrs = ['decorator']
1534 class DefNode(FuncDefNode):
1535 # A Python function definition.
1537 # name string the Python name of the function
1538 # decorators [DecoratorNode] list of decorators
1539 # args [CArgDeclNode] formal arguments
1540 # star_arg PyArgDeclNode or None * argument
1541 # starstar_arg PyArgDeclNode or None ** argument
1542 # doc EncodedString or None
1543 # body StatListNode
1545 # The following subnode is constructed internally
1546 # when the def statement is inside a Python class definition.
1548 # assmt AssignmentNode Function construction/assignment
1550 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1552 assmt = None
1553 num_kwonly_args = 0
1554 num_required_kw_args = 0
1555 reqd_kw_flags_cname = "0"
1556 is_wrapper = 0
1557 decorators = None
1558 entry = None
1561 def __init__(self, pos, **kwds):
1562 FuncDefNode.__init__(self, pos, **kwds)
1563 k = rk = r = 0
1564 for arg in self.args:
1565 if arg.kw_only:
1566 k += 1
1567 if not arg.default:
1568 rk += 1
1569 if not arg.default:
1570 r += 1
1571 self.num_kwonly_args = k
1572 self.num_required_kw_args = rk
1573 self.num_required_args = r
1575 def as_cfunction(self, cfunc=None, scope=None):
1576 if self.star_arg:
1577 error(self.star_arg.pos, "cdef function cannot have star argument")
1578 if self.starstar_arg:
1579 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1580 if cfunc is None:
1581 cfunc_args = []
1582 for formal_arg in self.args:
1583 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1584 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1585 cname = None,
1586 type = py_object_type,
1587 pos = formal_arg.pos))
1588 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1589 args = cfunc_args,
1590 has_varargs = False,
1591 exception_value = None,
1592 exception_check = False,
1593 nogil = False,
1594 with_gil = False,
1595 is_overridable = True)
1596 cfunc = CVarDefNode(self.pos, type=cfunc_type, pxd_locals=[])
1597 else:
1598 cfunc_type = cfunc.type
1599 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1600 error(self.pos, "wrong number of arguments")
1601 error(declarator.pos, "previous declaration here")
1602 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1603 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1604 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1605 formal_arg.type = type_arg.type
1606 formal_arg.name_declarator = name_declarator
1607 import ExprNodes
1608 if cfunc_type.exception_value is None:
1609 exception_value = None
1610 else:
1611 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1612 declarator = CFuncDeclaratorNode(self.pos,
1613 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1614 args = self.args,
1615 has_varargs = False,
1616 exception_check = cfunc_type.exception_check,
1617 exception_value = exception_value,
1618 with_gil = cfunc_type.with_gil,
1619 nogil = cfunc_type.nogil)
1620 return CFuncDefNode(self.pos,
1621 modifiers = [],
1622 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1623 declarator = declarator,
1624 body = self.body,
1625 doc = self.doc,
1626 overridable = cfunc_type.is_overridable,
1627 type = cfunc_type,
1628 with_gil = cfunc_type.with_gil,
1629 nogil = cfunc_type.nogil,
1630 visibility = 'private',
1631 api = False,
1632 pxd_locals = cfunc.pxd_locals)
1634 def analyse_declarations(self, env):
1635 if 'locals' in env.directives:
1636 directive_locals = env.directives['locals']
1637 else:
1638 directive_locals = {}
1639 self.directive_locals = directive_locals
1640 for arg in self.args:
1641 if hasattr(arg, 'name'):
1642 type = arg.type
1643 name_declarator = None
1644 else:
1645 base_type = arg.base_type.analyse(env)
1646 name_declarator, type = \
1647 arg.declarator.analyse(base_type, env)
1648 arg.name = name_declarator.name
1649 if arg.name in directive_locals:
1650 type_node = directive_locals[arg.name]
1651 other_type = type_node.analyse_as_type(env)
1652 if other_type is None:
1653 error(type_node.pos, "Not a type")
1654 elif (type is not PyrexTypes.py_object_type
1655 and not type.same_as(other_type)):
1656 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1657 error(type_node.pos, "Previous declaration here")
1658 else:
1659 type = other_type
1660 if name_declarator and name_declarator.cname:
1661 error(self.pos,
1662 "Python function argument cannot have C name specification")
1663 arg.type = type.as_argument_type()
1664 arg.hdr_type = None
1665 arg.needs_conversion = 0
1666 arg.needs_type_test = 0
1667 arg.is_generic = 1
1668 if arg.not_none and not arg.type.is_extension_type:
1669 error(self.pos,
1670 "Only extension type arguments can have 'not None'")
1671 self.declare_pyfunction(env)
1672 self.analyse_signature(env)
1673 self.return_type = self.entry.signature.return_type()
1675 def analyse_signature(self, env):
1676 any_type_tests_needed = 0
1677 # Use the simpler calling signature for zero- and one-argument functions.
1678 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1679 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1680 if len(self.args) == 0:
1681 self.entry.signature = TypeSlots.pyfunction_noargs
1682 elif len(self.args) == 1:
1683 if self.args[0].default is None and not self.args[0].kw_only:
1684 self.entry.signature = TypeSlots.pyfunction_onearg
1685 elif self.entry.signature is TypeSlots.pymethod_signature:
1686 if len(self.args) == 1:
1687 self.entry.signature = TypeSlots.unaryfunc
1688 elif len(self.args) == 2:
1689 if self.args[1].default is None and not self.args[1].kw_only:
1690 self.entry.signature = TypeSlots.ibinaryfunc
1691 elif self.entry.is_special:
1692 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1693 sig = self.entry.signature
1694 nfixed = sig.num_fixed_args()
1695 for i in range(nfixed):
1696 if i < len(self.args):
1697 arg = self.args[i]
1698 arg.is_generic = 0
1699 if sig.is_self_arg(i):
1700 arg.is_self_arg = 1
1701 arg.hdr_type = arg.type = env.parent_type
1702 arg.needs_conversion = 0
1703 else:
1704 arg.hdr_type = sig.fixed_arg_type(i)
1705 if not arg.type.same_as(arg.hdr_type):
1706 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1707 arg.needs_type_test = 1
1708 any_type_tests_needed = 1
1709 else:
1710 arg.needs_conversion = 1
1711 if arg.needs_conversion:
1712 arg.hdr_cname = Naming.arg_prefix + arg.name
1713 else:
1714 arg.hdr_cname = Naming.var_prefix + arg.name
1715 else:
1716 self.bad_signature()
1717 return
1718 if nfixed < len(self.args):
1719 if not sig.has_generic_args:
1720 self.bad_signature()
1721 for arg in self.args:
1722 if arg.is_generic and \
1723 (arg.type.is_extension_type or arg.type.is_builtin_type):
1724 arg.needs_type_test = 1
1725 any_type_tests_needed = 1
1726 elif arg.type is PyrexTypes.c_py_ssize_t_type:
1727 # Want to use __index__ rather than __int__ method
1728 # that PyArg_ParseTupleAndKeywords calls
1729 arg.needs_conversion = 1
1730 arg.hdr_type = PyrexTypes.py_object_type
1731 arg.hdr_cname = Naming.arg_prefix + arg.name
1732 if any_type_tests_needed:
1733 env.use_utility_code(arg_type_test_utility_code)
1735 def bad_signature(self):
1736 sig = self.entry.signature
1737 expected_str = "%d" % sig.num_fixed_args()
1738 if sig.has_generic_args:
1739 expected_str = expected_str + " or more"
1740 name = self.name
1741 if name.startswith("__") and name.endswith("__"):
1742 desc = "Special method"
1743 else:
1744 desc = "Method"
1745 error(self.pos,
1746 "%s %s has wrong number of arguments "
1747 "(%d declared, %s expected)" % (
1748 desc, self.name, len(self.args), expected_str))
1750 def signature_has_nongeneric_args(self):
1751 argcount = len(self.args)
1752 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1753 return 0
1754 return 1
1756 def signature_has_generic_args(self):
1757 return self.entry.signature.has_generic_args
1759 def declare_pyfunction(self, env):
1760 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1761 name = self.name
1762 entry = env.lookup_here(self.name)
1763 if entry and entry.type.is_cfunction and not self.is_wrapper:
1764 warning(self.pos, "Overriding cdef method with def method.", 5)
1765 entry = env.declare_pyfunction(self.name, self.pos)
1766 self.entry = entry
1767 prefix = env.scope_prefix
1768 entry.func_cname = \
1769 Naming.pyfunc_prefix + prefix + name
1770 entry.pymethdef_cname = \
1771 Naming.pymethdef_prefix + prefix + name
1772 if Options.docstrings:
1773 entry.doc = embed_position(self.pos, self.doc)
1774 entry.doc_cname = \
1775 Naming.funcdoc_prefix + prefix + name
1776 else:
1777 entry.doc = None
1779 def declare_arguments(self, env):
1780 for arg in self.args:
1781 if not arg.name:
1782 error(arg.pos, "Missing argument name")
1783 if arg.needs_conversion:
1784 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1785 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1786 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1787 if arg.type.is_pyobject:
1788 arg.entry.init = "0"
1789 arg.entry.init_to_none = 0
1790 else:
1791 arg.entry = self.declare_argument(env, arg)
1792 arg.entry.used = 1
1793 arg.entry.is_self_arg = arg.is_self_arg
1794 if not arg.is_self_arg:
1795 arg.name_entry = env.get_string_const(
1796 arg.name, identifier = True)
1797 env.add_py_string(arg.name_entry, identifier = True)
1798 if arg.hdr_type:
1799 if arg.is_self_arg or \
1800 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1801 arg.entry.is_declared_generic = 1
1802 self.declare_python_arg(env, self.star_arg)
1803 self.declare_python_arg(env, self.starstar_arg)
1805 def declare_python_arg(self, env, arg):
1806 if arg:
1807 entry = env.declare_var(arg.name,
1808 PyrexTypes.py_object_type, arg.pos)
1809 entry.used = 1
1810 entry.init = "0"
1811 entry.init_to_none = 0
1812 entry.xdecref_cleanup = 1
1813 arg.entry = entry
1814 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1816 def analyse_expressions(self, env):
1817 self.analyse_default_values(env)
1818 if env.is_py_class_scope:
1819 self.synthesize_assignment_node(env)
1821 def synthesize_assignment_node(self, env):
1822 import ExprNodes
1823 self.assmt = SingleAssignmentNode(self.pos,
1824 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1825 rhs = ExprNodes.UnboundMethodNode(self.pos,
1826 class_cname = env.class_obj_cname,
1827 function = ExprNodes.PyCFunctionNode(self.pos,
1828 pymethdef_cname = self.entry.pymethdef_cname)))
1829 self.assmt.analyse_declarations(env)
1830 self.assmt.analyse_expressions(env)
1832 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1833 arg_code_list = []
1834 sig = self.entry.signature
1835 if sig.has_dummy_arg:
1836 arg_code_list.append(
1837 "PyObject *%s" % Naming.self_cname)
1838 for arg in self.args:
1839 if not arg.is_generic:
1840 if arg.is_self_arg:
1841 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1842 else:
1843 arg_code_list.append(
1844 arg.hdr_type.declaration_code(arg.hdr_cname))
1845 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1846 arg_code_list.append("PyObject *unused")
1847 if sig.has_generic_args:
1848 arg_code_list.append(
1849 "PyObject *%s, PyObject *%s"
1850 % (Naming.args_cname, Naming.kwds_cname))
1851 arg_code = ", ".join(arg_code_list)
1852 dc = self.return_type.declaration_code(self.entry.func_cname)
1853 header = "static %s(%s)" % (dc, arg_code)
1854 code.putln("%s; /*proto*/" % header)
1855 if proto_only:
1856 return
1857 if self.entry.doc and Options.docstrings:
1858 docstr = self.entry.doc
1859 if not isinstance(docstr, str):
1860 docstr = docstr.utf8encode()
1861 code.putln(
1862 'static char %s[] = "%s";' % (
1863 self.entry.doc_cname,
1864 split_docstring(escape_byte_string(docstr))))
1865 if with_pymethdef:
1866 code.put(
1867 "static PyMethodDef %s = " %
1868 self.entry.pymethdef_cname)
1869 code.put_pymethoddef(self.entry, ";")
1870 code.putln("%s {" % header)
1872 def generate_argument_declarations(self, env, code):
1873 for arg in self.args:
1874 if arg.is_generic: # or arg.needs_conversion:
1875 if arg.needs_conversion:
1876 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1877 else:
1878 code.put_var_declaration(arg.entry)
1880 def generate_keyword_list(self, code):
1881 if self.signature_has_generic_args() and \
1882 self.signature_has_nongeneric_args():
1883 code.put(
1884 "static PyObject **%s[] = {" %
1885 Naming.pykwdlist_cname)
1886 for arg in self.args:
1887 if arg.is_generic:
1888 code.put('&%s,' % arg.name_entry.pystring_cname)
1889 code.putln("0};")
1891 def generate_argument_parsing_code(self, env, code):
1892 # Generate PyArg_ParseTuple call for generic
1893 # arguments, if any.
1894 if self.entry.signature.has_dummy_arg:
1895 # get rid of unused argument warning
1896 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1898 old_error_label = code.new_error_label()
1899 our_error_label = code.error_label
1900 end_label = code.new_label("argument_unpacking_done")
1902 has_kwonly_args = self.num_kwonly_args > 0
1903 has_star_or_kw_args = self.star_arg is not None \
1904 or self.starstar_arg is not None or has_kwonly_args
1906 if not self.signature_has_generic_args():
1907 if has_star_or_kw_args:
1908 error(self.pos, "This method cannot have * or keyword arguments")
1909 self.generate_argument_conversion_code(code)
1911 elif not self.signature_has_nongeneric_args():
1912 # func(*args) or func(**kw) or func(*args, **kw)
1913 self.generate_stararg_copy_code(code)
1915 else:
1916 positional_args = []
1917 kw_only_args = []
1918 default_seen = 0
1919 for arg in self.args:
1920 arg_entry = arg.entry
1921 if arg.is_generic:
1922 if arg.default:
1923 default_seen = 1
1924 if not arg.is_self_arg:
1925 if arg.kw_only:
1926 kw_only_args.append(arg)
1927 else:
1928 positional_args.append(arg)
1929 elif arg.kw_only:
1930 kw_only_args.append(arg)
1931 default_seen = 1
1932 elif default_seen:
1933 error(arg.pos, "Non-default argument following default argument")
1934 elif not arg.is_self_arg:
1935 positional_args.append(arg)
1936 if arg.needs_conversion:
1937 format = arg.hdr_type.parsetuple_format
1938 else:
1939 format = arg_entry.type.parsetuple_format
1940 if not format:
1941 error(arg.pos,
1942 "Cannot convert Python object argument to type '%s' (when parsing input arguments)"
1943 % arg.type)
1945 self.generate_tuple_and_keyword_parsing_code(
1946 positional_args, kw_only_args, end_label, code)
1948 code.error_label = old_error_label
1949 if code.label_used(our_error_label):
1950 if not code.label_used(end_label):
1951 code.put_goto(end_label)
1952 code.put_label(our_error_label)
1953 if has_star_or_kw_args:
1954 self.generate_arg_decref(self.star_arg, code)
1955 if self.starstar_arg:
1956 if self.starstar_arg.entry.xdecref_cleanup:
1957 code.put_var_xdecref(self.starstar_arg.entry)
1958 else:
1959 code.put_var_decref(self.starstar_arg.entry)
1960 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1961 code.putln("return %s;" % self.error_value())
1962 if code.label_used(end_label):
1963 code.put_label(end_label)
1965 def generate_arg_assignment(self, arg, item, code):
1966 if arg.type.is_pyobject:
1967 if arg.is_generic:
1968 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1969 code.putln("%s = %s;" % (arg.entry.cname, item))
1970 else:
1971 func = arg.type.from_py_function
1972 if func:
1973 code.putln("%s = %s(%s); %s" % (
1974 arg.entry.cname,
1975 func,
1976 item,
1977 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1978 else:
1979 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1981 def generate_arg_xdecref(self, arg, code):
1982 if arg:
1983 code.put_var_xdecref(arg.entry)
1985 def generate_arg_decref(self, arg, code):
1986 if arg:
1987 code.put_var_decref(arg.entry)
1989 def generate_stararg_copy_code(self, code):
1990 if not self.star_arg:
1991 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1992 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1993 Naming.args_cname)
1994 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
1995 self.name.utf8encode(), Naming.args_cname, self.error_value()))
1996 code.putln("}")
1998 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2000 if self.starstar_arg:
2001 if self.star_arg:
2002 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2003 else:
2004 kwarg_check = "%s" % Naming.kwds_cname
2005 else:
2006 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2007 Naming.kwds_cname, Naming.kwds_cname)
2008 code.putln(
2009 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2010 kwarg_check, Naming.kwds_cname, self.name,
2011 bool(self.starstar_arg), self.error_value()))
2013 if self.starstar_arg:
2014 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2015 self.starstar_arg.entry.cname,
2016 Naming.kwds_cname,
2017 Naming.kwds_cname))
2018 code.putln("if (unlikely(!%s)) return %s;" % (
2019 self.starstar_arg.entry.cname, self.error_value()))
2020 self.starstar_arg.entry.xdecref_cleanup = 0
2021 code.put_gotref(self.starstar_arg.entry.cname)
2024 if self.star_arg:
2025 code.put_incref(Naming.args_cname, py_object_type)
2026 code.putln("%s = %s;" % (
2027 self.star_arg.entry.cname,
2028 Naming.args_cname))
2029 self.star_arg.entry.xdecref_cleanup = 0
2031 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2032 kw_only_args, success_label, code):
2033 argtuple_error_label = code.new_label("argtuple_error")
2035 min_positional_args = self.num_required_args - self.num_required_kw_args
2036 if len(self.args) > 0 and self.args[0].is_self_arg:
2037 min_positional_args -= 1
2038 max_positional_args = len(positional_args)
2039 has_fixed_positional_count = not self.star_arg and \
2040 min_positional_args == max_positional_args
2042 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2043 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2044 if self.num_required_kw_args:
2045 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2047 if self.starstar_arg or self.star_arg:
2048 self.generate_stararg_init_code(max_positional_args, code)
2050 # --- optimised code when we receive keyword arguments
2051 if self.num_required_kw_args:
2052 likely_hint = "likely"
2053 else:
2054 likely_hint = "unlikely"
2055 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2056 self.generate_keyword_unpacking_code(
2057 min_positional_args, max_positional_args,
2058 has_fixed_positional_count,
2059 positional_args, kw_only_args, argtuple_error_label, code)
2061 # --- optimised code when we do not receive any keyword arguments
2062 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2063 # Python raises arg tuple related errors first, so we must
2064 # check the length here
2065 if min_positional_args == max_positional_args and not self.star_arg:
2066 compare = '!='
2067 else:
2068 compare = '<'
2069 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2070 Naming.args_cname, compare, min_positional_args))
2071 code.put_goto(argtuple_error_label)
2073 if self.num_required_kw_args:
2074 # pure error case: keywords required but not passed
2075 if max_positional_args > min_positional_args and not self.star_arg:
2076 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2077 Naming.args_cname, max_positional_args))
2078 code.put_goto(argtuple_error_label)
2079 code.putln('} else {')
2080 for i, arg in enumerate(kw_only_args):
2081 if not arg.default:
2082 # required keyword-only argument missing
2083 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2084 self.name.utf8encode(),
2085 arg.name_entry.pystring_cname))
2086 code.putln(code.error_goto(self.pos))
2087 break
2089 elif min_positional_args == max_positional_args:
2090 # parse the exact number of positional arguments from the
2091 # args tuple
2092 code.putln('} else {')
2093 for i, arg in enumerate(positional_args):
2094 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2095 self.generate_arg_assignment(arg, item, code)
2096 self.generate_arg_default_assignments(code)
2098 else:
2099 # parse the positional arguments from the variable length
2100 # args tuple
2101 code.putln('} else {')
2102 self.generate_arg_default_assignments(code)
2103 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2104 if self.star_arg:
2105 code.putln('default:')
2106 reversed_args = list(enumerate(positional_args))[::-1]
2107 for i, arg in reversed_args:
2108 if i >= min_positional_args-1:
2109 if min_positional_args > 1:
2110 code.putln('case %2d:' % (i+1)) # pure code beautification
2111 else:
2112 code.put('case %2d: ' % (i+1))
2113 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2114 self.generate_arg_assignment(arg, item, code)
2115 if min_positional_args == 0:
2116 code.put('case 0: ')
2117 code.putln('break;')
2118 if self.star_arg:
2119 if min_positional_args:
2120 for i in range(min_positional_args-1, -1, -1):
2121 code.putln('case %2d:' % i)
2122 code.put_goto(argtuple_error_label)
2123 else:
2124 code.put('default: ')
2125 code.put_goto(argtuple_error_label)
2126 code.putln('}')
2128 code.putln('}')
2130 if code.label_used(argtuple_error_label):
2131 code.put_goto(success_label)
2132 code.put_label(argtuple_error_label)
2133 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2134 self.name.utf8encode(), has_fixed_positional_count,
2135 min_positional_args, max_positional_args,
2136 Naming.args_cname))
2137 code.putln(code.error_goto(self.pos))
2139 def generate_arg_default_assignments(self, code):
2140 for arg in self.args:
2141 if arg.is_generic and arg.default:
2142 code.putln(
2143 "%s = %s;" % (
2144 arg.entry.cname,
2145 arg.default_result_code))
2147 def generate_stararg_init_code(self, max_positional_args, code):
2148 if self.starstar_arg:
2149 self.starstar_arg.entry.xdecref_cleanup = 0
2150 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2151 self.starstar_arg.entry.cname,
2152 self.starstar_arg.entry.cname,
2153 self.error_value()))
2154 code.put_gotref(self.starstar_arg.entry.cname)
2155 if self.star_arg:
2156 self.star_arg.entry.xdecref_cleanup = 0
2157 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2158 Naming.args_cname,
2159 max_positional_args))
2160 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2161 self.star_arg.entry.cname, Naming.args_cname,
2162 max_positional_args, Naming.args_cname))
2163 code.put_gotref(self.star_arg.entry.cname)
2164 if self.starstar_arg:
2165 code.putln("")
2166 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2167 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2168 code.putln('return %s;' % self.error_value())
2169 code.putln('}')
2170 else:
2171 code.putln("if (unlikely(!%s)) return %s;" % (
2172 self.star_arg.entry.cname, self.error_value()))
2173 code.putln('} else {')
2174 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2175 code.put_incref(Naming.empty_tuple, py_object_type)
2176 code.putln('}')
2178 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2179 has_fixed_positional_count, positional_args,
2180 kw_only_args, argtuple_error_label, code):
2181 all_args = tuple(positional_args) + tuple(kw_only_args)
2182 max_args = len(all_args)
2184 default_args = []
2185 for arg in all_args:
2186 if arg.default and arg.type.is_pyobject:
2187 default_value = arg.default_result_code
2188 if arg.type is not PyrexTypes.py_object_type:
2189 default_value = "(PyObject*)"+default_value
2190 default_args.append(default_value)
2191 else:
2192 default_args.append('0')
2193 code.putln("PyObject* values[%d] = {%s};" % (
2194 max_args, ', '.join(default_args)))
2195 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2196 Naming.kwds_cname)
2198 # parse the tuple and check that it's not too long
2199 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2200 if self.star_arg:
2201 code.putln('default:')
2202 for i in range(max_positional_args-1, -1, -1):
2203 code.put('case %2d: ' % (i+1))
2204 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2205 i, Naming.args_cname, i))
2206 code.putln('case 0: break;')
2207 if not self.star_arg:
2208 code.put('default: ') # more arguments than allowed
2209 code.put_goto(argtuple_error_label)
2210 code.putln('}')
2212 # now fill up the required arguments with values from the kw dict
2213 if self.num_required_args:
2214 last_required_arg = -1
2215 for i, arg in enumerate(all_args):
2216 if not arg.default:
2217 last_required_arg = i
2218 if max_positional_args > 0:
2219 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2220 for i, arg in enumerate(all_args[:last_required_arg+1]):
2221 if max_positional_args > 0 and i <= max_positional_args:
2222 if self.star_arg and i == max_positional_args:
2223 code.putln('default:')
2224 else:
2225 code.putln('case %2d:' % i)
2226 if arg.default:
2227 # handled in ParseOptionalKeywords() below
2228 continue
2229 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2230 i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2231 code.putln('if (likely(values[%d])) kw_args--;' % i);
2232 if i < min_positional_args:
2233 if i == 0:
2234 # special case: we know arg 0 is missing
2235 code.put('else ')
2236 code.put_goto(argtuple_error_label)
2237 else:
2238 # print the correct number of values (args or
2239 # kwargs) that were passed into positional
2240 # arguments up to this point
2241 code.putln('else {')
2242 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2243 self.name.utf8encode(), has_fixed_positional_count,
2244 min_positional_args, max_positional_args, i))
2245 code.putln(code.error_goto(self.pos))
2246 code.putln('}')
2247 elif arg.kw_only:
2248 code.putln('else {')
2249 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2250 self.name.utf8encode(), arg.name_entry.pystring_cname))
2251 code.putln(code.error_goto(self.pos))
2252 code.putln('}')
2253 if max_positional_args > 0:
2254 code.putln('}')
2256 code.putln('if (unlikely(kw_args > 0)) {')
2257 # non-positional/-required kw args left in dict: default args, **kwargs or error
2258 if max_positional_args == 0:
2259 pos_arg_count = "0"
2260 elif self.star_arg:
2261 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2262 Naming.args_cname, max_positional_args,
2263 Naming.args_cname, max_positional_args))
2264 pos_arg_count = "used_pos_args"
2265 else:
2266 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2267 code.globalstate.use_utility_code(parse_keywords_utility_code)
2268 code.put(
2269 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2270 Naming.kwds_cname,
2271 Naming.pykwdlist_cname,
2272 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2273 pos_arg_count,
2274 self.name.utf8encode()))
2275 code.putln(code.error_goto(self.pos))
2276 code.putln('}')
2278 # convert arg values to their final type and assign them
2279 for i, arg in enumerate(all_args):
2280 if arg.default and not arg.type.is_pyobject:
2281 code.putln("if (values[%d]) {" % i)
2282 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2283 if arg.default and not arg.type.is_pyobject:
2284 code.putln('} else {')
2285 code.putln(
2286 "%s = %s;" % (
2287 arg.entry.cname,
2288 arg.default_result_code))
2289 code.putln('}')
2291 def generate_argument_conversion_code(self, code):
2292 # Generate code to convert arguments from
2293 # signature type to declared type, if needed.
2294 for arg in self.args:
2295 if arg.needs_conversion:
2296 self.generate_arg_conversion(arg, code)
2298 def generate_arg_conversion(self, arg, code):
2299 # Generate conversion code for one argument.
2300 old_type = arg.hdr_type
2301 new_type = arg.type
2302 if old_type.is_pyobject:
2303 if arg.default:
2304 code.putln("if (%s) {" % arg.hdr_cname)
2305 else:
2306 code.putln("assert(%s); {" % arg.hdr_cname)
2307 self.generate_arg_conversion_from_pyobject(arg, code)
2308 code.putln("}")
2309 elif new_type.is_pyobject:
2310 self.generate_arg_conversion_to_pyobject(arg, code)
2311 else:
2312 if new_type.assignable_from(old_type):
2313 code.putln(
2314 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2315 else:
2316 error(arg.pos,
2317 "Cannot convert 1 argument from '%s' to '%s'" %
2318 (old_type, new_type))
2320 def generate_arg_conversion_from_pyobject(self, arg, code):
2321 new_type = arg.type
2322 func = new_type.from_py_function
2323 # copied from CoerceFromPyTypeNode
2324 if func:
2325 code.putln("%s = %s(%s); %s" % (
2326 arg.entry.cname,
2327 func,
2328 arg.hdr_cname,
2329 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2330 else:
2331 error(arg.pos,
2332 "Cannot convert Python object argument to type '%s'"
2333 % new_type)
2335 def generate_arg_conversion_to_pyobject(self, arg, code):
2336 old_type = arg.hdr_type
2337 func = old_type.to_py_function
2338 if func:
2339 code.putln("%s = %s(%s); %s" % (
2340 arg.entry.cname,
2341 func,
2342 arg.hdr_cname,
2343 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2344 code.put_var_gotref(arg.entry)
2345 else:
2346 error(arg.pos,
2347 "Cannot convert argument of type '%s' to Python object"
2348 % old_type)
2350 def generate_argument_type_tests(self, code):
2351 # Generate type tests for args whose signature
2352 # type is PyObject * and whose declared type is
2353 # a subtype thereof.
2354 for arg in self.args:
2355 if arg.needs_type_test:
2356 self.generate_arg_type_test(arg, code)
2358 def generate_arg_type_test(self, arg, code):
2359 # Generate type test for one argument.
2360 if arg.type.typeobj_is_available():
2361 typeptr_cname = arg.type.typeptr_cname
2362 arg_code = "((PyObject *)%s)" % arg.entry.cname
2363 code.putln(
2364 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2365 arg_code,
2366 typeptr_cname,
2367 not arg.not_none,
2368 arg.name,
2369 arg.type.is_builtin_type,
2370 code.error_goto(arg.pos)))
2371 else:
2372 error(arg.pos, "Cannot test type of extern C class "
2373 "without type object name specification")
2375 def error_value(self):
2376 return self.entry.signature.error_value
2378 def caller_will_check_exceptions(self):
2379 return 1
2381 class OverrideCheckNode(StatNode):
2382 # A Node for dispatching to the def method if it
2383 # is overriden.
2385 # py_func
2387 # args
2388 # func_temp
2389 # body
2391 child_attrs = ['body']
2393 body = None
2395 def analyse_expressions(self, env):
2396 self.args = env.arg_entries
2397 if self.py_func.is_module_scope:
2398 first_arg = 0
2399 else:
2400 first_arg = 1
2401 import ExprNodes
2402 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2403 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2404 call_node = ExprNodes.SimpleCallNode(self.pos,
2405 function=self.func_node,
2406 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2407 self.body = ReturnStatNode(self.pos, value=call_node)
2408 self.body.analyse_expressions(env)
2410 def generate_execution_code(self, code):
2411 # Check to see if we are an extension type
2412 if self.py_func.is_module_scope:
2413 self_arg = "((PyObject *)%s)" % Naming.module_cname
2414 else:
2415 self_arg = "((PyObject *)%s)" % self.args[0].cname
2416 code.putln("/* Check if called by wrapper */")
2417 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2418 code.putln("/* Check if overriden in Python */")
2419 if self.py_func.is_module_scope:
2420 code.putln("else {")
2421 else:
2422 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2423 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2424 code.put_gotref(self.func_node.py_result())
2425 # need to get attribute manually--scope would return cdef method
2426 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2427 # It appears that this type is not anywhere exposed in the Python/C API
2428 is_builtin_function_or_method = '(strcmp(Py_TYPE(%s)->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result()
2429 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2430 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2431 self.body.generate_execution_code(code)
2432 code.putln('}')
2433 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2434 code.putln("}")
2436 class ClassDefNode(StatNode, BlockNode):
2437 pass
2439 class PyClassDefNode(ClassDefNode):
2440 # A Python class definition.
2442 # name EncodedString Name of the class
2443 # doc string or None
2444 # body StatNode Attribute definition code
2445 # entry Symtab.Entry
2446 # scope PyClassScope
2448 # The following subnodes are constructed internally:
2450 # dict DictNode Class dictionary
2451 # classobj ClassNode Class object
2452 # target NameNode Variable to assign class object to
2454 child_attrs = ["body", "dict", "classobj", "target"]
2456 def __init__(self, pos, name, bases, doc, body):
2457 StatNode.__init__(self, pos)
2458 self.name = name
2459 self.doc = doc
2460 self.body = body
2461 import ExprNodes
2462 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2463 if self.doc and Options.docstrings:
2464 doc = embed_position(self.pos, self.doc)
2465 doc_node = ExprNodes.StringNode(pos, value = doc)
2466 else:
2467 doc_node = None
2468 self.classobj = ExprNodes.ClassNode(pos, name = name,
2469 bases = bases, dict = self.dict, doc = doc_node)
2470 self.target = ExprNodes.NameNode(pos, name = name)
2472 def as_cclass(self):
2473 """
2474 Return this node as if it were declared as an extension class
2475 """
2476 bases = self.classobj.bases.args
2477 if len(bases) == 0:
2478 base_class_name = None
2479 base_class_module = None
2480 elif len(bases) == 1:
2481 base = bases[0]
2482 path = []
2483 from ExprNodes import AttributeNode, NameNode
2484 while isinstance(base, AttributeNode):
2485 path.insert(0, base.attribute)
2486 base = base.obj
2487 if isinstance(base, NameNode):
2488 path.insert(0, base.name)
2489 base_class_name = path[-1]
2490 if len(path) > 1:
2491 base_class_module = u'.'.join(path[:-1])
2492 else:
2493 base_class_module = None
2494 else:
2495 error(self.classobj.bases.args.pos, "Invalid base class")
2496 else:
2497 error(self.classobj.bases.args.pos, "C class may only have one base class")
2498 return None
2500 return CClassDefNode(self.pos,
2501 visibility = 'private',
2502 module_name = None,
2503 class_name = self.name,
2504 base_class_module = base_class_module,
2505 base_class_name = base_class_name,
2506 body = self.body,
2507 in_pxd = False,
2508 doc = self.doc)
2510 def create_scope(self, env):
2511 genv = env
2512 while env.is_py_class_scope or env.is_c_class_scope:
2513 env = env.outer_scope
2514 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2515 return cenv
2517 def analyse_declarations(self, env):
2518 self.target.analyse_target_declaration(env)
2519 cenv = self.create_scope(env)
2520 cenv.class_obj_cname = self.target.entry.cname
2521 self.body.analyse_declarations(cenv)
2523 def analyse_expressions(self, env):
2524 self.dict.analyse_expressions(env)
2525 self.classobj.analyse_expressions(env)
2526 genv = env.global_scope()
2527 cenv = self.scope
2528 cenv.class_dict_cname = self.dict.result()
2529 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2530 self.body.analyse_expressions(cenv)
2531 self.target.analyse_target_expression(env, self.classobj)
2532 self.dict.release_temp(env)
2533 #self.classobj.release_temp(env)
2534 #self.target.release_target_temp(env)
2536 def generate_function_definitions(self, env, code):
2537 self.generate_py_string_decls(self.scope, code)
2538 self.body.generate_function_definitions(self.scope, code)
2540 def generate_execution_code(self, code):
2541 self.dict.generate_evaluation_code(code)
2542 self.classobj.generate_evaluation_code(code)
2543 self.body.generate_execution_code(code)
2544 self.target.generate_assignment_code(self.classobj, code)
2545 self.dict.generate_disposal_code(code)
2546 self.dict.free_temps(code)
2549 class CClassDefNode(ClassDefNode):
2550 # An extension type definition.
2552 # visibility 'private' or 'public' or 'extern'
2553 # typedef_flag boolean
2554 # api boolean
2555 # module_name string or None For import of extern type objects
2556 # class_name string Unqualified name of class
2557 # as_name string or None Name to declare as in this scope
2558 # base_class_module string or None Module containing the base class
2559 # base_class_name string or None Name of the base class
2560 # objstruct_name string or None Specified C name of object struct
2561 # typeobj_name string or None Specified C name of type object
2562 # in_pxd boolean Is in a .pxd file
2563 # doc string or None
2564 # body StatNode or None
2565 # entry Symtab.Entry
2566 # base_type PyExtensionType or None
2567 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2568 # buffer_defaults_pos
2570 child_attrs = ["body"]
2571 buffer_defaults_node = None
2572 buffer_defaults_pos = None
2573 typedef_flag = False
2574 api = False
2575 objstruct_name = None
2576 typeobj_name = None
2578 def analyse_declarations(self, env):
2579 #print "CClassDefNode.analyse_declarations:", self.class_name
2580 #print "...visibility =", self.visibility
2581 #print "...module_name =", self.module_name
2583 import Buffer
2584 if self.buffer_defaults_node:
2585 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2586 env, [], self.buffer_defaults_node,
2587 need_complete=False)
2588 else:
2589 buffer_defaults = None
2591 if env.in_cinclude and not self.objstruct_name:
2592 error(self.pos, "Object struct name specification required for "
2593 "C class defined in 'extern from' block")
2594 self.base_type = None
2595 # Now that module imports are cached, we need to
2596 # import the modules for extern classes.
2597 if self.module_name:
2598 self.module = None
2599 for module in env.cimported_modules:
2600 if module.name == self.module_name:
2601 self.module = module
2602 if self.module is None:
2603 self.module = ModuleScope(self.module_name, None, env.context)
2604 self.module.has_extern_class = 1
2605 env.add_imported_module(self.module)
2607 if self.base_class_name:
2608 if self.base_class_module:
2609 base_class_scope = env.find_module(self.base_class_module, self.pos)
2610 else:
2611 base_class_scope = env
2612 if self.base_class_name == 'object':
2613 # extension classes are special and don't need to inherit from object
2614 if base_class_scope is None or base_class_scope.lookup('object') is None:
2615 self.base_class_name = None
2616 self.base_class_module = None
2617 base_class_scope = None
2618 if base_class_scope:
2619 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2620 if base_class_entry:
2621 if not base_class_entry.is_type:
2622 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2623 elif not base_class_entry.type.is_extension_type:
2624 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2625 elif not base_class_entry.type.is_complete():
2626 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2627 else:
2628 self.base_type = base_class_entry.type
2629 has_body = self.body is not None
2630 if self.module_name and self.visibility != 'extern':
2631 module_path = self.module_name.split(".")
2632 home_scope = env.find_imported_module(module_path, self.pos)
2633 if not home_scope:
2634 return
2635 else:
2636 home_scope = env
2637 self.entry = home_scope.declare_c_class(
2638 name = self.class_name,
2639 pos = self.pos,
2640 defining = has_body and self.in_pxd,
2641 implementing = has_body and not self.in_pxd,
2642 module_name = self.module_name,
2643 base_type = self.base_type,
2644 objstruct_cname = self.objstruct_name,
2645 typeobj_cname = self.typeobj_name,
2646 visibility = self.visibility,
2647 typedef_flag = self.typedef_flag,
2648 api = self.api,
2649 buffer_defaults = buffer_defaults)
2650 if home_scope is not env and self.visibility == 'extern':
2651 env.add_imported_entry(self.class_name, self.entry, pos)
2652 scope = self.entry.type.scope
2654 if self.doc and Options.docstrings:
2655 scope.doc = embed_position(self.pos, self.doc)
2657 if has_body:
2658 self.body.analyse_declarations(scope)
2659 if self.in_pxd:
2660 scope.defined = 1
2661 else:
2662 scope.implemented = 1
2663 env.allocate_vtable_names(self.entry)
2665 def analyse_expressions(self, env):
2666 if self.body:
2667 scope = self.entry.type.scope
2668 self.body.analyse_expressions(scope)
2670 def generate_function_definitions(self, env, code):
2671 self.generate_py_string_decls(self.entry.type.scope, code)
2672 if self.body:
2673 self.body.generate_function_definitions(
2674 self.entry.type.scope, code)
2676 def generate_execution_code(self, code):
2677 # This is needed to generate evaluation code for
2678 # default values of method arguments.
2679 if self.body:
2680 self.body.generate_execution_code(code)
2682 def annotate(self, code):
2683 if self.body:
2684 self.body.annotate(code)
2687 class PropertyNode(StatNode):
2688 # Definition of a property in an extension type.
2690 # name string
2691 # doc EncodedString or None Doc string
2692 # body StatListNode
2694 child_attrs = ["body"]
2696 def analyse_declarations(self, env):
2697 entry = env.declare_property(self.name, self.doc, self.pos)
2698 if entry:
2699 if self.doc and Options.docstrings:
2700 doc_entry = env.get_string_const(
2701 self.doc, identifier = False)
2702 entry.doc_cname = doc_entry.cname
2703 self.body.analyse_declarations(entry.scope)
2705 def analyse_expressions(self, env):
2706 self.body.analyse_expressions(env)
2708 def generate_function_definitions(self, env, code):
2709 self.body.generate_function_definitions(env, code)
2711 def generate_execution_code(self, code):
2712 pass
2714 def annotate(self, code):
2715 self.body.annotate(code)
2718 class GlobalNode(StatNode):
2719 # Global variable declaration.
2721 # names [string]
2723 child_attrs = []
2725 def analyse_declarations(self, env):
2726 for name in self.names:
2727 env.declare_global(name, self.pos)
2729 def analyse_expressions(self, env):
2730 pass
2732 def generate_execution_code(self, code):
2733 pass
2736 class ExprStatNode(StatNode):
2737 # Expression used as a statement.
2739 # expr ExprNode
2741 child_attrs = ["expr"]
2743 def analyse_declarations(self, env):
2744 import ExprNodes
2745 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2746 func = self.expr.function.as_cython_attribute()
2747 if func == u'declare':
2748 args, kwds = self.expr.explicit_args_kwds()
2749 if len(args):
2750 error(self.expr.pos, "Variable names must be specified.")
2751 for var, type_node in kwds.key_value_pairs:
2752 type = type_node.analyse_as_type(env)
2753 if type is None:
2754 error(type_node.pos, "Unknown type")
2755 else:
2756 env.declare_var(var.value, type, var.pos, is_cdef = True)
2757 self.__class__ = PassStatNode
2759 def analyse_expressions(self, env):
2760 self.expr.analyse_expressions(env)
2761 self.expr.release_temp(env)
2763 def generate_execution_code(self, code):
2764 self.expr.generate_evaluation_code(code)
2765 if not self.expr.is_temp and self.expr.result():
2766 code.putln("%s;" % self.expr.result())
2767 self.expr.generate_disposal_code(code)
2768 self.expr.free_temps(code)
2770 def annotate(self, code):
2771 self.expr.annotate(code)
2774 class AssignmentNode(StatNode):
2775 # Abstract base class for assignment nodes.
2777 # The analyse_expressions and generate_execution_code
2778 # phases of assignments are split into two sub-phases
2779 # each, to enable all the right hand sides of a
2780 # parallel assignment to be evaluated before assigning
2781 # to any of the left hand sides.
2783 def analyse_expressions(self, env):
2784 self.analyse_types(env)
2785 self.allocate_rhs_temps(env)
2786 self.allocate_lhs_temps(env)
2788 # def analyse_expressions(self, env):
2789 # self.analyse_expressions_1(env)
2790 # self.analyse_expressions_2(env)
2792 def generate_execution_code(self, code):
2793 self.generate_rhs_evaluation_code(code)
2794 self.generate_assignment_code(code)
2797 class SingleAssignmentNode(AssignmentNode):
2798 # The simplest case:
2800 # a = b
2802 # lhs ExprNode Left hand side
2803 # rhs ExprNode Right hand side
2804 # first bool Is this guaranteed the first assignment to lhs?
2806 child_attrs = ["lhs", "rhs"]
2807 first = False
2808 declaration_only = False
2810 def analyse_declarations(self, env):
2811 import ExprNodes
2813 # handle declarations of the form x = cython.foo()
2814 if isinstance(self.rhs, ExprNodes.CallNode):
2815 func_name = self.rhs.function.as_cython_attribute()
2816 if func_name:
2817 args, kwds = self.rhs.explicit_args_kwds()
2819 if func_name in ['declare', 'typedef']:
2820 if len(args) > 2 or kwds is not None:
2821 error(rhs.pos, "Can only declare one type at a time.")
2822 return
2823 type = args[0].analyse_as_type(env)
2824 if type is None:
2825 error(args[0].pos, "Unknown type")
2826 return
2827 lhs = self.lhs
2828 if func_name == 'declare':
2829 if isinstance(lhs, ExprNodes.NameNode):
2830 vars = [(lhs.name, lhs.pos)]
2831 elif isinstance(lhs, ExprNodes.TupleNode):
2832 vars = [(var.name, var.pos) for var in lhs.args]
2833 else:
2834 error(lhs.pos, "Invalid declaration")
2835 return
2836 for var, pos in vars:
2837 env.declare_var(var, type, pos, is_cdef = True)
2838 if len(args) == 2:
2839 # we have a value
2840 self.rhs = args[1]
2841 else:
2842 self.declaration_only = True
2843 else:
2844 self.declaration_only = True
2845 if not isinstance(lhs, ExprNodes.NameNode):
2846 error(lhs.pos, "Invalid declaration.")
2847 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2849 elif func_name in ['struct', 'union']:
2850 self.declaration_only = True
2851 if len(args) > 0 or kwds is None:
2852 error(rhs.pos, "Struct or union members must be given by name.")
2853 return
2854 members = []
2855 for member, type_node in kwds.key_value_pairs:
2856 type = type_node.analyse_as_type(env)
2857 if type is None:
2858 error(type_node.pos, "Unknown type")
2859 else:
2860 members.append((member.value, type, member.pos))
2861 if len(members) < len(kwds.key_value_pairs):
2862 return
2863 if not isinstance(self.lhs, ExprNodes.NameNode):
2864 error(self.lhs.pos, "Invalid declaration.")
2865 name = self.lhs.name
2866 scope = StructOrUnionScope(name)
2867 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2868 for member, type, pos in members:
2869 scope.declare_var(member, type, pos)
2871 if self.declaration_only:
2872 return
2873 else:
2874 self.lhs.analyse_target_declaration(env)
2876 def analyse_types(self, env, use_temp = 0):
2877 self.rhs.analyse_types(env)
2878 self.lhs.analyse_target_types(env)
2879 self.lhs.gil_assignment_check(env)
2880 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2881 if use_temp:
2882 self.rhs = self.rhs.coerce_to_temp(env)
2884 def allocate_rhs_temps(self, env):
2885 self.rhs.allocate_temps(env)
2887 def allocate_lhs_temps(self, env):
2888 self.lhs.allocate_target_temps(env, self.rhs)
2889 #self.lhs.release_target_temp(env)
2890 #self.rhs.release_temp(env)
2892 def generate_rhs_evaluation_code(self, code):
2893 self.rhs.generate_evaluation_code(code)
2895 def generate_assignment_code(self, code):
2896 self.lhs.generate_assignment_code(self.rhs, code)
2898 def annotate(self, code):
2899 self.lhs.annotate(code)
2900 self.rhs.annotate(code)
2903 class CascadedAssignmentNode(AssignmentNode):
2904 # An assignment with multiple left hand sides:
2906 # a = b = c
2908 # lhs_list [ExprNode] Left hand sides
2909 # rhs ExprNode Right hand sides
2911 # Used internally:
2913 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2915 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2916 coerced_rhs_list = None
2918 def analyse_declarations(self, env):
2919 for lhs in self.lhs_list:
2920 lhs.analyse_target_declaration(env)
2922 def analyse_types(self, env, use_temp = 0):
2923 self.rhs.analyse_types(env)
2924 if use_temp:
2925 self.rhs = self.rhs.coerce_to_temp(env)
2926 else:
2927 self.rhs = self.rhs.coerce_to_simple(env)
2928 from ExprNodes import CloneNode
2929 self.coerced_rhs_list = []
2930 for lhs in self.lhs_list:
2931 lhs.analyse_target_types(env)
2932 lhs.gil_assignment_check(env)
2933 rhs = CloneNode(self.rhs)
2934 rhs = rhs.coerce_to(lhs.type, env)
2935 self.coerced_rhs_list.append(rhs)
2937 def allocate_rhs_temps(self, env):
2938 self.rhs.allocate_temps(env)
2940 def allocate_lhs_temps(self, env):
2941 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2942 rhs.allocate_temps(env)
2943 lhs.allocate_target_temps(env, rhs)
2944 #lhs.release_target_temp(env)
2945 #rhs.release_temp(env)
2946 self.rhs.release_temp(env)
2948 def generate_rhs_evaluation_code(self, code):
2949 self.rhs.generate_evaluation_code(code)
2951 def generate_assignment_code(self, code):
2952 for i in range(len(self.lhs_list)):
2953 lhs = self.lhs_list[i]
2954 rhs = self.coerced_rhs_list[i]
2955 rhs.generate_evaluation_code(code)
2956 lhs.generate_assignment_code(rhs, code)
2957 # Assignment has disposed of the cloned RHS
2958 self.rhs.generate_disposal_code(code)
2959 self.rhs.free_temps(code)
2961 def annotate(self, code):
2962 for i in range(len(self.lhs_list)):
2963 lhs = self.lhs_list[i].annotate(code)
2964 rhs = self.coerced_rhs_list[i].annotate(code)
2965 self.rhs.annotate(code)
2968 class ParallelAssignmentNode(AssignmentNode):
2969 # A combined packing/unpacking assignment:
2971 # a, b, c = d, e, f
2973 # This has been rearranged by the parser into
2975 # a = d ; b = e ; c = f
2977 # but we must evaluate all the right hand sides
2978 # before assigning to any of the left hand sides.
2980 # stats [AssignmentNode] The constituent assignments
2982 child_attrs = ["stats"]
2984 def analyse_declarations(self, env):
2985 for stat in self.stats:
2986 stat.analyse_declarations(env)
2988 def analyse_expressions(self, env):
2989 for stat in self.stats:
2990 stat.analyse_types(env, use_temp = 1)
2991 stat.allocate_rhs_temps(env)
2992 for stat in self.stats:
2993 stat.allocate_lhs_temps(env)
2995 # def analyse_expressions(self, env):
2996 # for stat in self.stats:
2997 # stat.analyse_expressions_1(env, use_temp = 1)
2998 # for stat in self.stats:
2999 # stat.analyse_expressions_2(env)
3001 def generate_execution_code(self, code):
3002 for stat in self.stats:
3003 stat.generate_rhs_evaluation_code(code)
3004 for stat in self.stats:
3005 stat.generate_assignment_code(code)
3007 def annotate(self, code):
3008 for stat in self.stats:
3009 stat.annotate(code)
3012 class InPlaceAssignmentNode(AssignmentNode):
3013 # An in place arithmatic operand:
3015 # a += b
3016 # a -= b
3017 # ...
3019 # lhs ExprNode Left hand side
3020 # rhs ExprNode Right hand side
3021 # op char one of "+-*/%^&|"
3022 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3024 # This code is a bit tricky because in order to obey Python
3025 # semantics the sub-expressions (e.g. indices) of the lhs must
3026 # not be evaluated twice. So we must re-use the values calculated
3027 # in evaluation phase for the assignment phase as well.
3028 # Fortunately, the type of the lhs node is fairly constrained
3029 # (it must be a NameNode, AttributeNode, or IndexNode).
3031 child_attrs = ["lhs", "rhs"]
3032 dup = None
3034 def analyse_declarations(self, env):
3035 self.lhs.analyse_target_declaration(env)
3037 def analyse_types(self, env):
3038 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3039 self.rhs.analyse_types(env)
3040 self.lhs.analyse_target_types(env)
3041 if Options.incref_local_binop and self.dup.type.is_pyobject:
3042 self.dup = self.dup.coerce_to_temp(env)
3044 def allocate_rhs_temps(self, env):
3045 import ExprNodes
3046 if self.lhs.type.is_pyobject:
3047 self.rhs = self.rhs.coerce_to_pyobject(env)
3048 elif self.rhs.type.is_pyobject:
3049 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3050 if self.lhs.type.is_pyobject:
3051 self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
3052 self.result_value.allocate_temps(env)
3053 # if use_temp:
3054 # self.rhs = self.rhs.coerce_to_temp(env)
3055 self.rhs.allocate_temps(env)
3056 self.dup.allocate_subexpr_temps(env)
3057 self.dup.allocate_temp(env)
3059 def allocate_lhs_temps(self, env):
3060 self.lhs.allocate_target_temps(env, self.rhs)
3061 # self.lhs.release_target_temp(env)
3062 self.dup.release_temp(env)
3063 if self.dup.is_temp:
3064 self.dup.release_subexpr_temps(env)
3065 # self.rhs.release_temp(env)
3066 if self.lhs.type.is_pyobject:
3067 self.result_value.release_temp(env)
3069 def generate_execution_code(self, code):
3070 import ExprNodes
3071 self.rhs.generate_evaluation_code(code)
3072 self.dup.generate_subexpr_evaluation_code(code)
3073 if isinstance(self.dup, ExprNodes.NewTempExprNode):
3074 # This is because we're manually messing with subexpr nodes
3075 if self.dup.is_temp:
3076 self.dup.allocate_temp_result(code)
3077 # self.dup.generate_result_code is run only if it is not buffer access
3078 if self.operator == "**":
3079 extra = ", Py_None"
3080 else:
3081 extra = ""
3082 if self.lhs.type.is_pyobject:
3083 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3084 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3085 self.dup.generate_result_code(code)
3086 code.putln(
3087 "%s = %s(%s, %s%s); %s" % (
3088 self.result_value.result(),
3089 self.py_operation_function(),
3090 self.dup.py_result(),
3091 self.rhs.py_result(),
3092 extra,
3093 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3094 code.put_gotref(self.result_value.py_result())
3095 self.result_value.generate_evaluation_code(code) # May be a type check...
3096 self.rhs.generate_disposal_code(code)
3097 self.rhs.free_temps(code)
3098 self.dup.generate_disposal_code(code)
3099 self.dup.free_temps(code)
3100 self.lhs.generate_assignment_code(self.result_value, code)
3101 else:
3102 c_op = self.operator
3103 if c_op == "//":
3104 c_op = "/"
3105 elif c_op == "**":
3106 if self.lhs.type.is_int and self.rhs.type.is_int:
3107 error(self.pos, "** with two C int types is ambiguous")
3108 else:
3109 error(self.pos, "No C inplace power operator")
3110 # have to do assignment directly to avoid side-effects
3111 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3112 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3113 else:
3114 self.dup.generate_result_code(code)
3115 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3116 self.rhs.generate_disposal_code(code)
3117 self.rhs.free_temps(code)
3118 if self.dup.is_temp:
3119 self.dup.generate_subexpr_disposal_code(code)
3120 self.dup.free_subexpr_temps(code)
3122 def create_dup_node(self, env):
3123 import ExprNodes
3124 self.dup = self.lhs
3125 self.dup.analyse_types(env)
3126 if isinstance(self.lhs, ExprNodes.NameNode):
3127 target_lhs = ExprNodes.NameNode(self.dup.pos,
3128 name = self.dup.name,
3129 is_temp = self.dup.is_temp,
3130 entry = self.dup.entry)
3131 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3132 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3133 obj = ExprNodes.CloneNode(self.lhs.obj),
3134 attribute = self.dup.attribute,
3135 is_temp = self.dup.is_temp)
3136 elif isinstance(self.lhs, ExprNodes.IndexNode):
3137 if self.lhs.index:
3138 index = ExprNodes.CloneNode(self.lhs.index)
3139 else:
3140 index = None
3141 if self.lhs.indices:
3142 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3143 else:
3144 indices = []
3145 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3146 base = ExprNodes.CloneNode(self.dup.base),
3147 index = index,
3148 indices = indices,
3149 is_temp = self.dup.is_temp)
3150 else:
3151 assert False
3152 self.lhs = target_lhs
3153 return self.dup
3155 def py_operation_function(self):
3156 return self.py_functions[self.operator]
3158 py_functions = {
3159 "|": "PyNumber_InPlaceOr",
3160 "^": "PyNumber_InPlaceXor",
3161 "&": "PyNumber_InPlaceAnd",
3162 "+": "PyNumber_InPlaceAdd",
3163 "-": "PyNumber_InPlaceSubtract",
3164 "*": "PyNumber_InPlaceMultiply",
3165 "/": "PyNumber_InPlaceDivide",
3166 "%": "PyNumber_InPlaceRemainder",
3167 "<<": "PyNumber_InPlaceLshift",
3168 ">>": "PyNumber_InPlaceRshift",
3169 "**": "PyNumber_InPlacePower",
3170 "//": "PyNumber_InPlaceFloorDivide",
3173 def annotate(self, code):
3174 self.lhs.annotate(code)
3175 self.rhs.annotate(code)
3176 self.dup.annotate(code)
3179 class PrintStatNode(StatNode):
3180 # print statement
3182 # arg_tuple TupleNode
3183 # append_newline boolean
3185 child_attrs = ["arg_tuple"]
3187 def analyse_expressions(self, env):
3188 self.arg_tuple.analyse_expressions(env)
3189 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3190 self.arg_tuple.release_temp(env)
3191 env.use_utility_code(printing_utility_code)
3192 self.gil_check(env)
3194 gil_message = "Python print statement"
3196 def generate_execution_code(self, code):
3197 self.arg_tuple.generate_evaluation_code(code)
3198 code.putln(
3199 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3200 self.arg_tuple.py_result(),
3201 self.append_newline,
3202 code.error_goto(self.pos)))
3203 self.arg_tuple.generate_disposal_code(code)
3204 self.arg_tuple.free_temps(code)
3206 def annotate(self, code):
3207 self.arg_tuple.annotate(code)
3210 class ExecStatNode(StatNode):
3211 # exec statement
3213 # args [ExprNode]
3215 child_attrs = ["args"]
3217 def analyse_expressions(self, env):
3218 for i, arg in enumerate(self.args):
3219 arg.analyse_expressions(env)
3220 arg = arg.coerce_to_pyobject(env)
3221 arg.release_temp(env)
3222 self.args[i] = arg
3223 self.temp_result = env.allocate_temp_pyobject()
3224 env.release_temp(self.temp_result)
3225 env.use_utility_code(Builtin.pyexec_utility_code)
3226 self.gil_check(env)
3228 gil_message = "Python exec statement"
3230 def generate_execution_code(self, code):
3231 args = []
3232 for arg in self.args:
3233 arg.generate_evaluation_code(code)
3234 args.append( arg.py_result() )
3235 args = tuple(args + ['0', '0'][:3-len(args)])
3236 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3237 (self.temp_result,) + args))
3238 for arg in self.args:
3239 arg.generate_disposal_code(code)
3240 arg.free_temps(code)
3241 code.putln(
3242 code.error_goto_if_null(self.temp_result, self.pos))
3243 code.put_gotref(self.temp_result)
3244 code.put_decref_clear(self.temp_result, py_object_type)
3246 def annotate(self, code):
3247 for arg in self.args:
3248 arg.annotate(code)
3251 class DelStatNode(StatNode):
3252 # del statement
3254 # args [ExprNode]
3256 child_attrs = ["args"]
3258 def analyse_declarations(self, env):
3259 for arg in self.args:
3260 arg.analyse_target_declaration(env)
3262 def analyse_expressions(self, env):
3263 for arg in self.args:
3264 arg.analyse_target_expression(env, None)
3265 if arg.type.is_pyobject:
3266 self.gil_check(env)
3267 else:
3268 error(arg.pos, "Deletion of non-Python object")
3269 #arg.release_target_temp(env)
3271 gil_message = "Deleting Python object"
3273 def generate_execution_code(self, code):
3274 for arg in self.args:
3275 if arg.type.is_pyobject:
3276 arg.generate_deletion_code(code)
3277 # else error reported earlier
3279 def annotate(self, code):
3280 for arg in self.args:
3281 arg.annotate(code)
3284 class PassStatNode(StatNode):
3285 # pass statement
3287 child_attrs = []
3289 def analyse_expressions(self, env):
3290 pass
3292 def generate_execution_code(self, code):
3293 pass
3296 class BreakStatNode(StatNode):
3298 child_attrs = []
3300 def analyse_expressions(self, env):
3301 pass
3303 def generate_execution_code(self, code):
3304 if not code.break_label:
3305 error(self.pos, "break statement not inside loop")
3306 else:
3307 #code.putln(
3308 # "goto %s;" %
3309 # code.break_label)
3310 code.put_goto(code.break_label)
3313 class ContinueStatNode(StatNode):
3315 child_attrs = []
3317 def analyse_expressions(self, env):
3318 pass
3320 def generate_execution_code(self, code):
3321 if code.funcstate.in_try_finally:
3322 error(self.pos, "continue statement inside try of try...finally")
3323 elif not code.continue_label:
3324 error(self.pos, "continue statement not inside loop")
3325 else:
3326 code.put_goto(code.continue_label)
3329 class ReturnStatNode(StatNode):
3330 # return statement
3332 # value ExprNode or None
3333 # return_type PyrexType
3334 # temps_in_use [Entry] Temps in use at time of return
3336 child_attrs = ["value"]
3338 def analyse_expressions(self, env):
3339 return_type = env.return_type
3340 self.return_type = return_type
3341 self.temps_in_use = env.temps_in_use()
3342 if not return_type:
3343 error(self.pos, "Return not inside a function body")
3344 return
3345 if self.value:
3346 self.value.analyse_types(env)
3347 if return_type.is_void or return_type.is_returncode:
3348 error(self.value.pos,
3349 "Return with value in void function")
3350 else:
3351 self.value = self.value.coerce_to(env.return_type, env)
3352 self.value.allocate_temps(env)
3353 self.value.release_temp(env)
3354 else:
3355 if (not return_type.is_void
3356 and not return_type.is_pyobject
3357 and not return_type.is_returncode):
3358 error(self.pos, "Return value required")
3359 if return_type.is_pyobject:
3360 self.gil_check(env)
3362 gil_message = "Returning Python object"
3364 def generate_execution_code(self, code):
3365 code.mark_pos(self.pos)
3366 if not self.return_type:
3367 # error reported earlier
3368 return
3369 if self.value:
3370 self.value.generate_evaluation_code(code)
3371 self.value.make_owned_reference(code)
3372 code.putln(
3373 "%s = %s;" % (
3374 Naming.retval_cname,
3375 self.value.result_as(self.return_type)))
3376 self.value.generate_post_assignment_code(code)
3377 self.value.free_temps(code)
3378 else:
3379 if self.return_type.is_pyobject:
3380 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3381 elif self.return_type.is_returncode:
3382 code.putln(
3383 "%s = %s;" % (
3384 Naming.retval_cname,
3385 self.return_type.default_value))
3386 # free temps the old way
3387 for entry in self.temps_in_use:
3388 code.put_var_decref_clear(entry)
3389 # free temps the new way
3390 for cname, type in code.funcstate.temps_holding_reference():
3391 code.put_decref_clear(cname, type)
3392 #code.putln(
3393 # "goto %s;" %
3394 # code.return_label)
3395 code.put_goto(code.return_label)
3397 def annotate(self, code):
3398 if self.value:
3399 self.value.annotate(code)
3402 class RaiseStatNode(StatNode):
3403 # raise statement
3405 # exc_type ExprNode or None
3406 # exc_value ExprNode or None
3407 # exc_tb ExprNode or None
3409 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3411 def analyse_expressions(self, env):
3412 if self.exc_type:
3413 self.exc_type.analyse_types(env)
3414 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3415 self.exc_type.allocate_temps(env)
3416 if self.exc_value:
3417 self.exc_value.analyse_types(env)
3418 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3419 self.exc_value.allocate_temps(env)
3420 if self.exc_tb:
3421 self.exc_tb.analyse_types(env)
3422 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3423 self.exc_tb.allocate_temps(env)
3424 if self.exc_type:
3425 self.exc_type.release_temp(env)
3426 if self.exc_value:
3427 self.exc_value.release_temp(env)
3428 if self.exc_tb:
3429 self.exc_tb.release_temp(env)
3430 env.use_utility_code(raise_utility_code)
3431 env.use_utility_code(restore_exception_utility_code)
3432 self.gil_check(env)
3434 gil_message = "Raising exception"
3436 def generate_execution_code(self, code):
3437 if self.exc_type:
3438 self.exc_type.generate_evaluation_code(code)
3439 type_code = self.exc_type.py_result()
3440 else:
3441 type_code = 0
3442 if self.exc_value:
3443 self.exc_value.generate_evaluation_code(code)
3444 value_code = self.exc_value.py_result()
3445 else:
3446 value_code = "0"
3447 if self.exc_tb:
3448 self.exc_tb.generate_evaluation_code(code)
3449 tb_code = self.exc_tb.py_result()
3450 else:
3451 tb_code = "0"
3452 if self.exc_type or self.exc_value or self.exc_tb:
3453 code.putln(
3454 "__Pyx_Raise(%s, %s, %s);" % (
3455 type_code,
3456 value_code,
3457 tb_code))
3458 else:
3459 code.putln(
3460 "__Pyx_ReRaise();")
3461 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3462 if obj:
3463 obj.generate_disposal_code(code)
3464 obj.free_temps(code)
3465 code.putln(
3466 code.error_goto(self.pos))
3468 def annotate(self, code):
3469 if self.exc_type:
3470 self.exc_type.annotate(code)
3471 if self.exc_value:
3472 self.exc_value.annotate(code)
3473 if self.exc_tb:
3474 self.exc_tb.annotate(code)
3477 class ReraiseStatNode(StatNode):
3479 child_attrs = []
3481 def analyse_expressions(self, env):
3482 self.gil_check(env)
3483 env.use_utility_code(raise_utility_code)
3484 env.use_utility_code(restore_exception_utility_code)
3486 gil_message = "Raising exception"
3488 def generate_execution_code(self, code):
3489 vars = code.funcstate.exc_vars
3490 if vars:
3491 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3492 code.putln(code.error_goto(self.pos))
3493 else:
3494 error(self.pos, "Reraise not inside except clause")
3497 class AssertStatNode(StatNode):
3498 # assert statement
3500 # cond ExprNode
3501 # value ExprNode or None
3503 child_attrs = ["cond", "value"]
3505 def analyse_expressions(self, env):
3506 self.cond = self.cond.analyse_boolean_expression(env)
3507 if self.value:
3508 self.value.analyse_types(env)
3509 self.value = self.value.coerce_to_pyobject(env)
3510 self.value.allocate_temps(env)
3511 self.cond.release_temp(env)
3512 if self.value:
3513 self.value.release_temp(env)
3514 self.gil_check(env)
3515 #env.recycle_pending_temps() # TEMPORARY
3517 gil_message = "Raising exception"
3519 def generate_execution_code(self, code):
3520 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3521 self.cond.generate_evaluation_code(code)
3522 code.putln(
3523 "if (unlikely(!%s)) {" %
3524 self.cond.result())
3525 if self.value:
3526 self.value.generate_evaluation_code(code)
3527 code.putln(
3528 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3529 self.value.py_result())
3530 self.value.generate_disposal_code(code)
3531 self.value.free_temps(code)
3532 else:
3533 code.putln(
3534 "PyErr_SetNone(PyExc_AssertionError);")
3535 code.putln(
3536 code.error_goto(self.pos))
3537 code.putln(
3538 "}")
3539 self.cond.generate_disposal_code(code)
3540 self.cond.free_temps(code)
3541 code.putln("#endif")
3543 def annotate(self, code):
3544 self.cond.annotate(code)
3545 if self.value:
3546 self.value.annotate(code)
3549 class IfStatNode(StatNode):
3550 # if statement
3552 # if_clauses [IfClauseNode]
3553 # else_clause StatNode or None
3555 child_attrs = ["if_clauses", "else_clause"]
3557 def analyse_control_flow(self, env):
3558 env.start_branching(self.pos)
3559 for if_clause in self.if_clauses:
3560 if_clause.analyse_control_flow(env)
3561 env.next_branch(if_clause.end_pos())
3562 if self.else_clause:
3563 self.else_clause.analyse_control_flow(env)
3564 env.finish_branching(self.end_pos())
3566 def analyse_declarations(self, env):
3567 for if_clause in self.if_clauses:
3568 if_clause.analyse_declarations(env)
3569 if self.else_clause:
3570 self.else_clause.analyse_declarations(env)
3572 def analyse_expressions(self, env):
3573 for if_clause in self.if_clauses:
3574 if_clause.analyse_expressions(env)
3575 if self.else_clause:
3576 self.else_clause.analyse_expressions(env)
3578 def generate_execution_code(self, code):
3579 code.mark_pos(self.pos)
3580 end_label = code.new_label()
3581 for if_clause in self.if_clauses:
3582 if_clause.generate_execution_code(code, end_label)
3583 if self.else_clause:
3584 code.putln("/*else*/ {")
3585 self.else_clause.generate_execution_code(code)
3586 code.putln("}")
3587 code.put_label(end_label)
3589 def annotate(self, code):
3590 for if_clause in self.if_clauses:
3591 if_clause.annotate(code)
3592 if self.else_clause:
3593 self.else_clause.annotate(code)
3596 class IfClauseNode(Node):
3597 # if or elif clause in an if statement
3599 # condition ExprNode
3600 # body StatNode
3602 child_attrs = ["condition", "body"]
3604 def analyse_control_flow(self, env):
3605 self.body.analyse_control_flow(env)
3607 def analyse_declarations(self, env):
3608 self.condition.analyse_declarations(env)
3609 self.body.analyse_declarations(env)
3611 def analyse_expressions(self, env):
3612 self.condition = \
3613 self.condition.analyse_temp_boolean_expression(env)
3614 self.condition.release_temp(env)
3615 self.body.analyse_expressions(env)
3617 def generate_execution_code(self, code, end_label):
3618 self.condition.generate_evaluation_code(code)
3619 code.putln(
3620 "if (%s) {" %
3621 self.condition.result())
3622 self.condition.generate_disposal_code(code)
3623 self.condition.free_temps(code)
3624 self.body.generate_execution_code(code)
3625 #code.putln(
3626 # "goto %s;" %
3627 # end_label)
3628 code.put_goto(end_label)
3629 code.putln("}")
3631 def annotate(self, code):
3632 self.condition.annotate(code)
3633 self.body.annotate(code)
3636 class SwitchCaseNode(StatNode):
3637 # Generated in the optimization of an if-elif-else node
3639 # conditions [ExprNode]
3640 # body StatNode
3642 child_attrs = ['conditions', 'body']
3644 def generate_execution_code(self, code):
3645 for cond in self.conditions:
3646 code.putln("case %s:" % cond.calculate_result_code())
3647 self.body.generate_execution_code(code)
3648 code.putln("break;")
3650 def annotate(self, code):
3651 for cond in self.conditions:
3652 cond.annotate(code)
3653 self.body.annotate(code)
3655 class SwitchStatNode(StatNode):
3656 # Generated in the optimization of an if-elif-else node
3658 # test ExprNode
3659 # cases [SwitchCaseNode]
3660 # else_clause StatNode or None
3662 child_attrs = ['test', 'cases', 'else_clause']
3664 def generate_execution_code(self, code):
3665 code.putln("switch (%s) {" % self.test.calculate_result_code())
3666 for case in self.cases:
3667 case.generate_execution_code(code)
3668 if self.else_clause is not None:
3669 code.putln("default:")
3670 self.else_clause.generate_execution_code(code)
3671 code.putln("break;")
3672 code.putln("}")
3674 def annotate(self, code):
3675 self.test.annotate(code)
3676 for case in self.cases:
3677 case.annotate(code)
3678 if self.else_clause is not None:
3679 self.else_clause.annotate(code)
3681 class LoopNode:
3683 def analyse_control_flow(self, env):
3684 env.start_branching(self.pos)
3685 self.body.analyse_control_flow(env)
3686 env.next_branch(self.body.end_pos())
3687 if self.else_clause:
3688 self.else_clause.analyse_control_flow(env)
3689 env.finish_branching(self.end_pos())
3692 class WhileStatNode(LoopNode, StatNode):
3693 # while statement
3695 # condition ExprNode
3696 # body StatNode
3697 # else_clause StatNode
3699 child_attrs = ["condition", "body", "else_clause"]
3701 def analyse_declarations(self, env):
3702 self.body.analyse_declarations(env)
3703 if self.else_clause:
3704 self.else_clause.analyse_declarations(env)
3706 def analyse_expressions(self, env):
3707 self.condition = \
3708 self.condition.analyse_temp_boolean_expression(env)
3709 self.condition.release_temp(env)
3710 #env.recycle_pending_temps() # TEMPORARY
3711 self.body.analyse_expressions(env)
3712 if self.else_clause:
3713 self.else_clause.analyse_expressions(env)
3715 def generate_execution_code(self, code):
3716 old_loop_labels = code.new_loop_labels()
3717 code.putln(
3718 "while (1) {")
3719 self.condition.generate_evaluation_code(code)
3720 self.condition.generate_disposal_code(code)
3721 code.putln(
3722 "if (!%s) break;" %
3723 self.condition.result())
3724 self.condition.free_temps(code)
3725 self.body.generate_execution_code(code)
3726 code.put_label(code.continue_label)
3727 code.putln("}")
3728 break_label = code.break_label
3729 code.set_loop_labels(old_loop_labels)
3730 if self.else_clause:
3731 code.putln("/*else*/ {")
3732 self.else_clause.generate_execution_code(code)
3733 code.putln("}")
3734 code.put_label(break_label)
3736 def annotate(self, code):
3737 self.condition.annotate(code)
3738 self.body.annotate(code)
3739 if self.else_clause:
3740 self.else_clause.annotate(code)
3743 def ForStatNode(pos, **kw):
3744 if kw.has_key('iterator'):
3745 return ForInStatNode(pos, **kw)
3746 else:
3747 return ForFromStatNode(pos, **kw)
3749 class ForInStatNode(LoopNode, StatNode):
3750 # for statement
3752 # target ExprNode
3753 # iterator IteratorNode
3754 # body StatNode
3755 # else_clause StatNode
3756 # item NextNode used internally
3758 child_attrs = ["target", "iterator", "body", "else_clause"]
3759 item = None
3761 def analyse_declarations(self, env):
3762 self.target.analyse_target_declaration(env)
3763 self.body.analyse_declarations(env)
3764 if self.else_clause:
3765 self.else_clause.analyse_declarations(env)
3767 def analyse_expressions(self, env):
3768 import ExprNodes
3769 self.target.analyse_target_types(env)
3770 self.iterator.analyse_expressions(env)
3771 self.item = ExprNodes.NextNode(self.iterator, env)
3772 self.item = self.item.coerce_to(self.target.type, env)
3773 self.item.allocate_temps(env)
3774 self.target.allocate_target_temps(env, self.item)
3775 #self.item.release_temp(env)
3776 #self.target.release_target_temp(env)
3777 self.body.analyse_expressions(env)
3778 if self.else_clause:
3779 self.else_clause.analyse_expressions(env)
3780 self.iterator.release_temp(env)
3782 def generate_execution_code(self, code):
3783 old_loop_labels = code.new_loop_labels()
3784 self.iterator.allocate_counter_temp(code)
3785 self.iterator.generate_evaluation_code(code)
3786 code.putln(
3787 "for (;;) {")
3788 self.item.generate_evaluation_code(code)
3789 self.target.generate_assignment_code(self.item, code)
3790 self.body.generate_execution_code(code)
3791 code.put_label(code.continue_label)
3792 code.putln(
3793 "}")
3794 break_label = code.break_label
3795 code.set_loop_labels(old_loop_labels)
3796 if self.else_clause:
3797 code.putln("/*else*/ {")
3798 self.else_clause.generate_execution_code(code)
3799 code.putln("}")
3800 code.put_label(break_label)
3801 self.iterator.release_counter_temp(code)
3802 self.iterator.generate_disposal_code(code)
3803 self.iterator.free_temps(code)
3805 def annotate(self, code):
3806 self.target.annotate(code)
3807 self.iterator.annotate(code)
3808 self.body.annotate(code)
3809 if self.else_clause:
3810 self.else_clause.annotate(code)
3811 self.item.annotate(code)
3814 class ForFromStatNode(LoopNode, StatNode):
3815 # for name from expr rel name rel expr
3817 # target NameNode
3818 # bound1 ExprNode
3819 # relation1 string
3820 # relation2 string
3821 # bound2 ExprNode
3822 # step ExprNode or None
3823 # body StatNode
3824 # else_clause StatNode or None
3826 # Used internally:
3828 # is_py_target bool
3829 # loopvar_node ExprNode (usually a NameNode or temp node)
3830 # py_loopvar_node PyTempNode or None
3831 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3833 is_py_target = False
3834 loopvar_node = None
3835 py_loopvar_node = None
3837 def analyse_declarations(self, env):
3838 self.target.analyse_target_declaration(env)
3839 self.body.analyse_declarations(env)
3840 if self.else_clause:
3841 self.else_clause.analyse_declarations(env)
3843 def analyse_expressions(self, env):
3844 import ExprNodes
3845 self.target.analyse_target_types(env)
3846 self.bound1.analyse_types(env)
3847 self.bound2.analyse_types(env)
3848 if self.target.type.is_numeric:
3849 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3850 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3851 else:
3852 self.bound1 = self.bound1.coerce_to_integer(env)
3853 self.bound2 = self.bound2.coerce_to_integer(env)
3854 if self.step is not None:
3855 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3856 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3857 self.step.analyse_types(env)
3858 self.step = self.step.coerce_to_integer(env)
3859 if not (self.bound2.is_name or self.bound2.is_literal):
3860 self.bound2 = self.bound2.coerce_to_temp(env)
3861 target_type = self.target.type
3862 if not (target_type.is_pyobject or target_type.is_numeric):
3863 error(self.target.pos,
3864 "Integer for-loop variable must be of type int or Python object")
3865 #if not (target_type.is_pyobject
3866 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3867 # error(self.target.pos,
3868 # "Cannot assign integer to variable of type '%s'" % target_type)
3869 if target_type.is_numeric:
3870 self.is_py_target = 0
3871 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3872 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3873 self.loopvar_node = self.target
3874 self.py_loopvar_node = None
3875 else:
3876 self.is_py_target = 1
3877 c_loopvar_node = ExprNodes.TempNode(self.pos,
3878 PyrexTypes.c_long_type, env)
3879 c_loopvar_node.allocate_temps(env)
3880 self.loopvar_node = c_loopvar_node
3881 self.py_loopvar_node = \
3882 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3883 self.bound1.allocate_temps(env)
3884 self.bound2.allocate_temps(env)
3885 if self.step is not None:
3886 self.step.allocate_temps(env)
3887 if self.is_py_target:
3888 self.py_loopvar_node.allocate_temps(env)
3889 self.target.allocate_target_temps(env, self.py_loopvar_node)
3890 #self.target.release_target_temp(env)
3891 #self.py_loopvar_node.release_temp(env)
3892 self.body.analyse_expressions(env)
3893 if self.is_py_target:
3894 c_loopvar_node.release_temp(env)
3895 if self.else_clause:
3896 self.else_clause.analyse_expressions(env)
3897 self.bound1.release_temp(env)
3898 self.bound2.release_temp(env)
3899 if self.step is not None:
3900 self.step.release_temp(env)
3902 def generate_execution_code(self, code):
3903 old_loop_labels = code.new_loop_labels()
3904 self.bound1.generate_evaluation_code(code)
3905 self.bound2.generate_evaluation_code(code)
3906 offset, incop = self.relation_table[self.relation1]
3907 if incop == "++":
3908 decop = "--"
3909 else:
3910 decop = "++"
3911 if self.step is not None:
3912 self.step.generate_evaluation_code(code)
3913 step = self.step.result()
3914 incop = "%s=%s" % (incop[0], step)
3915 decop = "%s=%s" % (decop[0], step)
3916 loopvar_name = self.loopvar_node.result()
3917 code.putln(
3918 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3919 loopvar_name,
3920 self.bound1.result(), offset,
3921 loopvar_name, self.relation2, self.bound2.result(),
3922 loopvar_name, incop))
3923 if self.py_loopvar_node:
3924 self.py_loopvar_node.generate_evaluation_code(code)
3925 self.target.generate_assignment_code(self.py_loopvar_node, code)
3926 self.body.generate_execution_code(code)
3927 code.put_label(code.continue_label)
3928 if getattr(self, "from_range", False):
3929 # Undo last increment to maintain Python semantics:
3930 code.putln("} %s%s;" % (loopvar_name, decop))
3931 else:
3932 code.putln("}")
3933 break_label = code.break_label
3934 code.set_loop_labels(old_loop_labels)
3935 if self.else_clause:
3936 code.putln("/*else*/ {")
3937 self.else_clause.generate_execution_code(code)
3938 code.putln("}")
3939 code.put_label(break_label)
3940 self.bound1.generate_disposal_code(code)
3941 self.bound1.free_temps(code)
3942 self.bound2.generate_disposal_code(code)
3943 self.bound2.free_temps(code)
3944 if self.step is not None:
3945 self.step.generate_disposal_code(code)
3946 self.step.free_temps(code)
3948 relation_table = {
3949 # {relop : (initial offset, increment op)}
3950 '<=': ("", "++"),
3951 '<' : ("+1", "++"),
3952 '>=': ("", "--"),
3953 '>' : ("-1", "--")
3956 def annotate(self, code):
3957 self.target.annotate(code)
3958 self.bound1.annotate(code)
3959 self.bound2.annotate(code)
3960 if self.step:
3961 self.bound2.annotate(code)
3962 self.body.annotate(code)
3963 if self.else_clause:
3964 self.else_clause.annotate(code)
3967 class WithStatNode(StatNode):
3968 """
3969 Represents a Python with statement.
3971 This is only used at parse tree level; and is not present in
3972 analysis or generation phases.
3973 """
3974 # manager The with statement manager object
3975 # target Node (lhs expression)
3976 # body StatNode
3977 child_attrs = ["manager", "target", "body"]
3979 class TryExceptStatNode(StatNode):
3980 # try .. except statement
3982 # body StatNode
3983 # except_clauses [ExceptClauseNode]
3984 # else_clause StatNode or None
3985 # cleanup_list [Entry] old style temps to clean up on error
3987 child_attrs = ["body", "except_clauses", "else_clause"]
3989 def analyse_control_flow(self, env):
3990 env.start_branching(self.pos)
3991 self.body.analyse_control_flow(env)
3992 successful_try = env.control_flow # grab this for later
3993 env.next_branch(self.body.end_pos())
3994 env.finish_branching(self.body.end_pos())
3996 env.start_branching(self.except_clauses[0].pos)
3997 for except_clause in self.except_clauses:
3998 except_clause.analyse_control_flow(env)
3999 env.next_branch(except_clause.end_pos())
4001 # the else cause it executed only when the try clause finishes
4002 env.control_flow.incoming = successful_try
4003 if self.else_clause:
4004 self.else_clause.analyse_control_flow(env)
4005 env.finish_branching(self.end_pos())
4007 def analyse_declarations(self, env):
4008 self.body.analyse_declarations(env)
4009 for except_clause in self.except_clauses:
4010 except_clause.analyse_declarations(env)
4011 if self.else_clause:
4012 self.else_clause.analyse_declarations(env)
4013 self.gil_check(env)
4014 env.use_utility_code(reset_exception_utility_code)
4016 def analyse_expressions(self, env):
4017 self.body.analyse_expressions(env)
4018 self.cleanup_list = env.free_temp_entries[:]
4019 default_clause_seen = 0
4020 for except_clause in self.except_clauses:
4021 except_clause.analyse_expressions(env)
4022 if default_clause_seen:
4023 error(except_clause.pos, "default 'except:' must be last")
4024 if not except_clause.pattern:
4025 default_clause_seen = 1
4026 self.has_default_clause = default_clause_seen
4027 if self.else_clause:
4028 self.else_clause.analyse_expressions(env)
4029 self.gil_check(env)
4031 gil_message = "Try-except statement"
4033 def generate_execution_code(self, code):
4034 old_return_label = code.return_label
4035 old_error_label = code.new_error_label()
4036 our_error_label = code.error_label
4037 except_end_label = code.new_label('exception_handled')
4038 except_error_label = code.new_label('except_error')
4039 except_return_label = code.new_label('except_return')
4040 try_return_label = code.new_label('try_return')
4041 try_end_label = code.new_label('try')
4043 code.putln("{")
4044 code.putln("PyObject %s;" %
4045 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4046 code.putln("__Pyx_ExceptionSave(%s);" %
4047 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4048 for var in Naming.exc_save_vars:
4049 code.put_xgotref(var)
4050 code.putln(
4051 "/*try:*/ {")
4052 code.return_label = try_return_label
4053 self.body.generate_execution_code(code)
4054 code.putln(
4055 "}")
4056 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4057 code.error_label = except_error_label
4058 code.return_label = except_return_label
4059 if self.else_clause:
4060 code.putln(
4061 "/*else:*/ {")
4062 self.else_clause.generate_execution_code(code)
4063 code.putln(
4064 "}")
4065 for var in Naming.exc_save_vars:
4066 code.put_xdecref_clear(var, py_object_type)
4067 code.put_goto(try_end_label)
4068 if code.label_used(try_return_label):
4069 code.put_label(try_return_label)
4070 for var in Naming.exc_save_vars:
4071 code.put_xdecref_clear(var, py_object_type)
4072 code.put_goto(old_return_label)
4073 code.put_label(our_error_label)
4074 code.put_var_xdecrefs_clear(self.cleanup_list)
4075 for temp_name, type in temps_to_clean_up:
4076 code.put_xdecref_clear(temp_name, type)
4077 for except_clause in self.except_clauses:
4078 except_clause.generate_handling_code(code, except_end_label)
4080 error_label_used = code.label_used(except_error_label)
4081 if error_label_used or not self.has_default_clause:
4082 if error_label_used:
4083 code.put_label(except_error_label)
4084 for var in Naming.exc_save_vars:
4085 code.put_xdecref(var, py_object_type)
4086 code.put_goto(old_error_label)
4088 if code.label_used(except_return_label):
4089 code.put_label(except_return_label)
4090 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4091 code.putln("__Pyx_ExceptionReset(%s);" %
4092 ', '.join(Naming.exc_save_vars))
4093 code.put_goto(old_return_label)
4095 if code.label_used(except_end_label):
4096 code.put_label(except_end_label)
4097 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4098 code.putln("__Pyx_ExceptionReset(%s);" %
4099 ', '.join(Naming.exc_save_vars))
4100 code.put_label(try_end_label)
4101 code.putln("}")
4103 code.return_label = old_return_label
4104 code.error_label = old_error_label
4106 def annotate(self, code):
4107 self.body.annotate(code)
4108 for except_node in self.except_clauses:
4109 except_node.annotate(code)
4110 if self.else_clause:
4111 self.else_clause.annotate(code)
4114 class ExceptClauseNode(Node):
4115 # Part of try ... except statement.
4117 # pattern ExprNode
4118 # target ExprNode or None
4119 # body StatNode
4120 # excinfo_target NameNode or None optional target for exception info
4121 # match_flag string result of exception match
4122 # exc_value ExcValueNode used internally
4123 # function_name string qualified name of enclosing function
4124 # exc_vars (string * 3) local exception variables
4126 # excinfo_target is never set by the parser, but can be set by a transform
4127 # in order to extract more extensive information about the exception as a
4128 # sys.exc_info()-style tuple into a target variable
4130 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4132 exc_value = None
4133 excinfo_target = None
4135 def analyse_declarations(self, env):
4136 if self.target:
4137 self.target.analyse_target_declaration(env)
4138 if self.excinfo_target is not None:
4139 self.excinfo_target.analyse_target_declaration(env)
4140 self.body.analyse_declarations(env)
4142 def analyse_expressions(self, env):
4143 import ExprNodes
4144 genv = env.global_scope()
4145 self.function_name = env.qualified_name
4146 if self.pattern:
4147 self.pattern.analyse_expressions(env)
4148 self.pattern = self.pattern.coerce_to_pyobject(env)
4149 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
4150 self.pattern.release_temp(env)
4151 env.release_temp(self.match_flag)
4152 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
4153 if self.target:
4154 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
4155 self.exc_value.allocate_temps(env)
4156 self.target.analyse_target_expression(env, self.exc_value)
4157 if self.excinfo_target is not None:
4158 import ExprNodes
4159 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4160 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
4161 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
4162 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
4163 ])
4164 self.excinfo_tuple.analyse_expressions(env)
4165 self.excinfo_tuple.allocate_temps(env)
4166 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4168 self.body.analyse_expressions(env)
4169 for var in self.exc_vars:
4170 env.release_temp(var)
4171 env.use_utility_code(get_exception_utility_code)
4172 env.use_utility_code(restore_exception_utility_code)
4174 def generate_handling_code(self, code, end_label):
4175 code.mark_pos(self.pos)
4176 if self.pattern:
4177 self.pattern.generate_evaluation_code(code)
4178 code.putln(
4179 "%s = PyErr_ExceptionMatches(%s);" % (
4180 self.match_flag,
4181 self.pattern.py_result()))
4182 self.pattern.generate_disposal_code(code)
4183 self.pattern.free_temps(code)
4184 code.putln(
4185 "if (%s) {" %
4186 self.match_flag)
4187 else:
4188 code.putln("/*except:*/ {")
4189 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4190 # We always have to fetch the exception value even if
4191 # there is no target, because this also normalises the
4192 # exception and stores it in the thread state.
4193 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
4194 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4195 code.error_goto(self.pos)))
4196 for x in self.exc_vars:
4197 code.put_gotref(x)
4198 if self.target:
4199 self.exc_value.generate_evaluation_code(code)
4200 self.target.generate_assignment_code(self.exc_value, code)
4201 if self.excinfo_target is not None:
4202 self.excinfo_tuple.generate_evaluation_code(code)
4203 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4205 old_exc_vars = code.funcstate.exc_vars
4206 code.funcstate.exc_vars = self.exc_vars
4207 self.body.generate_execution_code(code)
4208 code.funcstate.exc_vars = old_exc_vars
4209 for var in self.exc_vars:
4210 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4211 code.put_goto(end_label)
4212 code.putln(
4213 "}")
4215 def annotate(self, code):
4216 if self.pattern:
4217 self.pattern.annotate(code)
4218 if self.target:
4219 self.target.annotate(code)
4220 self.body.annotate(code)
4223 class TryFinallyStatNode(StatNode):
4224 # try ... finally statement
4226 # body StatNode
4227 # finally_clause StatNode
4229 # cleanup_list [Entry] old_style temps to clean up on error
4231 # The plan is that we funnel all continue, break
4232 # return and error gotos into the beginning of the
4233 # finally block, setting a variable to remember which
4234 # one we're doing. At the end of the finally block, we
4235 # switch on the variable to figure out where to go.
4236 # In addition, if we're doing an error, we save the
4237 # exception on entry to the finally block and restore
4238 # it on exit.
4240 child_attrs = ["body", "finally_clause"]
4242 preserve_exception = 1
4244 disallow_continue_in_try_finally = 0
4245 # There doesn't seem to be any point in disallowing
4246 # continue in the try block, since we have no problem
4247 # handling it.
4249 def create_analysed(pos, env, body, finally_clause):
4250 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4251 node.cleanup_list = []
4252 return node
4253 create_analysed = staticmethod(create_analysed)
4255 def analyse_control_flow(self, env):
4256 env.start_branching(self.pos)
4257 self.body.analyse_control_flow(env)
4258 env.next_branch(self.body.end_pos())
4259 env.finish_branching(self.body.end_pos())
4260 self.finally_clause.analyse_control_flow(env)
4262 def analyse_declarations(self, env):
4263 self.body.analyse_declarations(env)
4264 self.finally_clause.analyse_declarations(env)
4266 def analyse_expressions(self, env):
4267 self.body.analyse_expressions(env)
4268 self.cleanup_list = env.free_temp_entries[:]
4269 self.finally_clause.analyse_expressions(env)
4270 self.gil_check(env)
4272 gil_message = "Try-finally statement"
4274 def generate_execution_code(self, code):
4275 old_error_label = code.error_label
4276 old_labels = code.all_new_labels()
4277 new_labels = code.get_all_labels()
4278 new_error_label = code.error_label
4279 catch_label = code.new_label()
4280 code.putln(
4281 "/*try:*/ {")
4282 if self.disallow_continue_in_try_finally:
4283 was_in_try_finally = code.funcstate.in_try_finally
4284 code.funcstate.in_try_finally = 1
4285 self.body.generate_execution_code(code)
4286 if self.disallow_continue_in_try_finally:
4287 code.funcstate.in_try_finally = was_in_try_finally
4288 code.putln(
4289 "}")
4290 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4291 code.putln(
4292 "/*finally:*/ {")
4293 cases_used = []
4294 error_label_used = 0
4295 for i, new_label in enumerate(new_labels):
4296 if new_label in code.labels_used:
4297 cases_used.append(i)
4298 if new_label == new_error_label:
4299 error_label_used = 1
4300 error_label_case = i
4301 if cases_used:
4302 code.putln(
4303 "int __pyx_why;")
4304 if error_label_used and self.preserve_exception:
4305 code.putln(
4306 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4307 code.putln(
4308 "int %s;" % Naming.exc_lineno_name)
4309 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4310 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4311 code.putln(exc_var_init_zero)
4312 else:
4313 exc_var_init_zero = None
4314 code.use_label(catch_label)
4315 code.putln(
4316 "__pyx_why = 0; goto %s;" % catch_label)
4317 for i in cases_used:
4318 new_label = new_labels[i]
4319 #if new_label and new_label != "<try>":
4320 if new_label == new_error_label and self.preserve_exception:
4321 self.put_error_catcher(code,
4322 new_error_label, i+1, catch_label, temps_to_clean_up)
4323 else:
4324 code.put('%s: ' % new_label)
4325 if exc_var_init_zero:
4326 code.putln(exc_var_init_zero)
4327 code.putln("__pyx_why = %s; goto %s;" % (
4328 i+1,
4329 catch_label))
4330 code.put_label(catch_label)
4331 code.set_all_labels(old_labels)
4332 if error_label_used:
4333 code.new_error_label()
4334 finally_error_label = code.error_label
4335 self.finally_clause.generate_execution_code(code)
4336 if error_label_used:
4337 if finally_error_label in code.labels_used and self.preserve_exception:
4338 over_label = code.new_label()
4339 code.put_goto(over_label);
4340 code.put_label(finally_error_label)
4341 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4342 for var in Naming.exc_vars:
4343 code.putln("Py_XDECREF(%s);" % var)
4344 code.putln("}")
4345 code.put_goto(old_error_label)
4346 code.put_label(over_label)
4347 code.error_label = old_error_label
4348 if cases_used:
4349 code.putln(
4350 "switch (__pyx_why) {")
4351 for i in cases_used:
4352 old_label = old_labels[i]
4353 if old_label == old_error_label and self.preserve_exception:
4354 self.put_error_uncatcher(code, i+1, old_error_label)
4355 else:
4356 code.use_label(old_label)
4357 code.putln(
4358 "case %s: goto %s;" % (
4359 i+1,
4360 old_label))
4361 code.putln(
4362 "}")
4363 code.putln(
4364 "}")
4366 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4367 code.globalstate.use_utility_code(restore_exception_utility_code)
4368 code.putln(
4369 "%s: {" %
4370 error_label)
4371 code.putln(
4372 "__pyx_why = %s;" %
4373 i)
4374 code.put_var_xdecrefs_clear(self.cleanup_list)
4375 for temp_name, type in temps_to_clean_up:
4376 code.put_xdecref_clear(temp_name, type)
4377 code.putln(
4378 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4379 Naming.exc_vars)
4380 code.putln(
4381 "%s = %s;" % (
4382 Naming.exc_lineno_name, Naming.lineno_cname))
4383 #code.putln(
4384 # "goto %s;" %
4385 # catch_label)
4386 code.put_goto(catch_label)
4387 code.putln(
4388 "}")
4390 def put_error_uncatcher(self, code, i, error_label):
4391 code.globalstate.use_utility_code(restore_exception_utility_code)
4392 code.putln(
4393 "case %s: {" %
4394 i)
4395 code.putln(
4396 "__Pyx_ErrRestore(%s, %s, %s);" %
4397 Naming.exc_vars)
4398 code.putln(
4399 "%s = %s;" % (
4400 Naming.lineno_cname, Naming.exc_lineno_name))
4401 for var in Naming.exc_vars:
4402 code.putln(
4403 "%s = 0;" %
4404 var)
4405 code.put_goto(error_label)
4406 code.putln(
4407 "}")
4409 def annotate(self, code):
4410 self.body.annotate(code)
4411 self.finally_clause.annotate(code)
4414 class GILStatNode(TryFinallyStatNode):
4415 # 'with gil' or 'with nogil' statement
4417 # state string 'gil' or 'nogil'
4419 child_attrs = []
4421 preserve_exception = 0
4423 def __init__(self, pos, state, body):
4424 self.state = state
4425 TryFinallyStatNode.__init__(self, pos,
4426 body = body,
4427 finally_clause = GILExitNode(pos, state = state))
4429 def analyse_expressions(self, env):
4430 was_nogil = env.nogil
4431 env.nogil = 1
4432 TryFinallyStatNode.analyse_expressions(self, env)
4433 env.nogil = was_nogil
4435 def gil_check(self, env):
4436 pass
4438 def generate_execution_code(self, code):
4439 code.putln("/*with %s:*/ {" % self.state)
4440 if self.state == 'gil':
4441 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
4442 else:
4443 code.putln("PyThreadState *_save;")
4444 code.putln("Py_UNBLOCK_THREADS")
4445 TryFinallyStatNode.generate_execution_code(self, code)
4446 code.putln("}")
4449 class GILExitNode(StatNode):
4450 # Used as the 'finally' block in a GILStatNode
4452 # state string 'gil' or 'nogil'
4454 child_attrs = []
4456 def analyse_expressions(self, env):
4457 pass
4459 def generate_execution_code(self, code):
4460 if self.state == 'gil':
4461 code.putln("PyGILState_Release();")
4462 else:
4463 code.putln("Py_BLOCK_THREADS")
4466 class CImportStatNode(StatNode):
4467 # cimport statement
4469 # module_name string Qualified name of module being imported
4470 # as_name string or None Name specified in "as" clause, if any
4472 child_attrs = []
4474 def analyse_declarations(self, env):
4475 if not env.is_module_scope:
4476 error(self.pos, "cimport only allowed at module level")
4477 return
4478 module_scope = env.find_module(self.module_name, self.pos)
4479 if "." in self.module_name:
4480 names = [EncodedString(name) for name in self.module_name.split(".")]
4481 top_name = names[0]
4482 top_module_scope = env.context.find_submodule(top_name)
4483 module_scope = top_module_scope
4484 for name in names[1:]:
4485 submodule_scope = module_scope.find_submodule(name)
4486 module_scope.declare_module(name, submodule_scope, self.pos)
4487 module_scope = submodule_scope
4488 if self.as_name:
4489 env.declare_module(self.as_name, module_scope, self.pos)
4490 else:
4491 env.declare_module(top_name, top_module_scope, self.pos)
4492 else:
4493 name = self.as_name or self.module_name
4494 env.declare_module(name, module_scope, self.pos)
4496 def analyse_expressions(self, env):
4497 pass
4499 def generate_execution_code(self, code):
4500 pass
4503 class FromCImportStatNode(StatNode):
4504 # from ... cimport statement
4506 # module_name string Qualified name of module
4507 # imported_names [(pos, name, as_name, kind)] Names to be imported
4509 child_attrs = []
4511 def analyse_declarations(self, env):
4512 if not env.is_module_scope:
4513 error(self.pos, "cimport only allowed at module level")
4514 return
4515 module_scope = env.find_module(self.module_name, self.pos)
4516 env.add_imported_module(module_scope)
4517 for pos, name, as_name, kind in self.imported_names:
4518 if name == "*":
4519 for local_name, entry in module_scope.entries.items():
4520 env.add_imported_entry(local_name, entry, pos)
4521 else:
4522 entry = module_scope.lookup(name)
4523 if entry:
4524 if kind and not self.declaration_matches(entry, kind):
4525 entry.redeclared(pos)
4526 else:
4527 if kind == 'struct' or kind == 'union':
4528 entry = module_scope.declare_struct_or_union(name,
4529 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4530 elif kind == 'class':
4531 entry = module_scope.declare_c_class(name, pos = pos,
4532 module_name = self.module_name)
4533 else:
4534 error(pos, "Name '%s' not declared in module '%s'"
4535 % (name, self.module_name))
4537 if entry:
4538 local_name = as_name or name
4539 env.add_imported_entry(local_name, entry, pos)
4541 def declaration_matches(self, entry, kind):
4542 if not entry.is_type:
4543 return 0
4544 type = entry.type
4545 if kind == 'class':
4546 if not type.is_extension_type:
4547 return 0
4548 else:
4549 if not type.is_struct_or_union:
4550 return 0
4551 if kind != type.kind:
4552 return 0
4553 return 1
4555 def analyse_expressions(self, env):
4556 pass
4558 def generate_execution_code(self, code):
4559 pass
4562 class FromImportStatNode(StatNode):
4563 # from ... import statement
4565 # module ImportNode
4566 # items [(string, NameNode)]
4567 # interned_items [(string, NameNode)]
4568 # item PyTempNode used internally
4569 # import_star boolean used internally
4571 child_attrs = ["module"]
4572 import_star = 0
4574 def analyse_declarations(self, env):
4575 for name, target in self.items:
4576 if name == "*":
4577 if not env.is_module_scope:
4578 error(self.pos, "import * only allowed at module level")
4579 return
4580 env.has_import_star = 1
4581 self.import_star = 1
4582 else:
4583 target.analyse_target_declaration(env)
4585 def analyse_expressions(self, env):
4586 import ExprNodes
4587 self.module.analyse_expressions(env)
4588 self.item = ExprNodes.PyTempNode(self.pos, env)
4589 self.item.allocate_temp(env)
4590 self.interned_items = []
4591 for name, target in self.items:
4592 if name == '*':
4593 for _, entry in env.entries.items():
4594 if not entry.is_type and entry.type.is_extension_type:
4595 env.use_utility_code(ExprNodes.type_test_utility_code)
4596 break
4597 else:
4598 entry = env.lookup(target.name)
4599 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4600 continue # already cimported
4601 self.interned_items.append(
4602 (env.intern_identifier(name), target))
4603 target.analyse_target_expression(env, None)
4604 #target.release_target_temp(env) # was release_temp ?!?
4605 self.module.release_temp(env)
4606 self.item.release_temp(env)
4608 def generate_execution_code(self, code):
4609 self.module.generate_evaluation_code(code)
4610 if self.import_star:
4611 code.putln(
4612 'if (%s(%s) < 0) %s;' % (
4613 Naming.import_star,
4614 self.module.py_result(),
4615 code.error_goto(self.pos)))
4616 for cname, target in self.interned_items:
4617 code.putln(
4618 '%s = PyObject_GetAttr(%s, %s); %s' % (
4619 self.item.result(),
4620 self.module.py_result(),
4621 cname,
4622 code.error_goto_if_null(self.item.result(), self.pos)))
4623 code.put_gotref(self.item.py_result())
4624 target.generate_assignment_code(self.item, code)
4625 self.module.generate_disposal_code(code)
4626 self.module.free_temps(code)
4630 #------------------------------------------------------------------------------------
4632 # Runtime support code
4634 #------------------------------------------------------------------------------------
4636 utility_function_predeclarations = \
4637 """
4638 #ifdef __GNUC__
4639 #define INLINE __inline__
4640 #elif _WIN32
4641 #define INLINE __inline
4642 #else
4643 #define INLINE
4644 #endif
4646 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4648 """ + """
4650 static int %(skip_dispatch_cname)s = 0;
4652 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4654 if Options.gcc_branch_hints:
4655 branch_prediction_macros = \
4656 """
4657 #ifdef __GNUC__
4658 /* Test for GCC > 2.95 */
4659 #if __GNUC__ > 2 || \
4660 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4661 #define likely(x) __builtin_expect(!!(x), 1)
4662 #define unlikely(x) __builtin_expect(!!(x), 0)
4663 #else /* __GNUC__ > 2 ... */
4664 #define likely(x) (x)
4665 #define unlikely(x) (x)
4666 #endif /* __GNUC__ > 2 ... */
4667 #else /* __GNUC__ */
4668 #define likely(x) (x)
4669 #define unlikely(x) (x)
4670 #endif /* __GNUC__ */
4671 """
4672 else:
4673 branch_prediction_macros = \
4674 """
4675 #define likely(x) (x)
4676 #define unlikely(x) (x)
4677 """
4679 #get_name_predeclaration = \
4680 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4682 #get_name_interned_predeclaration = \
4683 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4685 #------------------------------------------------------------------------------------
4687 printing_utility_code = UtilityCode(
4688 proto = """
4689 static int __Pyx_Print(PyObject *, int); /*proto*/
4690 #if PY_MAJOR_VERSION >= 3
4691 static PyObject* %s = 0;
4692 static PyObject* %s = 0;
4693 #endif
4694 """ % (Naming.print_function, Naming.print_function_kwargs),
4695 impl = r"""
4696 #if PY_MAJOR_VERSION < 3
4697 static PyObject *__Pyx_GetStdout(void) {
4698 PyObject *f = PySys_GetObject((char *)"stdout");
4699 if (!f) {
4700 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4702 return f;
4705 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4706 PyObject *f;
4707 PyObject* v;
4708 int i;
4710 if (!(f = __Pyx_GetStdout()))
4711 return -1;
4712 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4713 if (PyFile_SoftSpace(f, 1)) {
4714 if (PyFile_WriteString(" ", f) < 0)
4715 return -1;
4717 v = PyTuple_GET_ITEM(arg_tuple, i);
4718 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4719 return -1;
4720 if (PyString_Check(v)) {
4721 char *s = PyString_AsString(v);
4722 Py_ssize_t len = PyString_Size(v);
4723 if (len > 0 &&
4724 isspace(Py_CHARMASK(s[len-1])) &&
4725 s[len-1] != ' ')
4726 PyFile_SoftSpace(f, 0);
4729 if (newline) {
4730 if (PyFile_WriteString("\n", f) < 0)
4731 return -1;
4732 PyFile_SoftSpace(f, 0);
4734 return 0;
4737 #else /* Python 3 has a print function */
4738 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4739 PyObject* kwargs = 0;
4740 PyObject* result = 0;
4741 PyObject* end_string;
4742 if (!%(PRINT_FUNCTION)s) {
4743 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4744 if (!%(PRINT_FUNCTION)s)
4745 return -1;
4747 if (!newline) {
4748 if (!%(PRINT_KWARGS)s) {
4749 %(PRINT_KWARGS)s = PyDict_New();
4750 if (!%(PRINT_KWARGS)s)
4751 return -1;
4752 end_string = PyUnicode_FromStringAndSize(" ", 1);
4753 if (!end_string)
4754 return -1;
4755 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4756 Py_DECREF(end_string);
4757 return -1;
4759 Py_DECREF(end_string);
4761 kwargs = %(PRINT_KWARGS)s;
4763 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4764 if (!result)
4765 return -1;
4766 Py_DECREF(result);
4767 return 0;
4769 #endif
4770 """ % {'BUILTINS' : Naming.builtins_cname,
4771 'PRINT_FUNCTION' : Naming.print_function,
4772 'PRINT_KWARGS' : Naming.print_function_kwargs}
4775 #------------------------------------------------------------------------------------
4777 # The following function is based on do_raise() from ceval.c.
4779 raise_utility_code = UtilityCode(
4780 proto = """
4781 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4782 """,
4783 impl = """
4784 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4785 Py_XINCREF(type);
4786 Py_XINCREF(value);
4787 Py_XINCREF(tb);
4788 /* First, check the traceback argument, replacing None with NULL. */
4789 if (tb == Py_None) {
4790 Py_DECREF(tb);
4791 tb = 0;
4793 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4794 PyErr_SetString(PyExc_TypeError,
4795 "raise: arg 3 must be a traceback or None");
4796 goto raise_error;
4798 /* Next, replace a missing value with None */
4799 if (value == NULL) {
4800 value = Py_None;
4801 Py_INCREF(value);
4803 #if PY_VERSION_HEX < 0x02050000
4804 if (!PyClass_Check(type))
4805 #else
4806 if (!PyType_Check(type))
4807 #endif
4809 /* Raising an instance. The value should be a dummy. */
4810 if (value != Py_None) {
4811 PyErr_SetString(PyExc_TypeError,
4812 "instance exception may not have a separate value");
4813 goto raise_error;
4815 /* Normalize to raise <class>, <instance> */
4816 Py_DECREF(value);
4817 value = type;
4818 #if PY_VERSION_HEX < 0x02050000
4819 if (PyInstance_Check(type)) {
4820 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4821 Py_INCREF(type);
4823 else {
4824 type = 0;
4825 PyErr_SetString(PyExc_TypeError,
4826 "raise: exception must be an old-style class or instance");
4827 goto raise_error;
4829 #else
4830 type = (PyObject*) Py_TYPE(type);
4831 Py_INCREF(type);
4832 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4833 PyErr_SetString(PyExc_TypeError,
4834 "raise: exception class must be a subclass of BaseException");
4835 goto raise_error;
4837 #endif
4839 __Pyx_ErrRestore(type, value, tb);
4840 return;
4841 raise_error:
4842 Py_XDECREF(value);
4843 Py_XDECREF(type);
4844 Py_XDECREF(tb);
4845 return;
4847 """)
4849 #------------------------------------------------------------------------------------
4851 reraise_utility_code = UtilityCode(
4852 proto = """
4853 static void __Pyx_ReRaise(void); /*proto*/
4854 """,
4855 impl = """
4856 static void __Pyx_ReRaise(void) {
4857 PyThreadState *tstate = PyThreadState_Get();
4858 PyObject *type = tstate->exc_type;
4859 PyObject *value = tstate->exc_value;
4860 PyObject *tb = tstate->exc_traceback;
4861 Py_XINCREF(type);
4862 Py_XINCREF(value);
4863 Py_XINCREF(tb);
4864 __Pyx_ErrRestore(type, value, tb);
4866 """)
4868 #------------------------------------------------------------------------------------
4870 arg_type_test_utility_code = UtilityCode(
4871 proto = """
4872 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4873 const char *name, int exact); /*proto*/
4874 """,
4875 impl = """
4876 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4877 const char *name, int exact)
4879 if (!type) {
4880 PyErr_Format(PyExc_SystemError, "Missing type object");
4881 return 0;
4883 if (none_allowed && obj == Py_None) return 1;
4884 else if (exact) {
4885 if (Py_TYPE(obj) == type) return 1;
4887 else {
4888 if (PyObject_TypeCheck(obj, type)) return 1;
4890 PyErr_Format(PyExc_TypeError,
4891 "Argument '%s' has incorrect type (expected %s, got %s)",
4892 name, type->tp_name, Py_TYPE(obj)->tp_name);
4893 return 0;
4895 """)
4897 #------------------------------------------------------------------------------------
4899 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
4900 # many or too few positional arguments were found. This handles
4901 # Py_ssize_t formatting correctly.
4903 raise_argtuple_invalid_utility_code = UtilityCode(
4904 proto = """
4905 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
4906 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
4907 """,
4908 impl = """
4909 static void __Pyx_RaiseArgtupleInvalid(
4910 const char* func_name,
4911 int exact,
4912 Py_ssize_t num_min,
4913 Py_ssize_t num_max,
4914 Py_ssize_t num_found)
4916 Py_ssize_t num_expected;
4917 const char *number, *more_or_less;
4919 if (num_found < num_min) {
4920 num_expected = num_min;
4921 more_or_less = "at least";
4922 } else {
4923 num_expected = num_max;
4924 more_or_less = "at most";
4926 if (exact) {
4927 more_or_less = "exactly";
4929 number = (num_expected == 1) ? "" : "s";
4930 PyErr_Format(PyExc_TypeError,
4931 #if PY_VERSION_HEX < 0x02050000
4932 "%s() takes %s %d positional argument%s (%d given)",
4933 #else
4934 "%s() takes %s %zd positional argument%s (%zd given)",
4935 #endif
4936 func_name, more_or_less, num_expected, number, num_found);
4938 """)
4940 raise_keyword_required_utility_code = UtilityCode(
4941 proto = """
4942 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
4943 """,
4944 impl = """
4945 static INLINE void __Pyx_RaiseKeywordRequired(
4946 const char* func_name,
4947 PyObject* kw_name)
4949 PyErr_Format(PyExc_TypeError,
4950 #if PY_MAJOR_VERSION >= 3
4951 "%s() needs keyword-only argument %U", func_name, kw_name);
4952 #else
4953 "%s() needs keyword-only argument %s", func_name,
4954 PyString_AS_STRING(kw_name));
4955 #endif
4957 """)
4959 raise_double_keywords_utility_code = UtilityCode(
4960 proto = """
4961 static void __Pyx_RaiseDoubleKeywordsError(
4962 const char* func_name, PyObject* kw_name); /*proto*/
4963 """,
4964 impl = """
4965 static void __Pyx_RaiseDoubleKeywordsError(
4966 const char* func_name,
4967 PyObject* kw_name)
4969 PyErr_Format(PyExc_TypeError,
4970 #if PY_MAJOR_VERSION >= 3
4971 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
4972 #else
4973 "%s() got multiple values for keyword argument '%s'", func_name,
4974 PyString_AS_STRING(kw_name));
4975 #endif
4977 """)
4979 #------------------------------------------------------------------------------------
4981 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
4982 # were passed to a function, or if any keywords were passed to a
4983 # function that does not accept them.
4985 keyword_string_check_utility_code = UtilityCode(
4986 proto = """
4987 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
4988 const char* function_name, int kw_allowed); /*proto*/
4989 """,
4990 impl = """
4991 static INLINE int __Pyx_CheckKeywordStrings(
4992 PyObject *kwdict,
4993 const char* function_name,
4994 int kw_allowed)
4996 PyObject* key = 0;
4997 Py_ssize_t pos = 0;
4998 while (PyDict_Next(kwdict, &pos, &key, 0)) {
4999 #if PY_MAJOR_VERSION < 3
5000 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5001 #else
5002 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5003 #endif
5004 goto invalid_keyword_type;
5006 if ((!kw_allowed) && unlikely(key))
5007 goto invalid_keyword;
5008 return 1;
5009 invalid_keyword_type:
5010 PyErr_Format(PyExc_TypeError,
5011 "%s() keywords must be strings", function_name);
5012 return 0;
5013 invalid_keyword:
5014 PyErr_Format(PyExc_TypeError,
5015 #if PY_MAJOR_VERSION < 3
5016 "%s() got an unexpected keyword argument '%s'",
5017 function_name, PyString_AsString(key));
5018 #else
5019 "%s() got an unexpected keyword argument '%U'",
5020 function_name, key);
5021 #endif
5022 return 0;
5024 """)
5026 #------------------------------------------------------------------------------------
5028 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5029 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5030 # keywords will raise an invalid keyword error.
5032 # Three kinds of errors are checked: 1) non-string keywords, 2)
5033 # unexpected keywords and 3) overlap with positional arguments.
5035 # If num_posargs is greater 0, it denotes the number of positional
5036 # arguments that were passed and that must therefore not appear
5037 # amongst the keywords as well.
5039 # This method does not check for required keyword arguments.
5042 parse_keywords_utility_code = UtilityCode(
5043 proto = """
5044 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5045 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5046 const char* function_name); /*proto*/
5047 """,
5048 impl = """
5049 static int __Pyx_ParseOptionalKeywords(
5050 PyObject *kwds,
5051 PyObject **argnames[],
5052 PyObject *kwds2,
5053 PyObject *values[],
5054 Py_ssize_t num_pos_args,
5055 const char* function_name)
5057 PyObject *key = 0, *value = 0;
5058 Py_ssize_t pos = 0;
5059 PyObject*** name;
5060 PyObject*** first_kw_arg = argnames + num_pos_args;
5062 while (PyDict_Next(kwds, &pos, &key, &value)) {
5063 name = first_kw_arg;
5064 while (*name && (**name != key)) name++;
5065 if (*name) {
5066 values[name-argnames] = value;
5067 } else {
5068 #if PY_MAJOR_VERSION < 3
5069 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5070 #else
5071 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5072 #endif
5073 goto invalid_keyword_type;
5074 } else {
5075 for (name = first_kw_arg; *name; name++) {
5076 #if PY_MAJOR_VERSION >= 3
5077 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5078 PyUnicode_Compare(**name, key) == 0) break;
5079 #else
5080 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5081 strcmp(PyString_AS_STRING(**name),
5082 PyString_AS_STRING(key)) == 0) break;
5083 #endif
5085 if (*name) {
5086 values[name-argnames] = value;
5087 } else {
5088 /* unexpected keyword found */
5089 for (name=argnames; name != first_kw_arg; name++) {
5090 if (**name == key) goto arg_passed_twice;
5091 #if PY_MAJOR_VERSION >= 3
5092 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5093 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5094 #else
5095 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5096 strcmp(PyString_AS_STRING(**name),
5097 PyString_AS_STRING(key)) == 0) goto arg_passed_twice;
5098 #endif
5100 if (kwds2) {
5101 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5102 } else {
5103 goto invalid_keyword;
5109 return 0;
5110 arg_passed_twice:
5111 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5112 goto bad;
5113 invalid_keyword_type:
5114 PyErr_Format(PyExc_TypeError,
5115 "%s() keywords must be strings", function_name);
5116 goto bad;
5117 invalid_keyword:
5118 PyErr_Format(PyExc_TypeError,
5119 #if PY_MAJOR_VERSION < 3
5120 "%s() got an unexpected keyword argument '%s'",
5121 function_name, PyString_AsString(key));
5122 #else
5123 "%s() got an unexpected keyword argument '%U'",
5124 function_name, key);
5125 #endif
5126 bad:
5127 return -1;
5129 """)
5131 #------------------------------------------------------------------------------------
5133 unraisable_exception_utility_code = UtilityCode(
5134 proto = """
5135 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5136 """,
5137 impl = """
5138 static void __Pyx_WriteUnraisable(const char *name) {
5139 PyObject *old_exc, *old_val, *old_tb;
5140 PyObject *ctx;
5141 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5142 #if PY_MAJOR_VERSION < 3
5143 ctx = PyString_FromString(name);
5144 #else
5145 ctx = PyUnicode_FromString(name);
5146 #endif
5147 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5148 if (!ctx) {
5149 PyErr_WriteUnraisable(Py_None);
5150 } else {
5151 PyErr_WriteUnraisable(ctx);
5152 Py_DECREF(ctx);
5155 """)
5157 #------------------------------------------------------------------------------------
5159 traceback_utility_code = UtilityCode(
5160 proto = """
5161 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5162 """,
5163 impl = """
5164 #include "compile.h"
5165 #include "frameobject.h"
5166 #include "traceback.h"
5168 static void __Pyx_AddTraceback(const char *funcname) {
5169 PyObject *py_srcfile = 0;
5170 PyObject *py_funcname = 0;
5171 PyObject *py_globals = 0;
5172 PyObject *empty_string = 0;
5173 PyCodeObject *py_code = 0;
5174 PyFrameObject *py_frame = 0;
5176 #if PY_MAJOR_VERSION < 3
5177 py_srcfile = PyString_FromString(%(FILENAME)s);
5178 #else
5179 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5180 #endif
5181 if (!py_srcfile) goto bad;
5182 if (%(CLINENO)s) {
5183 #if PY_MAJOR_VERSION < 3
5184 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5185 #else
5186 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5187 #endif
5189 else {
5190 #if PY_MAJOR_VERSION < 3
5191 py_funcname = PyString_FromString(funcname);
5192 #else
5193 py_funcname = PyUnicode_FromString(funcname);
5194 #endif
5196 if (!py_funcname) goto bad;
5197 py_globals = PyModule_GetDict(%(GLOBALS)s);
5198 if (!py_globals) goto bad;
5199 #if PY_MAJOR_VERSION < 3
5200 empty_string = PyString_FromStringAndSize("", 0);
5201 #else
5202 empty_string = PyBytes_FromStringAndSize("", 0);
5203 #endif
5204 if (!empty_string) goto bad;
5205 py_code = PyCode_New(
5206 0, /*int argcount,*/
5207 #if PY_MAJOR_VERSION >= 3
5208 0, /*int kwonlyargcount,*/
5209 #endif
5210 0, /*int nlocals,*/
5211 0, /*int stacksize,*/
5212 0, /*int flags,*/
5213 empty_string, /*PyObject *code,*/
5214 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5215 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5216 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5217 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5218 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5219 py_srcfile, /*PyObject *filename,*/
5220 py_funcname, /*PyObject *name,*/
5221 %(LINENO)s, /*int firstlineno,*/
5222 empty_string /*PyObject *lnotab*/
5223 );
5224 if (!py_code) goto bad;
5225 py_frame = PyFrame_New(
5226 PyThreadState_GET(), /*PyThreadState *tstate,*/
5227 py_code, /*PyCodeObject *code,*/
5228 py_globals, /*PyObject *globals,*/
5229 0 /*PyObject *locals*/
5230 );
5231 if (!py_frame) goto bad;
5232 py_frame->f_lineno = %(LINENO)s;
5233 PyTraceBack_Here(py_frame);
5234 bad:
5235 Py_XDECREF(py_srcfile);
5236 Py_XDECREF(py_funcname);
5237 Py_XDECREF(empty_string);
5238 Py_XDECREF(py_code);
5239 Py_XDECREF(py_frame);
5241 """ % {
5242 'FILENAME': Naming.filename_cname,
5243 'LINENO': Naming.lineno_cname,
5244 'CFILENAME': Naming.cfilenm_cname,
5245 'CLINENO': Naming.clineno_cname,
5246 'GLOBALS': Naming.module_cname,
5247 'EMPTY_TUPLE' : Naming.empty_tuple,
5248 })
5250 restore_exception_utility_code = UtilityCode(
5251 proto = """
5252 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5253 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5254 """,
5255 impl = """
5256 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5257 PyObject *tmp_type, *tmp_value, *tmp_tb;
5258 PyThreadState *tstate = PyThreadState_GET();
5260 tmp_type = tstate->curexc_type;
5261 tmp_value = tstate->curexc_value;
5262 tmp_tb = tstate->curexc_traceback;
5263 tstate->curexc_type = type;
5264 tstate->curexc_value = value;
5265 tstate->curexc_traceback = tb;
5266 Py_XDECREF(tmp_type);
5267 Py_XDECREF(tmp_value);
5268 Py_XDECREF(tmp_tb);
5271 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5272 PyThreadState *tstate = PyThreadState_GET();
5273 *type = tstate->curexc_type;
5274 *value = tstate->curexc_value;
5275 *tb = tstate->curexc_traceback;
5277 tstate->curexc_type = 0;
5278 tstate->curexc_value = 0;
5279 tstate->curexc_traceback = 0;
5282 """)
5284 #------------------------------------------------------------------------------------
5286 set_vtable_utility_code = UtilityCode(
5287 proto = """
5288 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5289 """,
5290 impl = """
5291 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5292 PyObject *pycobj = 0;
5293 int result;
5295 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5296 if (!pycobj)
5297 goto bad;
5298 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5299 goto bad;
5300 result = 0;
5301 goto done;
5303 bad:
5304 result = -1;
5305 done:
5306 Py_XDECREF(pycobj);
5307 return result;
5309 """)
5311 #------------------------------------------------------------------------------------
5313 get_vtable_utility_code = UtilityCode(
5314 proto = """
5315 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5316 """,
5317 impl = r"""
5318 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5319 int result;
5320 PyObject *pycobj;
5322 pycobj = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5323 if (!pycobj)
5324 goto bad;
5325 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5326 if (!*(void **)vtabptr)
5327 goto bad;
5328 result = 0;
5329 goto done;
5331 bad:
5332 result = -1;
5333 done:
5334 Py_XDECREF(pycobj);
5335 return result;
5337 """)
5339 #------------------------------------------------------------------------------------
5341 init_string_tab_utility_code = UtilityCode(
5342 proto = """
5343 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5344 """,
5345 impl = """
5346 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5347 while (t->p) {
5348 #if PY_MAJOR_VERSION < 3
5349 if (t->is_unicode && (!t->is_identifier)) {
5350 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5351 } else if (t->intern) {
5352 *t->p = PyString_InternFromString(t->s);
5353 } else {
5354 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5356 #else /* Python 3+ has unicode identifiers */
5357 if (t->is_identifier || (t->is_unicode && t->intern)) {
5358 *t->p = PyUnicode_InternFromString(t->s);
5359 } else if (t->is_unicode) {
5360 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5361 } else {
5362 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5364 #endif
5365 if (!*t->p)
5366 return -1;
5367 ++t;
5369 return 0;
5371 """)
5373 #------------------------------------------------------------------------------------
5375 get_exception_utility_code = UtilityCode(
5376 proto = """
5377 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5378 """,
5379 impl = """
5380 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5381 PyObject *tmp_type, *tmp_value, *tmp_tb;
5382 PyThreadState *tstate = PyThreadState_GET();
5383 __Pyx_ErrFetch(type, value, tb);
5384 PyErr_NormalizeException(type, value, tb);
5385 if (PyErr_Occurred())
5386 goto bad;
5387 Py_INCREF(*type);
5388 Py_INCREF(*value);
5389 Py_INCREF(*tb);
5390 tmp_type = tstate->exc_type;
5391 tmp_value = tstate->exc_value;
5392 tmp_tb = tstate->exc_traceback;
5393 tstate->exc_type = *type;
5394 tstate->exc_value = *value;
5395 tstate->exc_traceback = *tb;
5396 /* Make sure tstate is in a consistent state when we XDECREF
5397 these objects (XDECREF may run arbitrary code). */
5398 Py_XDECREF(tmp_type);
5399 Py_XDECREF(tmp_value);
5400 Py_XDECREF(tmp_tb);
5401 return 0;
5402 bad:
5403 Py_XDECREF(*type);
5404 Py_XDECREF(*value);
5405 Py_XDECREF(*tb);
5406 return -1;
5409 """)
5411 #------------------------------------------------------------------------------------
5413 reset_exception_utility_code = UtilityCode(
5414 proto = """
5415 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5416 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5417 """,
5418 impl = """
5419 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5420 PyThreadState *tstate = PyThreadState_GET();
5421 *type = tstate->exc_type;
5422 *value = tstate->exc_value;
5423 *tb = tstate->exc_traceback;
5424 Py_XINCREF(*type);
5425 Py_XINCREF(*value);
5426 Py_XINCREF(*tb);
5429 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5430 PyObject *tmp_type, *tmp_value, *tmp_tb;
5431 PyThreadState *tstate = PyThreadState_GET();
5432 tmp_type = tstate->exc_type;
5433 tmp_value = tstate->exc_value;
5434 tmp_tb = tstate->exc_traceback;
5435 tstate->exc_type = type;
5436 tstate->exc_value = value;
5437 tstate->exc_traceback = tb;
5438 Py_XDECREF(tmp_type);
5439 Py_XDECREF(tmp_value);
5440 Py_XDECREF(tmp_tb);
5442 """)
5444 #------------------------------------------------------------------------------------