Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 1657:c2644f9a212d

Fix #117
author Dag Sverre Seljebotn <dagss@student.matnat.uio.no>
date Mon Jan 26 18:12:56 2009 +0100 (3 years ago)
parents 189c4e45461f
children ac06996d68f9
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 is_getbuffer_slot:
1072 self.getbuffer_init(code)
1073 if not lenv.nogil:
1074 code.put_setup_refcount_context(self.entry.name)
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)
1258 def getbuffer_error_cleanup(self, code):
1259 info = self.local_scope.arg_entries[1].cname
1260 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1261 (info, info))
1263 def getbuffer_normal_cleanup(self, code):
1264 info = self.local_scope.arg_entries[1].cname
1265 code.putln("if (%s->obj == Py_None) { __Pyx_DECREF(Py_None); %s->obj = NULL; }" %
1266 (info, info))
1268 class CFuncDefNode(FuncDefNode):
1269 # C function definition.
1271 # modifiers ['inline']
1272 # visibility 'private' or 'public' or 'extern'
1273 # base_type CBaseTypeNode
1274 # declarator CDeclaratorNode
1275 # body StatListNode
1276 # api boolean
1278 # with_gil boolean Acquire GIL around body
1279 # type CFuncType
1280 # py_func wrapper for calling from Python
1281 # overridable whether or not this is a cpdef function
1282 # inline_in_pxd whether this is an inline function in a pxd file
1284 child_attrs = ["base_type", "declarator", "body", "py_func"]
1286 inline_in_pxd = False
1288 def unqualified_name(self):
1289 return self.entry.name
1291 def analyse_declarations(self, env):
1292 if 'locals' in env.directives:
1293 directive_locals = env.directives['locals']
1294 else:
1295 directive_locals = {}
1296 self.directive_locals = directive_locals
1297 base_type = self.base_type.analyse(env)
1298 # The 2 here is because we need both function and argument names.
1299 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1300 if not type.is_cfunction:
1301 error(self.pos,
1302 "Suite attached to non-function declaration")
1303 # Remember the actual type according to the function header
1304 # written here, because the type in the symbol table entry
1305 # may be different if we're overriding a C method inherited
1306 # from the base type of an extension type.
1307 self.type = type
1308 type.is_overridable = self.overridable
1309 declarator = self.declarator
1310 while not hasattr(declarator, 'args'):
1311 declarator = declarator.base
1312 self.args = declarator.args
1313 for formal_arg, type_arg in zip(self.args, type.args):
1314 formal_arg.type = type_arg.type
1315 formal_arg.name = type_arg.name
1316 formal_arg.cname = type_arg.cname
1317 name = name_declarator.name
1318 cname = name_declarator.cname
1319 self.entry = env.declare_cfunction(
1320 name, type, self.pos,
1321 cname = cname, visibility = self.visibility,
1322 defining = self.body is not None,
1323 api = self.api, modifiers = self.modifiers)
1324 self.entry.inline_func_in_pxd = self.inline_in_pxd
1325 self.return_type = type.return_type
1327 if self.overridable:
1328 import ExprNodes
1329 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1330 self.py_func = DefNode(pos = self.pos,
1331 name = self.entry.name,
1332 args = self.args,
1333 star_arg = None,
1334 starstar_arg = None,
1335 doc = self.doc,
1336 body = py_func_body,
1337 is_wrapper = 1)
1338 self.py_func.is_module_scope = env.is_module_scope
1339 self.py_func.analyse_declarations(env)
1340 self.entry.as_variable = self.py_func.entry
1341 # Reset scope entry the above cfunction
1342 env.entries[name] = self.entry
1343 self.py_func.interned_attr_cname = env.intern_identifier(
1344 self.py_func.entry.name)
1345 if not env.is_module_scope or Options.lookup_module_cpdef:
1346 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1347 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1349 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1350 import ExprNodes
1351 args = self.type.args
1352 if omit_optional_args:
1353 args = args[:len(args) - self.type.optional_arg_count]
1354 arg_names = [arg.name for arg in args]
1355 if is_module_scope:
1356 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1357 else:
1358 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1359 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1360 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1361 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)
1362 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1364 def declare_arguments(self, env):
1365 for arg in self.type.args:
1366 if not arg.name:
1367 error(arg.pos, "Missing argument name")
1368 self.declare_argument(env, arg)
1370 def need_gil_acquisition(self, lenv):
1371 type = self.type
1372 with_gil = self.type.with_gil
1373 if type.nogil and not with_gil:
1374 if type.return_type.is_pyobject:
1375 error(self.pos,
1376 "Function with Python return type cannot be declared nogil")
1377 for entry in lenv.var_entries + lenv.temp_entries:
1378 if entry.type.is_pyobject:
1379 error(self.pos, "Function declared nogil has Python locals or temporaries")
1380 return with_gil
1382 def analyse_expressions(self, env):
1383 self.analyse_default_values(env)
1384 if self.overridable:
1385 self.py_func.analyse_expressions(env)
1387 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1388 arg_decls = []
1389 type = self.type
1390 visibility = self.entry.visibility
1391 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1392 arg_decls.append(arg.declaration_code())
1393 if with_dispatch and self.overridable:
1394 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1395 if type.optional_arg_count and with_opt_args:
1396 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1397 if type.has_varargs:
1398 arg_decls.append("...")
1399 if not arg_decls:
1400 arg_decls = ["void"]
1401 if cname is None:
1402 cname = self.entry.func_cname
1403 entity = type.function_header_code(cname, string.join(arg_decls, ", "))
1404 if visibility == 'public':
1405 dll_linkage = "DL_EXPORT"
1406 else:
1407 dll_linkage = None
1408 header = self.return_type.declaration_code(entity,
1409 dll_linkage = dll_linkage)
1410 if visibility == 'extern':
1411 storage_class = "%s " % Naming.extern_c_macro
1412 elif visibility == 'public':
1413 storage_class = ""
1414 else:
1415 storage_class = "static "
1416 code.putln("%s%s %s {" % (
1417 storage_class,
1418 ' '.join(self.modifiers).upper(), # macro forms
1419 header))
1421 def generate_argument_declarations(self, env, code):
1422 for arg in self.args:
1423 if arg.default:
1424 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1426 def generate_keyword_list(self, code):
1427 pass
1429 def generate_argument_parsing_code(self, env, code):
1430 i = 0
1431 if self.type.optional_arg_count:
1432 code.putln('if (%s) {' % Naming.optional_args_cname)
1433 for arg in self.args:
1434 if arg.default:
1435 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1436 declarator = arg.declarator
1437 while not hasattr(declarator, 'name'):
1438 declarator = declarator.base
1439 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1440 i += 1
1441 for _ in range(self.type.optional_arg_count):
1442 code.putln('}')
1443 code.putln('}')
1445 def generate_argument_conversion_code(self, code):
1446 pass
1448 def generate_argument_type_tests(self, code):
1449 # Generate type tests for args whose type in a parent
1450 # class is a supertype of the declared type.
1451 for arg in self.type.args:
1452 if arg.needs_type_test:
1453 self.generate_arg_type_test(arg, code)
1455 def generate_arg_type_test(self, arg, code):
1456 # Generate type test for one argument.
1457 if arg.type.typeobj_is_available():
1458 typeptr_cname = arg.type.typeptr_cname
1459 arg_code = "((PyObject *)%s)" % arg.cname
1460 code.putln(
1461 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1462 arg_code,
1463 typeptr_cname,
1464 not arg.not_none,
1465 arg.name,
1466 type.is_builtin_type,
1467 code.error_goto(arg.pos)))
1468 else:
1469 error(arg.pos, "Cannot test type of extern C class "
1470 "without type object name specification")
1472 def error_value(self):
1473 if self.return_type.is_pyobject:
1474 return "0"
1475 else:
1476 #return None
1477 return self.entry.type.exception_value
1479 def caller_will_check_exceptions(self):
1480 return self.entry.type.exception_check
1482 def generate_wrapper_functions(self, code):
1483 # If the C signature of a function has changed, we need to generate
1484 # wrappers to put in the slots here.
1485 k = 0
1486 entry = self.entry
1487 func_type = entry.type
1488 while entry.prev_entry is not None:
1489 k += 1
1490 entry = entry.prev_entry
1491 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1492 code.putln()
1493 self.generate_function_header(code,
1494 0,
1495 with_dispatch = entry.type.is_overridable,
1496 with_opt_args = entry.type.optional_arg_count,
1497 cname = entry.func_cname)
1498 if not self.return_type.is_void:
1499 code.put('return ')
1500 args = self.type.args
1501 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1502 if entry.type.is_overridable:
1503 arglist.append(Naming.skip_dispatch_cname)
1504 elif func_type.is_overridable:
1505 arglist.append('0')
1506 if entry.type.optional_arg_count:
1507 arglist.append(Naming.optional_args_cname)
1508 elif func_type.optional_arg_count:
1509 arglist.append('NULL')
1510 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1511 code.putln('}')
1514 class PyArgDeclNode(Node):
1515 # Argument which must be a Python object (used
1516 # for * and ** arguments).
1518 # name string
1519 # entry Symtab.Entry
1520 child_attrs = []
1523 class DecoratorNode(Node):
1524 # A decorator
1526 # decorator NameNode or CallNode
1527 child_attrs = ['decorator']
1530 class DefNode(FuncDefNode):
1531 # A Python function definition.
1533 # name string the Python name of the function
1534 # decorators [DecoratorNode] list of decorators
1535 # args [CArgDeclNode] formal arguments
1536 # star_arg PyArgDeclNode or None * argument
1537 # starstar_arg PyArgDeclNode or None ** argument
1538 # doc EncodedString or None
1539 # body StatListNode
1541 # The following subnode is constructed internally
1542 # when the def statement is inside a Python class definition.
1544 # assmt AssignmentNode Function construction/assignment
1546 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1548 assmt = None
1549 num_kwonly_args = 0
1550 num_required_kw_args = 0
1551 reqd_kw_flags_cname = "0"
1552 is_wrapper = 0
1553 decorators = None
1554 entry = None
1557 def __init__(self, pos, **kwds):
1558 FuncDefNode.__init__(self, pos, **kwds)
1559 k = rk = r = 0
1560 for arg in self.args:
1561 if arg.kw_only:
1562 k += 1
1563 if not arg.default:
1564 rk += 1
1565 if not arg.default:
1566 r += 1
1567 self.num_kwonly_args = k
1568 self.num_required_kw_args = rk
1569 self.num_required_args = r
1571 def as_cfunction(self, cfunc=None, scope=None):
1572 if self.star_arg:
1573 error(self.star_arg.pos, "cdef function cannot have star argument")
1574 if self.starstar_arg:
1575 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1576 if cfunc is None:
1577 cfunc_args = []
1578 for formal_arg in self.args:
1579 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1580 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1581 cname = None,
1582 type = py_object_type,
1583 pos = formal_arg.pos))
1584 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1585 args = cfunc_args,
1586 has_varargs = False,
1587 exception_value = None,
1588 exception_check = False,
1589 nogil = False,
1590 with_gil = False,
1591 is_overridable = True)
1592 cfunc = CVarDefNode(self.pos, type=cfunc_type, pxd_locals=[])
1593 else:
1594 cfunc_type = cfunc.type
1595 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1596 error(self.pos, "wrong number of arguments")
1597 error(declarator.pos, "previous declaration here")
1598 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1599 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1600 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1601 formal_arg.type = type_arg.type
1602 formal_arg.name_declarator = name_declarator
1603 import ExprNodes
1604 if cfunc_type.exception_value is None:
1605 exception_value = None
1606 else:
1607 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1608 declarator = CFuncDeclaratorNode(self.pos,
1609 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1610 args = self.args,
1611 has_varargs = False,
1612 exception_check = cfunc_type.exception_check,
1613 exception_value = exception_value,
1614 with_gil = cfunc_type.with_gil,
1615 nogil = cfunc_type.nogil)
1616 return CFuncDefNode(self.pos,
1617 modifiers = [],
1618 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1619 declarator = declarator,
1620 body = self.body,
1621 doc = self.doc,
1622 overridable = cfunc_type.is_overridable,
1623 type = cfunc_type,
1624 with_gil = cfunc_type.with_gil,
1625 nogil = cfunc_type.nogil,
1626 visibility = 'private',
1627 api = False,
1628 pxd_locals = cfunc.pxd_locals)
1630 def analyse_declarations(self, env):
1631 if 'locals' in env.directives:
1632 directive_locals = env.directives['locals']
1633 else:
1634 directive_locals = {}
1635 self.directive_locals = directive_locals
1636 for arg in self.args:
1637 if hasattr(arg, 'name'):
1638 type = arg.type
1639 name_declarator = None
1640 else:
1641 base_type = arg.base_type.analyse(env)
1642 name_declarator, type = \
1643 arg.declarator.analyse(base_type, env)
1644 arg.name = name_declarator.name
1645 if arg.name in directive_locals:
1646 type_node = directive_locals[arg.name]
1647 other_type = type_node.analyse_as_type(env)
1648 if other_type is None:
1649 error(type_node.pos, "Not a type")
1650 elif (type is not PyrexTypes.py_object_type
1651 and not type.same_as(other_type)):
1652 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1653 error(type_node.pos, "Previous declaration here")
1654 else:
1655 type = other_type
1656 if name_declarator and name_declarator.cname:
1657 error(self.pos,
1658 "Python function argument cannot have C name specification")
1659 arg.type = type.as_argument_type()
1660 arg.hdr_type = None
1661 arg.needs_conversion = 0
1662 arg.needs_type_test = 0
1663 arg.is_generic = 1
1664 if arg.not_none and not arg.type.is_extension_type:
1665 error(self.pos,
1666 "Only extension type arguments can have 'not None'")
1667 self.declare_pyfunction(env)
1668 self.analyse_signature(env)
1669 self.return_type = self.entry.signature.return_type()
1671 def analyse_signature(self, env):
1672 any_type_tests_needed = 0
1673 # Use the simpler calling signature for zero- and one-argument functions.
1674 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1675 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1676 if len(self.args) == 0:
1677 self.entry.signature = TypeSlots.pyfunction_noargs
1678 elif len(self.args) == 1:
1679 if self.args[0].default is None and not self.args[0].kw_only:
1680 self.entry.signature = TypeSlots.pyfunction_onearg
1681 elif self.entry.signature is TypeSlots.pymethod_signature:
1682 if len(self.args) == 1:
1683 self.entry.signature = TypeSlots.unaryfunc
1684 elif len(self.args) == 2:
1685 if self.args[1].default is None and not self.args[1].kw_only:
1686 self.entry.signature = TypeSlots.ibinaryfunc
1687 elif self.entry.is_special:
1688 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1689 sig = self.entry.signature
1690 nfixed = sig.num_fixed_args()
1691 for i in range(nfixed):
1692 if i < len(self.args):
1693 arg = self.args[i]
1694 arg.is_generic = 0
1695 if sig.is_self_arg(i):
1696 arg.is_self_arg = 1
1697 arg.hdr_type = arg.type = env.parent_type
1698 arg.needs_conversion = 0
1699 else:
1700 arg.hdr_type = sig.fixed_arg_type(i)
1701 if not arg.type.same_as(arg.hdr_type):
1702 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1703 arg.needs_type_test = 1
1704 any_type_tests_needed = 1
1705 else:
1706 arg.needs_conversion = 1
1707 if arg.needs_conversion:
1708 arg.hdr_cname = Naming.arg_prefix + arg.name
1709 else:
1710 arg.hdr_cname = Naming.var_prefix + arg.name
1711 else:
1712 self.bad_signature()
1713 return
1714 if nfixed < len(self.args):
1715 if not sig.has_generic_args:
1716 self.bad_signature()
1717 for arg in self.args:
1718 if arg.is_generic and \
1719 (arg.type.is_extension_type or arg.type.is_builtin_type):
1720 arg.needs_type_test = 1
1721 any_type_tests_needed = 1
1722 elif arg.type is PyrexTypes.c_py_ssize_t_type:
1723 # Want to use __index__ rather than __int__ method
1724 # that PyArg_ParseTupleAndKeywords calls
1725 arg.needs_conversion = 1
1726 arg.hdr_type = PyrexTypes.py_object_type
1727 arg.hdr_cname = Naming.arg_prefix + arg.name
1728 if any_type_tests_needed:
1729 env.use_utility_code(arg_type_test_utility_code)
1731 def bad_signature(self):
1732 sig = self.entry.signature
1733 expected_str = "%d" % sig.num_fixed_args()
1734 if sig.has_generic_args:
1735 expected_str = expected_str + " or more"
1736 name = self.name
1737 if name.startswith("__") and name.endswith("__"):
1738 desc = "Special method"
1739 else:
1740 desc = "Method"
1741 error(self.pos,
1742 "%s %s has wrong number of arguments "
1743 "(%d declared, %s expected)" % (
1744 desc, self.name, len(self.args), expected_str))
1746 def signature_has_nongeneric_args(self):
1747 argcount = len(self.args)
1748 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1749 return 0
1750 return 1
1752 def signature_has_generic_args(self):
1753 return self.entry.signature.has_generic_args
1755 def declare_pyfunction(self, env):
1756 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1757 name = self.name
1758 entry = env.lookup_here(self.name)
1759 if entry and entry.type.is_cfunction and not self.is_wrapper:
1760 warning(self.pos, "Overriding cdef method with def method.", 5)
1761 entry = env.declare_pyfunction(self.name, self.pos)
1762 self.entry = entry
1763 prefix = env.scope_prefix
1764 entry.func_cname = \
1765 Naming.pyfunc_prefix + prefix + name
1766 entry.pymethdef_cname = \
1767 Naming.pymethdef_prefix + prefix + name
1768 if Options.docstrings:
1769 entry.doc = embed_position(self.pos, self.doc)
1770 entry.doc_cname = \
1771 Naming.funcdoc_prefix + prefix + name
1772 else:
1773 entry.doc = None
1775 def declare_arguments(self, env):
1776 for arg in self.args:
1777 if not arg.name:
1778 error(arg.pos, "Missing argument name")
1779 if arg.needs_conversion:
1780 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1781 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1782 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1783 if arg.type.is_pyobject:
1784 arg.entry.init = "0"
1785 arg.entry.init_to_none = 0
1786 else:
1787 arg.entry = self.declare_argument(env, arg)
1788 arg.entry.used = 1
1789 arg.entry.is_self_arg = arg.is_self_arg
1790 if not arg.is_self_arg:
1791 arg.name_entry = env.get_string_const(
1792 arg.name, identifier = True)
1793 env.add_py_string(arg.name_entry, identifier = True)
1794 if arg.hdr_type:
1795 if arg.is_self_arg or \
1796 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1797 arg.entry.is_declared_generic = 1
1798 self.declare_python_arg(env, self.star_arg)
1799 self.declare_python_arg(env, self.starstar_arg)
1801 def declare_python_arg(self, env, arg):
1802 if arg:
1803 entry = env.declare_var(arg.name,
1804 PyrexTypes.py_object_type, arg.pos)
1805 entry.used = 1
1806 entry.init = "0"
1807 entry.init_to_none = 0
1808 entry.xdecref_cleanup = 1
1809 arg.entry = entry
1810 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1812 def analyse_expressions(self, env):
1813 self.analyse_default_values(env)
1814 if env.is_py_class_scope:
1815 self.synthesize_assignment_node(env)
1817 def synthesize_assignment_node(self, env):
1818 import ExprNodes
1819 self.assmt = SingleAssignmentNode(self.pos,
1820 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1821 rhs = ExprNodes.UnboundMethodNode(self.pos,
1822 class_cname = env.class_obj_cname,
1823 function = ExprNodes.PyCFunctionNode(self.pos,
1824 pymethdef_cname = self.entry.pymethdef_cname)))
1825 self.assmt.analyse_declarations(env)
1826 self.assmt.analyse_expressions(env)
1828 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1829 arg_code_list = []
1830 sig = self.entry.signature
1831 if sig.has_dummy_arg:
1832 arg_code_list.append(
1833 "PyObject *%s" % Naming.self_cname)
1834 for arg in self.args:
1835 if not arg.is_generic:
1836 if arg.is_self_arg:
1837 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1838 else:
1839 arg_code_list.append(
1840 arg.hdr_type.declaration_code(arg.hdr_cname))
1841 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1842 arg_code_list.append("PyObject *unused")
1843 if sig.has_generic_args:
1844 arg_code_list.append(
1845 "PyObject *%s, PyObject *%s"
1846 % (Naming.args_cname, Naming.kwds_cname))
1847 arg_code = ", ".join(arg_code_list)
1848 dc = self.return_type.declaration_code(self.entry.func_cname)
1849 header = "static %s(%s)" % (dc, arg_code)
1850 code.putln("%s; /*proto*/" % header)
1851 if proto_only:
1852 return
1853 if self.entry.doc and Options.docstrings:
1854 docstr = self.entry.doc
1855 if not isinstance(docstr, str):
1856 docstr = docstr.utf8encode()
1857 code.putln(
1858 'static char %s[] = "%s";' % (
1859 self.entry.doc_cname,
1860 split_docstring(escape_byte_string(docstr))))
1861 if with_pymethdef:
1862 code.put(
1863 "static PyMethodDef %s = " %
1864 self.entry.pymethdef_cname)
1865 code.put_pymethoddef(self.entry, ";")
1866 code.putln("%s {" % header)
1868 def generate_argument_declarations(self, env, code):
1869 for arg in self.args:
1870 if arg.is_generic: # or arg.needs_conversion:
1871 if arg.needs_conversion:
1872 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1873 else:
1874 code.put_var_declaration(arg.entry)
1876 def generate_keyword_list(self, code):
1877 if self.signature_has_generic_args() and \
1878 self.signature_has_nongeneric_args():
1879 code.put(
1880 "static PyObject **%s[] = {" %
1881 Naming.pykwdlist_cname)
1882 for arg in self.args:
1883 if arg.is_generic:
1884 code.put('&%s,' % arg.name_entry.pystring_cname)
1885 code.putln("0};")
1887 def generate_argument_parsing_code(self, env, code):
1888 # Generate PyArg_ParseTuple call for generic
1889 # arguments, if any.
1890 if self.entry.signature.has_dummy_arg:
1891 # get rid of unused argument warning
1892 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1894 old_error_label = code.new_error_label()
1895 our_error_label = code.error_label
1896 end_label = code.new_label("argument_unpacking_done")
1898 has_kwonly_args = self.num_kwonly_args > 0
1899 has_star_or_kw_args = self.star_arg is not None \
1900 or self.starstar_arg is not None or has_kwonly_args
1902 if not self.signature_has_generic_args():
1903 if has_star_or_kw_args:
1904 error(self.pos, "This method cannot have * or keyword arguments")
1905 self.generate_argument_conversion_code(code)
1907 elif not self.signature_has_nongeneric_args():
1908 # func(*args) or func(**kw) or func(*args, **kw)
1909 self.generate_stararg_copy_code(code)
1911 else:
1912 positional_args = []
1913 kw_only_args = []
1914 default_seen = 0
1915 for arg in self.args:
1916 arg_entry = arg.entry
1917 if arg.is_generic:
1918 if arg.default:
1919 default_seen = 1
1920 if not arg.is_self_arg:
1921 if arg.kw_only:
1922 kw_only_args.append(arg)
1923 else:
1924 positional_args.append(arg)
1925 elif arg.kw_only:
1926 kw_only_args.append(arg)
1927 default_seen = 1
1928 elif default_seen:
1929 error(arg.pos, "Non-default argument following default argument")
1930 elif not arg.is_self_arg:
1931 positional_args.append(arg)
1932 if arg.needs_conversion:
1933 format = arg.hdr_type.parsetuple_format
1934 else:
1935 format = arg_entry.type.parsetuple_format
1936 if not format:
1937 error(arg.pos,
1938 "Cannot convert Python object argument to type '%s' (when parsing input arguments)"
1939 % arg.type)
1941 self.generate_tuple_and_keyword_parsing_code(
1942 positional_args, kw_only_args, end_label, code)
1944 code.error_label = old_error_label
1945 if code.label_used(our_error_label):
1946 if not code.label_used(end_label):
1947 code.put_goto(end_label)
1948 code.put_label(our_error_label)
1949 if has_star_or_kw_args:
1950 self.generate_arg_decref(self.star_arg, code)
1951 if self.starstar_arg:
1952 if self.starstar_arg.entry.xdecref_cleanup:
1953 code.put_var_xdecref(self.starstar_arg.entry)
1954 else:
1955 code.put_var_decref(self.starstar_arg.entry)
1956 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1957 code.putln("return %s;" % self.error_value())
1958 if code.label_used(end_label):
1959 code.put_label(end_label)
1961 def generate_arg_assignment(self, arg, item, code):
1962 if arg.type.is_pyobject:
1963 if arg.is_generic:
1964 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1965 code.putln("%s = %s;" % (arg.entry.cname, item))
1966 else:
1967 func = arg.type.from_py_function
1968 if func:
1969 code.putln("%s = %s(%s); %s" % (
1970 arg.entry.cname,
1971 func,
1972 item,
1973 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1974 else:
1975 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1977 def generate_arg_xdecref(self, arg, code):
1978 if arg:
1979 code.put_var_xdecref(arg.entry)
1981 def generate_arg_decref(self, arg, code):
1982 if arg:
1983 code.put_var_decref(arg.entry)
1985 def generate_stararg_copy_code(self, code):
1986 if not self.star_arg:
1987 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1988 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1989 Naming.args_cname)
1990 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
1991 self.name.utf8encode(), Naming.args_cname, self.error_value()))
1992 code.putln("}")
1994 code.globalstate.use_utility_code(keyword_string_check_utility_code)
1996 if self.starstar_arg:
1997 if self.star_arg:
1998 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
1999 else:
2000 kwarg_check = "%s" % Naming.kwds_cname
2001 else:
2002 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2003 Naming.kwds_cname, Naming.kwds_cname)
2004 code.putln(
2005 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2006 kwarg_check, Naming.kwds_cname, self.name,
2007 bool(self.starstar_arg), self.error_value()))
2009 if self.starstar_arg:
2010 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2011 self.starstar_arg.entry.cname,
2012 Naming.kwds_cname,
2013 Naming.kwds_cname))
2014 code.putln("if (unlikely(!%s)) return %s;" % (
2015 self.starstar_arg.entry.cname, self.error_value()))
2016 self.starstar_arg.entry.xdecref_cleanup = 0
2018 if self.star_arg:
2019 code.put_incref(Naming.args_cname, py_object_type)
2020 code.putln("%s = %s;" % (
2021 self.star_arg.entry.cname,
2022 Naming.args_cname))
2023 self.star_arg.entry.xdecref_cleanup = 0
2025 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2026 kw_only_args, success_label, code):
2027 argtuple_error_label = code.new_label("argtuple_error")
2029 min_positional_args = self.num_required_args - self.num_required_kw_args
2030 if len(self.args) > 0 and self.args[0].is_self_arg:
2031 min_positional_args -= 1
2032 max_positional_args = len(positional_args)
2033 has_fixed_positional_count = not self.star_arg and \
2034 min_positional_args == max_positional_args
2036 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2037 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2038 if self.num_required_kw_args:
2039 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2041 if self.starstar_arg or self.star_arg:
2042 self.generate_stararg_init_code(max_positional_args, code)
2044 # --- optimised code when we receive keyword arguments
2045 if self.num_required_kw_args:
2046 likely_hint = "likely"
2047 else:
2048 likely_hint = "unlikely"
2049 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2050 self.generate_keyword_unpacking_code(
2051 min_positional_args, max_positional_args,
2052 has_fixed_positional_count,
2053 positional_args, kw_only_args, argtuple_error_label, code)
2055 # --- optimised code when we do not receive any keyword arguments
2056 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2057 # Python raises arg tuple related errors first, so we must
2058 # check the length here
2059 if min_positional_args == max_positional_args and not self.star_arg:
2060 compare = '!='
2061 else:
2062 compare = '<'
2063 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2064 Naming.args_cname, compare, min_positional_args))
2065 code.put_goto(argtuple_error_label)
2067 if self.num_required_kw_args:
2068 # pure error case: keywords required but not passed
2069 if max_positional_args > min_positional_args and not self.star_arg:
2070 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2071 Naming.args_cname, max_positional_args))
2072 code.put_goto(argtuple_error_label)
2073 code.putln('} else {')
2074 for i, arg in enumerate(kw_only_args):
2075 if not arg.default:
2076 # required keyword-only argument missing
2077 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2078 self.name.utf8encode(),
2079 arg.name_entry.pystring_cname))
2080 code.putln(code.error_goto(self.pos))
2081 break
2083 elif min_positional_args == max_positional_args:
2084 # parse the exact number of positional arguments from the
2085 # args tuple
2086 code.putln('} else {')
2087 for i, arg in enumerate(positional_args):
2088 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2089 self.generate_arg_assignment(arg, item, code)
2090 self.generate_arg_default_assignments(code)
2092 else:
2093 # parse the positional arguments from the variable length
2094 # args tuple
2095 code.putln('} else {')
2096 self.generate_arg_default_assignments(code)
2097 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2098 if self.star_arg:
2099 code.putln('default:')
2100 reversed_args = list(enumerate(positional_args))[::-1]
2101 for i, arg in reversed_args:
2102 if i >= min_positional_args-1:
2103 if min_positional_args > 1:
2104 code.putln('case %2d:' % (i+1)) # pure code beautification
2105 else:
2106 code.put('case %2d: ' % (i+1))
2107 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2108 self.generate_arg_assignment(arg, item, code)
2109 if min_positional_args == 0:
2110 code.put('case 0: ')
2111 code.putln('break;')
2112 if self.star_arg:
2113 if min_positional_args:
2114 for i in range(min_positional_args-1, -1, -1):
2115 code.putln('case %2d:' % i)
2116 code.put_goto(argtuple_error_label)
2117 else:
2118 code.put('default: ')
2119 code.put_goto(argtuple_error_label)
2120 code.putln('}')
2122 code.putln('}')
2124 if code.label_used(argtuple_error_label):
2125 code.put_goto(success_label)
2126 code.put_label(argtuple_error_label)
2127 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2128 self.name.utf8encode(), has_fixed_positional_count,
2129 min_positional_args, max_positional_args,
2130 Naming.args_cname))
2131 code.putln(code.error_goto(self.pos))
2133 def generate_arg_default_assignments(self, code):
2134 for arg in self.args:
2135 if arg.is_generic and arg.default:
2136 code.putln(
2137 "%s = %s;" % (
2138 arg.entry.cname,
2139 arg.default_result_code))
2141 def generate_stararg_init_code(self, max_positional_args, code):
2142 if self.starstar_arg:
2143 self.starstar_arg.entry.xdecref_cleanup = 0
2144 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2145 self.starstar_arg.entry.cname,
2146 self.starstar_arg.entry.cname,
2147 self.error_value()))
2148 if self.star_arg:
2149 self.star_arg.entry.xdecref_cleanup = 0
2150 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2151 Naming.args_cname,
2152 max_positional_args))
2153 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2154 self.star_arg.entry.cname, Naming.args_cname,
2155 max_positional_args, Naming.args_cname))
2156 if self.starstar_arg:
2157 code.putln("")
2158 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2159 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2160 code.putln('return %s;' % self.error_value())
2161 code.putln('}')
2162 else:
2163 code.putln("if (unlikely(!%s)) return %s;" % (
2164 self.star_arg.entry.cname, self.error_value()))
2165 code.putln('} else {')
2166 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2167 code.put_incref(Naming.empty_tuple, py_object_type)
2168 code.putln('}')
2170 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2171 has_fixed_positional_count, positional_args,
2172 kw_only_args, argtuple_error_label, code):
2173 all_args = tuple(positional_args) + tuple(kw_only_args)
2174 max_args = len(all_args)
2176 default_args = []
2177 for arg in all_args:
2178 if arg.default and arg.type.is_pyobject:
2179 default_value = arg.default_result_code
2180 if arg.type is not PyrexTypes.py_object_type:
2181 default_value = "(PyObject*)"+default_value
2182 default_args.append(default_value)
2183 else:
2184 default_args.append('0')
2185 code.putln("PyObject* values[%d] = {%s};" % (
2186 max_args, ', '.join(default_args)))
2187 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2188 Naming.kwds_cname)
2190 # parse the tuple and check that it's not too long
2191 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2192 if self.star_arg:
2193 code.putln('default:')
2194 for i in range(max_positional_args-1, -1, -1):
2195 code.put('case %2d: ' % (i+1))
2196 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2197 i, Naming.args_cname, i))
2198 code.putln('case 0: break;')
2199 if not self.star_arg:
2200 code.put('default: ') # more arguments than allowed
2201 code.put_goto(argtuple_error_label)
2202 code.putln('}')
2204 # now fill up the required arguments with values from the kw dict
2205 if self.num_required_args:
2206 last_required_arg = -1
2207 for i, arg in enumerate(all_args):
2208 if not arg.default:
2209 last_required_arg = i
2210 if max_positional_args > 0:
2211 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2212 for i, arg in enumerate(all_args[:last_required_arg+1]):
2213 if max_positional_args > 0 and i <= max_positional_args:
2214 if self.star_arg and i == max_positional_args:
2215 code.putln('default:')
2216 else:
2217 code.putln('case %2d:' % i)
2218 if arg.default:
2219 # handled in ParseOptionalKeywords() below
2220 continue
2221 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2222 i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2223 code.putln('if (likely(values[%d])) kw_args--;' % i);
2224 if i < min_positional_args:
2225 if i == 0:
2226 # special case: we know arg 0 is missing
2227 code.put('else ')
2228 code.put_goto(argtuple_error_label)
2229 else:
2230 # print the correct number of values (args or
2231 # kwargs) that were passed into positional
2232 # arguments up to this point
2233 code.putln('else {')
2234 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2235 self.name.utf8encode(), has_fixed_positional_count,
2236 min_positional_args, max_positional_args, i))
2237 code.putln(code.error_goto(self.pos))
2238 code.putln('}')
2239 elif arg.kw_only:
2240 code.putln('else {')
2241 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2242 self.name.utf8encode(), arg.name_entry.pystring_cname))
2243 code.putln(code.error_goto(self.pos))
2244 code.putln('}')
2245 if max_positional_args > 0:
2246 code.putln('}')
2248 code.putln('if (unlikely(kw_args > 0)) {')
2249 # non-positional/-required kw args left in dict: default args, **kwargs or error
2250 if max_positional_args == 0:
2251 pos_arg_count = "0"
2252 elif self.star_arg:
2253 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2254 Naming.args_cname, max_positional_args,
2255 Naming.args_cname, max_positional_args))
2256 pos_arg_count = "used_pos_args"
2257 else:
2258 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2259 code.globalstate.use_utility_code(parse_keywords_utility_code)
2260 code.put(
2261 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2262 Naming.kwds_cname,
2263 Naming.pykwdlist_cname,
2264 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2265 pos_arg_count,
2266 self.name.utf8encode()))
2267 code.putln(code.error_goto(self.pos))
2268 code.putln('}')
2270 # convert arg values to their final type and assign them
2271 for i, arg in enumerate(all_args):
2272 if arg.default and not arg.type.is_pyobject:
2273 code.putln("if (values[%d]) {" % i)
2274 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2275 if arg.default and not arg.type.is_pyobject:
2276 code.putln('} else {')
2277 code.putln(
2278 "%s = %s;" % (
2279 arg.entry.cname,
2280 arg.default_result_code))
2281 code.putln('}')
2283 def generate_argument_conversion_code(self, code):
2284 # Generate code to convert arguments from
2285 # signature type to declared type, if needed.
2286 for arg in self.args:
2287 if arg.needs_conversion:
2288 self.generate_arg_conversion(arg, code)
2290 def generate_arg_conversion(self, arg, code):
2291 # Generate conversion code for one argument.
2292 old_type = arg.hdr_type
2293 new_type = arg.type
2294 if old_type.is_pyobject:
2295 if arg.default:
2296 code.putln("if (%s) {" % arg.hdr_cname)
2297 else:
2298 code.putln("assert(%s); {" % arg.hdr_cname)
2299 self.generate_arg_conversion_from_pyobject(arg, code)
2300 code.putln("}")
2301 elif new_type.is_pyobject:
2302 self.generate_arg_conversion_to_pyobject(arg, code)
2303 else:
2304 if new_type.assignable_from(old_type):
2305 code.putln(
2306 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2307 else:
2308 error(arg.pos,
2309 "Cannot convert 1 argument from '%s' to '%s'" %
2310 (old_type, new_type))
2312 def generate_arg_conversion_from_pyobject(self, arg, code):
2313 new_type = arg.type
2314 func = new_type.from_py_function
2315 # copied from CoerceFromPyTypeNode
2316 if func:
2317 code.putln("%s = %s(%s); %s" % (
2318 arg.entry.cname,
2319 func,
2320 arg.hdr_cname,
2321 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2322 else:
2323 error(arg.pos,
2324 "Cannot convert Python object argument to type '%s'"
2325 % new_type)
2327 def generate_arg_conversion_to_pyobject(self, arg, code):
2328 old_type = arg.hdr_type
2329 func = old_type.to_py_function
2330 if func:
2331 code.putln("%s = %s(%s); %s" % (
2332 arg.entry.cname,
2333 func,
2334 arg.hdr_cname,
2335 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2336 code.put_var_gotref(arg.entry)
2337 else:
2338 error(arg.pos,
2339 "Cannot convert argument of type '%s' to Python object"
2340 % old_type)
2342 def generate_argument_type_tests(self, code):
2343 # Generate type tests for args whose signature
2344 # type is PyObject * and whose declared type is
2345 # a subtype thereof.
2346 for arg in self.args:
2347 if arg.needs_type_test:
2348 self.generate_arg_type_test(arg, code)
2350 def generate_arg_type_test(self, arg, code):
2351 # Generate type test for one argument.
2352 if arg.type.typeobj_is_available():
2353 typeptr_cname = arg.type.typeptr_cname
2354 arg_code = "((PyObject *)%s)" % arg.entry.cname
2355 code.putln(
2356 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2357 arg_code,
2358 typeptr_cname,
2359 not arg.not_none,
2360 arg.name,
2361 arg.type.is_builtin_type,
2362 code.error_goto(arg.pos)))
2363 else:
2364 error(arg.pos, "Cannot test type of extern C class "
2365 "without type object name specification")
2367 def error_value(self):
2368 return self.entry.signature.error_value
2370 def caller_will_check_exceptions(self):
2371 return 1
2373 class OverrideCheckNode(StatNode):
2374 # A Node for dispatching to the def method if it
2375 # is overriden.
2377 # py_func
2379 # args
2380 # func_temp
2381 # body
2383 child_attrs = ['body']
2385 body = None
2387 def analyse_expressions(self, env):
2388 self.args = env.arg_entries
2389 if self.py_func.is_module_scope:
2390 first_arg = 0
2391 else:
2392 first_arg = 1
2393 import ExprNodes
2394 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2395 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2396 call_node = ExprNodes.SimpleCallNode(self.pos,
2397 function=self.func_node,
2398 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2399 self.body = ReturnStatNode(self.pos, value=call_node)
2400 self.body.analyse_expressions(env)
2402 def generate_execution_code(self, code):
2403 # Check to see if we are an extension type
2404 if self.py_func.is_module_scope:
2405 self_arg = "((PyObject *)%s)" % Naming.module_cname
2406 else:
2407 self_arg = "((PyObject *)%s)" % self.args[0].cname
2408 code.putln("/* Check if called by wrapper */")
2409 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2410 code.putln("/* Check if overriden in Python */")
2411 if self.py_func.is_module_scope:
2412 code.putln("else {")
2413 else:
2414 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2415 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2416 code.put_gotref(self.func_node.py_result())
2417 # need to get attribute manually--scope would return cdef method
2418 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2419 # It appears that this type is not anywhere exposed in the Python/C API
2420 is_builtin_function_or_method = '(strcmp(Py_TYPE(%s)->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result()
2421 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2422 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2423 self.body.generate_execution_code(code)
2424 code.putln('}')
2425 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2426 code.putln("}")
2428 class ClassDefNode(StatNode, BlockNode):
2429 pass
2431 class PyClassDefNode(ClassDefNode):
2432 # A Python class definition.
2434 # name EncodedString Name of the class
2435 # doc string or None
2436 # body StatNode Attribute definition code
2437 # entry Symtab.Entry
2438 # scope PyClassScope
2440 # The following subnodes are constructed internally:
2442 # dict DictNode Class dictionary
2443 # classobj ClassNode Class object
2444 # target NameNode Variable to assign class object to
2446 child_attrs = ["body", "dict", "classobj", "target"]
2448 def __init__(self, pos, name, bases, doc, body):
2449 StatNode.__init__(self, pos)
2450 self.name = name
2451 self.doc = doc
2452 self.body = body
2453 import ExprNodes
2454 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2455 if self.doc and Options.docstrings:
2456 doc = embed_position(self.pos, self.doc)
2457 doc_node = ExprNodes.StringNode(pos, value = doc)
2458 else:
2459 doc_node = None
2460 self.classobj = ExprNodes.ClassNode(pos, name = name,
2461 bases = bases, dict = self.dict, doc = doc_node)
2462 self.target = ExprNodes.NameNode(pos, name = name)
2464 def as_cclass(self):
2465 """
2466 Return this node as if it were declared as an extension class
2467 """
2468 bases = self.classobj.bases.args
2469 if len(bases) == 0:
2470 base_class_name = None
2471 base_class_module = None
2472 elif len(bases) == 1:
2473 base = bases[0]
2474 path = []
2475 from ExprNodes import AttributeNode, NameNode
2476 while isinstance(base, AttributeNode):
2477 path.insert(0, base.attribute)
2478 base = base.obj
2479 if isinstance(base, NameNode):
2480 path.insert(0, base.name)
2481 base_class_name = path[-1]
2482 if len(path) > 1:
2483 base_class_module = u'.'.join(path[:-1])
2484 else:
2485 base_class_module = None
2486 else:
2487 error(self.classobj.bases.args.pos, "Invalid base class")
2488 else:
2489 error(self.classobj.bases.args.pos, "C class may only have one base class")
2490 return None
2492 return CClassDefNode(self.pos,
2493 visibility = 'private',
2494 module_name = None,
2495 class_name = self.name,
2496 base_class_module = base_class_module,
2497 base_class_name = base_class_name,
2498 body = self.body,
2499 in_pxd = False,
2500 doc = self.doc)
2502 def create_scope(self, env):
2503 genv = env
2504 while env.is_py_class_scope or env.is_c_class_scope:
2505 env = env.outer_scope
2506 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2507 return cenv
2509 def analyse_declarations(self, env):
2510 self.target.analyse_target_declaration(env)
2511 cenv = self.create_scope(env)
2512 cenv.class_obj_cname = self.target.entry.cname
2513 self.body.analyse_declarations(cenv)
2515 def analyse_expressions(self, env):
2516 self.dict.analyse_expressions(env)
2517 self.classobj.analyse_expressions(env)
2518 genv = env.global_scope()
2519 cenv = self.scope
2520 cenv.class_dict_cname = self.dict.result()
2521 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2522 self.body.analyse_expressions(cenv)
2523 self.target.analyse_target_expression(env, self.classobj)
2524 self.dict.release_temp(env)
2525 #self.classobj.release_temp(env)
2526 #self.target.release_target_temp(env)
2528 def generate_function_definitions(self, env, code):
2529 self.generate_py_string_decls(self.scope, code)
2530 self.body.generate_function_definitions(self.scope, code)
2532 def generate_execution_code(self, code):
2533 self.dict.generate_evaluation_code(code)
2534 self.classobj.generate_evaluation_code(code)
2535 self.body.generate_execution_code(code)
2536 self.target.generate_assignment_code(self.classobj, code)
2537 self.dict.generate_disposal_code(code)
2538 self.dict.free_temps(code)
2541 class CClassDefNode(ClassDefNode):
2542 # An extension type definition.
2544 # visibility 'private' or 'public' or 'extern'
2545 # typedef_flag boolean
2546 # api boolean
2547 # module_name string or None For import of extern type objects
2548 # class_name string Unqualified name of class
2549 # as_name string or None Name to declare as in this scope
2550 # base_class_module string or None Module containing the base class
2551 # base_class_name string or None Name of the base class
2552 # objstruct_name string or None Specified C name of object struct
2553 # typeobj_name string or None Specified C name of type object
2554 # in_pxd boolean Is in a .pxd file
2555 # doc string or None
2556 # body StatNode or None
2557 # entry Symtab.Entry
2558 # base_type PyExtensionType or None
2559 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2560 # buffer_defaults_pos
2562 child_attrs = ["body"]
2563 buffer_defaults_node = None
2564 buffer_defaults_pos = None
2565 typedef_flag = False
2566 api = False
2567 objstruct_name = None
2568 typeobj_name = None
2570 def analyse_declarations(self, env):
2571 #print "CClassDefNode.analyse_declarations:", self.class_name
2572 #print "...visibility =", self.visibility
2573 #print "...module_name =", self.module_name
2575 import Buffer
2576 if self.buffer_defaults_node:
2577 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2578 env, [], self.buffer_defaults_node,
2579 need_complete=False)
2580 else:
2581 buffer_defaults = None
2583 if env.in_cinclude and not self.objstruct_name:
2584 error(self.pos, "Object struct name specification required for "
2585 "C class defined in 'extern from' block")
2586 self.base_type = None
2587 # Now that module imports are cached, we need to
2588 # import the modules for extern classes.
2589 if self.module_name:
2590 self.module = None
2591 for module in env.cimported_modules:
2592 if module.name == self.module_name:
2593 self.module = module
2594 if self.module is None:
2595 self.module = ModuleScope(self.module_name, None, env.context)
2596 self.module.has_extern_class = 1
2597 env.add_imported_module(self.module)
2599 if self.base_class_name:
2600 if self.base_class_module:
2601 base_class_scope = env.find_module(self.base_class_module, self.pos)
2602 else:
2603 base_class_scope = env
2604 if self.base_class_name == 'object':
2605 # extension classes are special and don't need to inherit from object
2606 if base_class_scope is None or base_class_scope.lookup('object') is None:
2607 self.base_class_name = None
2608 self.base_class_module = None
2609 base_class_scope = None
2610 if base_class_scope:
2611 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2612 if base_class_entry:
2613 if not base_class_entry.is_type:
2614 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2615 elif not base_class_entry.type.is_extension_type:
2616 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2617 elif not base_class_entry.type.is_complete():
2618 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2619 else:
2620 self.base_type = base_class_entry.type
2621 has_body = self.body is not None
2622 if self.module_name and self.visibility != 'extern':
2623 module_path = self.module_name.split(".")
2624 home_scope = env.find_imported_module(module_path, self.pos)
2625 if not home_scope:
2626 return
2627 else:
2628 home_scope = env
2629 self.entry = home_scope.declare_c_class(
2630 name = self.class_name,
2631 pos = self.pos,
2632 defining = has_body and self.in_pxd,
2633 implementing = has_body and not self.in_pxd,
2634 module_name = self.module_name,
2635 base_type = self.base_type,
2636 objstruct_cname = self.objstruct_name,
2637 typeobj_cname = self.typeobj_name,
2638 visibility = self.visibility,
2639 typedef_flag = self.typedef_flag,
2640 api = self.api,
2641 buffer_defaults = buffer_defaults)
2642 if home_scope is not env and self.visibility == 'extern':
2643 env.add_imported_entry(self.class_name, self.entry, pos)
2644 scope = self.entry.type.scope
2646 if self.doc and Options.docstrings:
2647 scope.doc = embed_position(self.pos, self.doc)
2649 if has_body:
2650 self.body.analyse_declarations(scope)
2651 if self.in_pxd:
2652 scope.defined = 1
2653 else:
2654 scope.implemented = 1
2655 env.allocate_vtable_names(self.entry)
2657 def analyse_expressions(self, env):
2658 if self.body:
2659 scope = self.entry.type.scope
2660 self.body.analyse_expressions(scope)
2662 def generate_function_definitions(self, env, code):
2663 self.generate_py_string_decls(self.entry.type.scope, code)
2664 if self.body:
2665 self.body.generate_function_definitions(
2666 self.entry.type.scope, code)
2668 def generate_execution_code(self, code):
2669 # This is needed to generate evaluation code for
2670 # default values of method arguments.
2671 if self.body:
2672 self.body.generate_execution_code(code)
2674 def annotate(self, code):
2675 if self.body:
2676 self.body.annotate(code)
2679 class PropertyNode(StatNode):
2680 # Definition of a property in an extension type.
2682 # name string
2683 # doc EncodedString or None Doc string
2684 # body StatListNode
2686 child_attrs = ["body"]
2688 def analyse_declarations(self, env):
2689 entry = env.declare_property(self.name, self.doc, self.pos)
2690 if entry:
2691 if self.doc and Options.docstrings:
2692 doc_entry = env.get_string_const(
2693 self.doc, identifier = False)
2694 entry.doc_cname = doc_entry.cname
2695 self.body.analyse_declarations(entry.scope)
2697 def analyse_expressions(self, env):
2698 self.body.analyse_expressions(env)
2700 def generate_function_definitions(self, env, code):
2701 self.body.generate_function_definitions(env, code)
2703 def generate_execution_code(self, code):
2704 pass
2706 def annotate(self, code):
2707 self.body.annotate(code)
2710 class GlobalNode(StatNode):
2711 # Global variable declaration.
2713 # names [string]
2715 child_attrs = []
2717 def analyse_declarations(self, env):
2718 for name in self.names:
2719 env.declare_global(name, self.pos)
2721 def analyse_expressions(self, env):
2722 pass
2724 def generate_execution_code(self, code):
2725 pass
2728 class ExprStatNode(StatNode):
2729 # Expression used as a statement.
2731 # expr ExprNode
2733 child_attrs = ["expr"]
2735 def analyse_declarations(self, env):
2736 import ExprNodes
2737 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2738 func = self.expr.function.as_cython_attribute()
2739 if func == u'declare':
2740 args, kwds = self.expr.explicit_args_kwds()
2741 if len(args):
2742 error(self.expr.pos, "Variable names must be specified.")
2743 for var, type_node in kwds.key_value_pairs:
2744 type = type_node.analyse_as_type(env)
2745 if type is None:
2746 error(type_node.pos, "Unknown type")
2747 else:
2748 env.declare_var(var.value, type, var.pos, is_cdef = True)
2749 self.__class__ = PassStatNode
2751 def analyse_expressions(self, env):
2752 self.expr.analyse_expressions(env)
2753 self.expr.release_temp(env)
2755 def generate_execution_code(self, code):
2756 self.expr.generate_evaluation_code(code)
2757 if not self.expr.is_temp and self.expr.result():
2758 code.putln("%s;" % self.expr.result())
2759 self.expr.generate_disposal_code(code)
2760 self.expr.free_temps(code)
2762 def annotate(self, code):
2763 self.expr.annotate(code)
2766 class AssignmentNode(StatNode):
2767 # Abstract base class for assignment nodes.
2769 # The analyse_expressions and generate_execution_code
2770 # phases of assignments are split into two sub-phases
2771 # each, to enable all the right hand sides of a
2772 # parallel assignment to be evaluated before assigning
2773 # to any of the left hand sides.
2775 def analyse_expressions(self, env):
2776 self.analyse_types(env)
2777 self.allocate_rhs_temps(env)
2778 self.allocate_lhs_temps(env)
2780 # def analyse_expressions(self, env):
2781 # self.analyse_expressions_1(env)
2782 # self.analyse_expressions_2(env)
2784 def generate_execution_code(self, code):
2785 self.generate_rhs_evaluation_code(code)
2786 self.generate_assignment_code(code)
2789 class SingleAssignmentNode(AssignmentNode):
2790 # The simplest case:
2792 # a = b
2794 # lhs ExprNode Left hand side
2795 # rhs ExprNode Right hand side
2796 # first bool Is this guaranteed the first assignment to lhs?
2798 child_attrs = ["lhs", "rhs"]
2799 first = False
2800 declaration_only = False
2802 def analyse_declarations(self, env):
2803 import ExprNodes
2805 # handle declarations of the form x = cython.foo()
2806 if isinstance(self.rhs, ExprNodes.CallNode):
2807 func_name = self.rhs.function.as_cython_attribute()
2808 if func_name:
2809 args, kwds = self.rhs.explicit_args_kwds()
2811 if func_name in ['declare', 'typedef']:
2812 if len(args) > 2 or kwds is not None:
2813 error(rhs.pos, "Can only declare one type at a time.")
2814 return
2815 type = args[0].analyse_as_type(env)
2816 if type is None:
2817 error(args[0].pos, "Unknown type")
2818 return
2819 lhs = self.lhs
2820 if func_name == 'declare':
2821 if isinstance(lhs, ExprNodes.NameNode):
2822 vars = [(lhs.name, lhs.pos)]
2823 elif isinstance(lhs, ExprNodes.TupleNode):
2824 vars = [(var.name, var.pos) for var in lhs.args]
2825 else:
2826 error(lhs.pos, "Invalid declaration")
2827 return
2828 for var, pos in vars:
2829 env.declare_var(var, type, pos, is_cdef = True)
2830 if len(args) == 2:
2831 # we have a value
2832 self.rhs = args[1]
2833 else:
2834 self.declaration_only = True
2835 else:
2836 self.declaration_only = True
2837 if not isinstance(lhs, ExprNodes.NameNode):
2838 error(lhs.pos, "Invalid declaration.")
2839 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2841 elif func_name in ['struct', 'union']:
2842 self.declaration_only = True
2843 if len(args) > 0 or kwds is None:
2844 error(rhs.pos, "Struct or union members must be given by name.")
2845 return
2846 members = []
2847 for member, type_node in kwds.key_value_pairs:
2848 type = type_node.analyse_as_type(env)
2849 if type is None:
2850 error(type_node.pos, "Unknown type")
2851 else:
2852 members.append((member.value, type, member.pos))
2853 if len(members) < len(kwds.key_value_pairs):
2854 return
2855 if not isinstance(self.lhs, ExprNodes.NameNode):
2856 error(self.lhs.pos, "Invalid declaration.")
2857 name = self.lhs.name
2858 scope = StructOrUnionScope(name)
2859 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2860 for member, type, pos in members:
2861 scope.declare_var(member, type, pos)
2863 if self.declaration_only:
2864 return
2865 else:
2866 self.lhs.analyse_target_declaration(env)
2868 def analyse_types(self, env, use_temp = 0):
2869 self.rhs.analyse_types(env)
2870 self.lhs.analyse_target_types(env)
2871 self.lhs.gil_assignment_check(env)
2872 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2873 if use_temp:
2874 self.rhs = self.rhs.coerce_to_temp(env)
2876 def allocate_rhs_temps(self, env):
2877 self.rhs.allocate_temps(env)
2879 def allocate_lhs_temps(self, env):
2880 self.lhs.allocate_target_temps(env, self.rhs)
2881 #self.lhs.release_target_temp(env)
2882 #self.rhs.release_temp(env)
2884 def generate_rhs_evaluation_code(self, code):
2885 self.rhs.generate_evaluation_code(code)
2887 def generate_assignment_code(self, code):
2888 self.lhs.generate_assignment_code(self.rhs, code)
2890 def annotate(self, code):
2891 self.lhs.annotate(code)
2892 self.rhs.annotate(code)
2895 class CascadedAssignmentNode(AssignmentNode):
2896 # An assignment with multiple left hand sides:
2898 # a = b = c
2900 # lhs_list [ExprNode] Left hand sides
2901 # rhs ExprNode Right hand sides
2903 # Used internally:
2905 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2907 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2908 coerced_rhs_list = None
2910 def analyse_declarations(self, env):
2911 for lhs in self.lhs_list:
2912 lhs.analyse_target_declaration(env)
2914 def analyse_types(self, env, use_temp = 0):
2915 self.rhs.analyse_types(env)
2916 if use_temp:
2917 self.rhs = self.rhs.coerce_to_temp(env)
2918 else:
2919 self.rhs = self.rhs.coerce_to_simple(env)
2920 from ExprNodes import CloneNode
2921 self.coerced_rhs_list = []
2922 for lhs in self.lhs_list:
2923 lhs.analyse_target_types(env)
2924 lhs.gil_assignment_check(env)
2925 rhs = CloneNode(self.rhs)
2926 rhs = rhs.coerce_to(lhs.type, env)
2927 self.coerced_rhs_list.append(rhs)
2929 def allocate_rhs_temps(self, env):
2930 self.rhs.allocate_temps(env)
2932 def allocate_lhs_temps(self, env):
2933 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2934 rhs.allocate_temps(env)
2935 lhs.allocate_target_temps(env, rhs)
2936 #lhs.release_target_temp(env)
2937 #rhs.release_temp(env)
2938 self.rhs.release_temp(env)
2940 def generate_rhs_evaluation_code(self, code):
2941 self.rhs.generate_evaluation_code(code)
2943 def generate_assignment_code(self, code):
2944 for i in range(len(self.lhs_list)):
2945 lhs = self.lhs_list[i]
2946 rhs = self.coerced_rhs_list[i]
2947 rhs.generate_evaluation_code(code)
2948 lhs.generate_assignment_code(rhs, code)
2949 # Assignment has disposed of the cloned RHS
2950 self.rhs.generate_disposal_code(code)
2951 self.rhs.free_temps(code)
2953 def annotate(self, code):
2954 for i in range(len(self.lhs_list)):
2955 lhs = self.lhs_list[i].annotate(code)
2956 rhs = self.coerced_rhs_list[i].annotate(code)
2957 self.rhs.annotate(code)
2960 class ParallelAssignmentNode(AssignmentNode):
2961 # A combined packing/unpacking assignment:
2963 # a, b, c = d, e, f
2965 # This has been rearranged by the parser into
2967 # a = d ; b = e ; c = f
2969 # but we must evaluate all the right hand sides
2970 # before assigning to any of the left hand sides.
2972 # stats [AssignmentNode] The constituent assignments
2974 child_attrs = ["stats"]
2976 def analyse_declarations(self, env):
2977 for stat in self.stats:
2978 stat.analyse_declarations(env)
2980 def analyse_expressions(self, env):
2981 for stat in self.stats:
2982 stat.analyse_types(env, use_temp = 1)
2983 stat.allocate_rhs_temps(env)
2984 for stat in self.stats:
2985 stat.allocate_lhs_temps(env)
2987 # def analyse_expressions(self, env):
2988 # for stat in self.stats:
2989 # stat.analyse_expressions_1(env, use_temp = 1)
2990 # for stat in self.stats:
2991 # stat.analyse_expressions_2(env)
2993 def generate_execution_code(self, code):
2994 for stat in self.stats:
2995 stat.generate_rhs_evaluation_code(code)
2996 for stat in self.stats:
2997 stat.generate_assignment_code(code)
2999 def annotate(self, code):
3000 for stat in self.stats:
3001 stat.annotate(code)
3004 class InPlaceAssignmentNode(AssignmentNode):
3005 # An in place arithmatic operand:
3007 # a += b
3008 # a -= b
3009 # ...
3011 # lhs ExprNode Left hand side
3012 # rhs ExprNode Right hand side
3013 # op char one of "+-*/%^&|"
3014 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3016 # This code is a bit tricky because in order to obey Python
3017 # semantics the sub-expressions (e.g. indices) of the lhs must
3018 # not be evaluated twice. So we must re-use the values calculated
3019 # in evaluation phase for the assignment phase as well.
3020 # Fortunately, the type of the lhs node is fairly constrained
3021 # (it must be a NameNode, AttributeNode, or IndexNode).
3023 child_attrs = ["lhs", "rhs"]
3024 dup = None
3026 def analyse_declarations(self, env):
3027 self.lhs.analyse_target_declaration(env)
3029 def analyse_types(self, env):
3030 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3031 self.rhs.analyse_types(env)
3032 self.lhs.analyse_target_types(env)
3033 if Options.incref_local_binop and self.dup.type.is_pyobject:
3034 self.dup = self.dup.coerce_to_temp(env)
3036 def allocate_rhs_temps(self, env):
3037 import ExprNodes
3038 if self.lhs.type.is_pyobject:
3039 self.rhs = self.rhs.coerce_to_pyobject(env)
3040 elif self.rhs.type.is_pyobject:
3041 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3042 if self.lhs.type.is_pyobject:
3043 self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
3044 self.result_value.allocate_temps(env)
3045 # if use_temp:
3046 # self.rhs = self.rhs.coerce_to_temp(env)
3047 self.rhs.allocate_temps(env)
3048 self.dup.allocate_subexpr_temps(env)
3049 self.dup.allocate_temp(env)
3051 def allocate_lhs_temps(self, env):
3052 self.lhs.allocate_target_temps(env, self.rhs)
3053 # self.lhs.release_target_temp(env)
3054 self.dup.release_temp(env)
3055 if self.dup.is_temp:
3056 self.dup.release_subexpr_temps(env)
3057 # self.rhs.release_temp(env)
3058 if self.lhs.type.is_pyobject:
3059 self.result_value.release_temp(env)
3061 def generate_execution_code(self, code):
3062 import ExprNodes
3063 self.rhs.generate_evaluation_code(code)
3064 self.dup.generate_subexpr_evaluation_code(code)
3065 if isinstance(self.dup, ExprNodes.NewTempExprNode):
3066 # This is because we're manually messing with subexpr nodes
3067 if self.dup.is_temp:
3068 self.dup.allocate_temp_result(code)
3069 # self.dup.generate_result_code is run only if it is not buffer access
3070 if self.operator == "**":
3071 extra = ", Py_None"
3072 else:
3073 extra = ""
3074 if self.lhs.type.is_pyobject:
3075 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3076 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3077 self.dup.generate_result_code(code)
3078 code.putln(
3079 "%s = %s(%s, %s%s); %s" % (
3080 self.result_value.result(),
3081 self.py_operation_function(),
3082 self.dup.py_result(),
3083 self.rhs.py_result(),
3084 extra,
3085 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3086 code.put_gotref(self.result_value.py_result())
3087 self.result_value.generate_evaluation_code(code) # May be a type check...
3088 self.rhs.generate_disposal_code(code)
3089 self.rhs.free_temps(code)
3090 self.dup.generate_disposal_code(code)
3091 self.dup.free_temps(code)
3092 self.lhs.generate_assignment_code(self.result_value, code)
3093 else:
3094 c_op = self.operator
3095 if c_op == "//":
3096 c_op = "/"
3097 elif c_op == "**":
3098 if self.lhs.type.is_int and self.rhs.type.is_int:
3099 error(self.pos, "** with two C int types is ambiguous")
3100 else:
3101 error(self.pos, "No C inplace power operator")
3102 # have to do assignment directly to avoid side-effects
3103 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3104 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3105 else:
3106 self.dup.generate_result_code(code)
3107 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3108 self.rhs.generate_disposal_code(code)
3109 self.rhs.free_temps(code)
3110 if self.dup.is_temp:
3111 self.dup.generate_subexpr_disposal_code(code)
3112 self.dup.free_subexpr_temps(code)
3114 def create_dup_node(self, env):
3115 import ExprNodes
3116 self.dup = self.lhs
3117 self.dup.analyse_types(env)
3118 if isinstance(self.lhs, ExprNodes.NameNode):
3119 target_lhs = ExprNodes.NameNode(self.dup.pos,
3120 name = self.dup.name,
3121 is_temp = self.dup.is_temp,
3122 entry = self.dup.entry)
3123 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3124 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3125 obj = ExprNodes.CloneNode(self.lhs.obj),
3126 attribute = self.dup.attribute,
3127 is_temp = self.dup.is_temp)
3128 elif isinstance(self.lhs, ExprNodes.IndexNode):
3129 if self.lhs.index:
3130 index = ExprNodes.CloneNode(self.lhs.index)
3131 else:
3132 index = None
3133 if self.lhs.indices:
3134 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3135 else:
3136 indices = []
3137 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3138 base = ExprNodes.CloneNode(self.dup.base),
3139 index = index,
3140 indices = indices,
3141 is_temp = self.dup.is_temp)
3142 else:
3143 assert False
3144 self.lhs = target_lhs
3145 return self.dup
3147 def py_operation_function(self):
3148 return self.py_functions[self.operator]
3150 py_functions = {
3151 "|": "PyNumber_InPlaceOr",
3152 "^": "PyNumber_InPlaceXor",
3153 "&": "PyNumber_InPlaceAnd",
3154 "+": "PyNumber_InPlaceAdd",
3155 "-": "PyNumber_InPlaceSubtract",
3156 "*": "PyNumber_InPlaceMultiply",
3157 "/": "PyNumber_InPlaceDivide",
3158 "%": "PyNumber_InPlaceRemainder",
3159 "<<": "PyNumber_InPlaceLshift",
3160 ">>": "PyNumber_InPlaceRshift",
3161 "**": "PyNumber_InPlacePower",
3162 "//": "PyNumber_InPlaceFloorDivide",
3165 def annotate(self, code):
3166 self.lhs.annotate(code)
3167 self.rhs.annotate(code)
3168 self.dup.annotate(code)
3171 class PrintStatNode(StatNode):
3172 # print statement
3174 # arg_tuple TupleNode
3175 # append_newline boolean
3177 child_attrs = ["arg_tuple"]
3179 def analyse_expressions(self, env):
3180 self.arg_tuple.analyse_expressions(env)
3181 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3182 self.arg_tuple.release_temp(env)
3183 env.use_utility_code(printing_utility_code)
3184 self.gil_check(env)
3186 gil_message = "Python print statement"
3188 def generate_execution_code(self, code):
3189 self.arg_tuple.generate_evaluation_code(code)
3190 code.putln(
3191 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3192 self.arg_tuple.py_result(),
3193 self.append_newline,
3194 code.error_goto(self.pos)))
3195 self.arg_tuple.generate_disposal_code(code)
3196 self.arg_tuple.free_temps(code)
3198 def annotate(self, code):
3199 self.arg_tuple.annotate(code)
3202 class ExecStatNode(StatNode):
3203 # exec statement
3205 # args [ExprNode]
3207 child_attrs = ["args"]
3209 def analyse_expressions(self, env):
3210 for i, arg in enumerate(self.args):
3211 arg.analyse_expressions(env)
3212 arg = arg.coerce_to_pyobject(env)
3213 arg.release_temp(env)
3214 self.args[i] = arg
3215 self.temp_result = env.allocate_temp_pyobject()
3216 env.release_temp(self.temp_result)
3217 env.use_utility_code(Builtin.pyexec_utility_code)
3218 self.gil_check(env)
3220 gil_message = "Python exec statement"
3222 def generate_execution_code(self, code):
3223 args = []
3224 for arg in self.args:
3225 arg.generate_evaluation_code(code)
3226 args.append( arg.py_result() )
3227 args = tuple(args + ['0', '0'][:3-len(args)])
3228 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3229 (self.temp_result,) + args))
3230 for arg in self.args:
3231 arg.generate_disposal_code(code)
3232 arg.free_temps(code)
3233 code.putln(
3234 code.error_goto_if_null(self.temp_result, self.pos))
3235 code.put_decref_clear(self.temp_result, py_object_type)
3237 def annotate(self, code):
3238 for arg in self.args:
3239 arg.annotate(code)
3242 class DelStatNode(StatNode):
3243 # del statement
3245 # args [ExprNode]
3247 child_attrs = ["args"]
3249 def analyse_declarations(self, env):
3250 for arg in self.args:
3251 arg.analyse_target_declaration(env)
3253 def analyse_expressions(self, env):
3254 for arg in self.args:
3255 arg.analyse_target_expression(env, None)
3256 if arg.type.is_pyobject:
3257 self.gil_check(env)
3258 else:
3259 error(arg.pos, "Deletion of non-Python object")
3260 #arg.release_target_temp(env)
3262 gil_message = "Deleting Python object"
3264 def generate_execution_code(self, code):
3265 for arg in self.args:
3266 if arg.type.is_pyobject:
3267 arg.generate_deletion_code(code)
3268 # else error reported earlier
3270 def annotate(self, code):
3271 for arg in self.args:
3272 arg.annotate(code)
3275 class PassStatNode(StatNode):
3276 # pass statement
3278 child_attrs = []
3280 def analyse_expressions(self, env):
3281 pass
3283 def generate_execution_code(self, code):
3284 pass
3287 class BreakStatNode(StatNode):
3289 child_attrs = []
3291 def analyse_expressions(self, env):
3292 pass
3294 def generate_execution_code(self, code):
3295 if not code.break_label:
3296 error(self.pos, "break statement not inside loop")
3297 else:
3298 #code.putln(
3299 # "goto %s;" %
3300 # code.break_label)
3301 code.put_goto(code.break_label)
3304 class ContinueStatNode(StatNode):
3306 child_attrs = []
3308 def analyse_expressions(self, env):
3309 pass
3311 def generate_execution_code(self, code):
3312 if code.funcstate.in_try_finally:
3313 error(self.pos, "continue statement inside try of try...finally")
3314 elif not code.continue_label:
3315 error(self.pos, "continue statement not inside loop")
3316 else:
3317 code.put_goto(code.continue_label)
3320 class ReturnStatNode(StatNode):
3321 # return statement
3323 # value ExprNode or None
3324 # return_type PyrexType
3325 # temps_in_use [Entry] Temps in use at time of return
3327 child_attrs = ["value"]
3329 def analyse_expressions(self, env):
3330 return_type = env.return_type
3331 self.return_type = return_type
3332 self.temps_in_use = env.temps_in_use()
3333 if not return_type:
3334 error(self.pos, "Return not inside a function body")
3335 return
3336 if self.value:
3337 self.value.analyse_types(env)
3338 if return_type.is_void or return_type.is_returncode:
3339 error(self.value.pos,
3340 "Return with value in void function")
3341 else:
3342 self.value = self.value.coerce_to(env.return_type, env)
3343 self.value.allocate_temps(env)
3344 self.value.release_temp(env)
3345 else:
3346 if (not return_type.is_void
3347 and not return_type.is_pyobject
3348 and not return_type.is_returncode):
3349 error(self.pos, "Return value required")
3350 if return_type.is_pyobject:
3351 self.gil_check(env)
3353 gil_message = "Returning Python object"
3355 def generate_execution_code(self, code):
3356 code.mark_pos(self.pos)
3357 if not self.return_type:
3358 # error reported earlier
3359 return
3360 if self.value:
3361 self.value.generate_evaluation_code(code)
3362 self.value.make_owned_reference(code)
3363 code.putln(
3364 "%s = %s;" % (
3365 Naming.retval_cname,
3366 self.value.result_as(self.return_type)))
3367 self.value.generate_post_assignment_code(code)
3368 self.value.free_temps(code)
3369 else:
3370 if self.return_type.is_pyobject:
3371 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3372 elif self.return_type.is_returncode:
3373 code.putln(
3374 "%s = %s;" % (
3375 Naming.retval_cname,
3376 self.return_type.default_value))
3377 # free temps the old way
3378 for entry in self.temps_in_use:
3379 code.put_var_decref_clear(entry)
3380 # free temps the new way
3381 for cname, type in code.funcstate.temps_holding_reference():
3382 code.put_decref_clear(cname, type)
3383 #code.putln(
3384 # "goto %s;" %
3385 # code.return_label)
3386 code.put_goto(code.return_label)
3388 def annotate(self, code):
3389 if self.value:
3390 self.value.annotate(code)
3393 class RaiseStatNode(StatNode):
3394 # raise statement
3396 # exc_type ExprNode or None
3397 # exc_value ExprNode or None
3398 # exc_tb ExprNode or None
3400 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3402 def analyse_expressions(self, env):
3403 if self.exc_type:
3404 self.exc_type.analyse_types(env)
3405 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3406 self.exc_type.allocate_temps(env)
3407 if self.exc_value:
3408 self.exc_value.analyse_types(env)
3409 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3410 self.exc_value.allocate_temps(env)
3411 if self.exc_tb:
3412 self.exc_tb.analyse_types(env)
3413 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3414 self.exc_tb.allocate_temps(env)
3415 if self.exc_type:
3416 self.exc_type.release_temp(env)
3417 if self.exc_value:
3418 self.exc_value.release_temp(env)
3419 if self.exc_tb:
3420 self.exc_tb.release_temp(env)
3421 env.use_utility_code(raise_utility_code)
3422 env.use_utility_code(restore_exception_utility_code)
3423 self.gil_check(env)
3425 gil_message = "Raising exception"
3427 def generate_execution_code(self, code):
3428 if self.exc_type:
3429 self.exc_type.generate_evaluation_code(code)
3430 type_code = self.exc_type.py_result()
3431 else:
3432 type_code = 0
3433 if self.exc_value:
3434 self.exc_value.generate_evaluation_code(code)
3435 value_code = self.exc_value.py_result()
3436 else:
3437 value_code = "0"
3438 if self.exc_tb:
3439 self.exc_tb.generate_evaluation_code(code)
3440 tb_code = self.exc_tb.py_result()
3441 else:
3442 tb_code = "0"
3443 if self.exc_type or self.exc_value or self.exc_tb:
3444 code.putln(
3445 "__Pyx_Raise(%s, %s, %s);" % (
3446 type_code,
3447 value_code,
3448 tb_code))
3449 else:
3450 code.putln(
3451 "__Pyx_ReRaise();")
3452 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3453 if obj:
3454 obj.generate_disposal_code(code)
3455 obj.free_temps(code)
3456 code.putln(
3457 code.error_goto(self.pos))
3459 def annotate(self, code):
3460 if self.exc_type:
3461 self.exc_type.annotate(code)
3462 if self.exc_value:
3463 self.exc_value.annotate(code)
3464 if self.exc_tb:
3465 self.exc_tb.annotate(code)
3468 class ReraiseStatNode(StatNode):
3470 child_attrs = []
3472 def analyse_expressions(self, env):
3473 self.gil_check(env)
3474 env.use_utility_code(raise_utility_code)
3475 env.use_utility_code(restore_exception_utility_code)
3477 gil_message = "Raising exception"
3479 def generate_execution_code(self, code):
3480 vars = code.funcstate.exc_vars
3481 if vars:
3482 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3483 code.putln(code.error_goto(self.pos))
3484 else:
3485 error(self.pos, "Reraise not inside except clause")
3488 class AssertStatNode(StatNode):
3489 # assert statement
3491 # cond ExprNode
3492 # value ExprNode or None
3494 child_attrs = ["cond", "value"]
3496 def analyse_expressions(self, env):
3497 self.cond = self.cond.analyse_boolean_expression(env)
3498 if self.value:
3499 self.value.analyse_types(env)
3500 self.value = self.value.coerce_to_pyobject(env)
3501 self.value.allocate_temps(env)
3502 self.cond.release_temp(env)
3503 if self.value:
3504 self.value.release_temp(env)
3505 self.gil_check(env)
3506 #env.recycle_pending_temps() # TEMPORARY
3508 gil_message = "Raising exception"
3510 def generate_execution_code(self, code):
3511 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3512 self.cond.generate_evaluation_code(code)
3513 code.putln(
3514 "if (unlikely(!%s)) {" %
3515 self.cond.result())
3516 if self.value:
3517 self.value.generate_evaluation_code(code)
3518 code.putln(
3519 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3520 self.value.py_result())
3521 self.value.generate_disposal_code(code)
3522 self.value.free_temps(code)
3523 else:
3524 code.putln(
3525 "PyErr_SetNone(PyExc_AssertionError);")
3526 code.putln(
3527 code.error_goto(self.pos))
3528 code.putln(
3529 "}")
3530 self.cond.generate_disposal_code(code)
3531 self.cond.free_temps(code)
3532 code.putln("#endif")
3534 def annotate(self, code):
3535 self.cond.annotate(code)
3536 if self.value:
3537 self.value.annotate(code)
3540 class IfStatNode(StatNode):
3541 # if statement
3543 # if_clauses [IfClauseNode]
3544 # else_clause StatNode or None
3546 child_attrs = ["if_clauses", "else_clause"]
3548 def analyse_control_flow(self, env):
3549 env.start_branching(self.pos)
3550 for if_clause in self.if_clauses:
3551 if_clause.analyse_control_flow(env)
3552 env.next_branch(if_clause.end_pos())
3553 if self.else_clause:
3554 self.else_clause.analyse_control_flow(env)
3555 env.finish_branching(self.end_pos())
3557 def analyse_declarations(self, env):
3558 for if_clause in self.if_clauses:
3559 if_clause.analyse_declarations(env)
3560 if self.else_clause:
3561 self.else_clause.analyse_declarations(env)
3563 def analyse_expressions(self, env):
3564 for if_clause in self.if_clauses:
3565 if_clause.analyse_expressions(env)
3566 if self.else_clause:
3567 self.else_clause.analyse_expressions(env)
3569 def generate_execution_code(self, code):
3570 code.mark_pos(self.pos)
3571 end_label = code.new_label()
3572 for if_clause in self.if_clauses:
3573 if_clause.generate_execution_code(code, end_label)
3574 if self.else_clause:
3575 code.putln("/*else*/ {")
3576 self.else_clause.generate_execution_code(code)
3577 code.putln("}")
3578 code.put_label(end_label)
3580 def annotate(self, code):
3581 for if_clause in self.if_clauses:
3582 if_clause.annotate(code)
3583 if self.else_clause:
3584 self.else_clause.annotate(code)
3587 class IfClauseNode(Node):
3588 # if or elif clause in an if statement
3590 # condition ExprNode
3591 # body StatNode
3593 child_attrs = ["condition", "body"]
3595 def analyse_control_flow(self, env):
3596 self.body.analyse_control_flow(env)
3598 def analyse_declarations(self, env):
3599 self.condition.analyse_declarations(env)
3600 self.body.analyse_declarations(env)
3602 def analyse_expressions(self, env):
3603 self.condition = \
3604 self.condition.analyse_temp_boolean_expression(env)
3605 self.condition.release_temp(env)
3606 self.body.analyse_expressions(env)
3608 def generate_execution_code(self, code, end_label):
3609 self.condition.generate_evaluation_code(code)
3610 code.putln(
3611 "if (%s) {" %
3612 self.condition.result())
3613 self.condition.generate_disposal_code(code)
3614 self.condition.free_temps(code)
3615 self.body.generate_execution_code(code)
3616 #code.putln(
3617 # "goto %s;" %
3618 # end_label)
3619 code.put_goto(end_label)
3620 code.putln("}")
3622 def annotate(self, code):
3623 self.condition.annotate(code)
3624 self.body.annotate(code)
3627 class SwitchCaseNode(StatNode):
3628 # Generated in the optimization of an if-elif-else node
3630 # conditions [ExprNode]
3631 # body StatNode
3633 child_attrs = ['conditions', 'body']
3635 def generate_execution_code(self, code):
3636 for cond in self.conditions:
3637 code.putln("case %s:" % cond.calculate_result_code())
3638 self.body.generate_execution_code(code)
3639 code.putln("break;")
3641 def annotate(self, code):
3642 for cond in self.conditions:
3643 cond.annotate(code)
3644 self.body.annotate(code)
3646 class SwitchStatNode(StatNode):
3647 # Generated in the optimization of an if-elif-else node
3649 # test ExprNode
3650 # cases [SwitchCaseNode]
3651 # else_clause StatNode or None
3653 child_attrs = ['test', 'cases', 'else_clause']
3655 def generate_execution_code(self, code):
3656 code.putln("switch (%s) {" % self.test.calculate_result_code())
3657 for case in self.cases:
3658 case.generate_execution_code(code)
3659 if self.else_clause is not None:
3660 code.putln("default:")
3661 self.else_clause.generate_execution_code(code)
3662 code.putln("break;")
3663 code.putln("}")
3665 def annotate(self, code):
3666 self.test.annotate(code)
3667 for case in self.cases:
3668 case.annotate(code)
3669 if self.else_clause is not None:
3670 self.else_clause.annotate(code)
3672 class LoopNode:
3674 def analyse_control_flow(self, env):
3675 env.start_branching(self.pos)
3676 self.body.analyse_control_flow(env)
3677 env.next_branch(self.body.end_pos())
3678 if self.else_clause:
3679 self.else_clause.analyse_control_flow(env)
3680 env.finish_branching(self.end_pos())
3683 class WhileStatNode(LoopNode, StatNode):
3684 # while statement
3686 # condition ExprNode
3687 # body StatNode
3688 # else_clause StatNode
3690 child_attrs = ["condition", "body", "else_clause"]
3692 def analyse_declarations(self, env):
3693 self.body.analyse_declarations(env)
3694 if self.else_clause:
3695 self.else_clause.analyse_declarations(env)
3697 def analyse_expressions(self, env):
3698 self.condition = \
3699 self.condition.analyse_temp_boolean_expression(env)
3700 self.condition.release_temp(env)
3701 #env.recycle_pending_temps() # TEMPORARY
3702 self.body.analyse_expressions(env)
3703 if self.else_clause:
3704 self.else_clause.analyse_expressions(env)
3706 def generate_execution_code(self, code):
3707 old_loop_labels = code.new_loop_labels()
3708 code.putln(
3709 "while (1) {")
3710 self.condition.generate_evaluation_code(code)
3711 self.condition.generate_disposal_code(code)
3712 code.putln(
3713 "if (!%s) break;" %
3714 self.condition.result())
3715 self.condition.free_temps(code)
3716 self.body.generate_execution_code(code)
3717 code.put_label(code.continue_label)
3718 code.putln("}")
3719 break_label = code.break_label
3720 code.set_loop_labels(old_loop_labels)
3721 if self.else_clause:
3722 code.putln("/*else*/ {")
3723 self.else_clause.generate_execution_code(code)
3724 code.putln("}")
3725 code.put_label(break_label)
3727 def annotate(self, code):
3728 self.condition.annotate(code)
3729 self.body.annotate(code)
3730 if self.else_clause:
3731 self.else_clause.annotate(code)
3734 def ForStatNode(pos, **kw):
3735 if kw.has_key('iterator'):
3736 return ForInStatNode(pos, **kw)
3737 else:
3738 return ForFromStatNode(pos, **kw)
3740 class ForInStatNode(LoopNode, StatNode):
3741 # for statement
3743 # target ExprNode
3744 # iterator IteratorNode
3745 # body StatNode
3746 # else_clause StatNode
3747 # item NextNode used internally
3749 child_attrs = ["target", "iterator", "body", "else_clause"]
3750 item = None
3752 def analyse_declarations(self, env):
3753 self.target.analyse_target_declaration(env)
3754 self.body.analyse_declarations(env)
3755 if self.else_clause:
3756 self.else_clause.analyse_declarations(env)
3758 def analyse_expressions(self, env):
3759 import ExprNodes
3760 self.target.analyse_target_types(env)
3761 self.iterator.analyse_expressions(env)
3762 self.item = ExprNodes.NextNode(self.iterator, env)
3763 self.item = self.item.coerce_to(self.target.type, env)
3764 self.item.allocate_temps(env)
3765 self.target.allocate_target_temps(env, self.item)
3766 #self.item.release_temp(env)
3767 #self.target.release_target_temp(env)
3768 self.body.analyse_expressions(env)
3769 if self.else_clause:
3770 self.else_clause.analyse_expressions(env)
3771 self.iterator.release_temp(env)
3773 def generate_execution_code(self, code):
3774 old_loop_labels = code.new_loop_labels()
3775 self.iterator.allocate_counter_temp(code)
3776 self.iterator.generate_evaluation_code(code)
3777 code.putln(
3778 "for (;;) {")
3779 self.item.generate_evaluation_code(code)
3780 self.target.generate_assignment_code(self.item, code)
3781 self.body.generate_execution_code(code)
3782 code.put_label(code.continue_label)
3783 code.putln(
3784 "}")
3785 break_label = code.break_label
3786 code.set_loop_labels(old_loop_labels)
3787 if self.else_clause:
3788 code.putln("/*else*/ {")
3789 self.else_clause.generate_execution_code(code)
3790 code.putln("}")
3791 code.put_label(break_label)
3792 self.iterator.release_counter_temp(code)
3793 self.iterator.generate_disposal_code(code)
3794 self.iterator.free_temps(code)
3796 def annotate(self, code):
3797 self.target.annotate(code)
3798 self.iterator.annotate(code)
3799 self.body.annotate(code)
3800 if self.else_clause:
3801 self.else_clause.annotate(code)
3802 self.item.annotate(code)
3805 class ForFromStatNode(LoopNode, StatNode):
3806 # for name from expr rel name rel expr
3808 # target NameNode
3809 # bound1 ExprNode
3810 # relation1 string
3811 # relation2 string
3812 # bound2 ExprNode
3813 # step ExprNode or None
3814 # body StatNode
3815 # else_clause StatNode or None
3817 # Used internally:
3819 # is_py_target bool
3820 # loopvar_node ExprNode (usually a NameNode or temp node)
3821 # py_loopvar_node PyTempNode or None
3822 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3824 is_py_target = False
3825 loopvar_node = None
3826 py_loopvar_node = None
3828 def analyse_declarations(self, env):
3829 self.target.analyse_target_declaration(env)
3830 self.body.analyse_declarations(env)
3831 if self.else_clause:
3832 self.else_clause.analyse_declarations(env)
3834 def analyse_expressions(self, env):
3835 import ExprNodes
3836 self.target.analyse_target_types(env)
3837 self.bound1.analyse_types(env)
3838 self.bound2.analyse_types(env)
3839 if self.target.type.is_numeric:
3840 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3841 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3842 else:
3843 self.bound1 = self.bound1.coerce_to_integer(env)
3844 self.bound2 = self.bound2.coerce_to_integer(env)
3845 if self.step is not None:
3846 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3847 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3848 self.step.analyse_types(env)
3849 self.step = self.step.coerce_to_integer(env)
3850 if not (self.bound2.is_name or self.bound2.is_literal):
3851 self.bound2 = self.bound2.coerce_to_temp(env)
3852 target_type = self.target.type
3853 if not (target_type.is_pyobject or target_type.is_numeric):
3854 error(self.target.pos,
3855 "Integer for-loop variable must be of type int or Python object")
3856 #if not (target_type.is_pyobject
3857 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3858 # error(self.target.pos,
3859 # "Cannot assign integer to variable of type '%s'" % target_type)
3860 if target_type.is_numeric:
3861 self.is_py_target = 0
3862 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3863 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3864 self.loopvar_node = self.target
3865 self.py_loopvar_node = None
3866 else:
3867 self.is_py_target = 1
3868 c_loopvar_node = ExprNodes.TempNode(self.pos,
3869 PyrexTypes.c_long_type, env)
3870 c_loopvar_node.allocate_temps(env)
3871 self.loopvar_node = c_loopvar_node
3872 self.py_loopvar_node = \
3873 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3874 self.bound1.allocate_temps(env)
3875 self.bound2.allocate_temps(env)
3876 if self.step is not None:
3877 self.step.allocate_temps(env)
3878 if self.is_py_target:
3879 self.py_loopvar_node.allocate_temps(env)
3880 self.target.allocate_target_temps(env, self.py_loopvar_node)
3881 #self.target.release_target_temp(env)
3882 #self.py_loopvar_node.release_temp(env)
3883 self.body.analyse_expressions(env)
3884 if self.is_py_target:
3885 c_loopvar_node.release_temp(env)
3886 if self.else_clause:
3887 self.else_clause.analyse_expressions(env)
3888 self.bound1.release_temp(env)
3889 self.bound2.release_temp(env)
3890 if self.step is not None:
3891 self.step.release_temp(env)
3893 def generate_execution_code(self, code):
3894 old_loop_labels = code.new_loop_labels()
3895 self.bound1.generate_evaluation_code(code)
3896 self.bound2.generate_evaluation_code(code)
3897 offset, incop = self.relation_table[self.relation1]
3898 if self.step is not None:
3899 self.step.generate_evaluation_code(code)
3900 incop = "%s=%s" % (incop[0], self.step.result())
3901 loopvar_name = self.loopvar_node.result()
3902 code.putln(
3903 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3904 loopvar_name,
3905 self.bound1.result(), offset,
3906 loopvar_name, self.relation2, self.bound2.result(),
3907 loopvar_name, incop))
3908 if self.py_loopvar_node:
3909 self.py_loopvar_node.generate_evaluation_code(code)
3910 self.target.generate_assignment_code(self.py_loopvar_node, code)
3911 self.body.generate_execution_code(code)
3912 code.put_label(code.continue_label)
3913 code.putln("}")
3914 break_label = code.break_label
3915 code.set_loop_labels(old_loop_labels)
3916 if self.else_clause:
3917 code.putln("/*else*/ {")
3918 self.else_clause.generate_execution_code(code)
3919 code.putln("}")
3920 code.put_label(break_label)
3921 self.bound1.generate_disposal_code(code)
3922 self.bound1.free_temps(code)
3923 self.bound2.generate_disposal_code(code)
3924 self.bound2.free_temps(code)
3925 if self.step is not None:
3926 self.step.generate_disposal_code(code)
3927 self.step.free_temps(code)
3929 relation_table = {
3930 # {relop : (initial offset, increment op)}
3931 '<=': ("", "++"),
3932 '<' : ("+1", "++"),
3933 '>=': ("", "--"),
3934 '>' : ("-1", "--")
3937 def annotate(self, code):
3938 self.target.annotate(code)
3939 self.bound1.annotate(code)
3940 self.bound2.annotate(code)
3941 if self.step:
3942 self.bound2.annotate(code)
3943 self.body.annotate(code)
3944 if self.else_clause:
3945 self.else_clause.annotate(code)
3948 class WithStatNode(StatNode):
3949 """
3950 Represents a Python with statement.
3952 This is only used at parse tree level; and is not present in
3953 analysis or generation phases.
3954 """
3955 # manager The with statement manager object
3956 # target Node (lhs expression)
3957 # body StatNode
3958 child_attrs = ["manager", "target", "body"]
3960 class TryExceptStatNode(StatNode):
3961 # try .. except statement
3963 # body StatNode
3964 # except_clauses [ExceptClauseNode]
3965 # else_clause StatNode or None
3966 # cleanup_list [Entry] old style temps to clean up on error
3968 child_attrs = ["body", "except_clauses", "else_clause"]
3970 def analyse_control_flow(self, env):
3971 env.start_branching(self.pos)
3972 self.body.analyse_control_flow(env)
3973 successful_try = env.control_flow # grab this for later
3974 env.next_branch(self.body.end_pos())
3975 env.finish_branching(self.body.end_pos())
3977 env.start_branching(self.except_clauses[0].pos)
3978 for except_clause in self.except_clauses:
3979 except_clause.analyse_control_flow(env)
3980 env.next_branch(except_clause.end_pos())
3982 # the else cause it executed only when the try clause finishes
3983 env.control_flow.incoming = successful_try
3984 if self.else_clause:
3985 self.else_clause.analyse_control_flow(env)
3986 env.finish_branching(self.end_pos())
3988 def analyse_declarations(self, env):
3989 self.body.analyse_declarations(env)
3990 for except_clause in self.except_clauses:
3991 except_clause.analyse_declarations(env)
3992 if self.else_clause:
3993 self.else_clause.analyse_declarations(env)
3994 self.gil_check(env)
3995 env.use_utility_code(reset_exception_utility_code)
3997 def analyse_expressions(self, env):
3998 self.body.analyse_expressions(env)
3999 self.cleanup_list = env.free_temp_entries[:]
4000 default_clause_seen = 0
4001 for except_clause in self.except_clauses:
4002 except_clause.analyse_expressions(env)
4003 if default_clause_seen:
4004 error(except_clause.pos, "default 'except:' must be last")
4005 if not except_clause.pattern:
4006 default_clause_seen = 1
4007 self.has_default_clause = default_clause_seen
4008 if self.else_clause:
4009 self.else_clause.analyse_expressions(env)
4010 self.gil_check(env)
4012 gil_message = "Try-except statement"
4014 def generate_execution_code(self, code):
4015 old_return_label = code.return_label
4016 old_error_label = code.new_error_label()
4017 our_error_label = code.error_label
4018 except_end_label = code.new_label('exception_handled')
4019 except_error_label = code.new_label('except_error')
4020 except_return_label = code.new_label('except_return')
4021 try_return_label = code.new_label('try_return')
4022 try_end_label = code.new_label('try')
4024 code.putln("{")
4025 code.putln("PyObject %s;" %
4026 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4027 code.putln("__Pyx_ExceptionSave(%s);" %
4028 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4029 code.putln(
4030 "/*try:*/ {")
4031 code.return_label = try_return_label
4032 self.body.generate_execution_code(code)
4033 code.putln(
4034 "}")
4035 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4036 code.error_label = except_error_label
4037 code.return_label = except_return_label
4038 if self.else_clause:
4039 code.putln(
4040 "/*else:*/ {")
4041 self.else_clause.generate_execution_code(code)
4042 code.putln(
4043 "}")
4044 for var in Naming.exc_save_vars:
4045 code.put_xdecref_clear(var, py_object_type)
4046 code.put_goto(try_end_label)
4047 if code.label_used(try_return_label):
4048 code.put_label(try_return_label)
4049 for var in Naming.exc_save_vars:
4050 code.put_xdecref_clear(var, py_object_type)
4051 code.put_goto(old_return_label)
4052 code.put_label(our_error_label)
4053 code.put_var_xdecrefs_clear(self.cleanup_list)
4054 for temp_name, type in temps_to_clean_up:
4055 code.put_xdecref_clear(temp_name, type)
4056 for except_clause in self.except_clauses:
4057 except_clause.generate_handling_code(code, except_end_label)
4059 error_label_used = code.label_used(except_error_label)
4060 if error_label_used or not self.has_default_clause:
4061 if error_label_used:
4062 code.put_label(except_error_label)
4063 for var in Naming.exc_save_vars:
4064 code.put_xdecref(var, py_object_type)
4065 code.put_goto(old_error_label)
4067 if code.label_used(except_return_label):
4068 code.put_label(except_return_label)
4069 code.putln("__Pyx_ExceptionReset(%s);" %
4070 ', '.join(Naming.exc_save_vars))
4071 code.put_goto(old_return_label)
4073 if code.label_used(except_end_label):
4074 code.put_label(except_end_label)
4075 code.putln("__Pyx_ExceptionReset(%s);" %
4076 ', '.join(Naming.exc_save_vars))
4077 code.put_label(try_end_label)
4078 code.putln("}")
4080 code.return_label = old_return_label
4081 code.error_label = old_error_label
4083 def annotate(self, code):
4084 self.body.annotate(code)
4085 for except_node in self.except_clauses:
4086 except_node.annotate(code)
4087 if self.else_clause:
4088 self.else_clause.annotate(code)
4091 class ExceptClauseNode(Node):
4092 # Part of try ... except statement.
4094 # pattern ExprNode
4095 # target ExprNode or None
4096 # body StatNode
4097 # excinfo_target NameNode or None optional target for exception info
4098 # match_flag string result of exception match
4099 # exc_value ExcValueNode used internally
4100 # function_name string qualified name of enclosing function
4101 # exc_vars (string * 3) local exception variables
4103 # excinfo_target is never set by the parser, but can be set by a transform
4104 # in order to extract more extensive information about the exception as a
4105 # sys.exc_info()-style tuple into a target variable
4107 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4109 exc_value = None
4110 excinfo_target = None
4112 def analyse_declarations(self, env):
4113 if self.target:
4114 self.target.analyse_target_declaration(env)
4115 if self.excinfo_target is not None:
4116 self.excinfo_target.analyse_target_declaration(env)
4117 self.body.analyse_declarations(env)
4119 def analyse_expressions(self, env):
4120 import ExprNodes
4121 genv = env.global_scope()
4122 self.function_name = env.qualified_name
4123 if self.pattern:
4124 self.pattern.analyse_expressions(env)
4125 self.pattern = self.pattern.coerce_to_pyobject(env)
4126 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
4127 self.pattern.release_temp(env)
4128 env.release_temp(self.match_flag)
4129 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
4130 if self.target:
4131 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
4132 self.exc_value.allocate_temps(env)
4133 self.target.analyse_target_expression(env, self.exc_value)
4134 if self.excinfo_target is not None:
4135 import ExprNodes
4136 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4137 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
4138 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
4139 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
4140 ])
4141 self.excinfo_tuple.analyse_expressions(env)
4142 self.excinfo_tuple.allocate_temps(env)
4143 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4145 self.body.analyse_expressions(env)
4146 for var in self.exc_vars:
4147 env.release_temp(var)
4148 env.use_utility_code(get_exception_utility_code)
4149 env.use_utility_code(restore_exception_utility_code)
4151 def generate_handling_code(self, code, end_label):
4152 code.mark_pos(self.pos)
4153 if self.pattern:
4154 self.pattern.generate_evaluation_code(code)
4155 code.putln(
4156 "%s = PyErr_ExceptionMatches(%s);" % (
4157 self.match_flag,
4158 self.pattern.py_result()))
4159 self.pattern.generate_disposal_code(code)
4160 self.pattern.free_temps(code)
4161 code.putln(
4162 "if (%s) {" %
4163 self.match_flag)
4164 else:
4165 code.putln("/*except:*/ {")
4166 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4167 # We always have to fetch the exception value even if
4168 # there is no target, because this also normalises the
4169 # exception and stores it in the thread state.
4170 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
4171 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4172 code.error_goto(self.pos)))
4173 if self.target:
4174 self.exc_value.generate_evaluation_code(code)
4175 self.target.generate_assignment_code(self.exc_value, code)
4176 if self.excinfo_target is not None:
4177 self.excinfo_tuple.generate_evaluation_code(code)
4178 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4180 old_exc_vars = code.funcstate.exc_vars
4181 code.funcstate.exc_vars = self.exc_vars
4182 self.body.generate_execution_code(code)
4183 code.funcstate.exc_vars = old_exc_vars
4184 for var in self.exc_vars:
4185 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4186 code.put_goto(end_label)
4187 code.putln(
4188 "}")
4190 def annotate(self, code):
4191 if self.pattern:
4192 self.pattern.annotate(code)
4193 if self.target:
4194 self.target.annotate(code)
4195 self.body.annotate(code)
4198 class TryFinallyStatNode(StatNode):
4199 # try ... finally statement
4201 # body StatNode
4202 # finally_clause StatNode
4204 # cleanup_list [Entry] old_style temps to clean up on error
4206 # The plan is that we funnel all continue, break
4207 # return and error gotos into the beginning of the
4208 # finally block, setting a variable to remember which
4209 # one we're doing. At the end of the finally block, we
4210 # switch on the variable to figure out where to go.
4211 # In addition, if we're doing an error, we save the
4212 # exception on entry to the finally block and restore
4213 # it on exit.
4215 child_attrs = ["body", "finally_clause"]
4217 preserve_exception = 1
4219 disallow_continue_in_try_finally = 0
4220 # There doesn't seem to be any point in disallowing
4221 # continue in the try block, since we have no problem
4222 # handling it.
4224 def create_analysed(pos, env, body, finally_clause):
4225 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4226 node.cleanup_list = []
4227 return node
4228 create_analysed = staticmethod(create_analysed)
4230 def analyse_control_flow(self, env):
4231 env.start_branching(self.pos)
4232 self.body.analyse_control_flow(env)
4233 env.next_branch(self.body.end_pos())
4234 env.finish_branching(self.body.end_pos())
4235 self.finally_clause.analyse_control_flow(env)
4237 def analyse_declarations(self, env):
4238 self.body.analyse_declarations(env)
4239 self.finally_clause.analyse_declarations(env)
4241 def analyse_expressions(self, env):
4242 self.body.analyse_expressions(env)
4243 self.cleanup_list = env.free_temp_entries[:]
4244 self.finally_clause.analyse_expressions(env)
4245 self.gil_check(env)
4247 gil_message = "Try-finally statement"
4249 def generate_execution_code(self, code):
4250 old_error_label = code.error_label
4251 old_labels = code.all_new_labels()
4252 new_labels = code.get_all_labels()
4253 new_error_label = code.error_label
4254 catch_label = code.new_label()
4255 code.putln(
4256 "/*try:*/ {")
4257 if self.disallow_continue_in_try_finally:
4258 was_in_try_finally = code.funcstate.in_try_finally
4259 code.funcstate.in_try_finally = 1
4260 self.body.generate_execution_code(code)
4261 if self.disallow_continue_in_try_finally:
4262 code.funcstate.in_try_finally = was_in_try_finally
4263 code.putln(
4264 "}")
4265 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4266 code.putln(
4267 "/*finally:*/ {")
4268 cases_used = []
4269 error_label_used = 0
4270 for i, new_label in enumerate(new_labels):
4271 if new_label in code.labels_used:
4272 cases_used.append(i)
4273 if new_label == new_error_label:
4274 error_label_used = 1
4275 error_label_case = i
4276 if cases_used:
4277 code.putln(
4278 "int __pyx_why;")
4279 if error_label_used and self.preserve_exception:
4280 code.putln(
4281 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4282 code.putln(
4283 "int %s;" % Naming.exc_lineno_name)
4284 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4285 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4286 code.putln(exc_var_init_zero)
4287 else:
4288 exc_var_init_zero = None
4289 code.use_label(catch_label)
4290 code.putln(
4291 "__pyx_why = 0; goto %s;" % catch_label)
4292 for i in cases_used:
4293 new_label = new_labels[i]
4294 #if new_label and new_label != "<try>":
4295 if new_label == new_error_label and self.preserve_exception:
4296 self.put_error_catcher(code,
4297 new_error_label, i+1, catch_label, temps_to_clean_up)
4298 else:
4299 code.put('%s: ' % new_label)
4300 if exc_var_init_zero:
4301 code.putln(exc_var_init_zero)
4302 code.putln("__pyx_why = %s; goto %s;" % (
4303 i+1,
4304 catch_label))
4305 code.put_label(catch_label)
4306 code.set_all_labels(old_labels)
4307 if error_label_used:
4308 code.new_error_label()
4309 finally_error_label = code.error_label
4310 self.finally_clause.generate_execution_code(code)
4311 if error_label_used:
4312 if finally_error_label in code.labels_used and self.preserve_exception:
4313 over_label = code.new_label()
4314 code.put_goto(over_label);
4315 code.put_label(finally_error_label)
4316 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4317 for var in Naming.exc_vars:
4318 code.putln("Py_XDECREF(%s);" % var)
4319 code.putln("}")
4320 code.put_goto(old_error_label)
4321 code.put_label(over_label)
4322 code.error_label = old_error_label
4323 if cases_used:
4324 code.putln(
4325 "switch (__pyx_why) {")
4326 for i in cases_used:
4327 old_label = old_labels[i]
4328 if old_label == old_error_label and self.preserve_exception:
4329 self.put_error_uncatcher(code, i+1, old_error_label)
4330 else:
4331 code.use_label(old_label)
4332 code.putln(
4333 "case %s: goto %s;" % (
4334 i+1,
4335 old_label))
4336 code.putln(
4337 "}")
4338 code.putln(
4339 "}")
4341 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4342 code.globalstate.use_utility_code(restore_exception_utility_code)
4343 code.putln(
4344 "%s: {" %
4345 error_label)
4346 code.putln(
4347 "__pyx_why = %s;" %
4348 i)
4349 code.put_var_xdecrefs_clear(self.cleanup_list)
4350 for temp_name, type in temps_to_clean_up:
4351 code.put_xdecref_clear(temp_name, type)
4352 code.putln(
4353 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4354 Naming.exc_vars)
4355 code.putln(
4356 "%s = %s;" % (
4357 Naming.exc_lineno_name, Naming.lineno_cname))
4358 #code.putln(
4359 # "goto %s;" %
4360 # catch_label)
4361 code.put_goto(catch_label)
4362 code.putln(
4363 "}")
4365 def put_error_uncatcher(self, code, i, error_label):
4366 code.globalstate.use_utility_code(restore_exception_utility_code)
4367 code.putln(
4368 "case %s: {" %
4369 i)
4370 code.putln(
4371 "__Pyx_ErrRestore(%s, %s, %s);" %
4372 Naming.exc_vars)
4373 code.putln(
4374 "%s = %s;" % (
4375 Naming.lineno_cname, Naming.exc_lineno_name))
4376 for var in Naming.exc_vars:
4377 code.putln(
4378 "%s = 0;" %
4379 var)
4380 code.put_goto(error_label)
4381 code.putln(
4382 "}")
4384 def annotate(self, code):
4385 self.body.annotate(code)
4386 self.finally_clause.annotate(code)
4389 class GILStatNode(TryFinallyStatNode):
4390 # 'with gil' or 'with nogil' statement
4392 # state string 'gil' or 'nogil'
4394 child_attrs = []
4396 preserve_exception = 0
4398 def __init__(self, pos, state, body):
4399 self.state = state
4400 TryFinallyStatNode.__init__(self, pos,
4401 body = body,
4402 finally_clause = GILExitNode(pos, state = state))
4404 def analyse_expressions(self, env):
4405 was_nogil = env.nogil
4406 env.nogil = 1
4407 TryFinallyStatNode.analyse_expressions(self, env)
4408 env.nogil = was_nogil
4410 def gil_check(self, env):
4411 pass
4413 def generate_execution_code(self, code):
4414 code.putln("/*with %s:*/ {" % self.state)
4415 if self.state == 'gil':
4416 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
4417 else:
4418 code.putln("PyThreadState *_save;")
4419 code.putln("Py_UNBLOCK_THREADS")
4420 TryFinallyStatNode.generate_execution_code(self, code)
4421 code.putln("}")
4424 class GILExitNode(StatNode):
4425 # Used as the 'finally' block in a GILStatNode
4427 # state string 'gil' or 'nogil'
4429 child_attrs = []
4431 def analyse_expressions(self, env):
4432 pass
4434 def generate_execution_code(self, code):
4435 if self.state == 'gil':
4436 code.putln("PyGILState_Release();")
4437 else:
4438 code.putln("Py_BLOCK_THREADS")
4441 class CImportStatNode(StatNode):
4442 # cimport statement
4444 # module_name string Qualified name of module being imported
4445 # as_name string or None Name specified in "as" clause, if any
4447 child_attrs = []
4449 def analyse_declarations(self, env):
4450 if not env.is_module_scope:
4451 error(self.pos, "cimport only allowed at module level")
4452 return
4453 module_scope = env.find_module(self.module_name, self.pos)
4454 if "." in self.module_name:
4455 names = [EncodedString(name) for name in self.module_name.split(".")]
4456 top_name = names[0]
4457 top_module_scope = env.context.find_submodule(top_name)
4458 module_scope = top_module_scope
4459 for name in names[1:]:
4460 submodule_scope = module_scope.find_submodule(name)
4461 module_scope.declare_module(name, submodule_scope, self.pos)
4462 module_scope = submodule_scope
4463 if self.as_name:
4464 env.declare_module(self.as_name, module_scope, self.pos)
4465 else:
4466 env.declare_module(top_name, top_module_scope, self.pos)
4467 else:
4468 name = self.as_name or self.module_name
4469 env.declare_module(name, module_scope, self.pos)
4471 def analyse_expressions(self, env):
4472 pass
4474 def generate_execution_code(self, code):
4475 pass
4478 class FromCImportStatNode(StatNode):
4479 # from ... cimport statement
4481 # module_name string Qualified name of module
4482 # imported_names [(pos, name, as_name, kind)] Names to be imported
4484 child_attrs = []
4486 def analyse_declarations(self, env):
4487 if not env.is_module_scope:
4488 error(self.pos, "cimport only allowed at module level")
4489 return
4490 module_scope = env.find_module(self.module_name, self.pos)
4491 env.add_imported_module(module_scope)
4492 for pos, name, as_name, kind in self.imported_names:
4493 if name == "*":
4494 for local_name, entry in module_scope.entries.items():
4495 env.add_imported_entry(local_name, entry, pos)
4496 else:
4497 entry = module_scope.lookup(name)
4498 if entry:
4499 if kind and not self.declaration_matches(entry, kind):
4500 entry.redeclared(pos)
4501 else:
4502 if kind == 'struct' or kind == 'union':
4503 entry = module_scope.declare_struct_or_union(name,
4504 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4505 elif kind == 'class':
4506 entry = module_scope.declare_c_class(name, pos = pos,
4507 module_name = self.module_name)
4508 else:
4509 error(pos, "Name '%s' not declared in module '%s'"
4510 % (name, self.module_name))
4512 if entry:
4513 local_name = as_name or name
4514 env.add_imported_entry(local_name, entry, pos)
4516 def declaration_matches(self, entry, kind):
4517 if not entry.is_type:
4518 return 0
4519 type = entry.type
4520 if kind == 'class':
4521 if not type.is_extension_type:
4522 return 0
4523 else:
4524 if not type.is_struct_or_union:
4525 return 0
4526 if kind != type.kind:
4527 return 0
4528 return 1
4530 def analyse_expressions(self, env):
4531 pass
4533 def generate_execution_code(self, code):
4534 pass
4537 class FromImportStatNode(StatNode):
4538 # from ... import statement
4540 # module ImportNode
4541 # items [(string, NameNode)]
4542 # interned_items [(string, NameNode)]
4543 # item PyTempNode used internally
4544 # import_star boolean used internally
4546 child_attrs = ["module"]
4547 import_star = 0
4549 def analyse_declarations(self, env):
4550 for name, target in self.items:
4551 if name == "*":
4552 if not env.is_module_scope:
4553 error(self.pos, "import * only allowed at module level")
4554 return
4555 env.has_import_star = 1
4556 self.import_star = 1
4557 else:
4558 target.analyse_target_declaration(env)
4560 def analyse_expressions(self, env):
4561 import ExprNodes
4562 self.module.analyse_expressions(env)
4563 self.item = ExprNodes.PyTempNode(self.pos, env)
4564 self.item.allocate_temp(env)
4565 self.interned_items = []
4566 for name, target in self.items:
4567 if name == '*':
4568 for _, entry in env.entries.items():
4569 if not entry.is_type and entry.type.is_extension_type:
4570 env.use_utility_code(ExprNodes.type_test_utility_code)
4571 break
4572 else:
4573 entry = env.lookup(target.name)
4574 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4575 continue # already cimported
4576 self.interned_items.append(
4577 (env.intern_identifier(name), target))
4578 target.analyse_target_expression(env, None)
4579 #target.release_target_temp(env) # was release_temp ?!?
4580 self.module.release_temp(env)
4581 self.item.release_temp(env)
4583 def generate_execution_code(self, code):
4584 self.module.generate_evaluation_code(code)
4585 if self.import_star:
4586 code.putln(
4587 'if (%s(%s) < 0) %s;' % (
4588 Naming.import_star,
4589 self.module.py_result(),
4590 code.error_goto(self.pos)))
4591 for cname, target in self.interned_items:
4592 code.putln(
4593 '%s = PyObject_GetAttr(%s, %s); %s' % (
4594 self.item.result(),
4595 self.module.py_result(),
4596 cname,
4597 code.error_goto_if_null(self.item.result(), self.pos)))
4598 code.put_gotref(self.item.py_result())
4599 target.generate_assignment_code(self.item, code)
4600 self.module.generate_disposal_code(code)
4601 self.module.free_temps(code)
4605 #------------------------------------------------------------------------------------
4607 # Runtime support code
4609 #------------------------------------------------------------------------------------
4611 utility_function_predeclarations = \
4612 """
4613 #ifdef __GNUC__
4614 #define INLINE __inline__
4615 #elif _WIN32
4616 #define INLINE __inline
4617 #else
4618 #define INLINE
4619 #endif
4621 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4623 """ + """
4625 static int %(skip_dispatch_cname)s = 0;
4627 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4629 if Options.gcc_branch_hints:
4630 branch_prediction_macros = \
4631 """
4632 #ifdef __GNUC__
4633 /* Test for GCC > 2.95 */
4634 #if __GNUC__ > 2 || \
4635 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4636 #define likely(x) __builtin_expect(!!(x), 1)
4637 #define unlikely(x) __builtin_expect(!!(x), 0)
4638 #else /* __GNUC__ > 2 ... */
4639 #define likely(x) (x)
4640 #define unlikely(x) (x)
4641 #endif /* __GNUC__ > 2 ... */
4642 #else /* __GNUC__ */
4643 #define likely(x) (x)
4644 #define unlikely(x) (x)
4645 #endif /* __GNUC__ */
4646 """
4647 else:
4648 branch_prediction_macros = \
4649 """
4650 #define likely(x) (x)
4651 #define unlikely(x) (x)
4652 """
4654 #get_name_predeclaration = \
4655 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4657 #get_name_interned_predeclaration = \
4658 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4660 #------------------------------------------------------------------------------------
4662 printing_utility_code = UtilityCode(
4663 proto = """
4664 static int __Pyx_Print(PyObject *, int); /*proto*/
4665 #if PY_MAJOR_VERSION >= 3
4666 static PyObject* %s = 0;
4667 static PyObject* %s = 0;
4668 #endif
4669 """ % (Naming.print_function, Naming.print_function_kwargs),
4670 impl = r"""
4671 #if PY_MAJOR_VERSION < 3
4672 static PyObject *__Pyx_GetStdout(void) {
4673 PyObject *f = PySys_GetObject((char *)"stdout");
4674 if (!f) {
4675 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4677 return f;
4680 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4681 PyObject *f;
4682 PyObject* v;
4683 int i;
4685 if (!(f = __Pyx_GetStdout()))
4686 return -1;
4687 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4688 if (PyFile_SoftSpace(f, 1)) {
4689 if (PyFile_WriteString(" ", f) < 0)
4690 return -1;
4692 v = PyTuple_GET_ITEM(arg_tuple, i);
4693 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4694 return -1;
4695 if (PyString_Check(v)) {
4696 char *s = PyString_AsString(v);
4697 Py_ssize_t len = PyString_Size(v);
4698 if (len > 0 &&
4699 isspace(Py_CHARMASK(s[len-1])) &&
4700 s[len-1] != ' ')
4701 PyFile_SoftSpace(f, 0);
4704 if (newline) {
4705 if (PyFile_WriteString("\n", f) < 0)
4706 return -1;
4707 PyFile_SoftSpace(f, 0);
4709 return 0;
4712 #else /* Python 3 has a print function */
4713 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4714 PyObject* kwargs = 0;
4715 PyObject* result = 0;
4716 PyObject* end_string;
4717 if (!%(PRINT_FUNCTION)s) {
4718 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4719 if (!%(PRINT_FUNCTION)s)
4720 return -1;
4722 if (!newline) {
4723 if (!%(PRINT_KWARGS)s) {
4724 %(PRINT_KWARGS)s = PyDict_New();
4725 if (!%(PRINT_KWARGS)s)
4726 return -1;
4727 end_string = PyUnicode_FromStringAndSize(" ", 1);
4728 if (!end_string)
4729 return -1;
4730 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4731 Py_DECREF(end_string);
4732 return -1;
4734 Py_DECREF(end_string);
4736 kwargs = %(PRINT_KWARGS)s;
4738 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4739 if (!result)
4740 return -1;
4741 Py_DECREF(result);
4742 return 0;
4744 #endif
4745 """ % {'BUILTINS' : Naming.builtins_cname,
4746 'PRINT_FUNCTION' : Naming.print_function,
4747 'PRINT_KWARGS' : Naming.print_function_kwargs}
4750 #------------------------------------------------------------------------------------
4752 # The following function is based on do_raise() from ceval.c.
4754 raise_utility_code = UtilityCode(
4755 proto = """
4756 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4757 """,
4758 impl = """
4759 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4760 Py_XINCREF(type);
4761 Py_XINCREF(value);
4762 Py_XINCREF(tb);
4763 /* First, check the traceback argument, replacing None with NULL. */
4764 if (tb == Py_None) {
4765 Py_DECREF(tb);
4766 tb = 0;
4768 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4769 PyErr_SetString(PyExc_TypeError,
4770 "raise: arg 3 must be a traceback or None");
4771 goto raise_error;
4773 /* Next, replace a missing value with None */
4774 if (value == NULL) {
4775 value = Py_None;
4776 Py_INCREF(value);
4778 #if PY_VERSION_HEX < 0x02050000
4779 if (!PyClass_Check(type))
4780 #else
4781 if (!PyType_Check(type))
4782 #endif
4784 /* Raising an instance. The value should be a dummy. */
4785 if (value != Py_None) {
4786 PyErr_SetString(PyExc_TypeError,
4787 "instance exception may not have a separate value");
4788 goto raise_error;
4790 /* Normalize to raise <class>, <instance> */
4791 Py_DECREF(value);
4792 value = type;
4793 #if PY_VERSION_HEX < 0x02050000
4794 if (PyInstance_Check(type)) {
4795 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4796 Py_INCREF(type);
4798 else {
4799 type = 0;
4800 PyErr_SetString(PyExc_TypeError,
4801 "raise: exception must be an old-style class or instance");
4802 goto raise_error;
4804 #else
4805 type = (PyObject*) Py_TYPE(type);
4806 Py_INCREF(type);
4807 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4808 PyErr_SetString(PyExc_TypeError,
4809 "raise: exception class must be a subclass of BaseException");
4810 goto raise_error;
4812 #endif
4814 __Pyx_ErrRestore(type, value, tb);
4815 return;
4816 raise_error:
4817 Py_XDECREF(value);
4818 Py_XDECREF(type);
4819 Py_XDECREF(tb);
4820 return;
4822 """)
4824 #------------------------------------------------------------------------------------
4826 reraise_utility_code = UtilityCode(
4827 proto = """
4828 static void __Pyx_ReRaise(void); /*proto*/
4829 """,
4830 impl = """
4831 static void __Pyx_ReRaise(void) {
4832 PyThreadState *tstate = PyThreadState_Get();
4833 PyObject *type = tstate->exc_type;
4834 PyObject *value = tstate->exc_value;
4835 PyObject *tb = tstate->exc_traceback;
4836 Py_XINCREF(type);
4837 Py_XINCREF(value);
4838 Py_XINCREF(tb);
4839 __Pyx_ErrRestore(type, value, tb);
4841 """)
4843 #------------------------------------------------------------------------------------
4845 arg_type_test_utility_code = UtilityCode(
4846 proto = """
4847 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4848 const char *name, int exact); /*proto*/
4849 """,
4850 impl = """
4851 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4852 const char *name, int exact)
4854 if (!type) {
4855 PyErr_Format(PyExc_SystemError, "Missing type object");
4856 return 0;
4858 if (none_allowed && obj == Py_None) return 1;
4859 else if (exact) {
4860 if (Py_TYPE(obj) == type) return 1;
4862 else {
4863 if (PyObject_TypeCheck(obj, type)) return 1;
4865 PyErr_Format(PyExc_TypeError,
4866 "Argument '%s' has incorrect type (expected %s, got %s)",
4867 name, type->tp_name, Py_TYPE(obj)->tp_name);
4868 return 0;
4870 """)
4872 #------------------------------------------------------------------------------------
4874 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
4875 # many or too few positional arguments were found. This handles
4876 # Py_ssize_t formatting correctly.
4878 raise_argtuple_invalid_utility_code = UtilityCode(
4879 proto = """
4880 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
4881 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
4882 """,
4883 impl = """
4884 static void __Pyx_RaiseArgtupleInvalid(
4885 const char* func_name,
4886 int exact,
4887 Py_ssize_t num_min,
4888 Py_ssize_t num_max,
4889 Py_ssize_t num_found)
4891 Py_ssize_t num_expected;
4892 const char *number, *more_or_less;
4894 if (num_found < num_min) {
4895 num_expected = num_min;
4896 more_or_less = "at least";
4897 } else {
4898 num_expected = num_max;
4899 more_or_less = "at most";
4901 if (exact) {
4902 more_or_less = "exactly";
4904 number = (num_expected == 1) ? "" : "s";
4905 PyErr_Format(PyExc_TypeError,
4906 #if PY_VERSION_HEX < 0x02050000
4907 "%s() takes %s %d positional argument%s (%d given)",
4908 #else
4909 "%s() takes %s %zd positional argument%s (%zd given)",
4910 #endif
4911 func_name, more_or_less, num_expected, number, num_found);
4913 """)
4915 raise_keyword_required_utility_code = UtilityCode(
4916 proto = """
4917 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
4918 """,
4919 impl = """
4920 static INLINE void __Pyx_RaiseKeywordRequired(
4921 const char* func_name,
4922 PyObject* kw_name)
4924 PyErr_Format(PyExc_TypeError,
4925 #if PY_MAJOR_VERSION >= 3
4926 "%s() needs keyword-only argument %U", func_name, kw_name);
4927 #else
4928 "%s() needs keyword-only argument %s", func_name,
4929 PyString_AS_STRING(kw_name));
4930 #endif
4932 """)
4934 raise_double_keywords_utility_code = UtilityCode(
4935 proto = """
4936 static void __Pyx_RaiseDoubleKeywordsError(
4937 const char* func_name, PyObject* kw_name); /*proto*/
4938 """,
4939 impl = """
4940 static void __Pyx_RaiseDoubleKeywordsError(
4941 const char* func_name,
4942 PyObject* kw_name)
4944 PyErr_Format(PyExc_TypeError,
4945 #if PY_MAJOR_VERSION >= 3
4946 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
4947 #else
4948 "%s() got multiple values for keyword argument '%s'", func_name,
4949 PyString_AS_STRING(kw_name));
4950 #endif
4952 """)
4954 #------------------------------------------------------------------------------------
4956 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
4957 # were passed to a function, or if any keywords were passed to a
4958 # function that does not accept them.
4960 keyword_string_check_utility_code = UtilityCode(
4961 proto = """
4962 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
4963 const char* function_name, int kw_allowed); /*proto*/
4964 """,
4965 impl = """
4966 static INLINE int __Pyx_CheckKeywordStrings(
4967 PyObject *kwdict,
4968 const char* function_name,
4969 int kw_allowed)
4971 PyObject* key = 0;
4972 Py_ssize_t pos = 0;
4973 while (PyDict_Next(kwdict, &pos, &key, 0)) {
4974 #if PY_MAJOR_VERSION < 3
4975 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
4976 #else
4977 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
4978 #endif
4979 goto invalid_keyword_type;
4981 if ((!kw_allowed) && unlikely(key))
4982 goto invalid_keyword;
4983 return 1;
4984 invalid_keyword_type:
4985 PyErr_Format(PyExc_TypeError,
4986 "%s() keywords must be strings", function_name);
4987 return 0;
4988 invalid_keyword:
4989 PyErr_Format(PyExc_TypeError,
4990 #if PY_MAJOR_VERSION < 3
4991 "%s() got an unexpected keyword argument '%s'",
4992 function_name, PyString_AsString(key));
4993 #else
4994 "%s() got an unexpected keyword argument '%U'",
4995 function_name, key);
4996 #endif
4997 return 0;
4999 """)
5001 #------------------------------------------------------------------------------------
5003 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5004 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5005 # keywords will raise an invalid keyword error.
5007 # Three kinds of errors are checked: 1) non-string keywords, 2)
5008 # unexpected keywords and 3) overlap with positional arguments.
5010 # If num_posargs is greater 0, it denotes the number of positional
5011 # arguments that were passed and that must therefore not appear
5012 # amongst the keywords as well.
5014 # This method does not check for required keyword arguments.
5017 parse_keywords_utility_code = UtilityCode(
5018 proto = """
5019 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5020 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5021 const char* function_name); /*proto*/
5022 """,
5023 impl = """
5024 static int __Pyx_ParseOptionalKeywords(
5025 PyObject *kwds,
5026 PyObject **argnames[],
5027 PyObject *kwds2,
5028 PyObject *values[],
5029 Py_ssize_t num_pos_args,
5030 const char* function_name)
5032 PyObject *key = 0, *value = 0;
5033 Py_ssize_t pos = 0;
5034 PyObject*** name;
5035 PyObject*** first_kw_arg = argnames + num_pos_args;
5037 while (PyDict_Next(kwds, &pos, &key, &value)) {
5038 name = first_kw_arg;
5039 while (*name && (**name != key)) name++;
5040 if (*name) {
5041 values[name-argnames] = value;
5042 } else {
5043 #if PY_MAJOR_VERSION < 3
5044 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5045 #else
5046 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5047 #endif
5048 goto invalid_keyword_type;
5049 } else {
5050 for (name = first_kw_arg; *name; name++) {
5051 #if PY_MAJOR_VERSION >= 3
5052 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5053 PyUnicode_Compare(**name, key) == 0) break;
5054 #else
5055 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5056 strcmp(PyString_AS_STRING(**name),
5057 PyString_AS_STRING(key)) == 0) break;
5058 #endif
5060 if (*name) {
5061 values[name-argnames] = value;
5062 } else {
5063 /* unexpected keyword found */
5064 for (name=argnames; name != first_kw_arg; name++) {
5065 if (**name == key) goto arg_passed_twice;
5066 #if PY_MAJOR_VERSION >= 3
5067 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5068 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5069 #else
5070 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5071 strcmp(PyString_AS_STRING(**name),
5072 PyString_AS_STRING(key)) == 0) goto arg_passed_twice;
5073 #endif
5075 if (kwds2) {
5076 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5077 } else {
5078 goto invalid_keyword;
5084 return 0;
5085 arg_passed_twice:
5086 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5087 goto bad;
5088 invalid_keyword_type:
5089 PyErr_Format(PyExc_TypeError,
5090 "%s() keywords must be strings", function_name);
5091 goto bad;
5092 invalid_keyword:
5093 PyErr_Format(PyExc_TypeError,
5094 #if PY_MAJOR_VERSION < 3
5095 "%s() got an unexpected keyword argument '%s'",
5096 function_name, PyString_AsString(key));
5097 #else
5098 "%s() got an unexpected keyword argument '%U'",
5099 function_name, key);
5100 #endif
5101 bad:
5102 return -1;
5104 """)
5106 #------------------------------------------------------------------------------------
5108 unraisable_exception_utility_code = UtilityCode(
5109 proto = """
5110 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5111 """,
5112 impl = """
5113 static void __Pyx_WriteUnraisable(const char *name) {
5114 PyObject *old_exc, *old_val, *old_tb;
5115 PyObject *ctx;
5116 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5117 #if PY_MAJOR_VERSION < 3
5118 ctx = PyString_FromString(name);
5119 #else
5120 ctx = PyUnicode_FromString(name);
5121 #endif
5122 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5123 if (!ctx) {
5124 PyErr_WriteUnraisable(Py_None);
5125 } else {
5126 PyErr_WriteUnraisable(ctx);
5127 Py_DECREF(ctx);
5130 """)
5132 #------------------------------------------------------------------------------------
5134 traceback_utility_code = UtilityCode(
5135 proto = """
5136 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5137 """,
5138 impl = """
5139 #include "compile.h"
5140 #include "frameobject.h"
5141 #include "traceback.h"
5143 static void __Pyx_AddTraceback(const char *funcname) {
5144 PyObject *py_srcfile = 0;
5145 PyObject *py_funcname = 0;
5146 PyObject *py_globals = 0;
5147 PyObject *empty_string = 0;
5148 PyCodeObject *py_code = 0;
5149 PyFrameObject *py_frame = 0;
5151 #if PY_MAJOR_VERSION < 3
5152 py_srcfile = PyString_FromString(%(FILENAME)s);
5153 #else
5154 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5155 #endif
5156 if (!py_srcfile) goto bad;
5157 if (%(CLINENO)s) {
5158 #if PY_MAJOR_VERSION < 3
5159 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5160 #else
5161 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5162 #endif
5164 else {
5165 #if PY_MAJOR_VERSION < 3
5166 py_funcname = PyString_FromString(funcname);
5167 #else
5168 py_funcname = PyUnicode_FromString(funcname);
5169 #endif
5171 if (!py_funcname) goto bad;
5172 py_globals = PyModule_GetDict(%(GLOBALS)s);
5173 if (!py_globals) goto bad;
5174 #if PY_MAJOR_VERSION < 3
5175 empty_string = PyString_FromStringAndSize("", 0);
5176 #else
5177 empty_string = PyBytes_FromStringAndSize("", 0);
5178 #endif
5179 if (!empty_string) goto bad;
5180 py_code = PyCode_New(
5181 0, /*int argcount,*/
5182 #if PY_MAJOR_VERSION >= 3
5183 0, /*int kwonlyargcount,*/
5184 #endif
5185 0, /*int nlocals,*/
5186 0, /*int stacksize,*/
5187 0, /*int flags,*/
5188 empty_string, /*PyObject *code,*/
5189 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5190 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5191 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5192 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5193 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5194 py_srcfile, /*PyObject *filename,*/
5195 py_funcname, /*PyObject *name,*/
5196 %(LINENO)s, /*int firstlineno,*/
5197 empty_string /*PyObject *lnotab*/
5198 );
5199 if (!py_code) goto bad;
5200 py_frame = PyFrame_New(
5201 PyThreadState_GET(), /*PyThreadState *tstate,*/
5202 py_code, /*PyCodeObject *code,*/
5203 py_globals, /*PyObject *globals,*/
5204 0 /*PyObject *locals*/
5205 );
5206 if (!py_frame) goto bad;
5207 py_frame->f_lineno = %(LINENO)s;
5208 PyTraceBack_Here(py_frame);
5209 bad:
5210 Py_XDECREF(py_srcfile);
5211 Py_XDECREF(py_funcname);
5212 Py_XDECREF(empty_string);
5213 Py_XDECREF(py_code);
5214 Py_XDECREF(py_frame);
5216 """ % {
5217 'FILENAME': Naming.filename_cname,
5218 'LINENO': Naming.lineno_cname,
5219 'CFILENAME': Naming.cfilenm_cname,
5220 'CLINENO': Naming.clineno_cname,
5221 'GLOBALS': Naming.module_cname,
5222 'EMPTY_TUPLE' : Naming.empty_tuple,
5223 })
5225 restore_exception_utility_code = UtilityCode(
5226 proto = """
5227 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5228 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5229 """,
5230 impl = """
5231 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5232 PyObject *tmp_type, *tmp_value, *tmp_tb;
5233 PyThreadState *tstate = PyThreadState_GET();
5235 tmp_type = tstate->curexc_type;
5236 tmp_value = tstate->curexc_value;
5237 tmp_tb = tstate->curexc_traceback;
5238 tstate->curexc_type = type;
5239 tstate->curexc_value = value;
5240 tstate->curexc_traceback = tb;
5241 Py_XDECREF(tmp_type);
5242 Py_XDECREF(tmp_value);
5243 Py_XDECREF(tmp_tb);
5246 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5247 PyThreadState *tstate = PyThreadState_GET();
5248 *type = tstate->curexc_type;
5249 *value = tstate->curexc_value;
5250 *tb = tstate->curexc_traceback;
5252 tstate->curexc_type = 0;
5253 tstate->curexc_value = 0;
5254 tstate->curexc_traceback = 0;
5257 """)
5259 #------------------------------------------------------------------------------------
5261 set_vtable_utility_code = UtilityCode(
5262 proto = """
5263 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5264 """,
5265 impl = """
5266 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5267 PyObject *pycobj = 0;
5268 int result;
5270 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5271 if (!pycobj)
5272 goto bad;
5273 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5274 goto bad;
5275 result = 0;
5276 goto done;
5278 bad:
5279 result = -1;
5280 done:
5281 Py_XDECREF(pycobj);
5282 return result;
5284 """)
5286 #------------------------------------------------------------------------------------
5288 get_vtable_utility_code = UtilityCode(
5289 proto = """
5290 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5291 """,
5292 impl = r"""
5293 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5294 int result;
5295 PyObject *pycobj;
5297 pycobj = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5298 if (!pycobj)
5299 goto bad;
5300 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5301 if (!*(void **)vtabptr)
5302 goto bad;
5303 result = 0;
5304 goto done;
5306 bad:
5307 result = -1;
5308 done:
5309 Py_XDECREF(pycobj);
5310 return result;
5312 """)
5314 #------------------------------------------------------------------------------------
5316 init_string_tab_utility_code = UtilityCode(
5317 proto = """
5318 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5319 """,
5320 impl = """
5321 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5322 while (t->p) {
5323 #if PY_MAJOR_VERSION < 3
5324 if (t->is_unicode && (!t->is_identifier)) {
5325 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5326 } else if (t->intern) {
5327 *t->p = PyString_InternFromString(t->s);
5328 } else {
5329 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5331 #else /* Python 3+ has unicode identifiers */
5332 if (t->is_identifier || (t->is_unicode && t->intern)) {
5333 *t->p = PyUnicode_InternFromString(t->s);
5334 } else if (t->is_unicode) {
5335 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5336 } else {
5337 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5339 #endif
5340 if (!*t->p)
5341 return -1;
5342 ++t;
5344 return 0;
5346 """)
5348 #------------------------------------------------------------------------------------
5350 get_exception_utility_code = UtilityCode(
5351 proto = """
5352 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5353 """,
5354 impl = """
5355 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5356 PyObject *tmp_type, *tmp_value, *tmp_tb;
5357 PyThreadState *tstate = PyThreadState_GET();
5358 __Pyx_ErrFetch(type, value, tb);
5359 PyErr_NormalizeException(type, value, tb);
5360 if (PyErr_Occurred())
5361 goto bad;
5362 Py_INCREF(*type);
5363 Py_INCREF(*value);
5364 Py_INCREF(*tb);
5365 tmp_type = tstate->exc_type;
5366 tmp_value = tstate->exc_value;
5367 tmp_tb = tstate->exc_traceback;
5368 tstate->exc_type = *type;
5369 tstate->exc_value = *value;
5370 tstate->exc_traceback = *tb;
5371 /* Make sure tstate is in a consistent state when we XDECREF
5372 these objects (XDECREF may run arbitrary code). */
5373 Py_XDECREF(tmp_type);
5374 Py_XDECREF(tmp_value);
5375 Py_XDECREF(tmp_tb);
5376 return 0;
5377 bad:
5378 Py_XDECREF(*type);
5379 Py_XDECREF(*value);
5380 Py_XDECREF(*tb);
5381 return -1;
5384 """)
5386 #------------------------------------------------------------------------------------
5388 reset_exception_utility_code = UtilityCode(
5389 proto = """
5390 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5391 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5392 """,
5393 impl = """
5394 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5395 PyThreadState *tstate = PyThreadState_GET();
5396 *type = tstate->exc_type;
5397 *value = tstate->exc_value;
5398 *tb = tstate->exc_traceback;
5399 Py_XINCREF(*type);
5400 Py_XINCREF(*value);
5401 Py_XINCREF(*tb);
5404 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5405 PyObject *tmp_type, *tmp_value, *tmp_tb;
5406 PyThreadState *tstate = PyThreadState_GET();
5407 tmp_type = tstate->exc_type;
5408 tmp_value = tstate->exc_value;
5409 tmp_tb = tstate->exc_traceback;
5410 tstate->exc_type = type;
5411 tstate->exc_value = value;
5412 tstate->exc_traceback = tb;
5413 Py_XDECREF(tmp_type);
5414 Py_XDECREF(tmp_value);
5415 Py_XDECREF(tmp_tb);
5417 """)
5419 #------------------------------------------------------------------------------------