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