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