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