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