Cython has moved to github.
cython-devel
view Cython/Compiler/Nodes.py @ 1727:6124ef21b1cf
Fix memleak when break used in try statement
| author | Robert Bradshaw <robertwb@math.washington.edu> |
|---|---|
| date | Fri Feb 20 21:22:46 2009 -0800 (3 years ago) |
| parents | 3c571857fd31 |
| children | f2d60fedb367 |
line source
1 #
2 # Pyrex - Parse tree nodes
3 #
5 import string, sys, os, time, copy
7 import Code
8 import Builtin
9 from Errors import error, warning, InternalError
10 import Naming
11 import PyrexTypes
12 import TypeSlots
13 from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType
14 from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
15 StructOrUnionScope, PyClassScope, CClassScope
16 from Cython.Utils import open_new_file, replace_suffix, UtilityCode
17 from StringEncoding import EncodedString, escape_byte_string, split_docstring
18 import Options
19 import ControlFlow
20 import DebugFlags
22 from DebugFlags import debug_disposal_code
24 absolute_path_length = 0
26 def relative_position(pos):
27 """
28 We embed the relative filename in the generated C file, since we
29 don't want to have to regnerate and compile all the source code
30 whenever the Python install directory moves (which could happen,
31 e.g,. when distributing binaries.)
33 INPUT:
34 a position tuple -- (absolute filename, line number column position)
36 OUTPUT:
37 relative filename
38 line number
40 AUTHOR: William Stein
41 """
42 global absolute_path_length
43 if absolute_path_length==0:
44 absolute_path_length = len(os.path.abspath(os.getcwd()))
45 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
47 def embed_position(pos, docstring):
48 if not Options.embed_pos_in_docstring:
49 return docstring
50 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
51 if docstring is None:
52 # unicode string
53 return EncodedString(pos_line)
55 # make sure we can encode the filename in the docstring encoding
56 # otherwise make the docstring a unicode string
57 encoding = docstring.encoding
58 if encoding is not None:
59 try:
60 encoded_bytes = pos_line.encode(encoding)
61 except UnicodeEncodeError:
62 encoding = None
64 if not docstring:
65 # reuse the string encoding of the original docstring
66 doc = EncodedString(pos_line)
67 else:
68 doc = EncodedString(pos_line + u'\n' + docstring)
69 doc.encoding = encoding
70 return doc
73 from Code import CCodeWriter
74 from types import FunctionType
76 def write_func_call(func):
77 def f(*args, **kwds):
78 if len(args) > 1 and isinstance(args[1], CCodeWriter):
79 # here we annotate the code with this function call
80 # but only if new code is generated
81 node, code = args[:2]
82 marker = ' /* %s -> %s.%s %s */' % (
83 ' ' * code.call_level,
84 node.__class__.__name__,
85 func.__name__,
86 node.pos[1:])
87 pristine = code.buffer.stream.tell()
88 code.putln(marker)
89 start = code.buffer.stream.tell()
90 code.call_level += 4
91 res = func(*args, **kwds)
92 code.call_level -= 4
93 if start == code.buffer.stream.tell():
94 code.buffer.stream.seek(pristine)
95 else:
96 marker = marker.replace('->', '<-')
97 code.putln(marker)
98 return res
99 else:
100 return func(*args, **kwds)
101 return f
103 class VerboseCodeWriter(type):
104 # Set this as a metaclass to trace function calls in code.
105 # This slows down code generation and makes much larger files.
106 def __new__(cls, name, bases, attrs):
107 attrs = dict(attrs)
108 for mname, m in attrs.items():
109 if isinstance(m, FunctionType):
110 attrs[mname] = write_func_call(m)
111 return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
114 class Node(object):
115 # pos (string, int, int) Source file position
116 # is_name boolean Is a NameNode
117 # is_literal boolean Is a ConstNode
119 # Uncomment this for debugging.
120 # __metaclass__ = VerboseCodeWriter
122 is_name = 0
123 is_literal = 0
124 temps = None
126 # All descandants should set child_attrs to a list of the attributes
127 # containing nodes considered "children" in the tree. Each such attribute
128 # can either contain a single node or a list of nodes. See Visitor.py.
129 child_attrs = None
131 def __init__(self, pos, **kw):
132 self.pos = pos
133 self.__dict__.update(kw)
135 gil_message = "Operation"
137 def gil_check(self, env):
138 if env.nogil:
139 self.gil_error()
141 def gil_error(self):
142 error(self.pos, "%s not allowed without gil" % self.gil_message)
144 def clone_node(self):
145 """Clone the node. This is defined as a shallow copy, except for member lists
146 amongst the child attributes (from get_child_accessors) which are also
147 copied. Lists containing child nodes are thus seen as a way for the node
148 to hold multiple children directly; the list is not treated as a seperate
149 level in the tree."""
150 result = copy.copy(self)
151 for attrname in result.child_attrs:
152 value = getattr(result, attrname)
153 if isinstance(value, list):
154 setattr(result, attrname, [x for x in value])
155 return result
158 #
159 # There are 4 phases of parse tree processing, applied in order to
160 # all the statements in a given scope-block:
161 #
162 # (0) analyse_control_flow
163 # Create the control flow tree into which state can be asserted and
164 # queried.
165 #
166 # (1) analyse_declarations
167 # Make symbol table entries for all declarations at the current
168 # level, both explicit (def, cdef, etc.) and implicit (assignment
169 # to an otherwise undeclared name).
170 #
171 # (2) analyse_expressions
172 # Determine the result types of expressions and fill in the
173 # 'type' attribute of each ExprNode. Insert coercion nodes into the
174 # tree where needed to convert to and from Python objects.
175 # Allocate temporary locals for intermediate results. Fill
176 # in the 'result_code' attribute of each ExprNode with a C code
177 # fragment.
178 #
179 # (3) generate_code
180 # Emit C code for all declarations, statements and expressions.
181 # Recursively applies the 3 processing phases to the bodies of
182 # functions.
183 #
185 def analyse_control_flow(self, env):
186 pass
188 def analyse_declarations(self, env):
189 pass
191 def analyse_expressions(self, env):
192 raise InternalError("analyse_expressions not implemented for %s" % \
193 self.__class__.__name__)
195 def generate_code(self, code):
196 raise InternalError("generate_code not implemented for %s" % \
197 self.__class__.__name__)
199 def annotate(self, code):
200 # mro does the wrong thing
201 if isinstance(self, BlockNode):
202 self.body.annotate(code)
204 def end_pos(self):
205 try:
206 return self._end_pos
207 except AttributeError:
208 pos = self.pos
209 if not self.child_attrs:
210 self._end_pos = pos
211 return pos
212 for attr in self.child_attrs:
213 child = getattr(self, attr)
214 # Sometimes lists, sometimes nodes
215 if child is None:
216 pass
217 elif isinstance(child, list):
218 for c in child:
219 pos = max(pos, c.end_pos())
220 else:
221 pos = max(pos, child.end_pos())
222 self._end_pos = pos
223 return pos
225 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
226 if cutoff == 0:
227 return "<...nesting level cutoff...>"
228 if encountered is None:
229 encountered = set()
230 if id(self) in encountered:
231 return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
232 encountered.add(id(self))
234 def dump_child(x, level):
235 if isinstance(x, Node):
236 return x.dump(level, filter_out, cutoff-1, encountered)
237 elif isinstance(x, list):
238 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
239 else:
240 return repr(x)
243 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
244 if len(attrs) == 0:
245 return "<%s (%d)>" % (self.__class__.__name__, id(self))
246 else:
247 indent = " " * level
248 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
249 for key, value in attrs:
250 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
251 res += "%s>" % indent
252 return res
254 class CompilerDirectivesNode(Node):
255 """
256 Sets compiler directives for the children nodes
257 """
258 # directives {string:value} A dictionary holding the right value for
259 # *all* possible directives.
260 # body Node
261 child_attrs = ["body"]
263 def analyse_control_flow(self, env):
264 old = env.directives
265 env.directives = self.directives
266 self.body.analyse_control_flow(env)
267 env.directives = old
269 def analyse_declarations(self, env):
270 old = env.directives
271 env.directives = self.directives
272 self.body.analyse_declarations(env)
273 env.directives = old
275 def analyse_expressions(self, env):
276 old = env.directives
277 env.directives = self.directives
278 self.body.analyse_expressions(env)
279 env.directives = old
281 def generate_function_definitions(self, env, code):
282 env_old = env.directives
283 code_old = code.globalstate.directives
284 code.globalstate.directives = self.directives
285 self.body.generate_function_definitions(env, code)
286 env.directives = env_old
287 code.globalstate.directives = code_old
289 def generate_execution_code(self, code):
290 old = code.globalstate.directives
291 code.globalstate.directives = self.directives
292 self.body.generate_execution_code(code)
293 code.globalstate.directives = old
295 def annotate(self, code):
296 old = code.globalstate.directives
297 code.globalstate.directives = self.directives
298 self.body.annotate(code)
299 code.globalstate.directives = old
301 class BlockNode(object):
302 # Mixin class for nodes representing a declaration block.
304 def generate_const_definitions(self, env, code):
305 if env.const_entries:
306 for entry in env.const_entries:
307 if not entry.is_interned:
308 code.globalstate.add_const_definition(entry)
310 def generate_interned_string_decls(self, env, code):
311 entries = env.global_scope().new_interned_string_entries
312 if entries:
313 for entry in entries:
314 code.globalstate.add_interned_string_decl(entry)
315 del entries[:]
317 def generate_py_string_decls(self, env, code):
318 if env is None:
319 return # earlier error
320 entries = env.pystring_entries
321 if entries:
322 for entry in entries:
323 if not entry.is_interned:
324 code.globalstate.add_py_string_decl(entry)
326 def generate_interned_num_decls(self, env, code):
327 # Flush accumulated interned nums from the global scope
328 # and generate declarations for them.
329 genv = env.global_scope()
330 entries = genv.interned_nums
331 if entries:
332 for entry in entries:
333 code.globalstate.add_interned_num_decl(entry)
334 del entries[:]
336 def generate_cached_builtins_decls(self, env, code):
337 entries = env.global_scope().undeclared_cached_builtins
338 for entry in entries:
339 code.globalstate.add_cached_builtin_decl(entry)
340 del entries[:]
343 class StatListNode(Node):
344 # stats a list of StatNode
346 child_attrs = ["stats"]
348 def create_analysed(pos, env, *args, **kw):
349 node = StatListNode(pos, *args, **kw)
350 return node # No node-specific analysis necesarry
351 create_analysed = staticmethod(create_analysed)
353 def analyse_control_flow(self, env):
354 for stat in self.stats:
355 stat.analyse_control_flow(env)
357 def analyse_declarations(self, env):
358 #print "StatListNode.analyse_declarations" ###
359 for stat in self.stats:
360 stat.analyse_declarations(env)
362 def analyse_expressions(self, env):
363 #print "StatListNode.analyse_expressions" ###
364 for stat in self.stats:
365 stat.analyse_expressions(env)
367 def generate_function_definitions(self, env, code):
368 #print "StatListNode.generate_function_definitions" ###
369 for stat in self.stats:
370 stat.generate_function_definitions(env, code)
372 def generate_execution_code(self, code):
373 #print "StatListNode.generate_execution_code" ###
374 for stat in self.stats:
375 code.mark_pos(stat.pos)
376 stat.generate_execution_code(code)
378 def annotate(self, code):
379 for stat in self.stats:
380 stat.annotate(code)
383 class StatNode(Node):
384 #
385 # Code generation for statements is split into the following subphases:
386 #
387 # (1) generate_function_definitions
388 # Emit C code for the definitions of any structs,
389 # unions, enums and functions defined in the current
390 # scope-block.
391 #
392 # (2) generate_execution_code
393 # Emit C code for executable statements.
394 #
396 def generate_function_definitions(self, env, code):
397 pass
399 def generate_execution_code(self, code):
400 raise InternalError("generate_execution_code not implemented for %s" % \
401 self.__class__.__name__)
404 class CDefExternNode(StatNode):
405 # include_file string or None
406 # body StatNode
408 child_attrs = ["body"]
410 def analyse_declarations(self, env):
411 if self.include_file:
412 env.add_include_file(self.include_file)
413 old_cinclude_flag = env.in_cinclude
414 env.in_cinclude = 1
415 self.body.analyse_declarations(env)
416 env.in_cinclude = old_cinclude_flag
418 def analyse_expressions(self, env):
419 pass
421 def generate_execution_code(self, code):
422 pass
424 def annotate(self, code):
425 self.body.annotate(code)
428 class CDeclaratorNode(Node):
429 # Part of a C declaration.
430 #
431 # Processing during analyse_declarations phase:
432 #
433 # analyse
434 # Returns (name, type) pair where name is the
435 # CNameDeclaratorNode of the name being declared
436 # and type is the type it is being declared as.
437 #
438 # calling_convention string Calling convention of CFuncDeclaratorNode
439 # for which this is a base
441 child_attrs = []
443 calling_convention = ""
446 class CNameDeclaratorNode(CDeclaratorNode):
447 # name string The Pyrex name being declared
448 # cname string or None C name, if specified
449 # default ExprNode or None the value assigned on declaration
451 child_attrs = ['default']
453 default = None
455 def analyse(self, base_type, env, nonempty = 0):
456 if nonempty and self.name == '':
457 # May have mistaken the name for the type.
458 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
459 error(self.pos, "Missing argument name")
460 elif base_type.is_void:
461 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
462 else:
463 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
464 base_type = py_object_type
465 self.type = base_type
466 return self, base_type
468 class CPtrDeclaratorNode(CDeclaratorNode):
469 # base CDeclaratorNode
471 child_attrs = ["base"]
473 def analyse(self, base_type, env, nonempty = 0):
474 if base_type.is_pyobject:
475 error(self.pos,
476 "Pointer base type cannot be a Python object")
477 ptr_type = PyrexTypes.c_ptr_type(base_type)
478 return self.base.analyse(ptr_type, env, nonempty = nonempty)
480 class CArrayDeclaratorNode(CDeclaratorNode):
481 # base CDeclaratorNode
482 # dimension ExprNode
484 child_attrs = ["base", "dimension"]
486 def analyse(self, base_type, env, nonempty = 0):
487 if self.dimension:
488 self.dimension.analyse_const_expression(env)
489 if not self.dimension.type.is_int:
490 error(self.dimension.pos, "Array dimension not integer")
491 size = self.dimension.result()
492 try:
493 size = int(size)
494 except ValueError:
495 # runtime constant?
496 pass
497 else:
498 size = None
499 if not base_type.is_complete():
500 error(self.pos,
501 "Array element type '%s' is incomplete" % base_type)
502 if base_type.is_pyobject:
503 error(self.pos,
504 "Array element cannot be a Python object")
505 if base_type.is_cfunction:
506 error(self.pos,
507 "Array element cannot be a function")
508 array_type = PyrexTypes.c_array_type(base_type, size)
509 return self.base.analyse(array_type, env, nonempty = nonempty)
512 class CFuncDeclaratorNode(CDeclaratorNode):
513 # base CDeclaratorNode
514 # args [CArgDeclNode]
515 # has_varargs boolean
516 # exception_value ConstNode
517 # exception_check boolean True if PyErr_Occurred check needed
518 # nogil boolean Can be called without gil
519 # with_gil boolean Acquire gil around function body
521 child_attrs = ["base", "args", "exception_value"]
523 overridable = 0
524 optional_arg_count = 0
526 def analyse(self, return_type, env, nonempty = 0):
527 if nonempty:
528 nonempty -= 1
529 func_type_args = []
530 for arg_node in self.args:
531 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
532 name = name_declarator.name
533 if name_declarator.cname:
534 error(self.pos,
535 "Function argument cannot have C name specification")
536 # Turn *[] argument into **
537 if type.is_array:
538 type = PyrexTypes.c_ptr_type(type.base_type)
539 # Catch attempted C-style func(void) decl
540 if type.is_void:
541 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
542 # if type.is_pyobject and self.nogil:
543 # error(self.pos,
544 # "Function with Python argument cannot be declared nogil")
545 func_type_args.append(
546 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
547 if arg_node.default:
548 self.optional_arg_count += 1
549 elif self.optional_arg_count:
550 error(self.pos, "Non-default argument follows default argument")
552 if self.optional_arg_count:
553 scope = StructOrUnionScope()
554 scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
555 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
556 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
557 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
558 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
559 kind = 'struct',
560 scope = scope,
561 typedef_flag = 0,
562 pos = self.pos,
563 cname = struct_cname)
564 self.op_args_struct.defined_in_pxd = 1
565 self.op_args_struct.used = 1
567 exc_val = None
568 exc_check = 0
569 if return_type.is_pyobject \
570 and (self.exception_value or self.exception_check) \
571 and self.exception_check != '+':
572 error(self.pos,
573 "Exception clause not allowed for function returning Python object")
574 else:
575 if self.exception_value:
576 self.exception_value.analyse_const_expression(env)
577 if self.exception_check == '+':
578 exc_val_type = self.exception_value.type
579 if not exc_val_type.is_error and \
580 not exc_val_type.is_pyobject and \
581 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
582 error(self.exception_value.pos,
583 "Exception value must be a Python exception or cdef function with no arguments.")
584 exc_val = self.exception_value
585 else:
586 exc_val = self.exception_value.result()
587 if not return_type.assignable_from(self.exception_value.type):
588 error(self.exception_value.pos,
589 "Exception value incompatible with function return type")
590 exc_check = self.exception_check
591 if return_type.is_array:
592 error(self.pos,
593 "Function cannot return an array")
594 if return_type.is_cfunction:
595 error(self.pos,
596 "Function cannot return a function")
597 func_type = PyrexTypes.CFuncType(
598 return_type, func_type_args, self.has_varargs,
599 optional_arg_count = self.optional_arg_count,
600 exception_value = exc_val, exception_check = exc_check,
601 calling_convention = self.base.calling_convention,
602 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
603 if self.optional_arg_count:
604 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
605 return self.base.analyse(func_type, env)
608 class CArgDeclNode(Node):
609 # Item in a function declaration argument list.
610 #
611 # base_type CBaseTypeNode
612 # declarator CDeclaratorNode
613 # not_none boolean Tagged with 'not None'
614 # default ExprNode or None
615 # default_entry Symtab.Entry Entry for the variable holding the default value
616 # default_result_code string cname or code fragment for default value
617 # is_self_arg boolean Is the "self" arg of an extension type method
618 # is_kw_only boolean Is a keyword-only argument
620 child_attrs = ["base_type", "declarator", "default"]
622 is_self_arg = 0
623 is_generic = 1
624 type = None
625 name_declarator = None
627 def analyse(self, env, nonempty = 0):
628 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
629 if self.type is None:
630 # The parser may missinterpret names as types...
631 # We fix that here.
632 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
633 if nonempty:
634 self.declarator.name = self.base_type.name
635 self.base_type.name = None
636 self.base_type.is_basic_c_type = False
637 could_be_name = True
638 else:
639 could_be_name = False
640 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
641 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
642 self.declarator.name = self.base_type.arg_name
643 return self.declarator.analyse(base_type, env, nonempty = nonempty)
644 else:
645 return self.name_declarator, self.type
647 def annotate(self, code):
648 if self.default:
649 self.default.annotate(code)
652 class CBaseTypeNode(Node):
653 # Abstract base class for C base type nodes.
654 #
655 # Processing during analyse_declarations phase:
656 #
657 # analyse
658 # Returns the type.
660 pass
662 class CAnalysedBaseTypeNode(Node):
663 # type type
665 child_attrs = []
667 def analyse(self, env, could_be_name = False):
668 return self.type
670 class CSimpleBaseTypeNode(CBaseTypeNode):
671 # name string
672 # module_path [string] Qualifying name components
673 # is_basic_c_type boolean
674 # signed boolean
675 # longness integer
676 # is_self_arg boolean Is self argument of C method
678 child_attrs = []
679 arg_name = None # in case the argument name was interpreted as a type
681 def analyse(self, env, could_be_name = False):
682 # Return type descriptor.
683 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
684 type = None
685 if self.is_basic_c_type:
686 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
687 if not type:
688 error(self.pos, "Unrecognised type modifier combination")
689 elif self.name == "object" and not self.module_path:
690 type = py_object_type
691 elif self.name is None:
692 if self.is_self_arg and env.is_c_class_scope:
693 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
694 type = env.parent_type
695 else:
696 type = py_object_type
697 else:
698 if self.module_path:
699 scope = env.find_imported_module(self.module_path, self.pos)
700 else:
701 scope = env
702 if scope:
703 if scope.is_c_class_scope:
704 scope = scope.global_scope()
705 entry = scope.lookup(self.name)
706 if entry and entry.is_type:
707 type = entry.type
708 elif could_be_name:
709 if self.is_self_arg and env.is_c_class_scope:
710 type = env.parent_type
711 else:
712 type = py_object_type
713 self.arg_name = self.name
714 else:
715 error(self.pos, "'%s' is not a type identifier" % self.name)
716 if type:
717 return type
718 else:
719 return PyrexTypes.error_type
721 class CBufferAccessTypeNode(CBaseTypeNode):
722 # After parsing:
723 # positional_args [ExprNode] List of positional arguments
724 # keyword_args DictNode Keyword arguments
725 # base_type_node CBaseTypeNode
727 # After analysis:
728 # type PyrexType.BufferType ...containing the right options
731 child_attrs = ["base_type_node", "positional_args",
732 "keyword_args", "dtype_node"]
734 dtype_node = None
736 name = None
738 def analyse(self, env, could_be_name = False):
739 base_type = self.base_type_node.analyse(env)
740 if base_type.is_error: return base_type
741 import Buffer
743 options = Buffer.analyse_buffer_options(
744 self.pos,
745 env,
746 self.positional_args,
747 self.keyword_args,
748 base_type.buffer_defaults)
750 self.type = PyrexTypes.BufferType(base_type, **options)
751 return self.type
753 class CComplexBaseTypeNode(CBaseTypeNode):
754 # base_type CBaseTypeNode
755 # declarator CDeclaratorNode
757 child_attrs = ["base_type", "declarator"]
759 def analyse(self, env, could_be_name = False):
760 base = self.base_type.analyse(env, could_be_name)
761 _, type = self.declarator.analyse(base, env)
762 return type
765 class CVarDefNode(StatNode):
766 # C variable definition or forward/extern function declaration.
767 #
768 # visibility 'private' or 'public' or 'extern'
769 # base_type CBaseTypeNode
770 # declarators [CDeclaratorNode]
771 # in_pxd boolean
772 # api boolean
773 # need_properties [entry]
774 # pxd_locals [CVarDefNode] (used for functions declared in pxd)
776 child_attrs = ["base_type", "declarators"]
777 need_properties = ()
778 pxd_locals = []
780 def analyse_declarations(self, env, dest_scope = None):
781 if not dest_scope:
782 dest_scope = env
783 self.dest_scope = dest_scope
784 base_type = self.base_type.analyse(env)
785 if (dest_scope.is_c_class_scope
786 and self.visibility == 'public'
787 and base_type.is_pyobject
788 and (base_type.is_builtin_type or base_type.is_extension_type)):
789 self.need_properties = []
790 need_property = True
791 visibility = 'private'
792 else:
793 need_property = False
794 visibility = self.visibility
796 for declarator in self.declarators:
797 name_declarator, type = declarator.analyse(base_type, env)
798 if not type.is_complete():
799 if not (self.visibility == 'extern' and type.is_array):
800 error(declarator.pos,
801 "Variable type '%s' is incomplete" % type)
802 if self.visibility == 'extern' and type.is_pyobject:
803 error(declarator.pos,
804 "Python object cannot be declared extern")
805 name = name_declarator.name
806 cname = name_declarator.cname
807 if name == '':
808 error(declarator.pos, "Missing name in declaration.")
809 return
810 if type.is_cfunction:
811 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
812 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
813 api = self.api)
814 if entry is not None:
815 entry.pxd_locals = self.pxd_locals
816 else:
817 if self.in_pxd and self.visibility != 'extern':
818 error(self.pos,
819 "Only 'extern' C variable declaration allowed in .pxd file")
820 entry = dest_scope.declare_var(name, type, declarator.pos,
821 cname = cname, visibility = visibility, is_cdef = 1)
822 if need_property:
823 self.need_properties.append(entry)
824 entry.needs_property = 1
827 class CStructOrUnionDefNode(StatNode):
828 # name string
829 # cname string or None
830 # kind "struct" or "union"
831 # typedef_flag boolean
832 # visibility "public" or "private"
833 # in_pxd boolean
834 # attributes [CVarDefNode] or None
835 # entry Entry
837 child_attrs = ["attributes"]
839 def analyse_declarations(self, env):
840 scope = None
841 if self.attributes is not None:
842 scope = StructOrUnionScope(self.name)
843 self.entry = env.declare_struct_or_union(
844 self.name, self.kind, scope, self.typedef_flag, self.pos,
845 self.cname, visibility = self.visibility)
846 if self.attributes is not None:
847 if self.in_pxd and not env.in_cinclude:
848 self.entry.defined_in_pxd = 1
849 for attr in self.attributes:
850 attr.analyse_declarations(env, scope)
851 if self.visibility != 'extern':
852 need_typedef_indirection = False
853 for attr in scope.var_entries:
854 type = attr.type
855 while type.is_array:
856 type = type.base_type
857 if type == self.entry.type:
858 error(attr.pos, "Struct cannot contain itself as a member.")
859 if self.typedef_flag:
860 while type.is_ptr:
861 type = type.base_type
862 if type == self.entry.type:
863 need_typedef_indirection = True
864 if need_typedef_indirection:
865 # C can't handle typedef structs that refer to themselves.
866 struct_entry = self.entry
867 cname = env.new_const_cname()
868 self.entry = env.declare_typedef(self.name, struct_entry.type, self.pos, cname = self.cname, visibility='ignore')
869 struct_entry.type.typedef_flag = False
870 struct_entry.cname = struct_entry.type.cname = env.new_const_cname()
872 def analyse_expressions(self, env):
873 pass
875 def generate_execution_code(self, code):
876 pass
879 class CEnumDefNode(StatNode):
880 # name string or None
881 # cname string or None
882 # items [CEnumDefItemNode]
883 # typedef_flag boolean
884 # visibility "public" or "private"
885 # in_pxd boolean
886 # entry Entry
888 child_attrs = ["items"]
890 def analyse_declarations(self, env):
891 self.entry = env.declare_enum(self.name, self.pos,
892 cname = self.cname, typedef_flag = self.typedef_flag,
893 visibility = self.visibility)
894 if self.items is not None:
895 if self.in_pxd and not env.in_cinclude:
896 self.entry.defined_in_pxd = 1
897 for item in self.items:
898 item.analyse_declarations(env, self.entry)
900 def analyse_expressions(self, env):
901 if self.visibility == 'public':
902 self.temp = env.allocate_temp_pyobject()
903 env.release_temp(self.temp)
905 def generate_execution_code(self, code):
906 if self.visibility == 'public':
907 for item in self.entry.enum_values:
908 code.putln("%s = PyInt_FromLong(%s); %s" % (
909 self.temp,
910 item.cname,
911 code.error_goto_if_null(self.temp, item.pos)))
912 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
913 Naming.module_cname,
914 item.name,
915 self.temp,
916 code.error_goto(item.pos)))
917 code.putln("%s = 0;" % self.temp)
920 class CEnumDefItemNode(StatNode):
921 # name string
922 # cname string or None
923 # value ExprNode or None
925 child_attrs = ["value"]
927 def analyse_declarations(self, env, enum_entry):
928 if self.value:
929 self.value.analyse_const_expression(env)
930 if not self.value.type.is_int:
931 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
932 self.value.analyse_const_expression(env)
933 value = self.value.result()
934 else:
935 value = self.name
936 entry = env.declare_const(self.name, enum_entry.type,
937 value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
938 enum_entry.enum_values.append(entry)
941 class CTypeDefNode(StatNode):
942 # base_type CBaseTypeNode
943 # declarator CDeclaratorNode
944 # visibility "public" or "private"
945 # in_pxd boolean
947 child_attrs = ["base_type", "declarator"]
949 def analyse_declarations(self, env):
950 base = self.base_type.analyse(env)
951 name_declarator, type = self.declarator.analyse(base, env)
952 name = name_declarator.name
953 cname = name_declarator.cname
954 entry = env.declare_typedef(name, type, self.pos,
955 cname = cname, visibility = self.visibility)
956 if self.in_pxd and not env.in_cinclude:
957 entry.defined_in_pxd = 1
959 def analyse_expressions(self, env):
960 pass
961 def generate_execution_code(self, code):
962 pass
965 class FuncDefNode(StatNode, BlockNode):
966 # Base class for function definition nodes.
967 #
968 # return_type PyrexType
969 # #filename string C name of filename string const
970 # entry Symtab.Entry
971 # needs_closure boolean Whether or not this function has inner functions/classes/yield
972 # pxd_locals [CVarDefNode] locals defined in the pxd
974 py_func = None
975 assmt = None
976 needs_closure = False
977 pxd_locals = []
979 def analyse_default_values(self, env):
980 genv = env.global_scope()
981 for arg in self.args:
982 if arg.default:
983 if arg.is_generic:
984 if not hasattr(arg, 'default_entry'):
985 arg.default.analyse_types(env)
986 arg.default = arg.default.coerce_to(arg.type, genv)
987 if arg.default.is_literal:
988 arg.default_entry = arg.default
989 arg.default_result_code = arg.default.calculate_result_code()
990 if arg.default.type != arg.type and not arg.type.is_int:
991 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
992 else:
993 arg.default.allocate_temps(genv)
994 arg.default_entry = genv.add_default_value(arg.type)
995 arg.default_entry.used = 1
996 arg.default_result_code = arg.default_entry.cname
997 else:
998 error(arg.pos,
999 "This argument cannot have a default value")
1000 arg.default = None
1002 def need_gil_acquisition(self, lenv):
1003 return 0
1005 def create_local_scope(self, env):
1006 genv = env
1007 while env.is_py_class_scope or env.is_c_class_scope:
1008 env = env.outer_scope
1009 if self.needs_closure:
1010 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
1011 else:
1012 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
1013 lenv.return_type = self.return_type
1014 type = self.entry.type
1015 if type.is_cfunction:
1016 lenv.nogil = type.nogil and not type.with_gil
1017 self.local_scope = lenv
1018 return lenv
1020 def generate_function_definitions(self, env, code):
1021 import Buffer
1023 lenv = self.local_scope
1025 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1026 self.entry.scope.is_c_class_scope)
1028 # Generate C code for header and body of function
1029 code.enter_cfunc_scope()
1030 code.return_from_error_cleanup_label = code.new_label()
1032 # ----- Top-level constants used by this function
1033 code.mark_pos(self.pos)
1034 self.generate_interned_num_decls(lenv, code)
1035 self.generate_interned_string_decls(lenv, code)
1036 self.generate_py_string_decls(lenv, code)
1037 self.generate_cached_builtins_decls(lenv, code)
1038 #code.putln("")
1039 #code.put_var_declarations(lenv.const_entries, static = 1)
1040 self.generate_const_definitions(lenv, code)
1041 # ----- Function header
1042 code.putln("")
1043 if self.py_func:
1044 self.py_func.generate_function_header(code,
1045 with_pymethdef = env.is_py_class_scope,
1046 proto_only=True)
1047 self.generate_function_header(code,
1048 with_pymethdef = env.is_py_class_scope)
1049 # ----- Local variable declarations
1050 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
1051 self.generate_argument_declarations(lenv, code)
1052 if self.needs_closure:
1053 code.putln("/* TODO: declare and create scope object */")
1054 code.put_var_declarations(lenv.var_entries)
1055 init = ""
1056 if not self.return_type.is_void:
1057 if self.return_type.is_pyobject:
1058 init = " = NULL"
1059 code.putln(
1060 "%s%s;" %
1061 (self.return_type.declaration_code(
1062 Naming.retval_cname),
1063 init))
1064 tempvardecl_code = code.insertion_point()
1065 self.generate_keyword_list(code)
1066 # ----- Extern library function declarations
1067 lenv.generate_library_function_declarations(code)
1068 # ----- GIL acquisition
1069 acquire_gil = self.need_gil_acquisition(lenv)
1070 if acquire_gil:
1071 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1072 # ----- Automatic lead-ins for certain special functions
1073 if not lenv.nogil:
1074 code.put_setup_refcount_context(self.entry.name)
1075 if is_getbuffer_slot:
1076 self.getbuffer_init(code)
1077 # ----- Fetch arguments
1078 self.generate_argument_parsing_code(env, code)
1079 # If an argument is assigned to in the body, we must
1080 # incref it to properly keep track of refcounts.
1081 for entry in lenv.arg_entries:
1082 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1083 code.put_var_incref(entry)
1084 # ----- Initialise local variables
1085 for entry in lenv.var_entries:
1086 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1087 code.put_init_var_to_py_none(entry)
1088 # ----- Initialise local buffer auxiliary variables
1089 for entry in lenv.var_entries + lenv.arg_entries:
1090 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1091 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1092 # ----- Check and convert arguments
1093 self.generate_argument_type_tests(code)
1094 # ----- Acquire buffer arguments
1095 for entry in lenv.arg_entries:
1096 if entry.type.is_buffer:
1097 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1098 # ----- Function body
1099 self.body.generate_execution_code(code)
1100 # ----- Default return value
1101 code.putln("")
1102 if self.return_type.is_pyobject:
1103 #if self.return_type.is_extension_type:
1104 # lhs = "(PyObject *)%s" % Naming.retval_cname
1105 #else:
1106 lhs = Naming.retval_cname
1107 code.put_init_to_py_none(lhs, self.return_type)
1108 else:
1109 val = self.return_type.default_value
1110 if val:
1111 code.putln("%s = %s;" % (Naming.retval_cname, val))
1112 # ----- Error cleanup
1113 if code.error_label in code.labels_used:
1114 code.put_goto(code.return_label)
1115 code.put_label(code.error_label)
1116 # cleanup temps the old way
1117 code.put_var_xdecrefs(lenv.temp_entries)
1118 # cleanup temps the new way
1119 for cname, type in code.funcstate.all_managed_temps():
1120 code.put_xdecref(cname, type)
1122 # Clean up buffers -- this calls a Python function
1123 # so need to save and restore error state
1124 buffers_present = len(lenv.buffer_entries) > 0
1125 if buffers_present:
1126 code.globalstate.use_utility_code(restore_exception_utility_code)
1127 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1128 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1129 for entry in lenv.buffer_entries:
1130 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1131 #code.putln("%s = 0;" % entry.cname)
1132 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1134 err_val = self.error_value()
1135 exc_check = self.caller_will_check_exceptions()
1136 if err_val is not None or exc_check:
1137 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1138 else:
1139 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1140 % self.entry.qualified_name, 0)
1141 code.putln(
1142 '__Pyx_WriteUnraisable("%s");' %
1143 self.entry.qualified_name)
1144 env.use_utility_code(unraisable_exception_utility_code)
1145 env.use_utility_code(restore_exception_utility_code)
1146 default_retval = self.return_type.default_value
1147 if err_val is None and default_retval:
1148 err_val = default_retval
1149 if err_val is not None:
1150 code.putln(
1151 "%s = %s;" % (
1152 Naming.retval_cname,
1153 err_val))
1155 if is_getbuffer_slot:
1156 self.getbuffer_error_cleanup(code)
1158 # If we are using the non-error cleanup section we should
1159 # jump past it if we have an error. The if-test below determine
1160 # whether this section is used.
1161 if buffers_present or is_getbuffer_slot:
1162 code.put_goto(code.return_from_error_cleanup_label)
1165 # ----- Non-error return cleanup
1166 # If you add anything here, remember to add a condition to the
1167 # if-test above in the error block (so that it can jump past this
1168 # block).
1169 code.put_label(code.return_label)
1170 for entry in lenv.buffer_entries:
1171 if entry.used:
1172 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1173 if is_getbuffer_slot:
1174 self.getbuffer_normal_cleanup(code)
1175 # ----- Return cleanup for both error and no-error return
1176 code.put_label(code.return_from_error_cleanup_label)
1177 if not Options.init_local_none:
1178 for entry in lenv.var_entries:
1179 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1180 entry.xdecref_cleanup = 1
1181 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1182 # Decref any increfed args
1183 for entry in lenv.arg_entries:
1184 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1185 code.put_var_decref(entry)
1187 # code.putln("/* TODO: decref scope object */")
1188 # ----- Return
1189 # This code is duplicated in ModuleNode.generate_module_init_func
1190 if not lenv.nogil:
1191 default_retval = self.return_type.default_value
1192 err_val = self.error_value()
1193 if err_val is None and default_retval:
1194 err_val = default_retval
1195 if self.return_type.is_pyobject:
1196 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1198 code.put_finish_refcount_context(self.pos,
1199 self.entry.qualified_name,
1200 Naming.retval_cname,
1201 err_val)
1203 if acquire_gil:
1204 code.putln("PyGILState_Release(_save);")
1206 if not self.return_type.is_void:
1207 code.putln("return %s;" % Naming.retval_cname)
1209 code.putln("}")
1210 # ----- Go back and insert temp variable declarations
1211 tempvardecl_code.put_var_declarations(lenv.temp_entries)
1212 tempvardecl_code.put_temp_declarations(code.funcstate)
1213 # ----- Python version
1214 code.exit_cfunc_scope()
1215 if self.py_func:
1216 self.py_func.generate_function_definitions(env, code)
1217 self.generate_wrapper_functions(code)
1219 def declare_argument(self, env, arg):
1220 if arg.type.is_void:
1221 error(arg.pos, "Invalid use of 'void'")
1222 elif not arg.type.is_complete() and not arg.type.is_array:
1223 error(arg.pos,
1224 "Argument type '%s' is incomplete" % arg.type)
1225 return env.declare_arg(arg.name, arg.type, arg.pos)
1227 def generate_wrapper_functions(self, code):
1228 pass
1230 def generate_execution_code(self, code):
1231 # Evaluate and store argument default values
1232 for arg in self.args:
1233 default = arg.default
1234 if default:
1235 if not default.is_literal:
1236 default.generate_evaluation_code(code)
1237 default.make_owned_reference(code)
1238 code.putln(
1239 "%s = %s;" % (
1240 arg.default_entry.cname,
1241 default.result_as(arg.default_entry.type)))
1242 if default.is_temp and default.type.is_pyobject:
1243 code.putln(
1244 "%s = 0;" %
1245 default.result())
1246 default.free_temps(code)
1247 # For Python class methods, create and store function object
1248 if self.assmt:
1249 self.assmt.generate_execution_code(code)
1251 #
1252 # Special code for the __getbuffer__ function
1253 #
1254 def getbuffer_init(self, code):
1255 info = self.local_scope.arg_entries[1].cname
1256 # Python 3.0 betas have a bug in memoryview which makes it call
1257 # getbuffer with a NULL parameter. For now we work around this;
1258 # the following line should be removed when this bug is fixed.
1259 code.putln("if (%s == NULL) return 0;" % info)
1260 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1261 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1263 def getbuffer_error_cleanup(self, code):
1264 info = self.local_scope.arg_entries[1].cname
1265 code.put_gotref("%s->obj" % info)
1266 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1267 (info, info))
1269 def getbuffer_normal_cleanup(self, code):
1270 info = self.local_scope.arg_entries[1].cname
1271 code.putln("if (%s->obj == Py_None) {" % info)
1272 code.put_gotref("Py_None")
1273 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1274 code.putln("}")
1276 class CFuncDefNode(FuncDefNode):
1277 # C function definition.
1278 #
1279 # modifiers ['inline']
1280 # visibility 'private' or 'public' or 'extern'
1281 # base_type CBaseTypeNode
1282 # declarator CDeclaratorNode
1283 # body StatListNode
1284 # api boolean
1285 #
1286 # with_gil boolean Acquire GIL around body
1287 # type CFuncType
1288 # py_func wrapper for calling from Python
1289 # overridable whether or not this is a cpdef function
1290 # inline_in_pxd whether this is an inline function in a pxd file
1292 child_attrs = ["base_type", "declarator", "body", "py_func"]
1294 inline_in_pxd = False
1296 def unqualified_name(self):
1297 return self.entry.name
1299 def analyse_declarations(self, env):
1300 if 'locals' in env.directives:
1301 directive_locals = env.directives['locals']
1302 else:
1303 directive_locals = {}
1304 self.directive_locals = directive_locals
1305 base_type = self.base_type.analyse(env)
1306 # The 2 here is because we need both function and argument names.
1307 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1308 if not type.is_cfunction:
1309 error(self.pos,
1310 "Suite attached to non-function declaration")
1311 # Remember the actual type according to the function header
1312 # written here, because the type in the symbol table entry
1313 # may be different if we're overriding a C method inherited
1314 # from the base type of an extension type.
1315 self.type = type
1316 type.is_overridable = self.overridable
1317 declarator = self.declarator
1318 while not hasattr(declarator, 'args'):
1319 declarator = declarator.base
1320 self.args = declarator.args
1321 for formal_arg, type_arg in zip(self.args, type.args):
1322 formal_arg.type = type_arg.type
1323 formal_arg.name = type_arg.name
1324 formal_arg.cname = type_arg.cname
1325 name = name_declarator.name
1326 cname = name_declarator.cname
1327 self.entry = env.declare_cfunction(
1328 name, type, self.pos,
1329 cname = cname, visibility = self.visibility,
1330 defining = self.body is not None,
1331 api = self.api, modifiers = self.modifiers)
1332 self.entry.inline_func_in_pxd = self.inline_in_pxd
1333 self.return_type = type.return_type
1335 if self.overridable:
1336 import ExprNodes
1337 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1338 self.py_func = DefNode(pos = self.pos,
1339 name = self.entry.name,
1340 args = self.args,
1341 star_arg = None,
1342 starstar_arg = None,
1343 doc = self.doc,
1344 body = py_func_body,
1345 is_wrapper = 1)
1346 self.py_func.is_module_scope = env.is_module_scope
1347 self.py_func.analyse_declarations(env)
1348 self.entry.as_variable = self.py_func.entry
1349 # Reset scope entry the above cfunction
1350 env.entries[name] = self.entry
1351 self.py_func.interned_attr_cname = env.intern_identifier(
1352 self.py_func.entry.name)
1353 if not env.is_module_scope or Options.lookup_module_cpdef:
1354 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1355 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1357 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1358 import ExprNodes
1359 args = self.type.args
1360 if omit_optional_args:
1361 args = args[:len(args) - self.type.optional_arg_count]
1362 arg_names = [arg.name for arg in args]
1363 if is_module_scope:
1364 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1365 else:
1366 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1367 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1368 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1369 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)
1370 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1372 def declare_arguments(self, env):
1373 for arg in self.type.args:
1374 if not arg.name:
1375 error(arg.pos, "Missing argument name")
1376 self.declare_argument(env, arg)
1378 def need_gil_acquisition(self, lenv):
1379 type = self.type
1380 with_gil = self.type.with_gil
1381 if type.nogil and not with_gil:
1382 if type.return_type.is_pyobject:
1383 error(self.pos,
1384 "Function with Python return type cannot be declared nogil")
1385 for entry in lenv.var_entries + lenv.temp_entries:
1386 if entry.type.is_pyobject:
1387 error(self.pos, "Function declared nogil has Python locals or temporaries")
1388 return with_gil
1390 def analyse_expressions(self, env):
1391 self.analyse_default_values(env)
1392 if self.overridable:
1393 self.py_func.analyse_expressions(env)
1395 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1396 arg_decls = []
1397 type = self.type
1398 visibility = self.entry.visibility
1399 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1400 arg_decls.append(arg.declaration_code())
1401 if with_dispatch and self.overridable:
1402 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1403 if type.optional_arg_count and with_opt_args:
1404 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1405 if type.has_varargs:
1406 arg_decls.append("...")
1407 if not arg_decls:
1408 arg_decls = ["void"]
1409 if cname is None:
1410 cname = self.entry.func_cname
1411 entity = type.function_header_code(cname, string.join(arg_decls, ", "))
1412 if visibility == 'public':
1413 dll_linkage = "DL_EXPORT"
1414 else:
1415 dll_linkage = None
1416 header = self.return_type.declaration_code(entity,
1417 dll_linkage = dll_linkage)
1418 if visibility == 'extern':
1419 storage_class = "%s " % Naming.extern_c_macro
1420 elif visibility == 'public':
1421 storage_class = ""
1422 else:
1423 storage_class = "static "
1424 code.putln("%s%s %s {" % (
1425 storage_class,
1426 ' '.join(self.modifiers).upper(), # macro forms
1427 header))
1429 def generate_argument_declarations(self, env, code):
1430 for arg in self.args:
1431 if arg.default:
1432 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1434 def generate_keyword_list(self, code):
1435 pass
1437 def generate_argument_parsing_code(self, env, code):
1438 i = 0
1439 if self.type.optional_arg_count:
1440 code.putln('if (%s) {' % Naming.optional_args_cname)
1441 for arg in self.args:
1442 if arg.default:
1443 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1444 declarator = arg.declarator
1445 while not hasattr(declarator, 'name'):
1446 declarator = declarator.base
1447 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1448 i += 1
1449 for _ in range(self.type.optional_arg_count):
1450 code.putln('}')
1451 code.putln('}')
1453 def generate_argument_conversion_code(self, code):
1454 pass
1456 def generate_argument_type_tests(self, code):
1457 # Generate type tests for args whose type in a parent
1458 # class is a supertype of the declared type.
1459 for arg in self.type.args:
1460 if arg.needs_type_test:
1461 self.generate_arg_type_test(arg, code)
1463 def generate_arg_type_test(self, arg, code):
1464 # Generate type test for one argument.
1465 if arg.type.typeobj_is_available():
1466 typeptr_cname = arg.type.typeptr_cname
1467 arg_code = "((PyObject *)%s)" % arg.cname
1468 code.putln(
1469 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1470 arg_code,
1471 typeptr_cname,
1472 not arg.not_none,
1473 arg.name,
1474 type.is_builtin_type,
1475 code.error_goto(arg.pos)))
1476 else:
1477 error(arg.pos, "Cannot test type of extern C class "
1478 "without type object name specification")
1480 def error_value(self):
1481 if self.return_type.is_pyobject:
1482 return "0"
1483 else:
1484 #return None
1485 return self.entry.type.exception_value
1487 def caller_will_check_exceptions(self):
1488 return self.entry.type.exception_check
1490 def generate_wrapper_functions(self, code):
1491 # If the C signature of a function has changed, we need to generate
1492 # wrappers to put in the slots here.
1493 k = 0
1494 entry = self.entry
1495 func_type = entry.type
1496 while entry.prev_entry is not None:
1497 k += 1
1498 entry = entry.prev_entry
1499 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1500 code.putln()
1501 self.generate_function_header(code,
1502 0,
1503 with_dispatch = entry.type.is_overridable,
1504 with_opt_args = entry.type.optional_arg_count,
1505 cname = entry.func_cname)
1506 if not self.return_type.is_void:
1507 code.put('return ')
1508 args = self.type.args
1509 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1510 if entry.type.is_overridable:
1511 arglist.append(Naming.skip_dispatch_cname)
1512 elif func_type.is_overridable:
1513 arglist.append('0')
1514 if entry.type.optional_arg_count:
1515 arglist.append(Naming.optional_args_cname)
1516 elif func_type.optional_arg_count:
1517 arglist.append('NULL')
1518 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1519 code.putln('}')
1522 class PyArgDeclNode(Node):
1523 # Argument which must be a Python object (used
1524 # for * and ** arguments).
1525 #
1526 # name string
1527 # entry Symtab.Entry
1528 child_attrs = []
1531 class DecoratorNode(Node):
1532 # A decorator
1533 #
1534 # decorator NameNode or CallNode
1535 child_attrs = ['decorator']
1538 class DefNode(FuncDefNode):
1539 # A Python function definition.
1540 #
1541 # name string the Python name of the function
1542 # decorators [DecoratorNode] list of decorators
1543 # args [CArgDeclNode] formal arguments
1544 # star_arg PyArgDeclNode or None * argument
1545 # starstar_arg PyArgDeclNode or None ** argument
1546 # doc EncodedString or None
1547 # body StatListNode
1548 #
1549 # The following subnode is constructed internally
1550 # when the def statement is inside a Python class definition.
1551 #
1552 # assmt AssignmentNode Function construction/assignment
1554 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1556 assmt = None
1557 num_kwonly_args = 0
1558 num_required_kw_args = 0
1559 reqd_kw_flags_cname = "0"
1560 is_wrapper = 0
1561 decorators = None
1562 entry = None
1565 def __init__(self, pos, **kwds):
1566 FuncDefNode.__init__(self, pos, **kwds)
1567 k = rk = r = 0
1568 for arg in self.args:
1569 if arg.kw_only:
1570 k += 1
1571 if not arg.default:
1572 rk += 1
1573 if not arg.default:
1574 r += 1
1575 self.num_kwonly_args = k
1576 self.num_required_kw_args = rk
1577 self.num_required_args = r
1579 def as_cfunction(self, cfunc=None, scope=None):
1580 if self.star_arg:
1581 error(self.star_arg.pos, "cdef function cannot have star argument")
1582 if self.starstar_arg:
1583 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1584 if cfunc is None:
1585 cfunc_args = []
1586 for formal_arg in self.args:
1587 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1588 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1589 cname = None,
1590 type = py_object_type,
1591 pos = formal_arg.pos))
1592 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1593 args = cfunc_args,
1594 has_varargs = False,
1595 exception_value = None,
1596 exception_check = False,
1597 nogil = False,
1598 with_gil = False,
1599 is_overridable = True)
1600 cfunc = CVarDefNode(self.pos, type=cfunc_type, pxd_locals=[])
1601 else:
1602 cfunc_type = cfunc.type
1603 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1604 error(self.pos, "wrong number of arguments")
1605 error(declarator.pos, "previous declaration here")
1606 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1607 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1608 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1609 formal_arg.type = type_arg.type
1610 formal_arg.name_declarator = name_declarator
1611 import ExprNodes
1612 if cfunc_type.exception_value is None:
1613 exception_value = None
1614 else:
1615 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1616 declarator = CFuncDeclaratorNode(self.pos,
1617 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1618 args = self.args,
1619 has_varargs = False,
1620 exception_check = cfunc_type.exception_check,
1621 exception_value = exception_value,
1622 with_gil = cfunc_type.with_gil,
1623 nogil = cfunc_type.nogil)
1624 return CFuncDefNode(self.pos,
1625 modifiers = [],
1626 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1627 declarator = declarator,
1628 body = self.body,
1629 doc = self.doc,
1630 overridable = cfunc_type.is_overridable,
1631 type = cfunc_type,
1632 with_gil = cfunc_type.with_gil,
1633 nogil = cfunc_type.nogil,
1634 visibility = 'private',
1635 api = False,
1636 pxd_locals = cfunc.pxd_locals)
1638 def analyse_declarations(self, env):
1639 if 'locals' in env.directives:
1640 directive_locals = env.directives['locals']
1641 else:
1642 directive_locals = {}
1643 self.directive_locals = directive_locals
1644 for arg in self.args:
1645 if hasattr(arg, 'name'):
1646 type = arg.type
1647 name_declarator = None
1648 else:
1649 base_type = arg.base_type.analyse(env)
1650 name_declarator, type = \
1651 arg.declarator.analyse(base_type, env)
1652 arg.name = name_declarator.name
1653 if arg.name in directive_locals:
1654 type_node = directive_locals[arg.name]
1655 other_type = type_node.analyse_as_type(env)
1656 if other_type is None:
1657 error(type_node.pos, "Not a type")
1658 elif (type is not PyrexTypes.py_object_type
1659 and not type.same_as(other_type)):
1660 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1661 error(type_node.pos, "Previous declaration here")
1662 else:
1663 type = other_type
1664 if name_declarator and name_declarator.cname:
1665 error(self.pos,
1666 "Python function argument cannot have C name specification")
1667 arg.type = type.as_argument_type()
1668 arg.hdr_type = None
1669 arg.needs_conversion = 0
1670 arg.needs_type_test = 0
1671 arg.is_generic = 1
1672 if arg.not_none and not arg.type.is_extension_type:
1673 error(self.pos,
1674 "Only extension type arguments can have 'not None'")
1675 self.declare_pyfunction(env)
1676 self.analyse_signature(env)
1677 self.return_type = self.entry.signature.return_type()
1679 def analyse_signature(self, env):
1680 any_type_tests_needed = 0
1681 # Use the simpler calling signature for zero- and one-argument functions.
1682 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1683 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1684 if len(self.args) == 0:
1685 self.entry.signature = TypeSlots.pyfunction_noargs
1686 elif len(self.args) == 1:
1687 if self.args[0].default is None and not self.args[0].kw_only:
1688 self.entry.signature = TypeSlots.pyfunction_onearg
1689 elif self.entry.signature is TypeSlots.pymethod_signature:
1690 if len(self.args) == 1:
1691 self.entry.signature = TypeSlots.unaryfunc
1692 elif len(self.args) == 2:
1693 if self.args[1].default is None and not self.args[1].kw_only:
1694 self.entry.signature = TypeSlots.ibinaryfunc
1695 elif self.entry.is_special:
1696 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1697 sig = self.entry.signature
1698 nfixed = sig.num_fixed_args()
1699 for i in range(nfixed):
1700 if i < len(self.args):
1701 arg = self.args[i]
1702 arg.is_generic = 0
1703 if sig.is_self_arg(i):
1704 arg.is_self_arg = 1
1705 arg.hdr_type = arg.type = env.parent_type
1706 arg.needs_conversion = 0
1707 else:
1708 arg.hdr_type = sig.fixed_arg_type(i)
1709 if not arg.type.same_as(arg.hdr_type):
1710 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1711 arg.needs_type_test = 1
1712 any_type_tests_needed = 1
1713 else:
1714 arg.needs_conversion = 1
1715 if arg.needs_conversion:
1716 arg.hdr_cname = Naming.arg_prefix + arg.name
1717 else:
1718 arg.hdr_cname = Naming.var_prefix + arg.name
1719 else:
1720 self.bad_signature()
1721 return
1722 if nfixed < len(self.args):
1723 if not sig.has_generic_args:
1724 self.bad_signature()
1725 for arg in self.args:
1726 if arg.is_generic and \
1727 (arg.type.is_extension_type or arg.type.is_builtin_type):
1728 arg.needs_type_test = 1
1729 any_type_tests_needed = 1
1730 elif (arg.type is PyrexTypes.c_py_ssize_t_type
1731 or arg.type is PyrexTypes.c_size_t_type):
1732 # Don't use PyArg_ParseTupleAndKeywords's parsing
1733 # Py_ssize_t: want to use __index__ rather than __int__
1734 # size_t: no Python format char
1735 arg.needs_conversion = 1
1736 arg.hdr_type = PyrexTypes.py_object_type
1737 arg.hdr_cname = Naming.arg_prefix + arg.name
1738 if any_type_tests_needed:
1739 env.use_utility_code(arg_type_test_utility_code)
1741 def bad_signature(self):
1742 sig = self.entry.signature
1743 expected_str = "%d" % sig.num_fixed_args()
1744 if sig.has_generic_args:
1745 expected_str = expected_str + " or more"
1746 name = self.name
1747 if name.startswith("__") and name.endswith("__"):
1748 desc = "Special method"
1749 else:
1750 desc = "Method"
1751 error(self.pos,
1752 "%s %s has wrong number of arguments "
1753 "(%d declared, %s expected)" % (
1754 desc, self.name, len(self.args), expected_str))
1756 def signature_has_nongeneric_args(self):
1757 argcount = len(self.args)
1758 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1759 return 0
1760 return 1
1762 def signature_has_generic_args(self):
1763 return self.entry.signature.has_generic_args
1765 def declare_pyfunction(self, env):
1766 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1767 name = self.name
1768 entry = env.lookup_here(self.name)
1769 if entry and entry.type.is_cfunction and not self.is_wrapper:
1770 warning(self.pos, "Overriding cdef method with def method.", 5)
1771 entry = env.declare_pyfunction(self.name, self.pos)
1772 self.entry = entry
1773 prefix = env.scope_prefix
1774 entry.func_cname = \
1775 Naming.pyfunc_prefix + prefix + name
1776 entry.pymethdef_cname = \
1777 Naming.pymethdef_prefix + prefix + name
1778 if Options.docstrings:
1779 entry.doc = embed_position(self.pos, self.doc)
1780 entry.doc_cname = \
1781 Naming.funcdoc_prefix + prefix + name
1782 else:
1783 entry.doc = None
1785 def declare_arguments(self, env):
1786 for arg in self.args:
1787 if not arg.name:
1788 error(arg.pos, "Missing argument name")
1789 if arg.needs_conversion:
1790 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1791 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1792 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1793 if arg.type.is_pyobject:
1794 arg.entry.init = "0"
1795 arg.entry.init_to_none = 0
1796 else:
1797 arg.entry = self.declare_argument(env, arg)
1798 arg.entry.used = 1
1799 arg.entry.is_self_arg = arg.is_self_arg
1800 if not arg.is_self_arg:
1801 arg.name_entry = env.get_string_const(
1802 arg.name, identifier = True)
1803 env.add_py_string(arg.name_entry, identifier = True)
1804 if arg.hdr_type:
1805 if arg.is_self_arg or \
1806 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1807 arg.entry.is_declared_generic = 1
1808 self.declare_python_arg(env, self.star_arg)
1809 self.declare_python_arg(env, self.starstar_arg)
1811 def declare_python_arg(self, env, arg):
1812 if arg:
1813 entry = env.declare_var(arg.name,
1814 PyrexTypes.py_object_type, arg.pos)
1815 entry.used = 1
1816 entry.init = "0"
1817 entry.init_to_none = 0
1818 entry.xdecref_cleanup = 1
1819 arg.entry = entry
1820 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1822 def analyse_expressions(self, env):
1823 self.analyse_default_values(env)
1824 if env.is_py_class_scope:
1825 self.synthesize_assignment_node(env)
1827 def synthesize_assignment_node(self, env):
1828 import ExprNodes
1829 self.assmt = SingleAssignmentNode(self.pos,
1830 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1831 rhs = ExprNodes.UnboundMethodNode(self.pos,
1832 class_cname = env.class_obj_cname,
1833 function = ExprNodes.PyCFunctionNode(self.pos,
1834 pymethdef_cname = self.entry.pymethdef_cname)))
1835 self.assmt.analyse_declarations(env)
1836 self.assmt.analyse_expressions(env)
1838 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1839 arg_code_list = []
1840 sig = self.entry.signature
1841 if sig.has_dummy_arg:
1842 arg_code_list.append(
1843 "PyObject *%s" % Naming.self_cname)
1844 for arg in self.args:
1845 if not arg.is_generic:
1846 if arg.is_self_arg:
1847 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1848 else:
1849 arg_code_list.append(
1850 arg.hdr_type.declaration_code(arg.hdr_cname))
1851 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1852 arg_code_list.append("PyObject *unused")
1853 if sig.has_generic_args:
1854 arg_code_list.append(
1855 "PyObject *%s, PyObject *%s"
1856 % (Naming.args_cname, Naming.kwds_cname))
1857 arg_code = ", ".join(arg_code_list)
1858 dc = self.return_type.declaration_code(self.entry.func_cname)
1859 header = "static %s(%s)" % (dc, arg_code)
1860 code.putln("%s; /*proto*/" % header)
1861 if proto_only:
1862 return
1863 if self.entry.doc and Options.docstrings:
1864 docstr = self.entry.doc
1865 if not isinstance(docstr, str):
1866 docstr = docstr.utf8encode()
1867 code.putln(
1868 'static char %s[] = "%s";' % (
1869 self.entry.doc_cname,
1870 split_docstring(escape_byte_string(docstr))))
1871 if with_pymethdef:
1872 code.put(
1873 "static PyMethodDef %s = " %
1874 self.entry.pymethdef_cname)
1875 code.put_pymethoddef(self.entry, ";")
1876 code.putln("%s {" % header)
1878 def generate_argument_declarations(self, env, code):
1879 for arg in self.args:
1880 if arg.is_generic: # or arg.needs_conversion:
1881 if arg.needs_conversion:
1882 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1883 else:
1884 code.put_var_declaration(arg.entry)
1886 def generate_keyword_list(self, code):
1887 if self.signature_has_generic_args() and \
1888 self.signature_has_nongeneric_args():
1889 code.put(
1890 "static PyObject **%s[] = {" %
1891 Naming.pykwdlist_cname)
1892 for arg in self.args:
1893 if arg.is_generic:
1894 code.put('&%s,' % arg.name_entry.pystring_cname)
1895 code.putln("0};")
1897 def generate_argument_parsing_code(self, env, code):
1898 # Generate PyArg_ParseTuple call for generic
1899 # arguments, if any.
1900 if self.entry.signature.has_dummy_arg:
1901 # get rid of unused argument warning
1902 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1904 old_error_label = code.new_error_label()
1905 our_error_label = code.error_label
1906 end_label = code.new_label("argument_unpacking_done")
1908 has_kwonly_args = self.num_kwonly_args > 0
1909 has_star_or_kw_args = self.star_arg is not None \
1910 or self.starstar_arg is not None or has_kwonly_args
1912 if not self.signature_has_generic_args():
1913 if has_star_or_kw_args:
1914 error(self.pos, "This method cannot have * or keyword arguments")
1915 self.generate_argument_conversion_code(code)
1917 elif not self.signature_has_nongeneric_args():
1918 # func(*args) or func(**kw) or func(*args, **kw)
1919 self.generate_stararg_copy_code(code)
1921 else:
1922 positional_args = []
1923 kw_only_args = []
1924 default_seen = 0
1925 for arg in self.args:
1926 arg_entry = arg.entry
1927 if arg.is_generic:
1928 if arg.default:
1929 default_seen = 1
1930 if not arg.is_self_arg:
1931 if arg.kw_only:
1932 kw_only_args.append(arg)
1933 else:
1934 positional_args.append(arg)
1935 elif arg.kw_only:
1936 kw_only_args.append(arg)
1937 default_seen = 1
1938 elif default_seen:
1939 error(arg.pos, "Non-default argument following default argument")
1940 elif not arg.is_self_arg:
1941 positional_args.append(arg)
1942 if arg.needs_conversion:
1943 format = arg.hdr_type.parsetuple_format
1944 else:
1945 format = arg_entry.type.parsetuple_format
1946 if not format:
1947 error(arg.pos,
1948 "Cannot convert Python object argument to type '%s' (when parsing input arguments)"
1949 % arg.type)
1951 self.generate_tuple_and_keyword_parsing_code(
1952 positional_args, kw_only_args, end_label, code)
1954 code.error_label = old_error_label
1955 if code.label_used(our_error_label):
1956 if not code.label_used(end_label):
1957 code.put_goto(end_label)
1958 code.put_label(our_error_label)
1959 if has_star_or_kw_args:
1960 self.generate_arg_decref(self.star_arg, code)
1961 if self.starstar_arg:
1962 if self.starstar_arg.entry.xdecref_cleanup:
1963 code.put_var_xdecref(self.starstar_arg.entry)
1964 else:
1965 code.put_var_decref(self.starstar_arg.entry)
1966 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1967 code.putln("return %s;" % self.error_value())
1968 if code.label_used(end_label):
1969 code.put_label(end_label)
1971 def generate_arg_assignment(self, arg, item, code):
1972 if arg.type.is_pyobject:
1973 if arg.is_generic:
1974 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1975 code.putln("%s = %s;" % (arg.entry.cname, item))
1976 else:
1977 func = arg.type.from_py_function
1978 if func:
1979 code.putln("%s = %s(%s); %s" % (
1980 arg.entry.cname,
1981 func,
1982 item,
1983 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1984 else:
1985 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1987 def generate_arg_xdecref(self, arg, code):
1988 if arg:
1989 code.put_var_xdecref(arg.entry)
1991 def generate_arg_decref(self, arg, code):
1992 if arg:
1993 code.put_var_decref(arg.entry)
1995 def generate_stararg_copy_code(self, code):
1996 if not self.star_arg:
1997 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1998 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1999 Naming.args_cname)
2000 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2001 self.name.utf8encode(), Naming.args_cname, self.error_value()))
2002 code.putln("}")
2004 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2006 if self.starstar_arg:
2007 if self.star_arg:
2008 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2009 else:
2010 kwarg_check = "%s" % Naming.kwds_cname
2011 else:
2012 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2013 Naming.kwds_cname, Naming.kwds_cname)
2014 code.putln(
2015 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2016 kwarg_check, Naming.kwds_cname, self.name,
2017 bool(self.starstar_arg), self.error_value()))
2019 if self.starstar_arg:
2020 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2021 self.starstar_arg.entry.cname,
2022 Naming.kwds_cname,
2023 Naming.kwds_cname))
2024 code.putln("if (unlikely(!%s)) return %s;" % (
2025 self.starstar_arg.entry.cname, self.error_value()))
2026 self.starstar_arg.entry.xdecref_cleanup = 0
2027 code.put_gotref(self.starstar_arg.entry.cname)
2030 if self.star_arg:
2031 code.put_incref(Naming.args_cname, py_object_type)
2032 code.putln("%s = %s;" % (
2033 self.star_arg.entry.cname,
2034 Naming.args_cname))
2035 self.star_arg.entry.xdecref_cleanup = 0
2037 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2038 kw_only_args, success_label, code):
2039 argtuple_error_label = code.new_label("argtuple_error")
2041 min_positional_args = self.num_required_args - self.num_required_kw_args
2042 if len(self.args) > 0 and self.args[0].is_self_arg:
2043 min_positional_args -= 1
2044 max_positional_args = len(positional_args)
2045 has_fixed_positional_count = not self.star_arg and \
2046 min_positional_args == max_positional_args
2048 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2049 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2050 if self.num_required_kw_args:
2051 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2053 if self.starstar_arg or self.star_arg:
2054 self.generate_stararg_init_code(max_positional_args, code)
2056 # --- optimised code when we receive keyword arguments
2057 if self.num_required_kw_args:
2058 likely_hint = "likely"
2059 else:
2060 likely_hint = "unlikely"
2061 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2062 self.generate_keyword_unpacking_code(
2063 min_positional_args, max_positional_args,
2064 has_fixed_positional_count,
2065 positional_args, kw_only_args, argtuple_error_label, code)
2067 # --- optimised code when we do not receive any keyword arguments
2068 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2069 # Python raises arg tuple related errors first, so we must
2070 # check the length here
2071 if min_positional_args == max_positional_args and not self.star_arg:
2072 compare = '!='
2073 else:
2074 compare = '<'
2075 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2076 Naming.args_cname, compare, min_positional_args))
2077 code.put_goto(argtuple_error_label)
2079 if self.num_required_kw_args:
2080 # pure error case: keywords required but not passed
2081 if max_positional_args > min_positional_args and not self.star_arg:
2082 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2083 Naming.args_cname, max_positional_args))
2084 code.put_goto(argtuple_error_label)
2085 code.putln('} else {')
2086 for i, arg in enumerate(kw_only_args):
2087 if not arg.default:
2088 # required keyword-only argument missing
2089 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2090 self.name.utf8encode(),
2091 arg.name_entry.pystring_cname))
2092 code.putln(code.error_goto(self.pos))
2093 break
2095 elif min_positional_args == max_positional_args:
2096 # parse the exact number of positional arguments from the
2097 # args tuple
2098 code.putln('} else {')
2099 for i, arg in enumerate(positional_args):
2100 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2101 self.generate_arg_assignment(arg, item, code)
2102 self.generate_arg_default_assignments(code)
2104 else:
2105 # parse the positional arguments from the variable length
2106 # args tuple
2107 code.putln('} else {')
2108 self.generate_arg_default_assignments(code)
2109 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2110 if self.star_arg:
2111 code.putln('default:')
2112 reversed_args = list(enumerate(positional_args))[::-1]
2113 for i, arg in reversed_args:
2114 if i >= min_positional_args-1:
2115 if min_positional_args > 1:
2116 code.putln('case %2d:' % (i+1)) # pure code beautification
2117 else:
2118 code.put('case %2d: ' % (i+1))
2119 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2120 self.generate_arg_assignment(arg, item, code)
2121 if min_positional_args == 0:
2122 code.put('case 0: ')
2123 code.putln('break;')
2124 if self.star_arg:
2125 if min_positional_args:
2126 for i in range(min_positional_args-1, -1, -1):
2127 code.putln('case %2d:' % i)
2128 code.put_goto(argtuple_error_label)
2129 else:
2130 code.put('default: ')
2131 code.put_goto(argtuple_error_label)
2132 code.putln('}')
2134 code.putln('}')
2136 if code.label_used(argtuple_error_label):
2137 code.put_goto(success_label)
2138 code.put_label(argtuple_error_label)
2139 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2140 self.name.utf8encode(), has_fixed_positional_count,
2141 min_positional_args, max_positional_args,
2142 Naming.args_cname))
2143 code.putln(code.error_goto(self.pos))
2145 def generate_arg_default_assignments(self, code):
2146 for arg in self.args:
2147 if arg.is_generic and arg.default:
2148 code.putln(
2149 "%s = %s;" % (
2150 arg.entry.cname,
2151 arg.default_result_code))
2153 def generate_stararg_init_code(self, max_positional_args, code):
2154 if self.starstar_arg:
2155 self.starstar_arg.entry.xdecref_cleanup = 0
2156 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2157 self.starstar_arg.entry.cname,
2158 self.starstar_arg.entry.cname,
2159 self.error_value()))
2160 code.put_gotref(self.starstar_arg.entry.cname)
2161 if self.star_arg:
2162 self.star_arg.entry.xdecref_cleanup = 0
2163 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2164 Naming.args_cname,
2165 max_positional_args))
2166 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2167 self.star_arg.entry.cname, Naming.args_cname,
2168 max_positional_args, Naming.args_cname))
2169 code.put_gotref(self.star_arg.entry.cname)
2170 if self.starstar_arg:
2171 code.putln("")
2172 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2173 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2174 code.putln('return %s;' % self.error_value())
2175 code.putln('}')
2176 else:
2177 code.putln("if (unlikely(!%s)) return %s;" % (
2178 self.star_arg.entry.cname, self.error_value()))
2179 code.putln('} else {')
2180 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2181 code.put_incref(Naming.empty_tuple, py_object_type)
2182 code.putln('}')
2184 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2185 has_fixed_positional_count, positional_args,
2186 kw_only_args, argtuple_error_label, code):
2187 all_args = tuple(positional_args) + tuple(kw_only_args)
2188 max_args = len(all_args)
2190 default_args = []
2191 for arg in all_args:
2192 if arg.default and arg.type.is_pyobject:
2193 default_value = arg.default_result_code
2194 if arg.type is not PyrexTypes.py_object_type:
2195 default_value = "(PyObject*)"+default_value
2196 default_args.append(default_value)
2197 else:
2198 default_args.append('0')
2199 code.putln("PyObject* values[%d] = {%s};" % (
2200 max_args, ', '.join(default_args)))
2201 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2202 Naming.kwds_cname)
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_error_label = code.new_error_label()
4043 our_error_label = code.error_label
4044 except_end_label = code.new_label('exception_handled')
4045 except_error_label = code.new_label('except_error')
4046 except_return_label = code.new_label('except_return')
4047 try_return_label = code.new_label('try_return')
4048 try_break_label = code.new_label('try_break')
4049 try_end_label = code.new_label('try_end')
4051 code.putln("{")
4052 code.putln("PyObject %s;" %
4053 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4054 code.putln("__Pyx_ExceptionSave(%s);" %
4055 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4056 for var in Naming.exc_save_vars:
4057 code.put_xgotref(var)
4058 code.putln(
4059 "/*try:*/ {")
4060 code.return_label = try_return_label
4061 code.break_label = try_break_label
4062 self.body.generate_execution_code(code)
4063 code.putln(
4064 "}")
4065 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4066 code.error_label = except_error_label
4067 code.return_label = except_return_label
4068 if self.else_clause:
4069 code.putln(
4070 "/*else:*/ {")
4071 self.else_clause.generate_execution_code(code)
4072 code.putln(
4073 "}")
4074 for var in Naming.exc_save_vars:
4075 code.put_xdecref_clear(var, py_object_type)
4076 code.put_goto(try_end_label)
4077 if code.label_used(try_return_label):
4078 code.put_label(try_return_label)
4079 for var in Naming.exc_save_vars:
4080 code.put_xdecref_clear(var, py_object_type)
4081 code.put_goto(old_return_label)
4082 code.put_label(our_error_label)
4083 code.put_var_xdecrefs_clear(self.cleanup_list)
4084 for temp_name, type in temps_to_clean_up:
4085 code.put_xdecref_clear(temp_name, type)
4086 for except_clause in self.except_clauses:
4087 except_clause.generate_handling_code(code, except_end_label)
4089 error_label_used = code.label_used(except_error_label)
4090 if error_label_used or not self.has_default_clause:
4091 if error_label_used:
4092 code.put_label(except_error_label)
4093 for var in Naming.exc_save_vars:
4094 code.put_xdecref(var, py_object_type)
4095 code.put_goto(old_error_label)
4097 if code.label_used(try_break_label):
4098 code.put_label(try_break_label)
4099 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4100 code.putln("__Pyx_ExceptionReset(%s);" %
4101 ', '.join(Naming.exc_save_vars))
4102 code.put_goto(old_break_label)
4104 if code.label_used(except_return_label):
4105 code.put_label(except_return_label)
4106 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4107 code.putln("__Pyx_ExceptionReset(%s);" %
4108 ', '.join(Naming.exc_save_vars))
4109 code.put_goto(old_return_label)
4111 if code.label_used(except_end_label):
4112 code.put_label(except_end_label)
4113 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4114 code.putln("__Pyx_ExceptionReset(%s);" %
4115 ', '.join(Naming.exc_save_vars))
4116 code.put_label(try_end_label)
4117 code.putln("}")
4119 code.return_label = old_return_label
4120 code.break_label = old_break_label
4121 code.error_label = old_error_label
4123 def annotate(self, code):
4124 self.body.annotate(code)
4125 for except_node in self.except_clauses:
4126 except_node.annotate(code)
4127 if self.else_clause:
4128 self.else_clause.annotate(code)
4131 class ExceptClauseNode(Node):
4132 # Part of try ... except statement.
4133 #
4134 # pattern ExprNode
4135 # target ExprNode or None
4136 # body StatNode
4137 # excinfo_target NameNode or None optional target for exception info
4138 # match_flag string result of exception match
4139 # exc_value ExcValueNode used internally
4140 # function_name string qualified name of enclosing function
4141 # exc_vars (string * 3) local exception variables
4143 # excinfo_target is never set by the parser, but can be set by a transform
4144 # in order to extract more extensive information about the exception as a
4145 # sys.exc_info()-style tuple into a target variable
4147 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4149 exc_value = None
4150 excinfo_target = None
4152 def analyse_declarations(self, env):
4153 if self.target:
4154 self.target.analyse_target_declaration(env)
4155 if self.excinfo_target is not None:
4156 self.excinfo_target.analyse_target_declaration(env)
4157 self.body.analyse_declarations(env)
4159 def analyse_expressions(self, env):
4160 import ExprNodes
4161 genv = env.global_scope()
4162 self.function_name = env.qualified_name
4163 if self.pattern:
4164 self.pattern.analyse_expressions(env)
4165 self.pattern = self.pattern.coerce_to_pyobject(env)
4166 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
4167 self.pattern.release_temp(env)
4168 env.release_temp(self.match_flag)
4169 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
4170 if self.target:
4171 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
4172 self.exc_value.allocate_temps(env)
4173 self.target.analyse_target_expression(env, self.exc_value)
4174 if self.excinfo_target is not None:
4175 import ExprNodes
4176 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4177 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
4178 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
4179 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
4180 ])
4181 self.excinfo_tuple.analyse_expressions(env)
4182 self.excinfo_tuple.allocate_temps(env)
4183 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4185 self.body.analyse_expressions(env)
4186 for var in self.exc_vars:
4187 env.release_temp(var)
4188 env.use_utility_code(get_exception_utility_code)
4189 env.use_utility_code(restore_exception_utility_code)
4191 def generate_handling_code(self, code, end_label):
4192 code.mark_pos(self.pos)
4193 if self.pattern:
4194 self.pattern.generate_evaluation_code(code)
4195 code.putln(
4196 "%s = PyErr_ExceptionMatches(%s);" % (
4197 self.match_flag,
4198 self.pattern.py_result()))
4199 self.pattern.generate_disposal_code(code)
4200 self.pattern.free_temps(code)
4201 code.putln(
4202 "if (%s) {" %
4203 self.match_flag)
4204 else:
4205 code.putln("/*except:*/ {")
4206 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4207 # We always have to fetch the exception value even if
4208 # there is no target, because this also normalises the
4209 # exception and stores it in the thread state.
4210 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
4211 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4212 code.error_goto(self.pos)))
4213 for x in self.exc_vars:
4214 code.put_gotref(x)
4215 if self.target:
4216 self.exc_value.generate_evaluation_code(code)
4217 self.target.generate_assignment_code(self.exc_value, code)
4218 if self.excinfo_target is not None:
4219 self.excinfo_tuple.generate_evaluation_code(code)
4220 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4222 old_exc_vars = code.funcstate.exc_vars
4223 code.funcstate.exc_vars = self.exc_vars
4224 self.body.generate_execution_code(code)
4225 code.funcstate.exc_vars = old_exc_vars
4226 for var in self.exc_vars:
4227 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4228 code.put_goto(end_label)
4229 code.putln(
4230 "}")
4232 def annotate(self, code):
4233 if self.pattern:
4234 self.pattern.annotate(code)
4235 if self.target:
4236 self.target.annotate(code)
4237 self.body.annotate(code)
4240 class TryFinallyStatNode(StatNode):
4241 # try ... finally statement
4242 #
4243 # body StatNode
4244 # finally_clause StatNode
4245 #
4246 # cleanup_list [Entry] old_style temps to clean up on error
4247 #
4248 # The plan is that we funnel all continue, break
4249 # return and error gotos into the beginning of the
4250 # finally block, setting a variable to remember which
4251 # one we're doing. At the end of the finally block, we
4252 # switch on the variable to figure out where to go.
4253 # In addition, if we're doing an error, we save the
4254 # exception on entry to the finally block and restore
4255 # it on exit.
4257 child_attrs = ["body", "finally_clause"]
4259 preserve_exception = 1
4261 disallow_continue_in_try_finally = 0
4262 # There doesn't seem to be any point in disallowing
4263 # continue in the try block, since we have no problem
4264 # handling it.
4266 def create_analysed(pos, env, body, finally_clause):
4267 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4268 node.cleanup_list = []
4269 return node
4270 create_analysed = staticmethod(create_analysed)
4272 def analyse_control_flow(self, env):
4273 env.start_branching(self.pos)
4274 self.body.analyse_control_flow(env)
4275 env.next_branch(self.body.end_pos())
4276 env.finish_branching(self.body.end_pos())
4277 self.finally_clause.analyse_control_flow(env)
4279 def analyse_declarations(self, env):
4280 self.body.analyse_declarations(env)
4281 self.finally_clause.analyse_declarations(env)
4283 def analyse_expressions(self, env):
4284 self.body.analyse_expressions(env)
4285 self.cleanup_list = env.free_temp_entries[:]
4286 self.finally_clause.analyse_expressions(env)
4287 self.gil_check(env)
4289 gil_message = "Try-finally statement"
4291 def generate_execution_code(self, code):
4292 old_error_label = code.error_label
4293 old_labels = code.all_new_labels()
4294 new_labels = code.get_all_labels()
4295 new_error_label = code.error_label
4296 catch_label = code.new_label()
4297 code.putln(
4298 "/*try:*/ {")
4299 if self.disallow_continue_in_try_finally:
4300 was_in_try_finally = code.funcstate.in_try_finally
4301 code.funcstate.in_try_finally = 1
4302 self.body.generate_execution_code(code)
4303 if self.disallow_continue_in_try_finally:
4304 code.funcstate.in_try_finally = was_in_try_finally
4305 code.putln(
4306 "}")
4307 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4308 code.putln(
4309 "/*finally:*/ {")
4310 cases_used = []
4311 error_label_used = 0
4312 for i, new_label in enumerate(new_labels):
4313 if new_label in code.labels_used:
4314 cases_used.append(i)
4315 if new_label == new_error_label:
4316 error_label_used = 1
4317 error_label_case = i
4318 if cases_used:
4319 code.putln(
4320 "int __pyx_why;")
4321 if error_label_used and self.preserve_exception:
4322 code.putln(
4323 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4324 code.putln(
4325 "int %s;" % Naming.exc_lineno_name)
4326 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4327 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4328 code.putln(exc_var_init_zero)
4329 else:
4330 exc_var_init_zero = None
4331 code.use_label(catch_label)
4332 code.putln(
4333 "__pyx_why = 0; goto %s;" % catch_label)
4334 for i in cases_used:
4335 new_label = new_labels[i]
4336 #if new_label and new_label != "<try>":
4337 if new_label == new_error_label and self.preserve_exception:
4338 self.put_error_catcher(code,
4339 new_error_label, i+1, catch_label, temps_to_clean_up)
4340 else:
4341 code.put('%s: ' % new_label)
4342 if exc_var_init_zero:
4343 code.putln(exc_var_init_zero)
4344 code.putln("__pyx_why = %s; goto %s;" % (
4345 i+1,
4346 catch_label))
4347 code.put_label(catch_label)
4348 code.set_all_labels(old_labels)
4349 if error_label_used:
4350 code.new_error_label()
4351 finally_error_label = code.error_label
4352 self.finally_clause.generate_execution_code(code)
4353 if error_label_used:
4354 if finally_error_label in code.labels_used and self.preserve_exception:
4355 over_label = code.new_label()
4356 code.put_goto(over_label);
4357 code.put_label(finally_error_label)
4358 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4359 for var in Naming.exc_vars:
4360 code.putln("Py_XDECREF(%s);" % var)
4361 code.putln("}")
4362 code.put_goto(old_error_label)
4363 code.put_label(over_label)
4364 code.error_label = old_error_label
4365 if cases_used:
4366 code.putln(
4367 "switch (__pyx_why) {")
4368 for i in cases_used:
4369 old_label = old_labels[i]
4370 if old_label == old_error_label and self.preserve_exception:
4371 self.put_error_uncatcher(code, i+1, old_error_label)
4372 else:
4373 code.use_label(old_label)
4374 code.putln(
4375 "case %s: goto %s;" % (
4376 i+1,
4377 old_label))
4378 code.putln(
4379 "}")
4380 code.putln(
4381 "}")
4383 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4384 code.globalstate.use_utility_code(restore_exception_utility_code)
4385 code.putln(
4386 "%s: {" %
4387 error_label)
4388 code.putln(
4389 "__pyx_why = %s;" %
4390 i)
4391 code.put_var_xdecrefs_clear(self.cleanup_list)
4392 for temp_name, type in temps_to_clean_up:
4393 code.put_xdecref_clear(temp_name, type)
4394 code.putln(
4395 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4396 Naming.exc_vars)
4397 code.putln(
4398 "%s = %s;" % (
4399 Naming.exc_lineno_name, Naming.lineno_cname))
4400 #code.putln(
4401 # "goto %s;" %
4402 # catch_label)
4403 code.put_goto(catch_label)
4404 code.putln(
4405 "}")
4407 def put_error_uncatcher(self, code, i, error_label):
4408 code.globalstate.use_utility_code(restore_exception_utility_code)
4409 code.putln(
4410 "case %s: {" %
4411 i)
4412 code.putln(
4413 "__Pyx_ErrRestore(%s, %s, %s);" %
4414 Naming.exc_vars)
4415 code.putln(
4416 "%s = %s;" % (
4417 Naming.lineno_cname, Naming.exc_lineno_name))
4418 for var in Naming.exc_vars:
4419 code.putln(
4420 "%s = 0;" %
4421 var)
4422 code.put_goto(error_label)
4423 code.putln(
4424 "}")
4426 def annotate(self, code):
4427 self.body.annotate(code)
4428 self.finally_clause.annotate(code)
4431 class GILStatNode(TryFinallyStatNode):
4432 # 'with gil' or 'with nogil' statement
4433 #
4434 # state string 'gil' or 'nogil'
4436 child_attrs = []
4438 preserve_exception = 0
4440 def __init__(self, pos, state, body):
4441 self.state = state
4442 TryFinallyStatNode.__init__(self, pos,
4443 body = body,
4444 finally_clause = GILExitNode(pos, state = state))
4446 def analyse_expressions(self, env):
4447 was_nogil = env.nogil
4448 env.nogil = 1
4449 TryFinallyStatNode.analyse_expressions(self, env)
4450 env.nogil = was_nogil
4452 def gil_check(self, env):
4453 pass
4455 def generate_execution_code(self, code):
4456 code.putln("/*with %s:*/ {" % self.state)
4457 if self.state == 'gil':
4458 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
4459 else:
4460 code.putln("PyThreadState *_save;")
4461 code.putln("Py_UNBLOCK_THREADS")
4462 TryFinallyStatNode.generate_execution_code(self, code)
4463 code.putln("}")
4466 class GILExitNode(StatNode):
4467 # Used as the 'finally' block in a GILStatNode
4468 #
4469 # state string 'gil' or 'nogil'
4471 child_attrs = []
4473 def analyse_expressions(self, env):
4474 pass
4476 def generate_execution_code(self, code):
4477 if self.state == 'gil':
4478 code.putln("PyGILState_Release();")
4479 else:
4480 code.putln("Py_BLOCK_THREADS")
4483 class CImportStatNode(StatNode):
4484 # cimport statement
4485 #
4486 # module_name string Qualified name of module being imported
4487 # as_name string or None Name specified in "as" clause, if any
4489 child_attrs = []
4491 def analyse_declarations(self, env):
4492 if not env.is_module_scope:
4493 error(self.pos, "cimport only allowed at module level")
4494 return
4495 module_scope = env.find_module(self.module_name, self.pos)
4496 if "." in self.module_name:
4497 names = [EncodedString(name) for name in self.module_name.split(".")]
4498 top_name = names[0]
4499 top_module_scope = env.context.find_submodule(top_name)
4500 module_scope = top_module_scope
4501 for name in names[1:]:
4502 submodule_scope = module_scope.find_submodule(name)
4503 module_scope.declare_module(name, submodule_scope, self.pos)
4504 module_scope = submodule_scope
4505 if self.as_name:
4506 env.declare_module(self.as_name, module_scope, self.pos)
4507 else:
4508 env.declare_module(top_name, top_module_scope, self.pos)
4509 else:
4510 name = self.as_name or self.module_name
4511 env.declare_module(name, module_scope, self.pos)
4513 def analyse_expressions(self, env):
4514 pass
4516 def generate_execution_code(self, code):
4517 pass
4520 class FromCImportStatNode(StatNode):
4521 # from ... cimport statement
4522 #
4523 # module_name string Qualified name of module
4524 # imported_names [(pos, name, as_name, kind)] Names to be imported
4526 child_attrs = []
4528 def analyse_declarations(self, env):
4529 if not env.is_module_scope:
4530 error(self.pos, "cimport only allowed at module level")
4531 return
4532 module_scope = env.find_module(self.module_name, self.pos)
4533 env.add_imported_module(module_scope)
4534 for pos, name, as_name, kind in self.imported_names:
4535 if name == "*":
4536 for local_name, entry in module_scope.entries.items():
4537 env.add_imported_entry(local_name, entry, pos)
4538 else:
4539 entry = module_scope.lookup(name)
4540 if entry:
4541 if kind and not self.declaration_matches(entry, kind):
4542 entry.redeclared(pos)
4543 else:
4544 if kind == 'struct' or kind == 'union':
4545 entry = module_scope.declare_struct_or_union(name,
4546 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4547 elif kind == 'class':
4548 entry = module_scope.declare_c_class(name, pos = pos,
4549 module_name = self.module_name)
4550 else:
4551 error(pos, "Name '%s' not declared in module '%s'"
4552 % (name, self.module_name))
4554 if entry:
4555 local_name = as_name or name
4556 env.add_imported_entry(local_name, entry, pos)
4558 def declaration_matches(self, entry, kind):
4559 if not entry.is_type:
4560 return 0
4561 type = entry.type
4562 if kind == 'class':
4563 if not type.is_extension_type:
4564 return 0
4565 else:
4566 if not type.is_struct_or_union:
4567 return 0
4568 if kind != type.kind:
4569 return 0
4570 return 1
4572 def analyse_expressions(self, env):
4573 pass
4575 def generate_execution_code(self, code):
4576 pass
4579 class FromImportStatNode(StatNode):
4580 # from ... import statement
4581 #
4582 # module ImportNode
4583 # items [(string, NameNode)]
4584 # interned_items [(string, NameNode)]
4585 # item PyTempNode used internally
4586 # import_star boolean used internally
4588 child_attrs = ["module"]
4589 import_star = 0
4591 def analyse_declarations(self, env):
4592 for name, target in self.items:
4593 if name == "*":
4594 if not env.is_module_scope:
4595 error(self.pos, "import * only allowed at module level")
4596 return
4597 env.has_import_star = 1
4598 self.import_star = 1
4599 else:
4600 target.analyse_target_declaration(env)
4602 def analyse_expressions(self, env):
4603 import ExprNodes
4604 self.module.analyse_expressions(env)
4605 self.item = ExprNodes.PyTempNode(self.pos, env)
4606 self.item.allocate_temp(env)
4607 self.interned_items = []
4608 for name, target in self.items:
4609 if name == '*':
4610 for _, entry in env.entries.items():
4611 if not entry.is_type and entry.type.is_extension_type:
4612 env.use_utility_code(ExprNodes.type_test_utility_code)
4613 break
4614 else:
4615 entry = env.lookup(target.name)
4616 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4617 continue # already cimported
4618 self.interned_items.append(
4619 (env.intern_identifier(name), target))
4620 target.analyse_target_expression(env, None)
4621 #target.release_target_temp(env) # was release_temp ?!?
4622 self.module.release_temp(env)
4623 self.item.release_temp(env)
4625 def generate_execution_code(self, code):
4626 self.module.generate_evaluation_code(code)
4627 if self.import_star:
4628 code.putln(
4629 'if (%s(%s) < 0) %s;' % (
4630 Naming.import_star,
4631 self.module.py_result(),
4632 code.error_goto(self.pos)))
4633 for cname, target in self.interned_items:
4634 code.putln(
4635 '%s = PyObject_GetAttr(%s, %s); %s' % (
4636 self.item.result(),
4637 self.module.py_result(),
4638 cname,
4639 code.error_goto_if_null(self.item.result(), self.pos)))
4640 code.put_gotref(self.item.py_result())
4641 target.generate_assignment_code(self.item, code)
4642 self.module.generate_disposal_code(code)
4643 self.module.free_temps(code)
4647 #------------------------------------------------------------------------------------
4648 #
4649 # Runtime support code
4650 #
4651 #------------------------------------------------------------------------------------
4653 utility_function_predeclarations = \
4654 """
4655 #ifdef __GNUC__
4656 #define INLINE __inline__
4657 #elif _WIN32
4658 #define INLINE __inline
4659 #else
4660 #define INLINE
4661 #endif
4663 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4665 """ + """
4667 static int %(skip_dispatch_cname)s = 0;
4669 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4671 if Options.gcc_branch_hints:
4672 branch_prediction_macros = \
4673 """
4674 #ifdef __GNUC__
4675 /* Test for GCC > 2.95 */
4676 #if __GNUC__ > 2 || \
4677 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4678 #define likely(x) __builtin_expect(!!(x), 1)
4679 #define unlikely(x) __builtin_expect(!!(x), 0)
4680 #else /* __GNUC__ > 2 ... */
4681 #define likely(x) (x)
4682 #define unlikely(x) (x)
4683 #endif /* __GNUC__ > 2 ... */
4684 #else /* __GNUC__ */
4685 #define likely(x) (x)
4686 #define unlikely(x) (x)
4687 #endif /* __GNUC__ */
4688 """
4689 else:
4690 branch_prediction_macros = \
4691 """
4692 #define likely(x) (x)
4693 #define unlikely(x) (x)
4694 """
4696 #get_name_predeclaration = \
4697 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4699 #get_name_interned_predeclaration = \
4700 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4702 #------------------------------------------------------------------------------------
4704 printing_utility_code = UtilityCode(
4705 proto = """
4706 static int __Pyx_Print(PyObject *, int); /*proto*/
4707 #if PY_MAJOR_VERSION >= 3
4708 static PyObject* %s = 0;
4709 static PyObject* %s = 0;
4710 #endif
4711 """ % (Naming.print_function, Naming.print_function_kwargs),
4712 impl = r"""
4713 #if PY_MAJOR_VERSION < 3
4714 static PyObject *__Pyx_GetStdout(void) {
4715 PyObject *f = PySys_GetObject((char *)"stdout");
4716 if (!f) {
4717 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4718 }
4719 return f;
4720 }
4722 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4723 PyObject *f;
4724 PyObject* v;
4725 int i;
4727 if (!(f = __Pyx_GetStdout()))
4728 return -1;
4729 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4730 if (PyFile_SoftSpace(f, 1)) {
4731 if (PyFile_WriteString(" ", f) < 0)
4732 return -1;
4733 }
4734 v = PyTuple_GET_ITEM(arg_tuple, i);
4735 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4736 return -1;
4737 if (PyString_Check(v)) {
4738 char *s = PyString_AsString(v);
4739 Py_ssize_t len = PyString_Size(v);
4740 if (len > 0 &&
4741 isspace(Py_CHARMASK(s[len-1])) &&
4742 s[len-1] != ' ')
4743 PyFile_SoftSpace(f, 0);
4744 }
4745 }
4746 if (newline) {
4747 if (PyFile_WriteString("\n", f) < 0)
4748 return -1;
4749 PyFile_SoftSpace(f, 0);
4750 }
4751 return 0;
4752 }
4754 #else /* Python 3 has a print function */
4755 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4756 PyObject* kwargs = 0;
4757 PyObject* result = 0;
4758 PyObject* end_string;
4759 if (!%(PRINT_FUNCTION)s) {
4760 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4761 if (!%(PRINT_FUNCTION)s)
4762 return -1;
4763 }
4764 if (!newline) {
4765 if (!%(PRINT_KWARGS)s) {
4766 %(PRINT_KWARGS)s = PyDict_New();
4767 if (!%(PRINT_KWARGS)s)
4768 return -1;
4769 end_string = PyUnicode_FromStringAndSize(" ", 1);
4770 if (!end_string)
4771 return -1;
4772 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4773 Py_DECREF(end_string);
4774 return -1;
4775 }
4776 Py_DECREF(end_string);
4777 }
4778 kwargs = %(PRINT_KWARGS)s;
4779 }
4780 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4781 if (!result)
4782 return -1;
4783 Py_DECREF(result);
4784 return 0;
4785 }
4786 #endif
4787 """ % {'BUILTINS' : Naming.builtins_cname,
4788 'PRINT_FUNCTION' : Naming.print_function,
4789 'PRINT_KWARGS' : Naming.print_function_kwargs}
4790 )
4792 #------------------------------------------------------------------------------------
4794 # The following function is based on do_raise() from ceval.c.
4796 raise_utility_code = UtilityCode(
4797 proto = """
4798 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4799 """,
4800 impl = """
4801 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4802 Py_XINCREF(type);
4803 Py_XINCREF(value);
4804 Py_XINCREF(tb);
4805 /* First, check the traceback argument, replacing None with NULL. */
4806 if (tb == Py_None) {
4807 Py_DECREF(tb);
4808 tb = 0;
4809 }
4810 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4811 PyErr_SetString(PyExc_TypeError,
4812 "raise: arg 3 must be a traceback or None");
4813 goto raise_error;
4814 }
4815 /* Next, replace a missing value with None */
4816 if (value == NULL) {
4817 value = Py_None;
4818 Py_INCREF(value);
4819 }
4820 #if PY_VERSION_HEX < 0x02050000
4821 if (!PyClass_Check(type))
4822 #else
4823 if (!PyType_Check(type))
4824 #endif
4825 {
4826 /* Raising an instance. The value should be a dummy. */
4827 if (value != Py_None) {
4828 PyErr_SetString(PyExc_TypeError,
4829 "instance exception may not have a separate value");
4830 goto raise_error;
4831 }
4832 /* Normalize to raise <class>, <instance> */
4833 Py_DECREF(value);
4834 value = type;
4835 #if PY_VERSION_HEX < 0x02050000
4836 if (PyInstance_Check(type)) {
4837 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4838 Py_INCREF(type);
4839 }
4840 else {
4841 type = 0;
4842 PyErr_SetString(PyExc_TypeError,
4843 "raise: exception must be an old-style class or instance");
4844 goto raise_error;
4845 }
4846 #else
4847 type = (PyObject*) Py_TYPE(type);
4848 Py_INCREF(type);
4849 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4850 PyErr_SetString(PyExc_TypeError,
4851 "raise: exception class must be a subclass of BaseException");
4852 goto raise_error;
4853 }
4854 #endif
4855 }
4856 __Pyx_ErrRestore(type, value, tb);
4857 return;
4858 raise_error:
4859 Py_XDECREF(value);
4860 Py_XDECREF(type);
4861 Py_XDECREF(tb);
4862 return;
4863 }
4864 """)
4866 #------------------------------------------------------------------------------------
4868 reraise_utility_code = UtilityCode(
4869 proto = """
4870 static void __Pyx_ReRaise(void); /*proto*/
4871 """,
4872 impl = """
4873 static void __Pyx_ReRaise(void) {
4874 PyThreadState *tstate = PyThreadState_Get();
4875 PyObject *type = tstate->exc_type;
4876 PyObject *value = tstate->exc_value;
4877 PyObject *tb = tstate->exc_traceback;
4878 Py_XINCREF(type);
4879 Py_XINCREF(value);
4880 Py_XINCREF(tb);
4881 __Pyx_ErrRestore(type, value, tb);
4882 }
4883 """)
4885 #------------------------------------------------------------------------------------
4887 arg_type_test_utility_code = UtilityCode(
4888 proto = """
4889 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4890 const char *name, int exact); /*proto*/
4891 """,
4892 impl = """
4893 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4894 const char *name, int exact)
4895 {
4896 if (!type) {
4897 PyErr_Format(PyExc_SystemError, "Missing type object");
4898 return 0;
4899 }
4900 if (none_allowed && obj == Py_None) return 1;
4901 else if (exact) {
4902 if (Py_TYPE(obj) == type) return 1;
4903 }
4904 else {
4905 if (PyObject_TypeCheck(obj, type)) return 1;
4906 }
4907 PyErr_Format(PyExc_TypeError,
4908 "Argument '%s' has incorrect type (expected %s, got %s)",
4909 name, type->tp_name, Py_TYPE(obj)->tp_name);
4910 return 0;
4911 }
4912 """)
4914 #------------------------------------------------------------------------------------
4915 #
4916 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
4917 # many or too few positional arguments were found. This handles
4918 # Py_ssize_t formatting correctly.
4920 raise_argtuple_invalid_utility_code = UtilityCode(
4921 proto = """
4922 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
4923 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
4924 """,
4925 impl = """
4926 static void __Pyx_RaiseArgtupleInvalid(
4927 const char* func_name,
4928 int exact,
4929 Py_ssize_t num_min,
4930 Py_ssize_t num_max,
4931 Py_ssize_t num_found)
4932 {
4933 Py_ssize_t num_expected;
4934 const char *number, *more_or_less;
4936 if (num_found < num_min) {
4937 num_expected = num_min;
4938 more_or_less = "at least";
4939 } else {
4940 num_expected = num_max;
4941 more_or_less = "at most";
4942 }
4943 if (exact) {
4944 more_or_less = "exactly";
4945 }
4946 number = (num_expected == 1) ? "" : "s";
4947 PyErr_Format(PyExc_TypeError,
4948 #if PY_VERSION_HEX < 0x02050000
4949 "%s() takes %s %d positional argument%s (%d given)",
4950 #else
4951 "%s() takes %s %zd positional argument%s (%zd given)",
4952 #endif
4953 func_name, more_or_less, num_expected, number, num_found);
4954 }
4955 """)
4957 raise_keyword_required_utility_code = UtilityCode(
4958 proto = """
4959 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
4960 """,
4961 impl = """
4962 static INLINE void __Pyx_RaiseKeywordRequired(
4963 const char* func_name,
4964 PyObject* kw_name)
4965 {
4966 PyErr_Format(PyExc_TypeError,
4967 #if PY_MAJOR_VERSION >= 3
4968 "%s() needs keyword-only argument %U", func_name, kw_name);
4969 #else
4970 "%s() needs keyword-only argument %s", func_name,
4971 PyString_AS_STRING(kw_name));
4972 #endif
4973 }
4974 """)
4976 raise_double_keywords_utility_code = UtilityCode(
4977 proto = """
4978 static void __Pyx_RaiseDoubleKeywordsError(
4979 const char* func_name, PyObject* kw_name); /*proto*/
4980 """,
4981 impl = """
4982 static void __Pyx_RaiseDoubleKeywordsError(
4983 const char* func_name,
4984 PyObject* kw_name)
4985 {
4986 PyErr_Format(PyExc_TypeError,
4987 #if PY_MAJOR_VERSION >= 3
4988 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
4989 #else
4990 "%s() got multiple values for keyword argument '%s'", func_name,
4991 PyString_AS_STRING(kw_name));
4992 #endif
4993 }
4994 """)
4996 #------------------------------------------------------------------------------------
4997 #
4998 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
4999 # were passed to a function, or if any keywords were passed to a
5000 # function that does not accept them.
5002 keyword_string_check_utility_code = UtilityCode(
5003 proto = """
5004 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5005 const char* function_name, int kw_allowed); /*proto*/
5006 """,
5007 impl = """
5008 static INLINE int __Pyx_CheckKeywordStrings(
5009 PyObject *kwdict,
5010 const char* function_name,
5011 int kw_allowed)
5012 {
5013 PyObject* key = 0;
5014 Py_ssize_t pos = 0;
5015 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5016 #if PY_MAJOR_VERSION < 3
5017 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5018 #else
5019 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5020 #endif
5021 goto invalid_keyword_type;
5022 }
5023 if ((!kw_allowed) && unlikely(key))
5024 goto invalid_keyword;
5025 return 1;
5026 invalid_keyword_type:
5027 PyErr_Format(PyExc_TypeError,
5028 "%s() keywords must be strings", function_name);
5029 return 0;
5030 invalid_keyword:
5031 PyErr_Format(PyExc_TypeError,
5032 #if PY_MAJOR_VERSION < 3
5033 "%s() got an unexpected keyword argument '%s'",
5034 function_name, PyString_AsString(key));
5035 #else
5036 "%s() got an unexpected keyword argument '%U'",
5037 function_name, key);
5038 #endif
5039 return 0;
5040 }
5041 """)
5043 #------------------------------------------------------------------------------------
5044 #
5045 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5046 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5047 # keywords will raise an invalid keyword error.
5048 #
5049 # Three kinds of errors are checked: 1) non-string keywords, 2)
5050 # unexpected keywords and 3) overlap with positional arguments.
5051 #
5052 # If num_posargs is greater 0, it denotes the number of positional
5053 # arguments that were passed and that must therefore not appear
5054 # amongst the keywords as well.
5055 #
5056 # This method does not check for required keyword arguments.
5057 #
5059 parse_keywords_utility_code = UtilityCode(
5060 proto = """
5061 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5062 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5063 const char* function_name); /*proto*/
5064 """,
5065 impl = """
5066 static int __Pyx_ParseOptionalKeywords(
5067 PyObject *kwds,
5068 PyObject **argnames[],
5069 PyObject *kwds2,
5070 PyObject *values[],
5071 Py_ssize_t num_pos_args,
5072 const char* function_name)
5073 {
5074 PyObject *key = 0, *value = 0;
5075 Py_ssize_t pos = 0;
5076 PyObject*** name;
5077 PyObject*** first_kw_arg = argnames + num_pos_args;
5079 while (PyDict_Next(kwds, &pos, &key, &value)) {
5080 name = first_kw_arg;
5081 while (*name && (**name != key)) name++;
5082 if (*name) {
5083 values[name-argnames] = value;
5084 } else {
5085 #if PY_MAJOR_VERSION < 3
5086 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5087 #else
5088 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5089 #endif
5090 goto invalid_keyword_type;
5091 } else {
5092 for (name = first_kw_arg; *name; name++) {
5093 #if PY_MAJOR_VERSION >= 3
5094 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5095 PyUnicode_Compare(**name, key) == 0) break;
5096 #else
5097 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5098 strcmp(PyString_AS_STRING(**name),
5099 PyString_AS_STRING(key)) == 0) break;
5100 #endif
5101 }
5102 if (*name) {
5103 values[name-argnames] = value;
5104 } else {
5105 /* unexpected keyword found */
5106 for (name=argnames; name != first_kw_arg; name++) {
5107 if (**name == key) goto arg_passed_twice;
5108 #if PY_MAJOR_VERSION >= 3
5109 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5110 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5111 #else
5112 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5113 strcmp(PyString_AS_STRING(**name),
5114 PyString_AS_STRING(key)) == 0) goto arg_passed_twice;
5115 #endif
5116 }
5117 if (kwds2) {
5118 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5119 } else {
5120 goto invalid_keyword;
5121 }
5122 }
5123 }
5124 }
5125 }
5126 return 0;
5127 arg_passed_twice:
5128 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5129 goto bad;
5130 invalid_keyword_type:
5131 PyErr_Format(PyExc_TypeError,
5132 "%s() keywords must be strings", function_name);
5133 goto bad;
5134 invalid_keyword:
5135 PyErr_Format(PyExc_TypeError,
5136 #if PY_MAJOR_VERSION < 3
5137 "%s() got an unexpected keyword argument '%s'",
5138 function_name, PyString_AsString(key));
5139 #else
5140 "%s() got an unexpected keyword argument '%U'",
5141 function_name, key);
5142 #endif
5143 bad:
5144 return -1;
5145 }
5146 """)
5148 #------------------------------------------------------------------------------------
5150 unraisable_exception_utility_code = UtilityCode(
5151 proto = """
5152 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5153 """,
5154 impl = """
5155 static void __Pyx_WriteUnraisable(const char *name) {
5156 PyObject *old_exc, *old_val, *old_tb;
5157 PyObject *ctx;
5158 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5159 #if PY_MAJOR_VERSION < 3
5160 ctx = PyString_FromString(name);
5161 #else
5162 ctx = PyUnicode_FromString(name);
5163 #endif
5164 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5165 if (!ctx) {
5166 PyErr_WriteUnraisable(Py_None);
5167 } else {
5168 PyErr_WriteUnraisable(ctx);
5169 Py_DECREF(ctx);
5170 }
5171 }
5172 """)
5174 #------------------------------------------------------------------------------------
5176 traceback_utility_code = UtilityCode(
5177 proto = """
5178 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5179 """,
5180 impl = """
5181 #include "compile.h"
5182 #include "frameobject.h"
5183 #include "traceback.h"
5185 static void __Pyx_AddTraceback(const char *funcname) {
5186 PyObject *py_srcfile = 0;
5187 PyObject *py_funcname = 0;
5188 PyObject *py_globals = 0;
5189 PyObject *empty_string = 0;
5190 PyCodeObject *py_code = 0;
5191 PyFrameObject *py_frame = 0;
5193 #if PY_MAJOR_VERSION < 3
5194 py_srcfile = PyString_FromString(%(FILENAME)s);
5195 #else
5196 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5197 #endif
5198 if (!py_srcfile) goto bad;
5199 if (%(CLINENO)s) {
5200 #if PY_MAJOR_VERSION < 3
5201 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5202 #else
5203 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5204 #endif
5205 }
5206 else {
5207 #if PY_MAJOR_VERSION < 3
5208 py_funcname = PyString_FromString(funcname);
5209 #else
5210 py_funcname = PyUnicode_FromString(funcname);
5211 #endif
5212 }
5213 if (!py_funcname) goto bad;
5214 py_globals = PyModule_GetDict(%(GLOBALS)s);
5215 if (!py_globals) goto bad;
5216 #if PY_MAJOR_VERSION < 3
5217 empty_string = PyString_FromStringAndSize("", 0);
5218 #else
5219 empty_string = PyBytes_FromStringAndSize("", 0);
5220 #endif
5221 if (!empty_string) goto bad;
5222 py_code = PyCode_New(
5223 0, /*int argcount,*/
5224 #if PY_MAJOR_VERSION >= 3
5225 0, /*int kwonlyargcount,*/
5226 #endif
5227 0, /*int nlocals,*/
5228 0, /*int stacksize,*/
5229 0, /*int flags,*/
5230 empty_string, /*PyObject *code,*/
5231 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5232 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5233 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5234 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5235 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5236 py_srcfile, /*PyObject *filename,*/
5237 py_funcname, /*PyObject *name,*/
5238 %(LINENO)s, /*int firstlineno,*/
5239 empty_string /*PyObject *lnotab*/
5240 );
5241 if (!py_code) goto bad;
5242 py_frame = PyFrame_New(
5243 PyThreadState_GET(), /*PyThreadState *tstate,*/
5244 py_code, /*PyCodeObject *code,*/
5245 py_globals, /*PyObject *globals,*/
5246 0 /*PyObject *locals*/
5247 );
5248 if (!py_frame) goto bad;
5249 py_frame->f_lineno = %(LINENO)s;
5250 PyTraceBack_Here(py_frame);
5251 bad:
5252 Py_XDECREF(py_srcfile);
5253 Py_XDECREF(py_funcname);
5254 Py_XDECREF(empty_string);
5255 Py_XDECREF(py_code);
5256 Py_XDECREF(py_frame);
5257 }
5258 """ % {
5259 'FILENAME': Naming.filename_cname,
5260 'LINENO': Naming.lineno_cname,
5261 'CFILENAME': Naming.cfilenm_cname,
5262 'CLINENO': Naming.clineno_cname,
5263 'GLOBALS': Naming.module_cname,
5264 'EMPTY_TUPLE' : Naming.empty_tuple,
5265 })
5267 restore_exception_utility_code = UtilityCode(
5268 proto = """
5269 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5270 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5271 """,
5272 impl = """
5273 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5274 PyObject *tmp_type, *tmp_value, *tmp_tb;
5275 PyThreadState *tstate = PyThreadState_GET();
5277 tmp_type = tstate->curexc_type;
5278 tmp_value = tstate->curexc_value;
5279 tmp_tb = tstate->curexc_traceback;
5280 tstate->curexc_type = type;
5281 tstate->curexc_value = value;
5282 tstate->curexc_traceback = tb;
5283 Py_XDECREF(tmp_type);
5284 Py_XDECREF(tmp_value);
5285 Py_XDECREF(tmp_tb);
5286 }
5288 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5289 PyThreadState *tstate = PyThreadState_GET();
5290 *type = tstate->curexc_type;
5291 *value = tstate->curexc_value;
5292 *tb = tstate->curexc_traceback;
5294 tstate->curexc_type = 0;
5295 tstate->curexc_value = 0;
5296 tstate->curexc_traceback = 0;
5297 }
5299 """)
5301 #------------------------------------------------------------------------------------
5303 set_vtable_utility_code = UtilityCode(
5304 proto = """
5305 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5306 """,
5307 impl = """
5308 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5309 PyObject *pycobj = 0;
5310 int result;
5312 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5313 if (!pycobj)
5314 goto bad;
5315 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5316 goto bad;
5317 result = 0;
5318 goto done;
5320 bad:
5321 result = -1;
5322 done:
5323 Py_XDECREF(pycobj);
5324 return result;
5325 }
5326 """)
5328 #------------------------------------------------------------------------------------
5330 get_vtable_utility_code = UtilityCode(
5331 proto = """
5332 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5333 """,
5334 impl = r"""
5335 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5336 int result;
5337 PyObject *pycobj;
5339 pycobj = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5340 if (!pycobj)
5341 goto bad;
5342 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5343 if (!*(void **)vtabptr)
5344 goto bad;
5345 result = 0;
5346 goto done;
5348 bad:
5349 result = -1;
5350 done:
5351 Py_XDECREF(pycobj);
5352 return result;
5353 }
5354 """)
5356 #------------------------------------------------------------------------------------
5358 init_string_tab_utility_code = UtilityCode(
5359 proto = """
5360 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5361 """,
5362 impl = """
5363 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5364 while (t->p) {
5365 #if PY_MAJOR_VERSION < 3
5366 if (t->is_unicode && (!t->is_identifier)) {
5367 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5368 } else if (t->intern) {
5369 *t->p = PyString_InternFromString(t->s);
5370 } else {
5371 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5372 }
5373 #else /* Python 3+ has unicode identifiers */
5374 if (t->is_identifier || (t->is_unicode && t->intern)) {
5375 *t->p = PyUnicode_InternFromString(t->s);
5376 } else if (t->is_unicode) {
5377 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5378 } else {
5379 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5380 }
5381 #endif
5382 if (!*t->p)
5383 return -1;
5384 ++t;
5385 }
5386 return 0;
5387 }
5388 """)
5390 #------------------------------------------------------------------------------------
5392 get_exception_utility_code = UtilityCode(
5393 proto = """
5394 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5395 """,
5396 impl = """
5397 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5398 PyObject *tmp_type, *tmp_value, *tmp_tb;
5399 PyThreadState *tstate = PyThreadState_GET();
5400 __Pyx_ErrFetch(type, value, tb);
5401 PyErr_NormalizeException(type, value, tb);
5402 if (PyErr_Occurred())
5403 goto bad;
5404 Py_INCREF(*type);
5405 Py_INCREF(*value);
5406 Py_INCREF(*tb);
5407 tmp_type = tstate->exc_type;
5408 tmp_value = tstate->exc_value;
5409 tmp_tb = tstate->exc_traceback;
5410 tstate->exc_type = *type;
5411 tstate->exc_value = *value;
5412 tstate->exc_traceback = *tb;
5413 /* Make sure tstate is in a consistent state when we XDECREF
5414 these objects (XDECREF may run arbitrary code). */
5415 Py_XDECREF(tmp_type);
5416 Py_XDECREF(tmp_value);
5417 Py_XDECREF(tmp_tb);
5418 return 0;
5419 bad:
5420 Py_XDECREF(*type);
5421 Py_XDECREF(*value);
5422 Py_XDECREF(*tb);
5423 return -1;
5424 }
5426 """)
5428 #------------------------------------------------------------------------------------
5430 reset_exception_utility_code = UtilityCode(
5431 proto = """
5432 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5433 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5434 """,
5435 impl = """
5436 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5437 PyThreadState *tstate = PyThreadState_GET();
5438 *type = tstate->exc_type;
5439 *value = tstate->exc_value;
5440 *tb = tstate->exc_traceback;
5441 Py_XINCREF(*type);
5442 Py_XINCREF(*value);
5443 Py_XINCREF(*tb);
5444 }
5446 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5447 PyObject *tmp_type, *tmp_value, *tmp_tb;
5448 PyThreadState *tstate = PyThreadState_GET();
5449 tmp_type = tstate->exc_type;
5450 tmp_value = tstate->exc_value;
5451 tmp_tb = tstate->exc_traceback;
5452 tstate->exc_type = type;
5453 tstate->exc_value = value;
5454 tstate->exc_traceback = tb;
5455 Py_XDECREF(tmp_type);
5456 Py_XDECREF(tmp_value);
5457 Py_XDECREF(tmp_tb);
5458 }
5459 """)
5461 #------------------------------------------------------------------------------------
