Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 2687:76a814a1fc57

Fix bug in handling of environment directives.
author Robert Bradshaw <robertwb@math.washington.edu>
date Sat Nov 21 16:28:04 2009 -0800 (2 years ago)
parents 5a87e3f5706c
children 016f79ac7df1 51e3875b904b
line source
1 #
2 # Pyrex - Parse tree nodes
3 #
5 import sys, os, time, copy
7 try:
8 set
9 except NameError:
10 # Python 2.3
11 from sets import Set as set
13 import Code
14 import Builtin
15 from Errors import error, warning, InternalError
16 import Naming
17 import PyrexTypes
18 import TypeSlots
19 from PyrexTypes import py_object_type, error_type, CFuncType
20 from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
21 StructOrUnionScope, PyClassScope, CClassScope
22 from Cython.Utils import open_new_file, replace_suffix
23 from Code import UtilityCode
24 from StringEncoding import EncodedString, escape_byte_string, split_docstring
25 import Options
26 import ControlFlow
27 import DebugFlags
29 absolute_path_length = 0
31 def relative_position(pos):
32 """
33 We embed the relative filename in the generated C file, since we
34 don't want to have to regnerate and compile all the source code
35 whenever the Python install directory moves (which could happen,
36 e.g,. when distributing binaries.)
38 INPUT:
39 a position tuple -- (absolute filename, line number column position)
41 OUTPUT:
42 relative filename
43 line number
45 AUTHOR: William Stein
46 """
47 global absolute_path_length
48 if absolute_path_length==0:
49 absolute_path_length = len(os.path.abspath(os.getcwd()))
50 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
52 def embed_position(pos, docstring):
53 if not Options.embed_pos_in_docstring:
54 return docstring
55 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
56 if docstring is None:
57 # unicode string
58 return EncodedString(pos_line)
60 # make sure we can encode the filename in the docstring encoding
61 # otherwise make the docstring a unicode string
62 encoding = docstring.encoding
63 if encoding is not None:
64 try:
65 encoded_bytes = pos_line.encode(encoding)
66 except UnicodeEncodeError:
67 encoding = None
69 if not docstring:
70 # reuse the string encoding of the original docstring
71 doc = EncodedString(pos_line)
72 else:
73 doc = EncodedString(pos_line + u'\n' + docstring)
74 doc.encoding = encoding
75 return doc
78 from Code import CCodeWriter
79 from types import FunctionType
81 def write_func_call(func):
82 def f(*args, **kwds):
83 if len(args) > 1 and isinstance(args[1], CCodeWriter):
84 # here we annotate the code with this function call
85 # but only if new code is generated
86 node, code = args[:2]
87 marker = ' /* %s -> %s.%s %s */' % (
88 ' ' * code.call_level,
89 node.__class__.__name__,
90 func.__name__,
91 node.pos[1:])
92 pristine = code.buffer.stream.tell()
93 code.putln(marker)
94 start = code.buffer.stream.tell()
95 code.call_level += 4
96 res = func(*args, **kwds)
97 code.call_level -= 4
98 if start == code.buffer.stream.tell():
99 code.buffer.stream.seek(pristine)
100 else:
101 marker = marker.replace('->', '<-')
102 code.putln(marker)
103 return res
104 else:
105 return func(*args, **kwds)
106 return f
108 class VerboseCodeWriter(type):
109 # Set this as a metaclass to trace function calls in code.
110 # This slows down code generation and makes much larger files.
111 def __new__(cls, name, bases, attrs):
112 attrs = dict(attrs)
113 for mname, m in attrs.items():
114 if isinstance(m, FunctionType):
115 attrs[mname] = write_func_call(m)
116 return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
119 class Node(object):
120 # pos (string, int, int) Source file position
121 # is_name boolean Is a NameNode
122 # is_literal boolean Is a ConstNode
124 if DebugFlags.debug_trace_code_generation:
125 __metaclass__ = VerboseCodeWriter
127 is_name = 0
128 is_literal = 0
129 temps = None
131 # All descandants should set child_attrs to a list of the attributes
132 # containing nodes considered "children" in the tree. Each such attribute
133 # can either contain a single node or a list of nodes. See Visitor.py.
134 child_attrs = None
136 def __init__(self, pos, **kw):
137 self.pos = pos
138 self.__dict__.update(kw)
140 gil_message = "Operation"
142 nogil_check = None
144 def gil_error(self, env=None):
145 error(self.pos, "%s not allowed without gil" % self.gil_message)
147 def clone_node(self):
148 """Clone the node. This is defined as a shallow copy, except for member lists
149 amongst the child attributes (from get_child_accessors) which are also
150 copied. Lists containing child nodes are thus seen as a way for the node
151 to hold multiple children directly; the list is not treated as a seperate
152 level in the tree."""
153 result = copy.copy(self)
154 for attrname in result.child_attrs:
155 value = getattr(result, attrname)
156 if isinstance(value, list):
157 setattr(result, attrname, [x for x in value])
158 return result
161 #
162 # There are 4 phases of parse tree processing, applied in order to
163 # all the statements in a given scope-block:
164 #
165 # (0) analyse_control_flow
166 # Create the control flow tree into which state can be asserted and
167 # queried.
168 #
169 # (1) analyse_declarations
170 # Make symbol table entries for all declarations at the current
171 # level, both explicit (def, cdef, etc.) and implicit (assignment
172 # to an otherwise undeclared name).
173 #
174 # (2) analyse_expressions
175 # Determine the result types of expressions and fill in the
176 # 'type' attribute of each ExprNode. Insert coercion nodes into the
177 # tree where needed to convert to and from Python objects.
178 # Allocate temporary locals for intermediate results. Fill
179 # in the 'result_code' attribute of each ExprNode with a C code
180 # fragment.
181 #
182 # (3) generate_code
183 # Emit C code for all declarations, statements and expressions.
184 # Recursively applies the 3 processing phases to the bodies of
185 # functions.
186 #
188 def analyse_control_flow(self, env):
189 pass
191 def analyse_declarations(self, env):
192 pass
194 def analyse_expressions(self, env):
195 raise InternalError("analyse_expressions not implemented for %s" % \
196 self.__class__.__name__)
198 def generate_code(self, code):
199 raise InternalError("generate_code not implemented for %s" % \
200 self.__class__.__name__)
202 def annotate(self, code):
203 # mro does the wrong thing
204 if isinstance(self, BlockNode):
205 self.body.annotate(code)
207 def end_pos(self):
208 try:
209 return self._end_pos
210 except AttributeError:
211 pos = self.pos
212 if not self.child_attrs:
213 self._end_pos = pos
214 return pos
215 for attr in self.child_attrs:
216 child = getattr(self, attr)
217 # Sometimes lists, sometimes nodes
218 if child is None:
219 pass
220 elif isinstance(child, list):
221 for c in child:
222 pos = max(pos, c.end_pos())
223 else:
224 pos = max(pos, child.end_pos())
225 self._end_pos = pos
226 return pos
228 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
229 if cutoff == 0:
230 return "<...nesting level cutoff...>"
231 if encountered is None:
232 encountered = set()
233 if id(self) in encountered:
234 return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
235 encountered.add(id(self))
237 def dump_child(x, level):
238 if isinstance(x, Node):
239 return x.dump(level, filter_out, cutoff-1, encountered)
240 elif isinstance(x, list):
241 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
242 else:
243 return repr(x)
246 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
247 if len(attrs) == 0:
248 return "<%s (%d)>" % (self.__class__.__name__, id(self))
249 else:
250 indent = " " * level
251 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
252 for key, value in attrs:
253 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
254 res += "%s>" % indent
255 return res
257 class CompilerDirectivesNode(Node):
258 """
259 Sets compiler directives for the children nodes
260 """
261 # directives {string:value} A dictionary holding the right value for
262 # *all* possible directives.
263 # body Node
264 child_attrs = ["body"]
266 def analyse_control_flow(self, env):
267 old = env.directives
268 env.directives = self.directives
269 self.body.analyse_control_flow(env)
270 env.directives = old
272 def analyse_declarations(self, env):
273 old = env.directives
274 env.directives = self.directives
275 self.body.analyse_declarations(env)
276 env.directives = old
278 def analyse_expressions(self, env):
279 old = env.directives
280 env.directives = self.directives
281 self.body.analyse_expressions(env)
282 env.directives = old
284 def generate_function_definitions(self, env, code):
285 env_old = env.directives
286 code_old = code.globalstate.directives
287 code.globalstate.directives = self.directives
288 self.body.generate_function_definitions(env, code)
289 env.directives = env_old
290 code.globalstate.directives = code_old
292 def generate_execution_code(self, code):
293 old = code.globalstate.directives
294 code.globalstate.directives = self.directives
295 self.body.generate_execution_code(code)
296 code.globalstate.directives = old
298 def annotate(self, code):
299 old = code.globalstate.directives
300 code.globalstate.directives = self.directives
301 self.body.annotate(code)
302 code.globalstate.directives = old
304 class BlockNode(object):
305 # Mixin class for nodes representing a declaration block.
307 def generate_cached_builtins_decls(self, env, code):
308 entries = env.global_scope().undeclared_cached_builtins
309 for entry in entries:
310 code.globalstate.add_cached_builtin_decl(entry)
311 del entries[:]
314 class StatListNode(Node):
315 # stats a list of StatNode
317 child_attrs = ["stats"]
319 def create_analysed(pos, env, *args, **kw):
320 node = StatListNode(pos, *args, **kw)
321 return node # No node-specific analysis necesarry
322 create_analysed = staticmethod(create_analysed)
324 def analyse_control_flow(self, env):
325 for stat in self.stats:
326 stat.analyse_control_flow(env)
328 def analyse_declarations(self, env):
329 #print "StatListNode.analyse_declarations" ###
330 for stat in self.stats:
331 stat.analyse_declarations(env)
333 def analyse_expressions(self, env):
334 #print "StatListNode.analyse_expressions" ###
335 for stat in self.stats:
336 stat.analyse_expressions(env)
338 def generate_function_definitions(self, env, code):
339 #print "StatListNode.generate_function_definitions" ###
340 for stat in self.stats:
341 stat.generate_function_definitions(env, code)
343 def generate_execution_code(self, code):
344 #print "StatListNode.generate_execution_code" ###
345 for stat in self.stats:
346 code.mark_pos(stat.pos)
347 stat.generate_execution_code(code)
349 def annotate(self, code):
350 for stat in self.stats:
351 stat.annotate(code)
354 class StatNode(Node):
355 #
356 # Code generation for statements is split into the following subphases:
357 #
358 # (1) generate_function_definitions
359 # Emit C code for the definitions of any structs,
360 # unions, enums and functions defined in the current
361 # scope-block.
362 #
363 # (2) generate_execution_code
364 # Emit C code for executable statements.
365 #
367 def generate_function_definitions(self, env, code):
368 pass
370 def generate_execution_code(self, code):
371 raise InternalError("generate_execution_code not implemented for %s" % \
372 self.__class__.__name__)
375 class CDefExternNode(StatNode):
376 # include_file string or None
377 # body StatNode
379 child_attrs = ["body"]
381 def analyse_declarations(self, env):
382 if self.include_file:
383 env.add_include_file(self.include_file)
384 old_cinclude_flag = env.in_cinclude
385 env.in_cinclude = 1
386 self.body.analyse_declarations(env)
387 env.in_cinclude = old_cinclude_flag
389 def analyse_expressions(self, env):
390 pass
392 def generate_execution_code(self, code):
393 pass
395 def annotate(self, code):
396 self.body.annotate(code)
399 class CDeclaratorNode(Node):
400 # Part of a C declaration.
401 #
402 # Processing during analyse_declarations phase:
403 #
404 # analyse
405 # Returns (name, type) pair where name is the
406 # CNameDeclaratorNode of the name being declared
407 # and type is the type it is being declared as.
408 #
409 # calling_convention string Calling convention of CFuncDeclaratorNode
410 # for which this is a base
412 child_attrs = []
414 calling_convention = ""
417 class CNameDeclaratorNode(CDeclaratorNode):
418 # name string The Pyrex name being declared
419 # cname string or None C name, if specified
420 # default ExprNode or None the value assigned on declaration
422 child_attrs = ['default']
424 default = None
426 def analyse(self, base_type, env, nonempty = 0):
427 if nonempty and self.name == '':
428 # May have mistaken the name for the type.
429 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
430 error(self.pos, "Missing argument name")
431 elif base_type.is_void:
432 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
433 else:
434 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
435 base_type = py_object_type
436 self.type = base_type
437 return self, base_type
439 class CPtrDeclaratorNode(CDeclaratorNode):
440 # base CDeclaratorNode
442 child_attrs = ["base"]
444 def analyse(self, base_type, env, nonempty = 0):
445 if base_type.is_pyobject:
446 error(self.pos,
447 "Pointer base type cannot be a Python object")
448 ptr_type = PyrexTypes.c_ptr_type(base_type)
449 return self.base.analyse(ptr_type, env, nonempty = nonempty)
451 class CArrayDeclaratorNode(CDeclaratorNode):
452 # base CDeclaratorNode
453 # dimension ExprNode
455 child_attrs = ["base", "dimension"]
457 def analyse(self, base_type, env, nonempty = 0):
458 if self.dimension:
459 self.dimension.analyse_const_expression(env)
460 if not self.dimension.type.is_int:
461 error(self.dimension.pos, "Array dimension not integer")
462 size = self.dimension.get_constant_c_result_code()
463 if size is not None:
464 try:
465 size = int(size)
466 except ValueError:
467 # runtime constant?
468 pass
469 else:
470 size = None
471 if not base_type.is_complete():
472 error(self.pos,
473 "Array element type '%s' is incomplete" % base_type)
474 if base_type.is_pyobject:
475 error(self.pos,
476 "Array element cannot be a Python object")
477 if base_type.is_cfunction:
478 error(self.pos,
479 "Array element cannot be a function")
480 array_type = PyrexTypes.c_array_type(base_type, size)
481 return self.base.analyse(array_type, env, nonempty = nonempty)
484 class CFuncDeclaratorNode(CDeclaratorNode):
485 # base CDeclaratorNode
486 # args [CArgDeclNode]
487 # has_varargs boolean
488 # exception_value ConstNode
489 # exception_check boolean True if PyErr_Occurred check needed
490 # nogil boolean Can be called without gil
491 # with_gil boolean Acquire gil around function body
493 child_attrs = ["base", "args", "exception_value"]
495 overridable = 0
496 optional_arg_count = 0
498 def analyse(self, return_type, env, nonempty = 0):
499 if nonempty:
500 nonempty -= 1
501 func_type_args = []
502 for arg_node in self.args:
503 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
504 name = name_declarator.name
505 if name_declarator.cname:
506 error(self.pos,
507 "Function argument cannot have C name specification")
508 # Turn *[] argument into **
509 if type.is_array:
510 type = PyrexTypes.c_ptr_type(type.base_type)
511 # Catch attempted C-style func(void) decl
512 if type.is_void:
513 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
514 func_type_args.append(
515 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
516 if arg_node.default:
517 self.optional_arg_count += 1
518 elif self.optional_arg_count:
519 error(self.pos, "Non-default argument follows default argument")
521 if self.optional_arg_count:
522 scope = StructOrUnionScope()
523 arg_count_member = '%sn' % Naming.pyrex_prefix
524 scope.declare_var(arg_count_member, PyrexTypes.c_int_type, self.pos)
525 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
526 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
527 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
528 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
529 kind = 'struct',
530 scope = scope,
531 typedef_flag = 0,
532 pos = self.pos,
533 cname = struct_cname)
534 self.op_args_struct.defined_in_pxd = 1
535 self.op_args_struct.used = 1
537 exc_val = None
538 exc_check = 0
539 if self.exception_check == '+':
540 env.add_include_file('stdexcept')
541 if return_type.is_pyobject \
542 and (self.exception_value or self.exception_check) \
543 and self.exception_check != '+':
544 error(self.pos,
545 "Exception clause not allowed for function returning Python object")
546 else:
547 if self.exception_value:
548 self.exception_value.analyse_const_expression(env)
549 if self.exception_check == '+':
550 self.exception_value.analyse_types(env)
551 exc_val_type = self.exception_value.type
552 if not exc_val_type.is_error and \
553 not exc_val_type.is_pyobject and \
554 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
555 error(self.exception_value.pos,
556 "Exception value must be a Python exception or cdef function with no arguments.")
557 exc_val = self.exception_value
558 else:
559 if self.exception_value.analyse_const_expression(env):
560 exc_val = self.exception_value.get_constant_c_result_code()
561 if exc_val is None:
562 raise InternalError("get_constant_c_result_code not implemented for %s" %
563 self.exception_value.__class__.__name__)
564 if not return_type.assignable_from(self.exception_value.type):
565 error(self.exception_value.pos,
566 "Exception value incompatible with function return type")
567 exc_check = self.exception_check
568 if return_type.is_array:
569 error(self.pos,
570 "Function cannot return an array")
571 if return_type.is_cfunction:
572 error(self.pos,
573 "Function cannot return a function")
574 func_type = PyrexTypes.CFuncType(
575 return_type, func_type_args, self.has_varargs,
576 optional_arg_count = self.optional_arg_count,
577 exception_value = exc_val, exception_check = exc_check,
578 calling_convention = self.base.calling_convention,
579 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
580 if self.optional_arg_count:
581 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
582 callspec = env.directives['callspec']
583 if callspec:
584 current = func_type.calling_convention
585 if current and current != callspec:
586 error(self.pos, "cannot have both '%s' and '%s' "
587 "calling conventions" % (current, callspec))
588 func_type.calling_convention = callspec
589 return self.base.analyse(func_type, env)
592 class CArgDeclNode(Node):
593 # Item in a function declaration argument list.
594 #
595 # base_type CBaseTypeNode
596 # declarator CDeclaratorNode
597 # not_none boolean Tagged with 'not None'
598 # default ExprNode or None
599 # default_value PyObjectConst constant for default value
600 # is_self_arg boolean Is the "self" arg of an extension type method
601 # is_kw_only boolean Is a keyword-only argument
603 child_attrs = ["base_type", "declarator", "default"]
605 is_self_arg = 0
606 is_generic = 1
607 type = None
608 name_declarator = None
609 default_value = None
611 def analyse(self, env, nonempty = 0):
612 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
613 if self.type is None:
614 # The parser may missinterpret names as types...
615 # We fix that here.
616 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
617 if nonempty:
618 self.declarator.name = self.base_type.name
619 self.base_type.name = None
620 self.base_type.is_basic_c_type = False
621 could_be_name = True
622 else:
623 could_be_name = False
624 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
625 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
626 self.declarator.name = self.base_type.arg_name
627 return self.declarator.analyse(base_type, env, nonempty = nonempty)
628 else:
629 return self.name_declarator, self.type
631 def calculate_default_value_code(self, code):
632 if self.default_value is None:
633 if self.default:
634 if self.default.is_literal:
635 # will not output any code, just assign the result_code
636 self.default.generate_evaluation_code(code)
637 return self.type.cast_code(self.default.result())
638 self.default_value = code.get_argument_default_const(self.type)
639 return self.default_value
641 def annotate(self, code):
642 if self.default:
643 self.default.annotate(code)
646 class CBaseTypeNode(Node):
647 # Abstract base class for C base type nodes.
648 #
649 # Processing during analyse_declarations phase:
650 #
651 # analyse
652 # Returns the type.
654 pass
656 class CAnalysedBaseTypeNode(Node):
657 # type type
659 child_attrs = []
661 def analyse(self, env, could_be_name = False):
662 return self.type
664 class CSimpleBaseTypeNode(CBaseTypeNode):
665 # name string
666 # module_path [string] Qualifying name components
667 # is_basic_c_type boolean
668 # signed boolean
669 # longness integer
670 # complex boolean
671 # is_self_arg boolean Is self argument of C method
673 child_attrs = []
674 arg_name = None # in case the argument name was interpreted as a type
676 def analyse(self, env, could_be_name = False):
677 # Return type descriptor.
678 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
679 type = None
680 if self.is_basic_c_type:
681 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
682 if not type:
683 error(self.pos, "Unrecognised type modifier combination")
684 elif self.name == "object" and not self.module_path:
685 type = py_object_type
686 elif self.name is None:
687 if self.is_self_arg and env.is_c_class_scope:
688 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
689 type = env.parent_type
690 else:
691 type = py_object_type
692 else:
693 if self.module_path:
694 scope = env.find_imported_module(self.module_path, self.pos)
695 else:
696 scope = env
697 if scope:
698 if scope.is_c_class_scope:
699 scope = scope.global_scope()
700 entry = scope.lookup(self.name)
701 if entry and entry.is_type:
702 type = entry.type
703 elif could_be_name:
704 if self.is_self_arg and env.is_c_class_scope:
705 type = env.parent_type
706 else:
707 type = py_object_type
708 self.arg_name = self.name
709 else:
710 error(self.pos, "'%s' is not a type identifier" % self.name)
711 if self.complex:
712 if not type.is_numeric or type.is_complex:
713 error(self.pos, "can only complexify c numeric types")
714 type = PyrexTypes.CComplexType(type)
715 type.create_declaration_utility_code(env)
716 if type:
717 return type
718 else:
719 return PyrexTypes.error_type
721 class CBufferAccessTypeNode(CBaseTypeNode):
722 # After parsing:
723 # positional_args [ExprNode] List of positional arguments
724 # keyword_args DictNode Keyword arguments
725 # base_type_node CBaseTypeNode
727 # After analysis:
728 # type PyrexType.BufferType ...containing the right options
731 child_attrs = ["base_type_node", "positional_args",
732 "keyword_args", "dtype_node"]
734 dtype_node = None
736 name = None
738 def analyse(self, env, could_be_name = False):
739 base_type = self.base_type_node.analyse(env)
740 if base_type.is_error: return base_type
741 import Buffer
743 options = Buffer.analyse_buffer_options(
744 self.pos,
745 env,
746 self.positional_args,
747 self.keyword_args,
748 base_type.buffer_defaults)
750 if sys.version_info[0] < 3:
751 # Py 2.x enforces byte strings as keyword arguments ...
752 options = dict([ (name.encode('ASCII'), value)
753 for name, value in options.iteritems() ])
755 self.type = PyrexTypes.BufferType(base_type, **options)
756 return self.type
758 class CComplexBaseTypeNode(CBaseTypeNode):
759 # base_type CBaseTypeNode
760 # declarator CDeclaratorNode
762 child_attrs = ["base_type", "declarator"]
764 def analyse(self, env, could_be_name = False):
765 base = self.base_type.analyse(env, could_be_name)
766 _, type = self.declarator.analyse(base, env)
767 return type
770 class CVarDefNode(StatNode):
771 # C variable definition or forward/extern function declaration.
772 #
773 # visibility 'private' or 'public' or 'extern'
774 # base_type CBaseTypeNode
775 # declarators [CDeclaratorNode]
776 # in_pxd boolean
777 # api boolean
778 # need_properties [entry]
780 # decorators [cython.locals(...)] or None
781 # directive_locals { string : NameNode } locals defined by cython.locals(...)
783 child_attrs = ["base_type", "declarators"]
784 need_properties = ()
786 decorators = None
787 directive_locals = {}
789 def analyse_declarations(self, env, dest_scope = None):
790 if not dest_scope:
791 dest_scope = env
792 self.dest_scope = dest_scope
793 base_type = self.base_type.analyse(env)
795 # If the field is an external typedef, we cannot be sure about the type,
796 # so do conversion ourself rather than rely on the CPython mechanism (through
797 # a property; made in AnalyseDeclarationsTransform).
798 if (dest_scope.is_c_class_scope
799 and self.visibility == 'public'
800 and base_type.is_pyobject
801 and (base_type.is_builtin_type or base_type.is_extension_type)):
802 self.need_properties = []
803 need_property = True
804 visibility = 'private'
805 else:
806 need_property = False
807 visibility = self.visibility
809 for declarator in self.declarators:
810 name_declarator, type = declarator.analyse(base_type, env)
811 if not type.is_complete():
812 if not (self.visibility == 'extern' and type.is_array):
813 error(declarator.pos,
814 "Variable type '%s' is incomplete" % type)
815 if self.visibility == 'extern' and type.is_pyobject:
816 error(declarator.pos,
817 "Python object cannot be declared extern")
818 name = name_declarator.name
819 cname = name_declarator.cname
820 if name == '':
821 error(declarator.pos, "Missing name in declaration.")
822 return
823 if type.is_cfunction:
824 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
825 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
826 api = self.api)
827 if entry is not None:
828 entry.directive_locals = self.directive_locals
829 else:
830 if self.directive_locals:
831 s.error("Decorators can only be followed by functions")
832 if self.in_pxd and self.visibility != 'extern':
833 error(self.pos,
834 "Only 'extern' C variable declaration allowed in .pxd file")
835 entry = dest_scope.declare_var(name, type, declarator.pos,
836 cname = cname, visibility = visibility, is_cdef = 1)
837 if need_property:
838 self.need_properties.append(entry)
839 entry.needs_property = 1
842 class CStructOrUnionDefNode(StatNode):
843 # name string
844 # cname string or None
845 # kind "struct" or "union"
846 # typedef_flag boolean
847 # visibility "public" or "private"
848 # in_pxd boolean
849 # attributes [CVarDefNode] or None
850 # entry Entry
851 # packed boolean
853 child_attrs = ["attributes"]
855 def analyse_declarations(self, env):
856 scope = None
857 if self.visibility == 'extern' and self.packed:
858 error(self.pos, "Cannot declare extern struct as 'packed'")
859 if self.attributes is not None:
860 scope = StructOrUnionScope(self.name)
861 self.entry = env.declare_struct_or_union(
862 self.name, self.kind, scope, self.typedef_flag, self.pos,
863 self.cname, visibility = self.visibility, packed = self.packed)
864 if self.attributes is not None:
865 if self.in_pxd and not env.in_cinclude:
866 self.entry.defined_in_pxd = 1
867 for attr in self.attributes:
868 attr.analyse_declarations(env, scope)
869 if self.visibility != 'extern':
870 need_typedef_indirection = False
871 for attr in scope.var_entries:
872 type = attr.type
873 while type.is_array:
874 type = type.base_type
875 if type == self.entry.type:
876 error(attr.pos, "Struct cannot contain itself as a member.")
877 if self.typedef_flag:
878 while type.is_ptr:
879 type = type.base_type
880 if type == self.entry.type:
881 need_typedef_indirection = True
882 if need_typedef_indirection:
883 # C can't handle typedef structs that refer to themselves.
884 struct_entry = self.entry
885 self.entry = env.declare_typedef(
886 self.name, struct_entry.type, self.pos,
887 cname = self.cname, visibility='ignore')
888 struct_entry.type.typedef_flag = False
889 # FIXME: this might be considered a hack ;-)
890 struct_entry.cname = struct_entry.type.cname = \
891 '_' + self.entry.type.typedef_cname
893 def analyse_expressions(self, env):
894 pass
896 def generate_execution_code(self, code):
897 pass
900 class CEnumDefNode(StatNode):
901 # name string or None
902 # cname string or None
903 # items [CEnumDefItemNode]
904 # typedef_flag boolean
905 # visibility "public" or "private"
906 # in_pxd boolean
907 # entry Entry
909 child_attrs = ["items"]
911 def analyse_declarations(self, env):
912 self.entry = env.declare_enum(self.name, self.pos,
913 cname = self.cname, typedef_flag = self.typedef_flag,
914 visibility = self.visibility)
915 if self.items is not None:
916 if self.in_pxd and not env.in_cinclude:
917 self.entry.defined_in_pxd = 1
918 for item in self.items:
919 item.analyse_declarations(env, self.entry)
921 def analyse_expressions(self, env):
922 pass
924 def generate_execution_code(self, code):
925 if self.visibility == 'public':
926 temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
927 for item in self.entry.enum_values:
928 code.putln("%s = PyInt_FromLong(%s); %s" % (
929 temp,
930 item.cname,
931 code.error_goto_if_null(temp, item.pos)))
932 code.put_gotref(temp)
933 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
934 Naming.module_cname,
935 item.name,
936 temp,
937 code.error_goto(item.pos)))
938 code.put_decref_clear(temp, PyrexTypes.py_object_type)
939 code.funcstate.release_temp(temp)
942 class CEnumDefItemNode(StatNode):
943 # name string
944 # cname string or None
945 # value ExprNode or None
947 child_attrs = ["value"]
949 def analyse_declarations(self, env, enum_entry):
950 if self.value:
951 self.value.analyse_const_expression(env)
952 if not self.value.type.is_int:
953 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
954 self.value.analyse_const_expression(env)
955 entry = env.declare_const(self.name, enum_entry.type,
956 self.value, self.pos, cname = self.cname,
957 visibility = enum_entry.visibility)
958 enum_entry.enum_values.append(entry)
961 class CTypeDefNode(StatNode):
962 # base_type CBaseTypeNode
963 # declarator CDeclaratorNode
964 # visibility "public" or "private"
965 # in_pxd boolean
967 child_attrs = ["base_type", "declarator"]
969 def analyse_declarations(self, env):
970 base = self.base_type.analyse(env)
971 name_declarator, type = self.declarator.analyse(base, env)
972 name = name_declarator.name
973 cname = name_declarator.cname
974 entry = env.declare_typedef(name, type, self.pos,
975 cname = cname, visibility = self.visibility)
976 if self.in_pxd and not env.in_cinclude:
977 entry.defined_in_pxd = 1
979 def analyse_expressions(self, env):
980 pass
981 def generate_execution_code(self, code):
982 pass
985 class FuncDefNode(StatNode, BlockNode):
986 # Base class for function definition nodes.
987 #
988 # return_type PyrexType
989 # #filename string C name of filename string const
990 # entry Symtab.Entry
991 # needs_closure boolean Whether or not this function has inner functions/classes/yield
992 # directive_locals { string : NameNode } locals defined by cython.locals(...)
994 py_func = None
995 assmt = None
996 needs_closure = False
997 modifiers = []
999 def analyse_default_values(self, env):
1000 genv = env.global_scope()
1001 default_seen = 0
1002 for arg in self.args:
1003 if arg.default:
1004 default_seen = 1
1005 if arg.is_generic:
1006 arg.default.analyse_types(env)
1007 arg.default = arg.default.coerce_to(arg.type, genv)
1008 else:
1009 error(arg.pos,
1010 "This argument cannot have a default value")
1011 arg.default = None
1012 elif arg.kw_only:
1013 default_seen = 1
1014 elif default_seen:
1015 error(arg.pos, "Non-default argument following default argument")
1017 def need_gil_acquisition(self, lenv):
1018 return 0
1020 def create_local_scope(self, env):
1021 genv = env
1022 while genv.is_py_class_scope or genv.is_c_class_scope:
1023 genv = env.outer_scope
1024 if self.needs_closure:
1025 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
1026 else:
1027 lenv = LocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
1028 lenv.return_type = self.return_type
1029 type = self.entry.type
1030 if type.is_cfunction:
1031 lenv.nogil = type.nogil and not type.with_gil
1032 self.local_scope = lenv
1033 lenv.directives = env.directives
1034 return lenv
1036 def generate_function_definitions(self, env, code):
1037 import Buffer
1039 lenv = self.local_scope
1041 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1042 self.entry.scope.is_c_class_scope)
1044 profile = code.globalstate.directives['profile']
1045 if profile:
1046 if lenv.nogil:
1047 error(self.pos, "Cannot profile nogil function.")
1048 code.globalstate.use_utility_code(profile_utility_code)
1050 # Generate C code for header and body of function
1051 code.enter_cfunc_scope()
1052 code.return_from_error_cleanup_label = code.new_label()
1054 # ----- Top-level constants used by this function
1055 code.mark_pos(self.pos)
1056 self.generate_cached_builtins_decls(lenv, code)
1057 # ----- Function header
1058 code.putln("")
1059 if self.py_func:
1060 self.py_func.generate_function_header(code,
1061 with_pymethdef = env.is_py_class_scope,
1062 proto_only=True)
1063 self.generate_function_header(code,
1064 with_pymethdef = env.is_py_class_scope)
1065 # ----- Local variable declarations
1066 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
1067 self.generate_argument_declarations(lenv, code)
1068 if self.needs_closure:
1069 code.putln("/* TODO: declare and create scope object */")
1070 code.put_var_declarations(lenv.var_entries)
1071 init = ""
1072 if not self.return_type.is_void:
1073 if self.return_type.is_pyobject:
1074 init = " = NULL"
1075 code.putln(
1076 "%s%s;" %
1077 (self.return_type.declaration_code(
1078 Naming.retval_cname),
1079 init))
1080 tempvardecl_code = code.insertion_point()
1081 self.generate_keyword_list(code)
1082 # ----- Extern library function declarations
1083 lenv.generate_library_function_declarations(code)
1084 # ----- GIL acquisition
1085 acquire_gil = self.acquire_gil
1086 if acquire_gil:
1087 env.use_utility_code(force_init_threads_utility_code)
1088 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1089 # ----- Automatic lead-ins for certain special functions
1090 if not lenv.nogil:
1091 code.put_setup_refcount_context(self.entry.name)
1092 if profile:
1093 code.put_trace_call(self.entry.name, self.pos)
1094 if is_getbuffer_slot:
1095 self.getbuffer_init(code)
1096 # ----- Fetch arguments
1097 self.generate_argument_parsing_code(env, code)
1098 # If an argument is assigned to in the body, we must
1099 # incref it to properly keep track of refcounts.
1100 for entry in lenv.arg_entries:
1101 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1102 code.put_var_incref(entry)
1103 # ----- Initialise local variables
1104 for entry in lenv.var_entries:
1105 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1106 code.put_init_var_to_py_none(entry)
1107 # ----- Initialise local buffer auxiliary variables
1108 for entry in lenv.var_entries + lenv.arg_entries:
1109 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1110 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1111 # ----- Check and convert arguments
1112 self.generate_argument_type_tests(code)
1113 # ----- Acquire buffer arguments
1114 for entry in lenv.arg_entries:
1115 if entry.type.is_buffer:
1116 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1117 # ----- Function body
1118 self.body.generate_execution_code(code)
1119 # ----- Default return value
1120 code.putln("")
1121 if self.return_type.is_pyobject:
1122 #if self.return_type.is_extension_type:
1123 # lhs = "(PyObject *)%s" % Naming.retval_cname
1124 #else:
1125 lhs = Naming.retval_cname
1126 code.put_init_to_py_none(lhs, self.return_type)
1127 else:
1128 val = self.return_type.default_value
1129 if val:
1130 code.putln("%s = %s;" % (Naming.retval_cname, val))
1131 # ----- Error cleanup
1132 if code.error_label in code.labels_used:
1133 code.put_goto(code.return_label)
1134 code.put_label(code.error_label)
1135 for cname, type in code.funcstate.all_managed_temps():
1136 code.put_xdecref(cname, type)
1138 # Clean up buffers -- this calls a Python function
1139 # so need to save and restore error state
1140 buffers_present = len(lenv.buffer_entries) > 0
1141 if buffers_present:
1142 code.globalstate.use_utility_code(restore_exception_utility_code)
1143 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1144 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1145 for entry in lenv.buffer_entries:
1146 Buffer.put_release_buffer_code(code, entry)
1147 #code.putln("%s = 0;" % entry.cname)
1148 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1150 err_val = self.error_value()
1151 exc_check = self.caller_will_check_exceptions()
1152 if err_val is not None or exc_check:
1153 # TODO: Fix exception tracing (though currently unused by cProfile).
1154 # code.globalstate.use_utility_code(get_exception_tuple_utility_code)
1155 # code.put_trace_exception()
1156 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1157 else:
1158 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1159 % self.entry.qualified_name, 0)
1160 code.putln(
1161 '__Pyx_WriteUnraisable("%s");' %
1162 self.entry.qualified_name)
1163 env.use_utility_code(unraisable_exception_utility_code)
1164 env.use_utility_code(restore_exception_utility_code)
1165 default_retval = self.return_type.default_value
1166 if err_val is None and default_retval:
1167 err_val = default_retval
1168 if err_val is not None:
1169 code.putln(
1170 "%s = %s;" % (
1171 Naming.retval_cname,
1172 err_val))
1174 if is_getbuffer_slot:
1175 self.getbuffer_error_cleanup(code)
1177 # If we are using the non-error cleanup section we should
1178 # jump past it if we have an error. The if-test below determine
1179 # whether this section is used.
1180 if buffers_present or is_getbuffer_slot:
1181 code.put_goto(code.return_from_error_cleanup_label)
1184 # ----- Non-error return cleanup
1185 code.put_label(code.return_label)
1186 for entry in lenv.buffer_entries:
1187 if entry.used:
1188 Buffer.put_release_buffer_code(code, entry)
1189 if is_getbuffer_slot:
1190 self.getbuffer_normal_cleanup(code)
1191 # ----- Return cleanup for both error and no-error return
1192 code.put_label(code.return_from_error_cleanup_label)
1193 if not Options.init_local_none:
1194 for entry in lenv.var_entries:
1195 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1196 entry.xdecref_cleanup = 1
1197 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1198 # Decref any increfed args
1199 for entry in lenv.arg_entries:
1200 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1201 code.put_var_decref(entry)
1203 # code.putln("/* TODO: decref scope object */")
1204 # ----- Return
1205 # This code is duplicated in ModuleNode.generate_module_init_func
1206 if not lenv.nogil:
1207 default_retval = self.return_type.default_value
1208 err_val = self.error_value()
1209 if err_val is None and default_retval:
1210 err_val = default_retval
1211 if self.return_type.is_pyobject:
1212 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1214 if self.entry.is_special and self.entry.name == "__hash__":
1215 # Returning -1 for __hash__ is supposed to signal an error
1216 # We do as Python instances and coerce -1 into -2.
1217 code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (
1218 Naming.retval_cname, Naming.retval_cname))
1220 if profile:
1221 if self.return_type.is_pyobject:
1222 code.put_trace_return(Naming.retval_cname)
1223 else:
1224 code.put_trace_return("Py_None")
1225 if not lenv.nogil:
1226 code.put_finish_refcount_context()
1228 if acquire_gil:
1229 code.putln("PyGILState_Release(_save);")
1231 if not self.return_type.is_void:
1232 code.putln("return %s;" % Naming.retval_cname)
1234 code.putln("}")
1235 # ----- Go back and insert temp variable declarations
1236 tempvardecl_code.put_temp_declarations(code.funcstate)
1237 # ----- Python version
1238 code.exit_cfunc_scope()
1239 if self.py_func:
1240 self.py_func.generate_function_definitions(env, code)
1241 self.generate_wrapper_functions(code)
1243 def declare_argument(self, env, arg):
1244 if arg.type.is_void:
1245 error(arg.pos, "Invalid use of 'void'")
1246 elif not arg.type.is_complete() and not arg.type.is_array:
1247 error(arg.pos,
1248 "Argument type '%s' is incomplete" % arg.type)
1249 return env.declare_arg(arg.name, arg.type, arg.pos)
1251 def generate_wrapper_functions(self, code):
1252 pass
1254 def generate_execution_code(self, code):
1255 # Evaluate and store argument default values
1256 for arg in self.args:
1257 default = arg.default
1258 if default:
1259 if not default.is_literal:
1260 default.generate_evaluation_code(code)
1261 default.make_owned_reference(code)
1262 result = default.result_as(arg.type)
1263 code.putln(
1264 "%s = %s;" % (
1265 arg.calculate_default_value_code(code),
1266 result))
1267 if arg.type.is_pyobject:
1268 code.put_giveref(default.result())
1269 default.generate_post_assignment_code(code)
1270 default.free_temps(code)
1271 # For Python class methods, create and store function object
1272 if self.assmt:
1273 self.assmt.generate_execution_code(code)
1276 # Special code for the __getbuffer__ function
1278 def getbuffer_init(self, code):
1279 info = self.local_scope.arg_entries[1].cname
1280 # Python 3.0 betas have a bug in memoryview which makes it call
1281 # getbuffer with a NULL parameter. For now we work around this;
1282 # the following line should be removed when this bug is fixed.
1283 code.putln("if (%s == NULL) return 0;" % info)
1284 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1285 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1287 def getbuffer_error_cleanup(self, code):
1288 info = self.local_scope.arg_entries[1].cname
1289 code.put_gotref("%s->obj" % info)
1290 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1291 (info, info))
1293 def getbuffer_normal_cleanup(self, code):
1294 info = self.local_scope.arg_entries[1].cname
1295 code.putln("if (%s->obj == Py_None) {" % info)
1296 code.put_gotref("Py_None")
1297 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1298 code.putln("}")
1300 class CFuncDefNode(FuncDefNode):
1301 # C function definition.
1303 # modifiers ['inline']
1304 # visibility 'private' or 'public' or 'extern'
1305 # base_type CBaseTypeNode
1306 # declarator CDeclaratorNode
1307 # body StatListNode
1308 # api boolean
1309 # decorators [DecoratorNode] list of decorators
1311 # with_gil boolean Acquire GIL around body
1312 # type CFuncType
1313 # py_func wrapper for calling from Python
1314 # overridable whether or not this is a cpdef function
1315 # inline_in_pxd whether this is an inline function in a pxd file
1317 child_attrs = ["base_type", "declarator", "body", "py_func"]
1319 inline_in_pxd = False
1320 decorators = None
1321 directive_locals = {}
1323 def unqualified_name(self):
1324 return self.entry.name
1326 def analyse_declarations(self, env):
1327 self.directive_locals.update(env.directives['locals'])
1328 base_type = self.base_type.analyse(env)
1329 # The 2 here is because we need both function and argument names.
1330 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1331 if not type.is_cfunction:
1332 error(self.pos,
1333 "Suite attached to non-function declaration")
1334 # Remember the actual type according to the function header
1335 # written here, because the type in the symbol table entry
1336 # may be different if we're overriding a C method inherited
1337 # from the base type of an extension type.
1338 self.type = type
1339 type.is_overridable = self.overridable
1340 declarator = self.declarator
1341 while not hasattr(declarator, 'args'):
1342 declarator = declarator.base
1343 self.args = declarator.args
1344 for formal_arg, type_arg in zip(self.args, type.args):
1345 formal_arg.type = type_arg.type
1346 formal_arg.name = type_arg.name
1347 formal_arg.cname = type_arg.cname
1348 name = name_declarator.name
1349 cname = name_declarator.cname
1350 self.entry = env.declare_cfunction(
1351 name, type, self.pos,
1352 cname = cname, visibility = self.visibility,
1353 defining = self.body is not None,
1354 api = self.api, modifiers = self.modifiers)
1355 self.entry.inline_func_in_pxd = self.inline_in_pxd
1356 self.return_type = type.return_type
1358 if self.overridable and not env.is_module_scope:
1359 if len(self.args) < 1 or not self.args[0].type.is_pyobject:
1360 # An error will be produced in the cdef function
1361 self.overridable = False
1363 if self.overridable:
1364 import ExprNodes
1365 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1366 self.py_func = DefNode(pos = self.pos,
1367 name = self.entry.name,
1368 args = self.args,
1369 star_arg = None,
1370 starstar_arg = None,
1371 doc = self.doc,
1372 body = py_func_body,
1373 is_wrapper = 1)
1374 self.py_func.is_module_scope = env.is_module_scope
1375 self.py_func.analyse_declarations(env)
1376 self.entry.as_variable = self.py_func.entry
1377 # Reset scope entry the above cfunction
1378 env.entries[name] = self.entry
1379 if not env.is_module_scope or Options.lookup_module_cpdef:
1380 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1381 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1382 self.create_local_scope(env)
1384 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1385 import ExprNodes
1386 args = self.type.args
1387 if omit_optional_args:
1388 args = args[:len(args) - self.type.optional_arg_count]
1389 arg_names = [arg.name for arg in args]
1390 if is_module_scope:
1391 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1392 else:
1393 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1394 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1395 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1396 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)
1397 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1399 def declare_arguments(self, env):
1400 for arg in self.type.args:
1401 if not arg.name:
1402 error(arg.pos, "Missing argument name")
1403 self.declare_argument(env, arg)
1405 def need_gil_acquisition(self, lenv):
1406 return self.type.with_gil
1408 def nogil_check(self, env):
1409 type = self.type
1410 with_gil = type.with_gil
1411 if type.nogil and not with_gil:
1412 if type.return_type.is_pyobject:
1413 error(self.pos,
1414 "Function with Python return type cannot be declared nogil")
1415 for entry in self.local_scope.var_entries:
1416 if entry.type.is_pyobject:
1417 error(self.pos, "Function declared nogil has Python locals or temporaries")
1419 def analyse_expressions(self, env):
1420 self.local_scope.directives = env.directives
1421 if self.py_func is not None:
1422 # this will also analyse the default values
1423 self.py_func.analyse_expressions(env)
1424 else:
1425 self.analyse_default_values(env)
1426 self.acquire_gil = self.need_gil_acquisition(self.local_scope)
1428 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1429 arg_decls = []
1430 type = self.type
1431 visibility = self.entry.visibility
1432 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1433 arg_decls.append(arg.declaration_code())
1434 if with_dispatch and self.overridable:
1435 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1436 if type.optional_arg_count and with_opt_args:
1437 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1438 if type.has_varargs:
1439 arg_decls.append("...")
1440 if not arg_decls:
1441 arg_decls = ["void"]
1442 if cname is None:
1443 cname = self.entry.func_cname
1444 entity = type.function_header_code(cname, ', '.join(arg_decls))
1445 if visibility == 'public':
1446 dll_linkage = "DL_EXPORT"
1447 else:
1448 dll_linkage = None
1449 header = self.return_type.declaration_code(entity,
1450 dll_linkage = dll_linkage)
1451 if visibility == 'extern':
1452 storage_class = "%s " % Naming.extern_c_macro
1453 elif visibility == 'public':
1454 storage_class = ""
1455 else:
1456 storage_class = "static "
1457 code.putln("%s%s %s {" % (
1458 storage_class,
1459 ' '.join(self.modifiers).upper(), # macro forms
1460 header))
1462 def generate_argument_declarations(self, env, code):
1463 for arg in self.args:
1464 if arg.default:
1465 result = arg.calculate_default_value_code(code)
1466 code.putln('%s = %s;' % (
1467 arg.type.declaration_code(arg.cname), result))
1469 def generate_keyword_list(self, code):
1470 pass
1472 def generate_argument_parsing_code(self, env, code):
1473 i = 0
1474 if self.type.optional_arg_count:
1475 code.putln('if (%s) {' % Naming.optional_args_cname)
1476 for arg in self.args:
1477 if arg.default:
1478 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1479 declarator = arg.declarator
1480 while not hasattr(declarator, 'name'):
1481 declarator = declarator.base
1482 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, self.type.opt_arg_cname(declarator.name)))
1483 i += 1
1484 for _ in range(self.type.optional_arg_count):
1485 code.putln('}')
1486 code.putln('}')
1488 def generate_argument_conversion_code(self, code):
1489 pass
1491 def generate_argument_type_tests(self, code):
1492 # Generate type tests for args whose type in a parent
1493 # class is a supertype of the declared type.
1494 for arg in self.type.args:
1495 if arg.needs_type_test:
1496 self.generate_arg_type_test(arg, code)
1498 def generate_arg_type_test(self, arg, code):
1499 # Generate type test for one argument.
1500 if arg.type.typeobj_is_available():
1501 typeptr_cname = arg.type.typeptr_cname
1502 arg_code = "((PyObject *)%s)" % arg.cname
1503 code.putln(
1504 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1505 arg_code,
1506 typeptr_cname,
1507 not arg.not_none,
1508 arg.name,
1509 type.is_builtin_type,
1510 code.error_goto(arg.pos)))
1511 else:
1512 error(arg.pos, "Cannot test type of extern C class "
1513 "without type object name specification")
1515 def error_value(self):
1516 if self.return_type.is_pyobject:
1517 return "0"
1518 else:
1519 #return None
1520 return self.entry.type.exception_value
1522 def caller_will_check_exceptions(self):
1523 return self.entry.type.exception_check
1525 def generate_wrapper_functions(self, code):
1526 # If the C signature of a function has changed, we need to generate
1527 # wrappers to put in the slots here.
1528 k = 0
1529 entry = self.entry
1530 func_type = entry.type
1531 while entry.prev_entry is not None:
1532 k += 1
1533 entry = entry.prev_entry
1534 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1535 code.putln()
1536 self.generate_function_header(code,
1537 0,
1538 with_dispatch = entry.type.is_overridable,
1539 with_opt_args = entry.type.optional_arg_count,
1540 cname = entry.func_cname)
1541 if not self.return_type.is_void:
1542 code.put('return ')
1543 args = self.type.args
1544 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1545 if entry.type.is_overridable:
1546 arglist.append(Naming.skip_dispatch_cname)
1547 elif func_type.is_overridable:
1548 arglist.append('0')
1549 if entry.type.optional_arg_count:
1550 arglist.append(Naming.optional_args_cname)
1551 elif func_type.optional_arg_count:
1552 arglist.append('NULL')
1553 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1554 code.putln('}')
1557 class PyArgDeclNode(Node):
1558 # Argument which must be a Python object (used
1559 # for * and ** arguments).
1561 # name string
1562 # entry Symtab.Entry
1563 child_attrs = []
1566 class DecoratorNode(Node):
1567 # A decorator
1569 # decorator NameNode or CallNode
1570 child_attrs = ['decorator']
1573 class DefNode(FuncDefNode):
1574 # A Python function definition.
1576 # name string the Python name of the function
1577 # decorators [DecoratorNode] list of decorators
1578 # args [CArgDeclNode] formal arguments
1579 # star_arg PyArgDeclNode or None * argument
1580 # starstar_arg PyArgDeclNode or None ** argument
1581 # doc EncodedString or None
1582 # body StatListNode
1584 # The following subnode is constructed internally
1585 # when the def statement is inside a Python class definition.
1587 # assmt AssignmentNode Function construction/assignment
1589 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1591 assmt = None
1592 num_kwonly_args = 0
1593 num_required_kw_args = 0
1594 reqd_kw_flags_cname = "0"
1595 is_wrapper = 0
1596 decorators = None
1597 entry = None
1598 acquire_gil = 0
1601 def __init__(self, pos, **kwds):
1602 FuncDefNode.__init__(self, pos, **kwds)
1603 k = rk = r = 0
1604 for arg in self.args:
1605 if arg.kw_only:
1606 k += 1
1607 if not arg.default:
1608 rk += 1
1609 if not arg.default:
1610 r += 1
1611 self.num_kwonly_args = k
1612 self.num_required_kw_args = rk
1613 self.num_required_args = r
1615 def as_cfunction(self, cfunc=None, scope=None):
1616 if self.star_arg:
1617 error(self.star_arg.pos, "cdef function cannot have star argument")
1618 if self.starstar_arg:
1619 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1620 if cfunc is None:
1621 cfunc_args = []
1622 for formal_arg in self.args:
1623 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1624 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1625 cname = None,
1626 type = py_object_type,
1627 pos = formal_arg.pos))
1628 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1629 args = cfunc_args,
1630 has_varargs = False,
1631 exception_value = None,
1632 exception_check = False,
1633 nogil = False,
1634 with_gil = False,
1635 is_overridable = True)
1636 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1637 else:
1638 cfunc_type = cfunc.type
1639 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1640 error(self.pos, "wrong number of arguments")
1641 error(declarator.pos, "previous declaration here")
1642 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1643 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1644 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1645 formal_arg.type = type_arg.type
1646 formal_arg.name_declarator = name_declarator
1647 import ExprNodes
1648 if cfunc_type.exception_value is None:
1649 exception_value = None
1650 else:
1651 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1652 declarator = CFuncDeclaratorNode(self.pos,
1653 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1654 args = self.args,
1655 has_varargs = False,
1656 exception_check = cfunc_type.exception_check,
1657 exception_value = exception_value,
1658 with_gil = cfunc_type.with_gil,
1659 nogil = cfunc_type.nogil)
1660 return CFuncDefNode(self.pos,
1661 modifiers = [],
1662 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1663 declarator = declarator,
1664 body = self.body,
1665 doc = self.doc,
1666 overridable = cfunc_type.is_overridable,
1667 type = cfunc_type,
1668 with_gil = cfunc_type.with_gil,
1669 nogil = cfunc_type.nogil,
1670 visibility = 'private',
1671 api = False,
1672 directive_locals = getattr(cfunc, 'directive_locals', {}))
1674 def analyse_declarations(self, env):
1675 directive_locals = self.directive_locals = env.directives['locals']
1676 for arg in self.args:
1677 if hasattr(arg, 'name'):
1678 type = arg.type
1679 name_declarator = None
1680 else:
1681 base_type = arg.base_type.analyse(env)
1682 name_declarator, type = \
1683 arg.declarator.analyse(base_type, env)
1684 arg.name = name_declarator.name
1685 if arg.name in directive_locals:
1686 type_node = directive_locals[arg.name]
1687 other_type = type_node.analyse_as_type(env)
1688 if other_type is None:
1689 error(type_node.pos, "Not a type")
1690 elif (type is not PyrexTypes.py_object_type
1691 and not type.same_as(other_type)):
1692 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1693 error(type_node.pos, "Previous declaration here")
1694 else:
1695 type = other_type
1696 if name_declarator and name_declarator.cname:
1697 error(self.pos,
1698 "Python function argument cannot have C name specification")
1699 arg.type = type.as_argument_type()
1700 arg.hdr_type = None
1701 arg.needs_conversion = 0
1702 arg.needs_type_test = 0
1703 arg.is_generic = 1
1704 if arg.not_none and not arg.type.is_extension_type:
1705 error(self.pos,
1706 "Only extension type arguments can have 'not None'")
1707 self.declare_pyfunction(env)
1708 self.analyse_signature(env)
1709 self.return_type = self.entry.signature.return_type()
1710 self.create_local_scope(env)
1712 def analyse_signature(self, env):
1713 any_type_tests_needed = 0
1714 if self.entry.is_special:
1715 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1716 elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
1717 # Use the simpler calling signature for zero- and one-argument functions.
1718 if self.entry.signature is TypeSlots.pyfunction_signature:
1719 if len(self.args) == 0:
1720 self.entry.signature = TypeSlots.pyfunction_noargs
1721 elif len(self.args) == 1:
1722 if self.args[0].default is None and not self.args[0].kw_only:
1723 self.entry.signature = TypeSlots.pyfunction_onearg
1724 elif self.entry.signature is TypeSlots.pymethod_signature:
1725 if len(self.args) == 1:
1726 self.entry.signature = TypeSlots.unaryfunc
1727 elif len(self.args) == 2:
1728 if self.args[1].default is None and not self.args[1].kw_only:
1729 self.entry.signature = TypeSlots.ibinaryfunc
1730 sig = self.entry.signature
1731 nfixed = sig.num_fixed_args()
1732 for i in range(nfixed):
1733 if i < len(self.args):
1734 arg = self.args[i]
1735 arg.is_generic = 0
1736 if sig.is_self_arg(i):
1737 arg.is_self_arg = 1
1738 arg.hdr_type = arg.type = env.parent_type
1739 arg.needs_conversion = 0
1740 else:
1741 arg.hdr_type = sig.fixed_arg_type(i)
1742 if not arg.type.same_as(arg.hdr_type):
1743 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1744 arg.needs_type_test = 1
1745 any_type_tests_needed = 1
1746 else:
1747 arg.needs_conversion = 1
1748 if arg.needs_conversion:
1749 arg.hdr_cname = Naming.arg_prefix + arg.name
1750 else:
1751 arg.hdr_cname = Naming.var_prefix + arg.name
1752 else:
1753 self.bad_signature()
1754 return
1755 if nfixed < len(self.args):
1756 if not sig.has_generic_args:
1757 self.bad_signature()
1758 for arg in self.args:
1759 if arg.is_generic and \
1760 (arg.type.is_extension_type or arg.type.is_builtin_type):
1761 arg.needs_type_test = 1
1762 any_type_tests_needed = 1
1763 if any_type_tests_needed:
1764 env.use_utility_code(arg_type_test_utility_code)
1766 def bad_signature(self):
1767 sig = self.entry.signature
1768 expected_str = "%d" % sig.num_fixed_args()
1769 if sig.has_generic_args:
1770 expected_str = expected_str + " or more"
1771 name = self.name
1772 if name.startswith("__") and name.endswith("__"):
1773 desc = "Special method"
1774 else:
1775 desc = "Method"
1776 error(self.pos,
1777 "%s %s has wrong number of arguments "
1778 "(%d declared, %s expected)" % (
1779 desc, self.name, len(self.args), expected_str))
1781 def signature_has_nongeneric_args(self):
1782 argcount = len(self.args)
1783 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1784 return 0
1785 return 1
1787 def signature_has_generic_args(self):
1788 return self.entry.signature.has_generic_args
1790 def declare_pyfunction(self, env):
1791 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1792 name = self.name
1793 entry = env.lookup_here(self.name)
1794 if entry and entry.type.is_cfunction and not self.is_wrapper:
1795 warning(self.pos, "Overriding cdef method with def method.", 5)
1796 entry = env.declare_pyfunction(self.name, self.pos)
1797 self.entry = entry
1798 prefix = env.scope_prefix
1799 entry.func_cname = \
1800 Naming.pyfunc_prefix + prefix + name
1801 entry.pymethdef_cname = \
1802 Naming.pymethdef_prefix + prefix + name
1803 if Options.docstrings:
1804 entry.doc = embed_position(self.pos, self.doc)
1805 entry.doc_cname = \
1806 Naming.funcdoc_prefix + prefix + name
1807 else:
1808 entry.doc = None
1810 def declare_arguments(self, env):
1811 for arg in self.args:
1812 if not arg.name:
1813 error(arg.pos, "Missing argument name")
1814 if arg.needs_conversion:
1815 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1816 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1817 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1818 if arg.type.is_pyobject:
1819 arg.entry.init = "0"
1820 arg.entry.init_to_none = 0
1821 else:
1822 arg.entry = self.declare_argument(env, arg)
1823 arg.entry.used = 1
1824 arg.entry.is_self_arg = arg.is_self_arg
1825 if arg.hdr_type:
1826 if arg.is_self_arg or \
1827 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1828 arg.entry.is_declared_generic = 1
1829 self.declare_python_arg(env, self.star_arg)
1830 self.declare_python_arg(env, self.starstar_arg)
1832 def declare_python_arg(self, env, arg):
1833 if arg:
1834 entry = env.declare_var(arg.name,
1835 PyrexTypes.py_object_type, arg.pos)
1836 entry.used = 1
1837 entry.init = "0"
1838 entry.init_to_none = 0
1839 entry.xdecref_cleanup = 1
1840 arg.entry = entry
1841 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1843 def analyse_expressions(self, env):
1844 self.local_scope.directives = env.directives
1845 self.analyse_default_values(env)
1846 if env.is_py_class_scope:
1847 self.synthesize_assignment_node(env)
1849 def synthesize_assignment_node(self, env):
1850 import ExprNodes
1851 self.assmt = SingleAssignmentNode(self.pos,
1852 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1853 rhs = ExprNodes.UnboundMethodNode(self.pos,
1854 function = ExprNodes.PyCFunctionNode(self.pos,
1855 pymethdef_cname = self.entry.pymethdef_cname)))
1856 self.assmt.analyse_declarations(env)
1857 self.assmt.analyse_expressions(env)
1859 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1860 arg_code_list = []
1861 sig = self.entry.signature
1862 if sig.has_dummy_arg:
1863 arg_code_list.append(
1864 "PyObject *%s" % Naming.self_cname)
1865 for arg in self.args:
1866 if not arg.is_generic:
1867 if arg.is_self_arg:
1868 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1869 else:
1870 arg_code_list.append(
1871 arg.hdr_type.declaration_code(arg.hdr_cname))
1872 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1873 arg_code_list.append("PyObject *unused")
1874 if sig.has_generic_args:
1875 arg_code_list.append(
1876 "PyObject *%s, PyObject *%s"
1877 % (Naming.args_cname, Naming.kwds_cname))
1878 arg_code = ", ".join(arg_code_list)
1879 dc = self.return_type.declaration_code(self.entry.func_cname)
1880 header = "static %s(%s)" % (dc, arg_code)
1881 code.putln("%s; /*proto*/" % header)
1882 if proto_only:
1883 return
1884 if self.entry.doc and Options.docstrings:
1885 docstr = self.entry.doc
1886 if docstr.is_unicode:
1887 docstr = docstr.utf8encode()
1888 code.putln(
1889 'static char %s[] = "%s";' % (
1890 self.entry.doc_cname,
1891 split_docstring(escape_byte_string(docstr))))
1892 if with_pymethdef:
1893 code.put(
1894 "static PyMethodDef %s = " %
1895 self.entry.pymethdef_cname)
1896 code.put_pymethoddef(self.entry, ";")
1897 code.putln("%s {" % header)
1899 def generate_argument_declarations(self, env, code):
1900 for arg in self.args:
1901 if arg.is_generic: # or arg.needs_conversion:
1902 if arg.needs_conversion:
1903 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1904 else:
1905 code.put_var_declaration(arg.entry)
1907 def generate_keyword_list(self, code):
1908 if self.signature_has_generic_args() and \
1909 self.signature_has_nongeneric_args():
1910 code.put(
1911 "static PyObject **%s[] = {" %
1912 Naming.pykwdlist_cname)
1913 for arg in self.args:
1914 if arg.is_generic:
1915 pystring_cname = code.intern_identifier(arg.name)
1916 code.put('&%s,' % pystring_cname)
1917 code.putln("0};")
1919 def generate_argument_parsing_code(self, env, code):
1920 # Generate PyArg_ParseTuple call for generic
1921 # arguments, if any.
1922 if self.entry.signature.has_dummy_arg:
1923 # get rid of unused argument warning
1924 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1926 old_error_label = code.new_error_label()
1927 our_error_label = code.error_label
1928 end_label = code.new_label("argument_unpacking_done")
1930 has_kwonly_args = self.num_kwonly_args > 0
1931 has_star_or_kw_args = self.star_arg is not None \
1932 or self.starstar_arg is not None or has_kwonly_args
1934 for arg in self.args:
1935 if not arg.type.is_pyobject:
1936 done = arg.type.create_from_py_utility_code(env)
1937 if not done: pass # will fail later
1939 if not self.signature_has_generic_args():
1940 if has_star_or_kw_args:
1941 error(self.pos, "This method cannot have * or keyword arguments")
1942 self.generate_argument_conversion_code(code)
1944 elif not self.signature_has_nongeneric_args():
1945 # func(*args) or func(**kw) or func(*args, **kw)
1946 self.generate_stararg_copy_code(code)
1948 else:
1949 positional_args = []
1950 kw_only_args = []
1951 for arg in self.args:
1952 arg_entry = arg.entry
1953 if arg.is_generic:
1954 if arg.default:
1955 if not arg.is_self_arg:
1956 if arg.kw_only:
1957 kw_only_args.append(arg)
1958 else:
1959 positional_args.append(arg)
1960 elif arg.kw_only:
1961 kw_only_args.append(arg)
1962 elif not arg.is_self_arg:
1963 positional_args.append(arg)
1965 self.generate_tuple_and_keyword_parsing_code(
1966 positional_args, kw_only_args, end_label, code)
1968 code.error_label = old_error_label
1969 if code.label_used(our_error_label):
1970 if not code.label_used(end_label):
1971 code.put_goto(end_label)
1972 code.put_label(our_error_label)
1973 if has_star_or_kw_args:
1974 self.generate_arg_decref(self.star_arg, code)
1975 if self.starstar_arg:
1976 if self.starstar_arg.entry.xdecref_cleanup:
1977 code.put_var_xdecref(self.starstar_arg.entry)
1978 else:
1979 code.put_var_decref(self.starstar_arg.entry)
1980 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1981 code.putln("return %s;" % self.error_value())
1982 if code.label_used(end_label):
1983 code.put_label(end_label)
1985 def generate_arg_assignment(self, arg, item, code):
1986 if arg.type.is_pyobject:
1987 if arg.is_generic:
1988 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1989 code.putln("%s = %s;" % (arg.entry.cname, item))
1990 else:
1991 func = arg.type.from_py_function
1992 if func:
1993 code.putln("%s = %s(%s); %s" % (
1994 arg.entry.cname,
1995 func,
1996 item,
1997 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1998 else:
1999 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
2001 def generate_arg_xdecref(self, arg, code):
2002 if arg:
2003 code.put_var_xdecref(arg.entry)
2005 def generate_arg_decref(self, arg, code):
2006 if arg:
2007 code.put_var_decref(arg.entry)
2009 def generate_stararg_copy_code(self, code):
2010 if not self.star_arg:
2011 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2012 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
2013 Naming.args_cname)
2014 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2015 self.name, Naming.args_cname, self.error_value()))
2016 code.putln("}")
2018 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2020 if self.starstar_arg:
2021 if self.star_arg:
2022 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2023 else:
2024 kwarg_check = "%s" % Naming.kwds_cname
2025 else:
2026 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2027 Naming.kwds_cname, Naming.kwds_cname)
2028 code.putln(
2029 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2030 kwarg_check, Naming.kwds_cname, self.name,
2031 bool(self.starstar_arg), self.error_value()))
2033 if self.starstar_arg:
2034 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2035 self.starstar_arg.entry.cname,
2036 Naming.kwds_cname,
2037 Naming.kwds_cname))
2038 code.putln("if (unlikely(!%s)) return %s;" % (
2039 self.starstar_arg.entry.cname, self.error_value()))
2040 self.starstar_arg.entry.xdecref_cleanup = 0
2041 code.put_gotref(self.starstar_arg.entry.cname)
2044 if self.star_arg:
2045 code.put_incref(Naming.args_cname, py_object_type)
2046 code.putln("%s = %s;" % (
2047 self.star_arg.entry.cname,
2048 Naming.args_cname))
2049 self.star_arg.entry.xdecref_cleanup = 0
2051 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2052 kw_only_args, success_label, code):
2053 argtuple_error_label = code.new_label("argtuple_error")
2055 min_positional_args = self.num_required_args - self.num_required_kw_args
2056 if len(self.args) > 0 and self.args[0].is_self_arg:
2057 min_positional_args -= 1
2058 max_positional_args = len(positional_args)
2059 has_fixed_positional_count = not self.star_arg and \
2060 min_positional_args == max_positional_args
2062 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2063 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2064 if self.num_required_kw_args:
2065 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2067 if self.starstar_arg or self.star_arg:
2068 self.generate_stararg_init_code(max_positional_args, code)
2070 # --- optimised code when we receive keyword arguments
2071 if self.num_required_kw_args:
2072 likely_hint = "likely"
2073 else:
2074 likely_hint = "unlikely"
2075 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2076 self.generate_keyword_unpacking_code(
2077 min_positional_args, max_positional_args,
2078 has_fixed_positional_count,
2079 positional_args, kw_only_args, argtuple_error_label, code)
2081 # --- optimised code when we do not receive any keyword arguments
2082 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2083 # Python raises arg tuple related errors first, so we must
2084 # check the length here
2085 if min_positional_args == max_positional_args and not self.star_arg:
2086 compare = '!='
2087 else:
2088 compare = '<'
2089 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2090 Naming.args_cname, compare, min_positional_args))
2091 code.put_goto(argtuple_error_label)
2093 if self.num_required_kw_args:
2094 # pure error case: keywords required but not passed
2095 if max_positional_args > min_positional_args and not self.star_arg:
2096 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2097 Naming.args_cname, max_positional_args))
2098 code.put_goto(argtuple_error_label)
2099 code.putln('} else {')
2100 for i, arg in enumerate(kw_only_args):
2101 if not arg.default:
2102 pystring_cname = code.intern_identifier(arg.name)
2103 # required keyword-only argument missing
2104 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2105 self.name,
2106 pystring_cname))
2107 code.putln(code.error_goto(self.pos))
2108 break
2110 elif min_positional_args == max_positional_args:
2111 # parse the exact number of positional arguments from the
2112 # args tuple
2113 code.putln('} else {')
2114 for i, arg in enumerate(positional_args):
2115 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2116 self.generate_arg_assignment(arg, item, code)
2117 self.generate_arg_default_assignments(code)
2119 else:
2120 # parse the positional arguments from the variable length
2121 # args tuple
2122 code.putln('} else {')
2123 self.generate_arg_default_assignments(code)
2124 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2125 if self.star_arg:
2126 code.putln('default:')
2127 reversed_args = list(enumerate(positional_args))[::-1]
2128 for i, arg in reversed_args:
2129 if i >= min_positional_args-1:
2130 if min_positional_args > 1:
2131 code.putln('case %2d:' % (i+1)) # pure code beautification
2132 else:
2133 code.put('case %2d: ' % (i+1))
2134 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2135 self.generate_arg_assignment(arg, item, code)
2136 if min_positional_args == 0:
2137 code.put('case 0: ')
2138 code.putln('break;')
2139 if self.star_arg:
2140 if min_positional_args:
2141 for i in range(min_positional_args-1, -1, -1):
2142 code.putln('case %2d:' % i)
2143 code.put_goto(argtuple_error_label)
2144 else:
2145 code.put('default: ')
2146 code.put_goto(argtuple_error_label)
2147 code.putln('}')
2149 code.putln('}')
2151 if code.label_used(argtuple_error_label):
2152 code.put_goto(success_label)
2153 code.put_label(argtuple_error_label)
2154 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2155 self.name, has_fixed_positional_count,
2156 min_positional_args, max_positional_args,
2157 Naming.args_cname))
2158 code.putln(code.error_goto(self.pos))
2160 def generate_arg_default_assignments(self, code):
2161 for arg in self.args:
2162 if arg.is_generic and arg.default:
2163 code.putln(
2164 "%s = %s;" % (
2165 arg.entry.cname,
2166 arg.calculate_default_value_code(code)))
2168 def generate_stararg_init_code(self, max_positional_args, code):
2169 if self.starstar_arg:
2170 self.starstar_arg.entry.xdecref_cleanup = 0
2171 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2172 self.starstar_arg.entry.cname,
2173 self.starstar_arg.entry.cname,
2174 self.error_value()))
2175 code.put_gotref(self.starstar_arg.entry.cname)
2176 if self.star_arg:
2177 self.star_arg.entry.xdecref_cleanup = 0
2178 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2179 Naming.args_cname,
2180 max_positional_args))
2181 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2182 self.star_arg.entry.cname, Naming.args_cname,
2183 max_positional_args, Naming.args_cname))
2184 code.put_gotref(self.star_arg.entry.cname)
2185 if self.starstar_arg:
2186 code.putln("")
2187 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2188 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2189 code.putln('return %s;' % self.error_value())
2190 code.putln('}')
2191 else:
2192 code.putln("if (unlikely(!%s)) return %s;" % (
2193 self.star_arg.entry.cname, self.error_value()))
2194 code.putln('} else {')
2195 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2196 code.put_incref(Naming.empty_tuple, py_object_type)
2197 code.putln('}')
2199 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2200 has_fixed_positional_count, positional_args,
2201 kw_only_args, argtuple_error_label, code):
2202 all_args = tuple(positional_args) + tuple(kw_only_args)
2203 max_args = len(all_args)
2205 default_args = []
2206 for i, arg in enumerate(all_args):
2207 if arg.default and arg.type.is_pyobject:
2208 default_value = arg.calculate_default_value_code(code)
2209 if arg.type is not PyrexTypes.py_object_type:
2210 default_value = "(PyObject*)"+default_value
2211 default_args.append((i, default_value))
2213 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2214 Naming.kwds_cname)
2215 # it looks funny to separate the init-to-0 from setting the
2216 # default value, but C89 needs this
2217 code.putln("PyObject* values[%d] = {%s};" % (
2218 max_args, ','.join(['0']*max_args)))
2219 for i, default_value in default_args:
2220 code.putln('values[%d] = %s;' % (i, default_value))
2222 # parse the tuple and check that it's not too long
2223 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2224 if self.star_arg:
2225 code.putln('default:')
2226 for i in range(max_positional_args-1, -1, -1):
2227 code.put('case %2d: ' % (i+1))
2228 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2229 i, Naming.args_cname, i))
2230 code.putln('case 0: break;')
2231 if not self.star_arg:
2232 code.put('default: ') # more arguments than allowed
2233 code.put_goto(argtuple_error_label)
2234 code.putln('}')
2236 # now fill up the positional/required arguments with values
2237 # from the kw dict
2238 if self.num_required_args or max_positional_args > 0:
2239 last_required_arg = -1
2240 for i, arg in enumerate(all_args):
2241 if not arg.default:
2242 last_required_arg = i
2243 if last_required_arg < max_positional_args:
2244 last_required_arg = max_positional_args-1
2245 num_required_args = self.num_required_args
2246 if max_positional_args > 0:
2247 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2248 for i, arg in enumerate(all_args[:last_required_arg+1]):
2249 if max_positional_args > 0 and i <= max_positional_args:
2250 if self.star_arg and i == max_positional_args:
2251 code.putln('default:')
2252 else:
2253 code.putln('case %2d:' % i)
2254 pystring_cname = code.intern_identifier(arg.name)
2255 if arg.default:
2256 if arg.kw_only:
2257 # handled separately below
2258 continue
2259 code.putln('if (kw_args > %d) {' % num_required_args)
2260 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2261 Naming.kwds_cname, pystring_cname))
2262 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2263 code.putln('}')
2264 else:
2265 num_required_args -= 1
2266 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2267 i, Naming.kwds_cname, pystring_cname))
2268 code.putln('if (likely(values[%d])) kw_args--;' % i);
2269 if i < min_positional_args:
2270 if i == 0:
2271 # special case: we know arg 0 is missing
2272 code.put('else ')
2273 code.put_goto(argtuple_error_label)
2274 else:
2275 # print the correct number of values (args or
2276 # kwargs) that were passed into positional
2277 # arguments up to this point
2278 code.putln('else {')
2279 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2280 self.name, has_fixed_positional_count,
2281 min_positional_args, max_positional_args, i))
2282 code.putln(code.error_goto(self.pos))
2283 code.putln('}')
2284 elif arg.kw_only:
2285 code.putln('else {')
2286 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2287 self.name, pystring_cname))
2288 code.putln(code.error_goto(self.pos))
2289 code.putln('}')
2290 if max_positional_args > 0:
2291 code.putln('}')
2293 if kw_only_args and not self.starstar_arg:
2294 # unpack optional keyword-only arguments
2295 # checking for interned strings in a dict is faster than iterating
2296 # but it's too likely that we must iterate if we expect **kwargs
2297 optional_args = []
2298 for i, arg in enumerate(all_args[max_positional_args:]):
2299 if not arg.kw_only or not arg.default:
2300 continue
2301 optional_args.append((i+max_positional_args, arg))
2302 if optional_args:
2303 # this mimics an unrolled loop so that we can "break" out of it
2304 code.putln('while (kw_args > 0) {')
2305 code.putln('PyObject* value;')
2306 for i, arg in optional_args:
2307 pystring_cname = code.intern_identifier(arg.name)
2308 code.putln(
2309 'value = PyDict_GetItem(%s, %s);' % (
2310 Naming.kwds_cname, pystring_cname))
2311 code.putln(
2312 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2313 code.putln('break;')
2314 code.putln('}')
2316 code.putln('if (unlikely(kw_args > 0)) {')
2317 # non-positional/-required kw args left in dict: default args,
2318 # kw-only args, **kwargs or error
2320 # This is sort of a catch-all: except for checking required
2321 # arguments, this will always do the right thing for unpacking
2322 # keyword arguments, so that we can concentrate on optimising
2323 # common cases above.
2324 if max_positional_args == 0:
2325 pos_arg_count = "0"
2326 elif self.star_arg:
2327 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2328 Naming.args_cname, max_positional_args,
2329 Naming.args_cname, max_positional_args))
2330 pos_arg_count = "used_pos_args"
2331 else:
2332 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2333 code.globalstate.use_utility_code(parse_keywords_utility_code)
2334 code.put(
2335 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2336 Naming.kwds_cname,
2337 Naming.pykwdlist_cname,
2338 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2339 pos_arg_count,
2340 self.name))
2341 code.putln(code.error_goto(self.pos))
2342 code.putln('}')
2344 # convert arg values to their final type and assign them
2345 for i, arg in enumerate(all_args):
2346 if arg.default and not arg.type.is_pyobject:
2347 code.putln("if (values[%d]) {" % i)
2348 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2349 if arg.default and not arg.type.is_pyobject:
2350 code.putln('} else {')
2351 code.putln(
2352 "%s = %s;" % (
2353 arg.entry.cname,
2354 arg.calculate_default_value_code(code)))
2355 code.putln('}')
2357 def generate_argument_conversion_code(self, code):
2358 # Generate code to convert arguments from
2359 # signature type to declared type, if needed.
2360 for arg in self.args:
2361 if arg.needs_conversion:
2362 self.generate_arg_conversion(arg, code)
2364 def generate_arg_conversion(self, arg, code):
2365 # Generate conversion code for one argument.
2366 old_type = arg.hdr_type
2367 new_type = arg.type
2368 if old_type.is_pyobject:
2369 if arg.default:
2370 code.putln("if (%s) {" % arg.hdr_cname)
2371 else:
2372 code.putln("assert(%s); {" % arg.hdr_cname)
2373 self.generate_arg_conversion_from_pyobject(arg, code)
2374 code.putln("}")
2375 elif new_type.is_pyobject:
2376 self.generate_arg_conversion_to_pyobject(arg, code)
2377 else:
2378 if new_type.assignable_from(old_type):
2379 code.putln(
2380 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2381 else:
2382 error(arg.pos,
2383 "Cannot convert 1 argument from '%s' to '%s'" %
2384 (old_type, new_type))
2386 def generate_arg_conversion_from_pyobject(self, arg, code):
2387 new_type = arg.type
2388 func = new_type.from_py_function
2389 # copied from CoerceFromPyTypeNode
2390 if func:
2391 code.putln("%s = %s(%s); %s" % (
2392 arg.entry.cname,
2393 func,
2394 arg.hdr_cname,
2395 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2396 else:
2397 error(arg.pos,
2398 "Cannot convert Python object argument to type '%s'"
2399 % new_type)
2401 def generate_arg_conversion_to_pyobject(self, arg, code):
2402 old_type = arg.hdr_type
2403 func = old_type.to_py_function
2404 if func:
2405 code.putln("%s = %s(%s); %s" % (
2406 arg.entry.cname,
2407 func,
2408 arg.hdr_cname,
2409 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2410 code.put_var_gotref(arg.entry)
2411 else:
2412 error(arg.pos,
2413 "Cannot convert argument of type '%s' to Python object"
2414 % old_type)
2416 def generate_argument_type_tests(self, code):
2417 # Generate type tests for args whose signature
2418 # type is PyObject * and whose declared type is
2419 # a subtype thereof.
2420 for arg in self.args:
2421 if arg.needs_type_test:
2422 self.generate_arg_type_test(arg, code)
2424 def generate_arg_type_test(self, arg, code):
2425 # Generate type test for one argument.
2426 if arg.type.typeobj_is_available():
2427 typeptr_cname = arg.type.typeptr_cname
2428 arg_code = "((PyObject *)%s)" % arg.entry.cname
2429 code.putln(
2430 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2431 arg_code,
2432 typeptr_cname,
2433 not arg.not_none,
2434 arg.name,
2435 arg.type.is_builtin_type,
2436 code.error_goto(arg.pos)))
2437 else:
2438 error(arg.pos, "Cannot test type of extern C class "
2439 "without type object name specification")
2441 def error_value(self):
2442 return self.entry.signature.error_value
2444 def caller_will_check_exceptions(self):
2445 return 1
2447 class OverrideCheckNode(StatNode):
2448 # A Node for dispatching to the def method if it
2449 # is overriden.
2451 # py_func
2453 # args
2454 # func_temp
2455 # body
2457 child_attrs = ['body']
2459 body = None
2461 def analyse_expressions(self, env):
2462 self.args = env.arg_entries
2463 if self.py_func.is_module_scope:
2464 first_arg = 0
2465 else:
2466 first_arg = 1
2467 import ExprNodes
2468 self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
2469 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2470 call_node = ExprNodes.SimpleCallNode(self.pos,
2471 function=self.func_node,
2472 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2473 self.body = ReturnStatNode(self.pos, value=call_node)
2474 self.body.analyse_expressions(env)
2476 def generate_execution_code(self, code):
2477 interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
2478 # Check to see if we are an extension type
2479 if self.py_func.is_module_scope:
2480 self_arg = "((PyObject *)%s)" % Naming.module_cname
2481 else:
2482 self_arg = "((PyObject *)%s)" % self.args[0].cname
2483 code.putln("/* Check if called by wrapper */")
2484 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2485 code.putln("/* Check if overriden in Python */")
2486 if self.py_func.is_module_scope:
2487 code.putln("else {")
2488 else:
2489 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2490 func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
2491 self.func_node.set_cname(func_node_temp)
2492 # need to get attribute manually--scope would return cdef method
2493 err = code.error_goto_if_null(func_node_temp, self.pos)
2494 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
2495 func_node_temp, self_arg, interned_attr_cname, err))
2496 code.put_gotref(func_node_temp)
2497 is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
2498 is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)" % (
2499 func_node_temp, self.py_func.entry.func_cname)
2500 code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
2501 self.body.generate_execution_code(code)
2502 code.putln("}")
2503 code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
2504 code.funcstate.release_temp(func_node_temp)
2505 code.putln("}")
2507 class ClassDefNode(StatNode, BlockNode):
2508 pass
2510 class PyClassDefNode(ClassDefNode):
2511 # A Python class definition.
2513 # name EncodedString Name of the class
2514 # doc string or None
2515 # body StatNode Attribute definition code
2516 # entry Symtab.Entry
2517 # scope PyClassScope
2518 # decorators [DecoratorNode] list of decorators or None
2520 # The following subnodes are constructed internally:
2522 # dict DictNode Class dictionary
2523 # classobj ClassNode Class object
2524 # target NameNode Variable to assign class object to
2526 child_attrs = ["body", "dict", "classobj", "target"]
2527 decorators = None
2529 def __init__(self, pos, name, bases, doc, body, decorators = None):
2530 StatNode.__init__(self, pos)
2531 self.name = name
2532 self.doc = doc
2533 self.body = body
2534 self.decorators = decorators
2535 import ExprNodes
2536 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2537 if self.doc and Options.docstrings:
2538 doc = embed_position(self.pos, self.doc)
2539 # FIXME: correct string node?
2540 doc_node = ExprNodes.StringNode(pos, value = doc)
2541 else:
2542 doc_node = None
2543 self.classobj = ExprNodes.ClassNode(pos, name = name,
2544 bases = bases, dict = self.dict, doc = doc_node)
2545 self.target = ExprNodes.NameNode(pos, name = name)
2547 def as_cclass(self):
2548 """
2549 Return this node as if it were declared as an extension class
2550 """
2551 bases = self.classobj.bases.args
2552 if len(bases) == 0:
2553 base_class_name = None
2554 base_class_module = None
2555 elif len(bases) == 1:
2556 base = bases[0]
2557 path = []
2558 from ExprNodes import AttributeNode, NameNode
2559 while isinstance(base, AttributeNode):
2560 path.insert(0, base.attribute)
2561 base = base.obj
2562 if isinstance(base, NameNode):
2563 path.insert(0, base.name)
2564 base_class_name = path[-1]
2565 if len(path) > 1:
2566 base_class_module = u'.'.join(path[:-1])
2567 else:
2568 base_class_module = None
2569 else:
2570 error(self.classobj.bases.args.pos, "Invalid base class")
2571 else:
2572 error(self.classobj.bases.args.pos, "C class may only have one base class")
2573 return None
2575 return CClassDefNode(self.pos,
2576 visibility = 'private',
2577 module_name = None,
2578 class_name = self.name,
2579 base_class_module = base_class_module,
2580 base_class_name = base_class_name,
2581 decorators = self.decorators,
2582 body = self.body,
2583 in_pxd = False,
2584 doc = self.doc)
2586 def create_scope(self, env):
2587 genv = env
2588 while env.is_py_class_scope or env.is_c_class_scope:
2589 env = env.outer_scope
2590 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2591 return cenv
2593 def analyse_declarations(self, env):
2594 self.target.analyse_target_declaration(env)
2595 cenv = self.create_scope(env)
2596 cenv.directives = env.directives
2597 cenv.class_obj_cname = self.target.entry.cname
2598 self.body.analyse_declarations(cenv)
2600 def analyse_expressions(self, env):
2601 self.dict.analyse_expressions(env)
2602 self.classobj.analyse_expressions(env)
2603 genv = env.global_scope()
2604 cenv = self.scope
2605 self.body.analyse_expressions(cenv)
2606 self.target.analyse_target_expression(env, self.classobj)
2608 def generate_function_definitions(self, env, code):
2609 self.body.generate_function_definitions(self.scope, code)
2611 def generate_execution_code(self, code):
2612 code.pyclass_stack.append(self)
2613 cenv = self.scope
2614 self.dict.generate_evaluation_code(code)
2615 self.classobj.generate_evaluation_code(code)
2616 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2617 self.body.generate_execution_code(code)
2618 self.target.generate_assignment_code(self.classobj, code)
2619 self.dict.generate_disposal_code(code)
2620 self.dict.free_temps(code)
2621 code.pyclass_stack.pop()
2624 class CClassDefNode(ClassDefNode):
2625 # An extension type definition.
2627 # visibility 'private' or 'public' or 'extern'
2628 # typedef_flag boolean
2629 # api boolean
2630 # module_name string or None For import of extern type objects
2631 # class_name string Unqualified name of class
2632 # as_name string or None Name to declare as in this scope
2633 # base_class_module string or None Module containing the base class
2634 # base_class_name string or None Name of the base class
2635 # objstruct_name string or None Specified C name of object struct
2636 # typeobj_name string or None Specified C name of type object
2637 # in_pxd boolean Is in a .pxd file
2638 # decorators [DecoratorNode] list of decorators or None
2639 # doc string or None
2640 # body StatNode or None
2641 # entry Symtab.Entry
2642 # base_type PyExtensionType or None
2643 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2644 # buffer_defaults_pos
2646 child_attrs = ["body"]
2647 buffer_defaults_node = None
2648 buffer_defaults_pos = None
2649 typedef_flag = False
2650 api = False
2651 objstruct_name = None
2652 typeobj_name = None
2653 decorators = None
2655 def analyse_declarations(self, env):
2656 #print "CClassDefNode.analyse_declarations:", self.class_name
2657 #print "...visibility =", self.visibility
2658 #print "...module_name =", self.module_name
2660 import Buffer
2661 if self.buffer_defaults_node:
2662 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2663 env, [], self.buffer_defaults_node,
2664 need_complete=False)
2665 else:
2666 buffer_defaults = None
2668 if env.in_cinclude and not self.objstruct_name:
2669 error(self.pos, "Object struct name specification required for "
2670 "C class defined in 'extern from' block")
2671 self.base_type = None
2672 # Now that module imports are cached, we need to
2673 # import the modules for extern classes.
2674 if self.module_name:
2675 self.module = None
2676 for module in env.cimported_modules:
2677 if module.name == self.module_name:
2678 self.module = module
2679 if self.module is None:
2680 self.module = ModuleScope(self.module_name, None, env.context)
2681 self.module.has_extern_class = 1
2682 env.add_imported_module(self.module)
2684 if self.base_class_name:
2685 if self.base_class_module:
2686 base_class_scope = env.find_module(self.base_class_module, self.pos)
2687 else:
2688 base_class_scope = env
2689 if self.base_class_name == 'object':
2690 # extension classes are special and don't need to inherit from object
2691 if base_class_scope is None or base_class_scope.lookup('object') is None:
2692 self.base_class_name = None
2693 self.base_class_module = None
2694 base_class_scope = None
2695 if base_class_scope:
2696 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2697 if base_class_entry:
2698 if not base_class_entry.is_type:
2699 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2700 elif not base_class_entry.type.is_extension_type:
2701 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2702 elif not base_class_entry.type.is_complete():
2703 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2704 else:
2705 self.base_type = base_class_entry.type
2706 has_body = self.body is not None
2707 if self.module_name and self.visibility != 'extern':
2708 module_path = self.module_name.split(".")
2709 home_scope = env.find_imported_module(module_path, self.pos)
2710 if not home_scope:
2711 return
2712 else:
2713 home_scope = env
2715 if self.visibility == 'extern':
2716 if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
2717 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
2719 self.entry = home_scope.declare_c_class(
2720 name = self.class_name,
2721 pos = self.pos,
2722 defining = has_body and self.in_pxd,
2723 implementing = has_body and not self.in_pxd,
2724 module_name = self.module_name,
2725 base_type = self.base_type,
2726 objstruct_cname = self.objstruct_name,
2727 typeobj_cname = self.typeobj_name,
2728 visibility = self.visibility,
2729 typedef_flag = self.typedef_flag,
2730 api = self.api,
2731 buffer_defaults = buffer_defaults)
2732 if home_scope is not env and self.visibility == 'extern':
2733 env.add_imported_entry(self.class_name, self.entry, pos)
2734 self.scope = scope = self.entry.type.scope
2735 if scope is not None:
2736 scope.directives = env.directives
2738 if self.doc and Options.docstrings:
2739 scope.doc = embed_position(self.pos, self.doc)
2741 if has_body:
2742 self.body.analyse_declarations(scope)
2743 if self.in_pxd:
2744 scope.defined = 1
2745 else:
2746 scope.implemented = 1
2747 env.allocate_vtable_names(self.entry)
2749 def analyse_expressions(self, env):
2750 if self.body:
2751 scope = self.entry.type.scope
2752 self.body.analyse_expressions(scope)
2754 def generate_function_definitions(self, env, code):
2755 if self.body:
2756 self.body.generate_function_definitions(
2757 self.entry.type.scope, code)
2759 def generate_execution_code(self, code):
2760 # This is needed to generate evaluation code for
2761 # default values of method arguments.
2762 if self.body:
2763 self.body.generate_execution_code(code)
2765 def annotate(self, code):
2766 if self.body:
2767 self.body.annotate(code)
2770 class PropertyNode(StatNode):
2771 # Definition of a property in an extension type.
2773 # name string
2774 # doc EncodedString or None Doc string
2775 # body StatListNode
2777 child_attrs = ["body"]
2779 def analyse_declarations(self, env):
2780 entry = env.declare_property(self.name, self.doc, self.pos)
2781 if entry:
2782 entry.scope.directives = env.directives
2783 self.body.analyse_declarations(entry.scope)
2785 def analyse_expressions(self, env):
2786 self.body.analyse_expressions(env)
2788 def generate_function_definitions(self, env, code):
2789 self.body.generate_function_definitions(env, code)
2791 def generate_execution_code(self, code):
2792 pass
2794 def annotate(self, code):
2795 self.body.annotate(code)
2798 class GlobalNode(StatNode):
2799 # Global variable declaration.
2801 # names [string]
2803 child_attrs = []
2805 def analyse_declarations(self, env):
2806 for name in self.names:
2807 env.declare_global(name, self.pos)
2809 def analyse_expressions(self, env):
2810 pass
2812 def generate_execution_code(self, code):
2813 pass
2816 class ExprStatNode(StatNode):
2817 # Expression used as a statement.
2819 # expr ExprNode
2821 child_attrs = ["expr"]
2823 def analyse_declarations(self, env):
2824 import ExprNodes
2825 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2826 func = self.expr.function.as_cython_attribute()
2827 if func == u'declare':
2828 args, kwds = self.expr.explicit_args_kwds()
2829 if len(args):
2830 error(self.expr.pos, "Variable names must be specified.")
2831 for var, type_node in kwds.key_value_pairs:
2832 type = type_node.analyse_as_type(env)
2833 if type is None:
2834 error(type_node.pos, "Unknown type")
2835 else:
2836 env.declare_var(var.value, type, var.pos, is_cdef = True)
2837 self.__class__ = PassStatNode
2839 def analyse_expressions(self, env):
2840 self.expr.analyse_expressions(env)
2842 def generate_execution_code(self, code):
2843 self.expr.generate_evaluation_code(code)
2844 if not self.expr.is_temp and self.expr.result():
2845 code.putln("%s;" % self.expr.result())
2846 self.expr.generate_disposal_code(code)
2847 self.expr.free_temps(code)
2849 def annotate(self, code):
2850 self.expr.annotate(code)
2853 class AssignmentNode(StatNode):
2854 # Abstract base class for assignment nodes.
2856 # The analyse_expressions and generate_execution_code
2857 # phases of assignments are split into two sub-phases
2858 # each, to enable all the right hand sides of a
2859 # parallel assignment to be evaluated before assigning
2860 # to any of the left hand sides.
2862 def analyse_expressions(self, env):
2863 self.analyse_types(env)
2865 # def analyse_expressions(self, env):
2866 # self.analyse_expressions_1(env)
2867 # self.analyse_expressions_2(env)
2869 def generate_execution_code(self, code):
2870 self.generate_rhs_evaluation_code(code)
2871 self.generate_assignment_code(code)
2874 class SingleAssignmentNode(AssignmentNode):
2875 # The simplest case:
2877 # a = b
2879 # lhs ExprNode Left hand side
2880 # rhs ExprNode Right hand side
2881 # first bool Is this guaranteed the first assignment to lhs?
2883 child_attrs = ["lhs", "rhs"]
2884 first = False
2885 declaration_only = False
2887 def analyse_declarations(self, env):
2888 import ExprNodes
2890 # handle declarations of the form x = cython.foo()
2891 if isinstance(self.rhs, ExprNodes.CallNode):
2892 func_name = self.rhs.function.as_cython_attribute()
2893 if func_name:
2894 args, kwds = self.rhs.explicit_args_kwds()
2896 if func_name in ['declare', 'typedef']:
2897 if len(args) > 2 or kwds is not None:
2898 error(rhs.pos, "Can only declare one type at a time.")
2899 return
2900 type = args[0].analyse_as_type(env)
2901 if type is None:
2902 error(args[0].pos, "Unknown type")
2903 return
2904 lhs = self.lhs
2905 if func_name == 'declare':
2906 if isinstance(lhs, ExprNodes.NameNode):
2907 vars = [(lhs.name, lhs.pos)]
2908 elif isinstance(lhs, ExprNodes.TupleNode):
2909 vars = [(var.name, var.pos) for var in lhs.args]
2910 else:
2911 error(lhs.pos, "Invalid declaration")
2912 return
2913 for var, pos in vars:
2914 env.declare_var(var, type, pos, is_cdef = True)
2915 if len(args) == 2:
2916 # we have a value
2917 self.rhs = args[1]
2918 else:
2919 self.declaration_only = True
2920 else:
2921 self.declaration_only = True
2922 if not isinstance(lhs, ExprNodes.NameNode):
2923 error(lhs.pos, "Invalid declaration.")
2924 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2926 elif func_name in ['struct', 'union']:
2927 self.declaration_only = True
2928 if len(args) > 0 or kwds is None:
2929 error(rhs.pos, "Struct or union members must be given by name.")
2930 return
2931 members = []
2932 for member, type_node in kwds.key_value_pairs:
2933 type = type_node.analyse_as_type(env)
2934 if type is None:
2935 error(type_node.pos, "Unknown type")
2936 else:
2937 members.append((member.value, type, member.pos))
2938 if len(members) < len(kwds.key_value_pairs):
2939 return
2940 if not isinstance(self.lhs, ExprNodes.NameNode):
2941 error(self.lhs.pos, "Invalid declaration.")
2942 name = self.lhs.name
2943 scope = StructOrUnionScope(name)
2944 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2945 for member, type, pos in members:
2946 scope.declare_var(member, type, pos)
2948 if self.declaration_only:
2949 return
2950 else:
2951 self.lhs.analyse_target_declaration(env)
2953 def analyse_types(self, env, use_temp = 0):
2954 self.rhs.analyse_types(env)
2955 self.lhs.analyse_target_types(env)
2956 self.lhs.gil_assignment_check(env)
2957 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2958 if use_temp:
2959 self.rhs = self.rhs.coerce_to_temp(env)
2961 def generate_rhs_evaluation_code(self, code):
2962 self.rhs.generate_evaluation_code(code)
2964 def generate_assignment_code(self, code):
2965 self.lhs.generate_assignment_code(self.rhs, code)
2967 def annotate(self, code):
2968 self.lhs.annotate(code)
2969 self.rhs.annotate(code)
2972 class CascadedAssignmentNode(AssignmentNode):
2973 # An assignment with multiple left hand sides:
2975 # a = b = c
2977 # lhs_list [ExprNode] Left hand sides
2978 # rhs ExprNode Right hand sides
2980 # Used internally:
2982 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2984 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2985 coerced_rhs_list = None
2987 def analyse_declarations(self, env):
2988 for lhs in self.lhs_list:
2989 lhs.analyse_target_declaration(env)
2991 def analyse_types(self, env, use_temp = 0):
2992 self.rhs.analyse_types(env)
2993 if use_temp:
2994 self.rhs = self.rhs.coerce_to_temp(env)
2995 else:
2996 self.rhs = self.rhs.coerce_to_simple(env)
2997 from ExprNodes import CloneNode
2998 self.coerced_rhs_list = []
2999 for lhs in self.lhs_list:
3000 lhs.analyse_target_types(env)
3001 lhs.gil_assignment_check(env)
3002 rhs = CloneNode(self.rhs)
3003 rhs = rhs.coerce_to(lhs.type, env)
3004 self.coerced_rhs_list.append(rhs)
3006 def generate_rhs_evaluation_code(self, code):
3007 self.rhs.generate_evaluation_code(code)
3009 def generate_assignment_code(self, code):
3010 for i in range(len(self.lhs_list)):
3011 lhs = self.lhs_list[i]
3012 rhs = self.coerced_rhs_list[i]
3013 rhs.generate_evaluation_code(code)
3014 lhs.generate_assignment_code(rhs, code)
3015 # Assignment has disposed of the cloned RHS
3016 self.rhs.generate_disposal_code(code)
3017 self.rhs.free_temps(code)
3019 def annotate(self, code):
3020 for i in range(len(self.lhs_list)):
3021 lhs = self.lhs_list[i].annotate(code)
3022 rhs = self.coerced_rhs_list[i].annotate(code)
3023 self.rhs.annotate(code)
3026 class ParallelAssignmentNode(AssignmentNode):
3027 # A combined packing/unpacking assignment:
3029 # a, b, c = d, e, f
3031 # This has been rearranged by the parser into
3033 # a = d ; b = e ; c = f
3035 # but we must evaluate all the right hand sides
3036 # before assigning to any of the left hand sides.
3038 # stats [AssignmentNode] The constituent assignments
3040 child_attrs = ["stats"]
3042 def analyse_declarations(self, env):
3043 for stat in self.stats:
3044 stat.analyse_declarations(env)
3046 def analyse_expressions(self, env):
3047 for stat in self.stats:
3048 stat.analyse_types(env, use_temp = 1)
3050 # def analyse_expressions(self, env):
3051 # for stat in self.stats:
3052 # stat.analyse_expressions_1(env, use_temp = 1)
3053 # for stat in self.stats:
3054 # stat.analyse_expressions_2(env)
3056 def generate_execution_code(self, code):
3057 for stat in self.stats:
3058 stat.generate_rhs_evaluation_code(code)
3059 for stat in self.stats:
3060 stat.generate_assignment_code(code)
3062 def annotate(self, code):
3063 for stat in self.stats:
3064 stat.annotate(code)
3067 class InPlaceAssignmentNode(AssignmentNode):
3068 # An in place arithmatic operand:
3070 # a += b
3071 # a -= b
3072 # ...
3074 # lhs ExprNode Left hand side
3075 # rhs ExprNode Right hand side
3076 # op char one of "+-*/%^&|"
3077 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3079 # This code is a bit tricky because in order to obey Python
3080 # semantics the sub-expressions (e.g. indices) of the lhs must
3081 # not be evaluated twice. So we must re-use the values calculated
3082 # in evaluation phase for the assignment phase as well.
3083 # Fortunately, the type of the lhs node is fairly constrained
3084 # (it must be a NameNode, AttributeNode, or IndexNode).
3086 child_attrs = ["lhs", "rhs"]
3087 dup = None
3089 def analyse_declarations(self, env):
3090 self.lhs.analyse_target_declaration(env)
3092 def analyse_types(self, env):
3093 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3094 self.rhs.analyse_types(env)
3095 self.lhs.analyse_target_types(env)
3096 import ExprNodes
3097 if self.lhs.type.is_pyobject:
3098 self.rhs = self.rhs.coerce_to_pyobject(env)
3099 elif self.rhs.type.is_pyobject:
3100 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3101 if self.lhs.type.is_pyobject:
3102 self.result_value_temp = ExprNodes.PyTempNode(self.pos, env)
3103 self.result_value = self.result_value_temp.coerce_to(self.lhs.type, env)
3105 def generate_execution_code(self, code):
3106 import ExprNodes
3107 self.rhs.generate_evaluation_code(code)
3108 self.dup.generate_subexpr_evaluation_code(code)
3109 if self.dup.is_temp:
3110 self.dup.allocate_temp_result(code)
3111 # self.dup.generate_result_code is run only if it is not buffer access
3112 if self.operator == "**":
3113 extra = ", Py_None"
3114 else:
3115 extra = ""
3116 if self.lhs.type.is_pyobject:
3117 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3118 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3119 self.dup.generate_result_code(code)
3120 self.result_value_temp.allocate(code)
3121 code.putln(
3122 "%s = %s(%s, %s%s); %s" % (
3123 self.result_value.result(),
3124 self.py_operation_function(),
3125 self.dup.py_result(),
3126 self.rhs.py_result(),
3127 extra,
3128 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3129 code.put_gotref(self.result_value.py_result())
3130 self.result_value.generate_evaluation_code(code) # May be a type check...
3131 self.rhs.generate_disposal_code(code)
3132 self.rhs.free_temps(code)
3133 self.dup.generate_disposal_code(code)
3134 self.dup.free_temps(code)
3135 self.lhs.generate_assignment_code(self.result_value, code)
3136 self.result_value_temp.release(code)
3137 else:
3138 c_op = self.operator
3139 if c_op == "//":
3140 c_op = "/"
3141 elif c_op == "**":
3142 error(self.pos, "No C inplace power operator")
3143 elif self.lhs.type.is_complex:
3144 error(self.pos, "Inplace operators not implemented for complex types.")
3146 # have to do assignment directly to avoid side-effects
3147 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3148 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3149 else:
3150 self.dup.generate_result_code(code)
3151 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3152 self.rhs.generate_disposal_code(code)
3153 self.rhs.free_temps(code)
3154 if self.dup.is_temp:
3155 self.dup.generate_subexpr_disposal_code(code)
3156 self.dup.free_subexpr_temps(code)
3158 def create_dup_node(self, env):
3159 import ExprNodes
3160 self.dup = self.lhs
3161 self.dup.analyse_types(env)
3162 if isinstance(self.lhs, ExprNodes.NameNode):
3163 target_lhs = ExprNodes.NameNode(self.dup.pos,
3164 name = self.dup.name,
3165 is_temp = self.dup.is_temp,
3166 entry = self.dup.entry)
3167 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3168 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3169 obj = ExprNodes.CloneNode(self.lhs.obj),
3170 attribute = self.dup.attribute,
3171 is_temp = self.dup.is_temp)
3172 elif isinstance(self.lhs, ExprNodes.IndexNode):
3173 if self.lhs.index:
3174 index = ExprNodes.CloneNode(self.lhs.index)
3175 else:
3176 index = None
3177 if self.lhs.indices:
3178 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3179 else:
3180 indices = []
3181 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3182 base = ExprNodes.CloneNode(self.dup.base),
3183 index = index,
3184 indices = indices,
3185 is_temp = self.dup.is_temp)
3186 else:
3187 assert False
3188 self.lhs = target_lhs
3189 return self.dup
3191 def py_operation_function(self):
3192 return self.py_functions[self.operator]
3194 py_functions = {
3195 "|": "PyNumber_InPlaceOr",
3196 "^": "PyNumber_InPlaceXor",
3197 "&": "PyNumber_InPlaceAnd",
3198 "+": "PyNumber_InPlaceAdd",
3199 "-": "PyNumber_InPlaceSubtract",
3200 "*": "PyNumber_InPlaceMultiply",
3201 "/": "__Pyx_PyNumber_InPlaceDivide",
3202 "%": "PyNumber_InPlaceRemainder",
3203 "<<": "PyNumber_InPlaceLshift",
3204 ">>": "PyNumber_InPlaceRshift",
3205 "**": "PyNumber_InPlacePower",
3206 "//": "PyNumber_InPlaceFloorDivide",
3209 def annotate(self, code):
3210 self.lhs.annotate(code)
3211 self.rhs.annotate(code)
3212 self.dup.annotate(code)
3214 def create_binop_node(self):
3215 import ExprNodes
3216 return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
3219 class PrintStatNode(StatNode):
3220 # print statement
3222 # arg_tuple TupleNode
3223 # append_newline boolean
3225 child_attrs = ["arg_tuple"]
3227 def analyse_expressions(self, env):
3228 self.arg_tuple.analyse_expressions(env)
3229 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3230 env.use_utility_code(printing_utility_code)
3231 if len(self.arg_tuple.args) == 1 and self.append_newline:
3232 env.use_utility_code(printing_one_utility_code)
3234 nogil_check = Node.gil_error
3235 gil_message = "Python print statement"
3237 def generate_execution_code(self, code):
3238 if len(self.arg_tuple.args) == 1 and self.append_newline:
3239 arg = self.arg_tuple.args[0]
3240 arg.generate_evaluation_code(code)
3242 code.putln(
3243 "if (__Pyx_PrintOne(%s) < 0) %s" % (
3244 arg.py_result(),
3245 code.error_goto(self.pos)))
3246 arg.generate_disposal_code(code)
3247 arg.free_temps(code)
3248 else:
3249 self.arg_tuple.generate_evaluation_code(code)
3250 code.putln(
3251 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3252 self.arg_tuple.py_result(),
3253 self.append_newline,
3254 code.error_goto(self.pos)))
3255 self.arg_tuple.generate_disposal_code(code)
3256 self.arg_tuple.free_temps(code)
3258 def annotate(self, code):
3259 self.arg_tuple.annotate(code)
3262 class ExecStatNode(StatNode):
3263 # exec statement
3265 # args [ExprNode]
3267 child_attrs = ["args"]
3269 def analyse_expressions(self, env):
3270 for i, arg in enumerate(self.args):
3271 arg.analyse_expressions(env)
3272 arg = arg.coerce_to_pyobject(env)
3273 self.args[i] = arg
3274 env.use_utility_code(Builtin.pyexec_utility_code)
3276 nogil_check = Node.gil_error
3277 gil_message = "Python exec statement"
3279 def generate_execution_code(self, code):
3280 args = []
3281 for arg in self.args:
3282 arg.generate_evaluation_code(code)
3283 args.append( arg.py_result() )
3284 args = tuple(args + ['0', '0'][:3-len(args)])
3285 temp_result = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
3286 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3287 (temp_result,) + args))
3288 for arg in self.args:
3289 arg.generate_disposal_code(code)
3290 arg.free_temps(code)
3291 code.putln(
3292 code.error_goto_if_null(temp_result, self.pos))
3293 code.put_gotref(temp_result)
3294 code.put_decref_clear(temp_result, py_object_type)
3295 code.funcstate.release_temp(temp_result)
3297 def annotate(self, code):
3298 for arg in self.args:
3299 arg.annotate(code)
3302 class DelStatNode(StatNode):
3303 # del statement
3305 # args [ExprNode]
3307 child_attrs = ["args"]
3309 def analyse_declarations(self, env):
3310 for arg in self.args:
3311 arg.analyse_target_declaration(env)
3313 def analyse_expressions(self, env):
3314 for arg in self.args:
3315 arg.analyse_target_expression(env, None)
3316 if not arg.type.is_pyobject:
3317 error(arg.pos, "Deletion of non-Python object")
3318 #arg.release_target_temp(env)
3320 def nogil_check(self, env):
3321 for arg in self.args:
3322 if arg.type.is_pyobject:
3323 self.gil_error()
3325 gil_message = "Deleting Python object"
3327 def generate_execution_code(self, code):
3328 for arg in self.args:
3329 if arg.type.is_pyobject:
3330 arg.generate_deletion_code(code)
3331 # else error reported earlier
3333 def annotate(self, code):
3334 for arg in self.args:
3335 arg.annotate(code)
3338 class PassStatNode(StatNode):
3339 # pass statement
3341 child_attrs = []
3343 def analyse_expressions(self, env):
3344 pass
3346 def generate_execution_code(self, code):
3347 pass
3350 class BreakStatNode(StatNode):
3352 child_attrs = []
3354 def analyse_expressions(self, env):
3355 pass
3357 def generate_execution_code(self, code):
3358 if not code.break_label:
3359 error(self.pos, "break statement not inside loop")
3360 else:
3361 code.put_goto(code.break_label)
3364 class ContinueStatNode(StatNode):
3366 child_attrs = []
3368 def analyse_expressions(self, env):
3369 pass
3371 def generate_execution_code(self, code):
3372 if code.funcstate.in_try_finally:
3373 error(self.pos, "continue statement inside try of try...finally")
3374 elif not code.continue_label:
3375 error(self.pos, "continue statement not inside loop")
3376 else:
3377 code.put_goto(code.continue_label)
3380 class ReturnStatNode(StatNode):
3381 # return statement
3383 # value ExprNode or None
3384 # return_type PyrexType
3386 child_attrs = ["value"]
3388 def analyse_expressions(self, env):
3389 return_type = env.return_type
3390 self.return_type = return_type
3391 if not return_type:
3392 error(self.pos, "Return not inside a function body")
3393 return
3394 if self.value:
3395 self.value.analyse_types(env)
3396 if return_type.is_void or return_type.is_returncode:
3397 error(self.value.pos,
3398 "Return with value in void function")
3399 else:
3400 self.value = self.value.coerce_to(env.return_type, env)
3401 else:
3402 if (not return_type.is_void
3403 and not return_type.is_pyobject
3404 and not return_type.is_returncode):
3405 error(self.pos, "Return value required")
3407 def nogil_check(self, env):
3408 if self.return_type.is_pyobject:
3409 self.gil_error()
3411 gil_message = "Returning Python object"
3413 def generate_execution_code(self, code):
3414 code.mark_pos(self.pos)
3415 if not self.return_type:
3416 # error reported earlier
3417 return
3418 if self.return_type.is_pyobject:
3419 code.put_xdecref(Naming.retval_cname,
3420 self.return_type)
3421 if self.value:
3422 self.value.generate_evaluation_code(code)
3423 self.value.make_owned_reference(code)
3424 code.putln(
3425 "%s = %s;" % (
3426 Naming.retval_cname,
3427 self.value.result_as(self.return_type)))
3428 self.value.generate_post_assignment_code(code)
3429 self.value.free_temps(code)
3430 else:
3431 if self.return_type.is_pyobject:
3432 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3433 elif self.return_type.is_returncode:
3434 code.putln(
3435 "%s = %s;" % (
3436 Naming.retval_cname,
3437 self.return_type.default_value))
3438 for cname, type in code.funcstate.temps_holding_reference():
3439 code.put_decref_clear(cname, type)
3440 code.put_goto(code.return_label)
3442 def annotate(self, code):
3443 if self.value:
3444 self.value.annotate(code)
3447 class RaiseStatNode(StatNode):
3448 # raise statement
3450 # exc_type ExprNode or None
3451 # exc_value ExprNode or None
3452 # exc_tb ExprNode or None
3454 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3456 def analyse_expressions(self, env):
3457 if self.exc_type:
3458 self.exc_type.analyse_types(env)
3459 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3460 if self.exc_value:
3461 self.exc_value.analyse_types(env)
3462 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3463 if self.exc_tb:
3464 self.exc_tb.analyse_types(env)
3465 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3466 env.use_utility_code(raise_utility_code)
3468 nogil_check = Node.gil_error
3469 gil_message = "Raising exception"
3471 def generate_execution_code(self, code):
3472 if self.exc_type:
3473 self.exc_type.generate_evaluation_code(code)
3474 type_code = self.exc_type.py_result()
3475 else:
3476 type_code = "0"
3477 if self.exc_value:
3478 self.exc_value.generate_evaluation_code(code)
3479 value_code = self.exc_value.py_result()
3480 else:
3481 value_code = "0"
3482 if self.exc_tb:
3483 self.exc_tb.generate_evaluation_code(code)
3484 tb_code = self.exc_tb.py_result()
3485 else:
3486 tb_code = "0"
3487 code.putln(
3488 "__Pyx_Raise(%s, %s, %s);" % (
3489 type_code,
3490 value_code,
3491 tb_code))
3492 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3493 if obj:
3494 obj.generate_disposal_code(code)
3495 obj.free_temps(code)
3496 code.putln(
3497 code.error_goto(self.pos))
3499 def annotate(self, code):
3500 if self.exc_type:
3501 self.exc_type.annotate(code)
3502 if self.exc_value:
3503 self.exc_value.annotate(code)
3504 if self.exc_tb:
3505 self.exc_tb.annotate(code)
3508 class ReraiseStatNode(StatNode):
3510 child_attrs = []
3512 def analyse_expressions(self, env):
3513 env.use_utility_code(restore_exception_utility_code)
3515 nogil_check = Node.gil_error
3516 gil_message = "Raising exception"
3518 def generate_execution_code(self, code):
3519 vars = code.funcstate.exc_vars
3520 if vars:
3521 for varname in vars:
3522 code.put_giveref(varname)
3523 code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars))
3524 for varname in vars:
3525 code.put("%s = 0; " % varname)
3526 code.putln()
3527 code.putln(code.error_goto(self.pos))
3528 else:
3529 error(self.pos, "Reraise not inside except clause")
3532 class AssertStatNode(StatNode):
3533 # assert statement
3535 # cond ExprNode
3536 # value ExprNode or None
3538 child_attrs = ["cond", "value"]
3540 def analyse_expressions(self, env):
3541 self.cond = self.cond.analyse_boolean_expression(env)
3542 if self.value:
3543 self.value.analyse_types(env)
3544 self.value = self.value.coerce_to_pyobject(env)
3546 nogil_check = Node.gil_error
3547 gil_message = "Raising exception"
3549 def generate_execution_code(self, code):
3550 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3551 self.cond.generate_evaluation_code(code)
3552 code.putln(
3553 "if (unlikely(!%s)) {" %
3554 self.cond.result())
3555 if self.value:
3556 self.value.generate_evaluation_code(code)
3557 code.putln(
3558 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3559 self.value.py_result())
3560 self.value.generate_disposal_code(code)
3561 self.value.free_temps(code)
3562 else:
3563 code.putln(
3564 "PyErr_SetNone(PyExc_AssertionError);")
3565 code.putln(
3566 code.error_goto(self.pos))
3567 code.putln(
3568 "}")
3569 self.cond.generate_disposal_code(code)
3570 self.cond.free_temps(code)
3571 code.putln("#endif")
3573 def annotate(self, code):
3574 self.cond.annotate(code)
3575 if self.value:
3576 self.value.annotate(code)
3579 class IfStatNode(StatNode):
3580 # if statement
3582 # if_clauses [IfClauseNode]
3583 # else_clause StatNode or None
3585 child_attrs = ["if_clauses", "else_clause"]
3587 def analyse_control_flow(self, env):
3588 env.start_branching(self.pos)
3589 for if_clause in self.if_clauses:
3590 if_clause.analyse_control_flow(env)
3591 env.next_branch(if_clause.end_pos())
3592 if self.else_clause:
3593 self.else_clause.analyse_control_flow(env)
3594 env.finish_branching(self.end_pos())
3596 def analyse_declarations(self, env):
3597 for if_clause in self.if_clauses:
3598 if_clause.analyse_declarations(env)
3599 if self.else_clause:
3600 self.else_clause.analyse_declarations(env)
3602 def analyse_expressions(self, env):
3603 for if_clause in self.if_clauses:
3604 if_clause.analyse_expressions(env)
3605 if self.else_clause:
3606 self.else_clause.analyse_expressions(env)
3608 def generate_execution_code(self, code):
3609 code.mark_pos(self.pos)
3610 end_label = code.new_label()
3611 for if_clause in self.if_clauses:
3612 if_clause.generate_execution_code(code, end_label)
3613 if self.else_clause:
3614 code.putln("/*else*/ {")
3615 self.else_clause.generate_execution_code(code)
3616 code.putln("}")
3617 code.put_label(end_label)
3619 def annotate(self, code):
3620 for if_clause in self.if_clauses:
3621 if_clause.annotate(code)
3622 if self.else_clause:
3623 self.else_clause.annotate(code)
3626 class IfClauseNode(Node):
3627 # if or elif clause in an if statement
3629 # condition ExprNode
3630 # body StatNode
3632 child_attrs = ["condition", "body"]
3634 def analyse_control_flow(self, env):
3635 self.body.analyse_control_flow(env)
3637 def analyse_declarations(self, env):
3638 self.condition.analyse_declarations(env)
3639 self.body.analyse_declarations(env)
3641 def analyse_expressions(self, env):
3642 self.condition = \
3643 self.condition.analyse_temp_boolean_expression(env)
3644 self.body.analyse_expressions(env)
3646 def generate_execution_code(self, code, end_label):
3647 self.condition.generate_evaluation_code(code)
3648 code.putln(
3649 "if (%s) {" %
3650 self.condition.result())
3651 self.condition.generate_disposal_code(code)
3652 self.condition.free_temps(code)
3653 self.body.generate_execution_code(code)
3654 #code.putln(
3655 # "goto %s;" %
3656 # end_label)
3657 code.put_goto(end_label)
3658 code.putln("}")
3660 def annotate(self, code):
3661 self.condition.annotate(code)
3662 self.body.annotate(code)
3665 class SwitchCaseNode(StatNode):
3666 # Generated in the optimization of an if-elif-else node
3668 # conditions [ExprNode]
3669 # body StatNode
3671 child_attrs = ['conditions', 'body']
3673 def generate_execution_code(self, code):
3674 for cond in self.conditions:
3675 code.mark_pos(cond.pos)
3676 cond.generate_evaluation_code(code)
3677 code.putln("case %s:" % cond.result())
3678 self.body.generate_execution_code(code)
3679 code.putln("break;")
3681 def annotate(self, code):
3682 for cond in self.conditions:
3683 cond.annotate(code)
3684 self.body.annotate(code)
3686 class SwitchStatNode(StatNode):
3687 # Generated in the optimization of an if-elif-else node
3689 # test ExprNode
3690 # cases [SwitchCaseNode]
3691 # else_clause StatNode or None
3693 child_attrs = ['test', 'cases', 'else_clause']
3695 def generate_execution_code(self, code):
3696 code.putln("switch (%s) {" % self.test.result())
3697 for case in self.cases:
3698 case.generate_execution_code(code)
3699 if self.else_clause is not None:
3700 code.putln("default:")
3701 self.else_clause.generate_execution_code(code)
3702 code.putln("break;")
3703 code.putln("}")
3705 def annotate(self, code):
3706 self.test.annotate(code)
3707 for case in self.cases:
3708 case.annotate(code)
3709 if self.else_clause is not None:
3710 self.else_clause.annotate(code)
3712 class LoopNode(object):
3714 def analyse_control_flow(self, env):
3715 env.start_branching(self.pos)
3716 self.body.analyse_control_flow(env)
3717 env.next_branch(self.body.end_pos())
3718 if self.else_clause:
3719 self.else_clause.analyse_control_flow(env)
3720 env.finish_branching(self.end_pos())
3723 class WhileStatNode(LoopNode, StatNode):
3724 # while statement
3726 # condition ExprNode
3727 # body StatNode
3728 # else_clause StatNode
3730 child_attrs = ["condition", "body", "else_clause"]
3732 def analyse_declarations(self, env):
3733 self.body.analyse_declarations(env)
3734 if self.else_clause:
3735 self.else_clause.analyse_declarations(env)
3737 def analyse_expressions(self, env):
3738 self.condition = \
3739 self.condition.analyse_temp_boolean_expression(env)
3740 self.body.analyse_expressions(env)
3741 if self.else_clause:
3742 self.else_clause.analyse_expressions(env)
3744 def generate_execution_code(self, code):
3745 old_loop_labels = code.new_loop_labels()
3746 code.putln(
3747 "while (1) {")
3748 self.condition.generate_evaluation_code(code)
3749 self.condition.generate_disposal_code(code)
3750 code.putln(
3751 "if (!%s) break;" %
3752 self.condition.result())
3753 self.condition.free_temps(code)
3754 self.body.generate_execution_code(code)
3755 code.put_label(code.continue_label)
3756 code.putln("}")
3757 break_label = code.break_label
3758 code.set_loop_labels(old_loop_labels)
3759 if self.else_clause:
3760 code.putln("/*else*/ {")
3761 self.else_clause.generate_execution_code(code)
3762 code.putln("}")
3763 code.put_label(break_label)
3765 def annotate(self, code):
3766 self.condition.annotate(code)
3767 self.body.annotate(code)
3768 if self.else_clause:
3769 self.else_clause.annotate(code)
3772 def ForStatNode(pos, **kw):
3773 if 'iterator' in kw:
3774 return ForInStatNode(pos, **kw)
3775 else:
3776 return ForFromStatNode(pos, **kw)
3778 class ForInStatNode(LoopNode, StatNode):
3779 # for statement
3781 # target ExprNode
3782 # iterator IteratorNode
3783 # body StatNode
3784 # else_clause StatNode
3785 # item NextNode used internally
3787 child_attrs = ["target", "iterator", "body", "else_clause"]
3788 item = None
3790 def analyse_declarations(self, env):
3791 self.target.analyse_target_declaration(env)
3792 self.body.analyse_declarations(env)
3793 if self.else_clause:
3794 self.else_clause.analyse_declarations(env)
3796 def analyse_expressions(self, env):
3797 import ExprNodes
3798 self.target.analyse_target_types(env)
3799 self.iterator.analyse_expressions(env)
3800 self.item = ExprNodes.NextNode(self.iterator, env)
3801 self.item = self.item.coerce_to(self.target.type, env)
3802 self.body.analyse_expressions(env)
3803 if self.else_clause:
3804 self.else_clause.analyse_expressions(env)
3806 def generate_execution_code(self, code):
3807 old_loop_labels = code.new_loop_labels()
3808 self.iterator.allocate_counter_temp(code)
3809 self.iterator.generate_evaluation_code(code)
3810 code.putln(
3811 "for (;;) {")
3812 self.item.generate_evaluation_code(code)
3813 self.target.generate_assignment_code(self.item, code)
3814 self.body.generate_execution_code(code)
3815 code.put_label(code.continue_label)
3816 code.putln(
3817 "}")
3818 break_label = code.break_label
3819 code.set_loop_labels(old_loop_labels)
3820 if self.else_clause:
3821 code.putln("/*else*/ {")
3822 self.else_clause.generate_execution_code(code)
3823 code.putln("}")
3824 code.put_label(break_label)
3825 self.iterator.release_counter_temp(code)
3826 self.iterator.generate_disposal_code(code)
3827 self.iterator.free_temps(code)
3829 def annotate(self, code):
3830 self.target.annotate(code)
3831 self.iterator.annotate(code)
3832 self.body.annotate(code)
3833 if self.else_clause:
3834 self.else_clause.annotate(code)
3835 self.item.annotate(code)
3838 class ForFromStatNode(LoopNode, StatNode):
3839 # for name from expr rel name rel expr
3841 # target NameNode
3842 # bound1 ExprNode
3843 # relation1 string
3844 # relation2 string
3845 # bound2 ExprNode
3846 # step ExprNode or None
3847 # body StatNode
3848 # else_clause StatNode or None
3850 # Used internally:
3852 # from_range bool
3853 # is_py_target bool
3854 # loopvar_node ExprNode (usually a NameNode or temp node)
3855 # py_loopvar_node PyTempNode or None
3856 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3858 is_py_target = False
3859 loopvar_node = None
3860 py_loopvar_node = None
3861 from_range = False
3863 gil_message = "For-loop using object bounds or target"
3865 def nogil_check(self, env):
3866 for x in (self.target, self.bound1, self.bound2):
3867 if x.type.is_pyobject:
3868 self.gil_error()
3870 def analyse_declarations(self, env):
3871 self.target.analyse_target_declaration(env)
3872 self.body.analyse_declarations(env)
3873 if self.else_clause:
3874 self.else_clause.analyse_declarations(env)
3876 def analyse_expressions(self, env):
3877 import ExprNodes
3878 self.target.analyse_target_types(env)
3879 self.bound1.analyse_types(env)
3880 self.bound2.analyse_types(env)
3881 if self.step is not None:
3882 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3883 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3884 self.step.analyse_types(env)
3886 target_type = self.target.type
3887 if self.target.type.is_numeric:
3888 loop_type = self.target.type
3889 else:
3890 loop_type = PyrexTypes.c_int_type
3891 if not self.bound1.type.is_pyobject:
3892 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
3893 if not self.bound2.type.is_pyobject:
3894 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
3895 if self.step is not None and not self.step.type.is_pyobject:
3896 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
3897 self.bound1 = self.bound1.coerce_to(loop_type, env)
3898 self.bound2 = self.bound2.coerce_to(loop_type, env)
3899 if not self.bound2.is_literal:
3900 self.bound2 = self.bound2.coerce_to_temp(env)
3901 if self.step is not None:
3902 self.step = self.step.coerce_to(loop_type, env)
3903 if not self.step.is_literal:
3904 self.step = self.step.coerce_to_temp(env)
3906 target_type = self.target.type
3907 if not (target_type.is_pyobject or target_type.is_numeric):
3908 error(self.target.pos,
3909 "for-from loop variable must be c numeric type or Python object")
3910 if target_type.is_numeric:
3911 self.is_py_target = False
3912 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3913 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3914 self.loopvar_node = self.target
3915 self.py_loopvar_node = None
3916 else:
3917 self.is_py_target = True
3918 c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
3919 self.loopvar_node = c_loopvar_node
3920 self.py_loopvar_node = \
3921 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3922 self.body.analyse_expressions(env)
3923 if self.else_clause:
3924 self.else_clause.analyse_expressions(env)
3926 def generate_execution_code(self, code):
3927 old_loop_labels = code.new_loop_labels()
3928 from_range = self.from_range
3929 self.bound1.generate_evaluation_code(code)
3930 self.bound2.generate_evaluation_code(code)
3931 offset, incop = self.relation_table[self.relation1]
3932 if self.step is not None:
3933 self.step.generate_evaluation_code(code)
3934 step = self.step.result()
3935 incop = "%s=%s" % (incop[0], step)
3936 import ExprNodes
3937 if isinstance(self.loopvar_node, ExprNodes.TempNode):
3938 self.loopvar_node.allocate(code)
3939 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
3940 self.py_loopvar_node.allocate(code)
3941 if from_range:
3942 loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
3943 else:
3944 loopvar_name = self.loopvar_node.result()
3945 code.putln(
3946 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3947 loopvar_name,
3948 self.bound1.result(), offset,
3949 loopvar_name, self.relation2, self.bound2.result(),
3950 loopvar_name, incop))
3951 if self.py_loopvar_node:
3952 self.py_loopvar_node.generate_evaluation_code(code)
3953 self.target.generate_assignment_code(self.py_loopvar_node, code)
3954 elif from_range:
3955 code.putln("%s = %s;" % (
3956 self.target.result(), loopvar_name))
3957 self.body.generate_execution_code(code)
3958 code.put_label(code.continue_label)
3959 if self.py_loopvar_node:
3960 # This mess is to make for..from loops with python targets behave
3961 # exactly like those with C targets with regards to re-assignment
3962 # of the loop variable.
3963 import ExprNodes
3964 if self.target.entry.is_pyglobal:
3965 # We know target is a NameNode, this is the only ugly case.
3966 target_node = ExprNodes.PyTempNode(self.target.pos, None)
3967 target_node.allocate(code)
3968 interned_cname = code.intern_identifier(self.target.entry.name)
3969 code.putln("/*here*/")
3970 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
3971 target_node.result(),
3972 Naming.module_cname,
3973 interned_cname,
3974 code.error_goto_if_null(target_node.result(), self.target.pos)))
3975 code.put_gotref(target_node.result())
3976 else:
3977 target_node = self.target
3978 from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
3979 from_py_node.temp_code = loopvar_name
3980 from_py_node.generate_result_code(code)
3981 if self.target.entry.is_pyglobal:
3982 code.put_decref(target_node.result(), target_node.type)
3983 target_node.release(code)
3984 code.putln("}")
3985 if self.py_loopvar_node:
3986 # This is potentially wasteful, but we don't want the semantics to
3987 # depend on whether or not the loop is a python type.
3988 self.py_loopvar_node.generate_evaluation_code(code)
3989 self.target.generate_assignment_code(self.py_loopvar_node, code)
3990 if from_range:
3991 code.funcstate.release_temp(loopvar_name)
3992 break_label = code.break_label
3993 code.set_loop_labels(old_loop_labels)
3994 if self.else_clause:
3995 code.putln("/*else*/ {")
3996 self.else_clause.generate_execution_code(code)
3997 code.putln("}")
3998 code.put_label(break_label)
3999 self.bound1.generate_disposal_code(code)
4000 self.bound1.free_temps(code)
4001 self.bound2.generate_disposal_code(code)
4002 self.bound2.free_temps(code)
4003 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4004 self.loopvar_node.release(code)
4005 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4006 self.py_loopvar_node.release(code)
4007 if self.step is not None:
4008 self.step.generate_disposal_code(code)
4009 self.step.free_temps(code)
4011 relation_table = {
4012 # {relop : (initial offset, increment op)}
4013 '<=': ("", "++"),
4014 '<' : ("+1", "++"),
4015 '>=': ("", "--"),
4016 '>' : ("-1", "--")
4019 def annotate(self, code):
4020 self.target.annotate(code)
4021 self.bound1.annotate(code)
4022 self.bound2.annotate(code)
4023 if self.step:
4024 self.bound2.annotate(code)
4025 self.body.annotate(code)
4026 if self.else_clause:
4027 self.else_clause.annotate(code)
4030 class WithStatNode(StatNode):
4031 """
4032 Represents a Python with statement.
4034 This is only used at parse tree level; and is not present in
4035 analysis or generation phases.
4036 """
4037 # manager The with statement manager object
4038 # target Node (lhs expression)
4039 # body StatNode
4040 child_attrs = ["manager", "target", "body"]
4042 class TryExceptStatNode(StatNode):
4043 # try .. except statement
4045 # body StatNode
4046 # except_clauses [ExceptClauseNode]
4047 # else_clause StatNode or None
4049 child_attrs = ["body", "except_clauses", "else_clause"]
4051 def analyse_control_flow(self, env):
4052 env.start_branching(self.pos)
4053 self.body.analyse_control_flow(env)
4054 successful_try = env.control_flow # grab this for later
4055 env.next_branch(self.body.end_pos())
4056 env.finish_branching(self.body.end_pos())
4058 env.start_branching(self.except_clauses[0].pos)
4059 for except_clause in self.except_clauses:
4060 except_clause.analyse_control_flow(env)
4061 env.next_branch(except_clause.end_pos())
4063 # the else cause it executed only when the try clause finishes
4064 env.control_flow.incoming = successful_try
4065 if self.else_clause:
4066 self.else_clause.analyse_control_flow(env)
4067 env.finish_branching(self.end_pos())
4069 def analyse_declarations(self, env):
4070 self.body.analyse_declarations(env)
4071 for except_clause in self.except_clauses:
4072 except_clause.analyse_declarations(env)
4073 if self.else_clause:
4074 self.else_clause.analyse_declarations(env)
4075 env.use_utility_code(reset_exception_utility_code)
4077 def analyse_expressions(self, env):
4078 self.body.analyse_expressions(env)
4079 default_clause_seen = 0
4080 for except_clause in self.except_clauses:
4081 except_clause.analyse_expressions(env)
4082 if default_clause_seen:
4083 error(except_clause.pos, "default 'except:' must be last")
4084 if not except_clause.pattern:
4085 default_clause_seen = 1
4086 self.has_default_clause = default_clause_seen
4087 if self.else_clause:
4088 self.else_clause.analyse_expressions(env)
4090 nogil_check = Node.gil_error
4091 gil_message = "Try-except statement"
4093 def generate_execution_code(self, code):
4094 old_return_label = code.return_label
4095 old_break_label = code.break_label
4096 old_continue_label = code.continue_label
4097 old_error_label = code.new_error_label()
4098 our_error_label = code.error_label
4099 except_end_label = code.new_label('exception_handled')
4100 except_error_label = code.new_label('except_error')
4101 except_return_label = code.new_label('except_return')
4102 try_return_label = code.new_label('try_return')
4103 try_break_label = code.new_label('try_break')
4104 try_continue_label = code.new_label('try_continue')
4105 try_end_label = code.new_label('try_end')
4107 code.putln("{")
4108 code.putln("PyObject %s;" %
4109 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4110 code.putln("__Pyx_ExceptionSave(%s);" %
4111 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4112 for var in Naming.exc_save_vars:
4113 code.put_xgotref(var)
4114 code.putln(
4115 "/*try:*/ {")
4116 code.return_label = try_return_label
4117 code.break_label = try_break_label
4118 code.continue_label = try_continue_label
4119 self.body.generate_execution_code(code)
4120 code.putln(
4121 "}")
4122 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4123 code.error_label = except_error_label
4124 code.return_label = except_return_label
4125 if self.else_clause:
4126 code.putln(
4127 "/*else:*/ {")
4128 self.else_clause.generate_execution_code(code)
4129 code.putln(
4130 "}")
4131 for var in Naming.exc_save_vars:
4132 code.put_xdecref_clear(var, py_object_type)
4133 code.put_goto(try_end_label)
4134 if code.label_used(try_return_label):
4135 code.put_label(try_return_label)
4136 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4137 code.putln("__Pyx_ExceptionReset(%s);" %
4138 ', '.join(Naming.exc_save_vars))
4139 code.put_goto(old_return_label)
4140 code.put_label(our_error_label)
4141 for temp_name, type in temps_to_clean_up:
4142 code.put_xdecref_clear(temp_name, type)
4143 for except_clause in self.except_clauses:
4144 except_clause.generate_handling_code(code, except_end_label)
4146 error_label_used = code.label_used(except_error_label)
4147 if error_label_used or not self.has_default_clause:
4148 if error_label_used:
4149 code.put_label(except_error_label)
4150 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4151 code.putln("__Pyx_ExceptionReset(%s);" %
4152 ', '.join(Naming.exc_save_vars))
4153 code.put_goto(old_error_label)
4155 for exit_label, old_label in zip(
4156 [try_break_label, try_continue_label, except_return_label],
4157 [old_break_label, old_continue_label, old_return_label]):
4159 if code.label_used(exit_label):
4160 code.put_label(exit_label)
4161 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4162 code.putln("__Pyx_ExceptionReset(%s);" %
4163 ', '.join(Naming.exc_save_vars))
4164 code.put_goto(old_label)
4166 if code.label_used(except_end_label):
4167 code.put_label(except_end_label)
4168 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4169 code.putln("__Pyx_ExceptionReset(%s);" %
4170 ', '.join(Naming.exc_save_vars))
4171 code.put_label(try_end_label)
4172 code.putln("}")
4174 code.return_label = old_return_label
4175 code.break_label = old_break_label
4176 code.continue_label = old_continue_label
4177 code.error_label = old_error_label
4179 def annotate(self, code):
4180 self.body.annotate(code)
4181 for except_node in self.except_clauses:
4182 except_node.annotate(code)
4183 if self.else_clause:
4184 self.else_clause.annotate(code)
4187 class ExceptClauseNode(Node):
4188 # Part of try ... except statement.
4190 # pattern ExprNode
4191 # target ExprNode or None
4192 # body StatNode
4193 # excinfo_target NameNode or None optional target for exception info
4194 # match_flag string result of exception match
4195 # exc_value ExcValueNode used internally
4196 # function_name string qualified name of enclosing function
4197 # exc_vars (string * 3) local exception variables
4199 # excinfo_target is never set by the parser, but can be set by a transform
4200 # in order to extract more extensive information about the exception as a
4201 # sys.exc_info()-style tuple into a target variable
4203 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4205 exc_value = None
4206 excinfo_target = None
4208 def analyse_declarations(self, env):
4209 if self.target:
4210 self.target.analyse_target_declaration(env)
4211 if self.excinfo_target is not None:
4212 self.excinfo_target.analyse_target_declaration(env)
4213 self.body.analyse_declarations(env)
4215 def analyse_expressions(self, env):
4216 import ExprNodes
4217 genv = env.global_scope()
4218 self.function_name = env.qualified_name
4219 if self.pattern:
4220 self.pattern.analyse_expressions(env)
4221 self.pattern = self.pattern.coerce_to_pyobject(env)
4223 if self.target:
4224 self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
4225 self.target.analyse_target_expression(env, self.exc_value)
4226 if self.excinfo_target is not None:
4227 import ExprNodes
4228 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4229 ExprNodes.ExcValueNode(pos=self.pos, env=env) for x in range(3)])
4230 self.excinfo_tuple.analyse_expressions(env)
4231 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4233 self.body.analyse_expressions(env)
4235 def generate_handling_code(self, code, end_label):
4236 code.mark_pos(self.pos)
4237 if self.pattern:
4238 self.pattern.generate_evaluation_code(code)
4240 match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
4241 code.putln(
4242 "%s = PyErr_ExceptionMatches(%s);" % (
4243 match_flag,
4244 self.pattern.py_result()))
4245 self.pattern.generate_disposal_code(code)
4246 self.pattern.free_temps(code)
4247 code.putln(
4248 "if (%s) {" %
4249 match_flag)
4250 code.funcstate.release_temp(match_flag)
4251 else:
4252 code.putln("/*except:*/ {")
4254 if not getattr(self.body, 'stats', True):
4255 # most simple case: no exception variable, empty body (pass)
4256 # => reset the exception state, done
4257 code.putln("PyErr_Restore(0,0,0);")
4258 code.put_goto(end_label)
4259 code.putln("}")
4260 return
4262 exc_vars = [code.funcstate.allocate_temp(py_object_type,
4263 manage_ref=True)
4264 for i in xrange(3)]
4265 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4266 # We always have to fetch the exception value even if
4267 # there is no target, because this also normalises the
4268 # exception and stores it in the thread state.
4269 code.globalstate.use_utility_code(get_exception_utility_code)
4270 exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4271 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4272 code.error_goto(self.pos)))
4273 for x in exc_vars:
4274 code.put_gotref(x)
4275 if self.target:
4276 self.exc_value.set_var(exc_vars[1])
4277 self.exc_value.generate_evaluation_code(code)
4278 self.target.generate_assignment_code(self.exc_value, code)
4279 if self.excinfo_target is not None:
4280 for tempvar, node in zip(exc_vars, self.excinfo_tuple.args):
4281 node.set_var(tempvar)
4282 self.excinfo_tuple.generate_evaluation_code(code)
4283 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4285 old_break_label, old_continue_label = code.break_label, code.continue_label
4286 code.break_label = code.new_label('except_break')
4287 code.continue_label = code.new_label('except_continue')
4289 old_exc_vars = code.funcstate.exc_vars
4290 code.funcstate.exc_vars = exc_vars
4291 self.body.generate_execution_code(code)
4292 code.funcstate.exc_vars = old_exc_vars
4293 for var in exc_vars:
4294 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4295 code.put_goto(end_label)
4297 if code.label_used(code.break_label):
4298 code.put_label(code.break_label)
4299 for var in exc_vars:
4300 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4301 code.put_goto(old_break_label)
4302 code.break_label = old_break_label
4304 if code.label_used(code.continue_label):
4305 code.put_label(code.continue_label)
4306 for var in exc_vars:
4307 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4308 code.put_goto(old_continue_label)
4309 code.continue_label = old_continue_label
4311 for temp in exc_vars:
4312 code.funcstate.release_temp(temp)
4314 code.putln(
4315 "}")
4317 def annotate(self, code):
4318 if self.pattern:
4319 self.pattern.annotate(code)
4320 if self.target:
4321 self.target.annotate(code)
4322 self.body.annotate(code)
4325 class TryFinallyStatNode(StatNode):
4326 # try ... finally statement
4328 # body StatNode
4329 # finally_clause StatNode
4331 # The plan is that we funnel all continue, break
4332 # return and error gotos into the beginning of the
4333 # finally block, setting a variable to remember which
4334 # one we're doing. At the end of the finally block, we
4335 # switch on the variable to figure out where to go.
4336 # In addition, if we're doing an error, we save the
4337 # exception on entry to the finally block and restore
4338 # it on exit.
4340 child_attrs = ["body", "finally_clause"]
4342 preserve_exception = 1
4344 disallow_continue_in_try_finally = 0
4345 # There doesn't seem to be any point in disallowing
4346 # continue in the try block, since we have no problem
4347 # handling it.
4349 def create_analysed(pos, env, body, finally_clause):
4350 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4351 return node
4352 create_analysed = staticmethod(create_analysed)
4354 def analyse_control_flow(self, env):
4355 env.start_branching(self.pos)
4356 self.body.analyse_control_flow(env)
4357 env.next_branch(self.body.end_pos())
4358 env.finish_branching(self.body.end_pos())
4359 self.finally_clause.analyse_control_flow(env)
4361 def analyse_declarations(self, env):
4362 self.body.analyse_declarations(env)
4363 self.finally_clause.analyse_declarations(env)
4365 def analyse_expressions(self, env):
4366 self.body.analyse_expressions(env)
4367 self.finally_clause.analyse_expressions(env)
4369 nogil_check = Node.gil_error
4370 gil_message = "Try-finally statement"
4372 def generate_execution_code(self, code):
4373 old_error_label = code.error_label
4374 old_labels = code.all_new_labels()
4375 new_labels = code.get_all_labels()
4376 new_error_label = code.error_label
4377 catch_label = code.new_label()
4378 code.putln(
4379 "/*try:*/ {")
4380 if self.disallow_continue_in_try_finally:
4381 was_in_try_finally = code.funcstate.in_try_finally
4382 code.funcstate.in_try_finally = 1
4383 self.body.generate_execution_code(code)
4384 if self.disallow_continue_in_try_finally:
4385 code.funcstate.in_try_finally = was_in_try_finally
4386 code.putln(
4387 "}")
4388 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4389 code.putln(
4390 "/*finally:*/ {")
4391 cases_used = []
4392 error_label_used = 0
4393 for i, new_label in enumerate(new_labels):
4394 if new_label in code.labels_used:
4395 cases_used.append(i)
4396 if new_label == new_error_label:
4397 error_label_used = 1
4398 error_label_case = i
4399 if cases_used:
4400 code.putln(
4401 "int __pyx_why;")
4402 if error_label_used and self.preserve_exception:
4403 code.putln(
4404 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4405 code.putln(
4406 "int %s;" % Naming.exc_lineno_name)
4407 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4408 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4409 code.putln(exc_var_init_zero)
4410 else:
4411 exc_var_init_zero = None
4412 code.use_label(catch_label)
4413 code.putln(
4414 "__pyx_why = 0; goto %s;" % catch_label)
4415 for i in cases_used:
4416 new_label = new_labels[i]
4417 #if new_label and new_label != "<try>":
4418 if new_label == new_error_label and self.preserve_exception:
4419 self.put_error_catcher(code,
4420 new_error_label, i+1, catch_label, temps_to_clean_up)
4421 else:
4422 code.put('%s: ' % new_label)
4423 if exc_var_init_zero:
4424 code.putln(exc_var_init_zero)
4425 code.putln("__pyx_why = %s; goto %s;" % (
4426 i+1,
4427 catch_label))
4428 code.put_label(catch_label)
4429 code.set_all_labels(old_labels)
4430 if error_label_used:
4431 code.new_error_label()
4432 finally_error_label = code.error_label
4433 self.finally_clause.generate_execution_code(code)
4434 if error_label_used:
4435 if finally_error_label in code.labels_used and self.preserve_exception:
4436 over_label = code.new_label()
4437 code.put_goto(over_label);
4438 code.put_label(finally_error_label)
4439 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4440 for var in Naming.exc_vars:
4441 code.putln("Py_XDECREF(%s);" % var)
4442 code.putln("}")
4443 code.put_goto(old_error_label)
4444 code.put_label(over_label)
4445 code.error_label = old_error_label
4446 if cases_used:
4447 code.putln(
4448 "switch (__pyx_why) {")
4449 for i in cases_used:
4450 old_label = old_labels[i]
4451 if old_label == old_error_label and self.preserve_exception:
4452 self.put_error_uncatcher(code, i+1, old_error_label)
4453 else:
4454 code.use_label(old_label)
4455 code.putln(
4456 "case %s: goto %s;" % (
4457 i+1,
4458 old_label))
4459 code.putln(
4460 "}")
4461 code.putln(
4462 "}")
4464 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4465 code.globalstate.use_utility_code(restore_exception_utility_code)
4466 code.putln(
4467 "%s: {" %
4468 error_label)
4469 code.putln(
4470 "__pyx_why = %s;" %
4471 i)
4472 for temp_name, type in temps_to_clean_up:
4473 code.put_xdecref_clear(temp_name, type)
4474 code.putln(
4475 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4476 Naming.exc_vars)
4477 code.putln(
4478 "%s = %s;" % (
4479 Naming.exc_lineno_name, Naming.lineno_cname))
4480 #code.putln(
4481 # "goto %s;" %
4482 # catch_label)
4483 code.put_goto(catch_label)
4484 code.putln(
4485 "}")
4487 def put_error_uncatcher(self, code, i, error_label):
4488 code.globalstate.use_utility_code(restore_exception_utility_code)
4489 code.putln(
4490 "case %s: {" %
4491 i)
4492 code.putln(
4493 "__Pyx_ErrRestore(%s, %s, %s);" %
4494 Naming.exc_vars)
4495 code.putln(
4496 "%s = %s;" % (
4497 Naming.lineno_cname, Naming.exc_lineno_name))
4498 for var in Naming.exc_vars:
4499 code.putln(
4500 "%s = 0;" %
4501 var)
4502 code.put_goto(error_label)
4503 code.putln(
4504 "}")
4506 def annotate(self, code):
4507 self.body.annotate(code)
4508 self.finally_clause.annotate(code)
4511 class GILStatNode(TryFinallyStatNode):
4512 # 'with gil' or 'with nogil' statement
4514 # state string 'gil' or 'nogil'
4516 # child_attrs = []
4518 preserve_exception = 0
4520 def __init__(self, pos, state, body):
4521 self.state = state
4522 TryFinallyStatNode.__init__(self, pos,
4523 body = body,
4524 finally_clause = GILExitNode(pos, state = state))
4526 def analyse_expressions(self, env):
4527 env.use_utility_code(force_init_threads_utility_code)
4528 was_nogil = env.nogil
4529 env.nogil = 1
4530 TryFinallyStatNode.analyse_expressions(self, env)
4531 env.nogil = was_nogil
4533 nogil_check = None
4535 def generate_execution_code(self, code):
4536 code.mark_pos(self.pos)
4537 if self.state == 'gil':
4538 code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4539 else:
4540 code.putln("{ PyThreadState *_save;")
4541 code.putln("Py_UNBLOCK_THREADS")
4542 TryFinallyStatNode.generate_execution_code(self, code)
4543 code.putln("}")
4546 class GILExitNode(StatNode):
4547 # Used as the 'finally' block in a GILStatNode
4549 # state string 'gil' or 'nogil'
4551 child_attrs = []
4553 def analyse_expressions(self, env):
4554 pass
4556 def generate_execution_code(self, code):
4557 if self.state == 'gil':
4558 code.putln("PyGILState_Release();")
4559 else:
4560 code.putln("Py_BLOCK_THREADS")
4563 class CImportStatNode(StatNode):
4564 # cimport statement
4566 # module_name string Qualified name of module being imported
4567 # as_name string or None Name specified in "as" clause, if any
4569 child_attrs = []
4571 def analyse_declarations(self, env):
4572 if not env.is_module_scope:
4573 error(self.pos, "cimport only allowed at module level")
4574 return
4575 module_scope = env.find_module(self.module_name, self.pos)
4576 if "." in self.module_name:
4577 names = [EncodedString(name) for name in self.module_name.split(".")]
4578 top_name = names[0]
4579 top_module_scope = env.context.find_submodule(top_name)
4580 module_scope = top_module_scope
4581 for name in names[1:]:
4582 submodule_scope = module_scope.find_submodule(name)
4583 module_scope.declare_module(name, submodule_scope, self.pos)
4584 module_scope = submodule_scope
4585 if self.as_name:
4586 env.declare_module(self.as_name, module_scope, self.pos)
4587 else:
4588 env.declare_module(top_name, top_module_scope, self.pos)
4589 else:
4590 name = self.as_name or self.module_name
4591 env.declare_module(name, module_scope, self.pos)
4593 def analyse_expressions(self, env):
4594 pass
4596 def generate_execution_code(self, code):
4597 pass
4600 class FromCImportStatNode(StatNode):
4601 # from ... cimport statement
4603 # module_name string Qualified name of module
4604 # imported_names [(pos, name, as_name, kind)] Names to be imported
4606 child_attrs = []
4608 def analyse_declarations(self, env):
4609 if not env.is_module_scope:
4610 error(self.pos, "cimport only allowed at module level")
4611 return
4612 module_scope = env.find_module(self.module_name, self.pos)
4613 env.add_imported_module(module_scope)
4614 for pos, name, as_name, kind in self.imported_names:
4615 if name == "*":
4616 for local_name, entry in module_scope.entries.items():
4617 env.add_imported_entry(local_name, entry, pos)
4618 else:
4619 entry = module_scope.lookup(name)
4620 if entry:
4621 if kind and not self.declaration_matches(entry, kind):
4622 entry.redeclared(pos)
4623 else:
4624 if kind == 'struct' or kind == 'union':
4625 entry = module_scope.declare_struct_or_union(name,
4626 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4627 elif kind == 'class':
4628 entry = module_scope.declare_c_class(name, pos = pos,
4629 module_name = self.module_name)
4630 else:
4631 submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
4632 if submodule_scope.parent_module is module_scope:
4633 env.declare_module(as_name or name, submodule_scope, self.pos)
4634 else:
4635 error(pos, "Name '%s' not declared in module '%s'"
4636 % (name, self.module_name))
4638 if entry:
4639 local_name = as_name or name
4640 env.add_imported_entry(local_name, entry, pos)
4642 def declaration_matches(self, entry, kind):
4643 if not entry.is_type:
4644 return 0
4645 type = entry.type
4646 if kind == 'class':
4647 if not type.is_extension_type:
4648 return 0
4649 else:
4650 if not type.is_struct_or_union:
4651 return 0
4652 if kind != type.kind:
4653 return 0
4654 return 1
4656 def analyse_expressions(self, env):
4657 pass
4659 def generate_execution_code(self, code):
4660 pass
4663 class FromImportStatNode(StatNode):
4664 # from ... import statement
4666 # module ImportNode
4667 # items [(string, NameNode)]
4668 # interned_items [(string, NameNode, ExprNode)]
4669 # item PyTempNode used internally
4670 # import_star boolean used internally
4672 child_attrs = ["module"]
4673 import_star = 0
4675 def analyse_declarations(self, env):
4676 for name, target in self.items:
4677 if name == "*":
4678 if not env.is_module_scope:
4679 error(self.pos, "import * only allowed at module level")
4680 return
4681 env.has_import_star = 1
4682 self.import_star = 1
4683 else:
4684 target.analyse_target_declaration(env)
4686 def analyse_expressions(self, env):
4687 import ExprNodes
4688 self.module.analyse_expressions(env)
4689 self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
4690 self.interned_items = []
4691 for name, target in self.items:
4692 if name == '*':
4693 for _, entry in env.entries.items():
4694 if not entry.is_type and entry.type.is_extension_type:
4695 env.use_utility_code(ExprNodes.type_test_utility_code)
4696 break
4697 else:
4698 entry = env.lookup(target.name)
4699 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4700 continue # already cimported
4701 target.analyse_target_expression(env, None)
4702 if target.type is py_object_type:
4703 coerced_item = None
4704 else:
4705 coerced_item = self.item.coerce_to(target.type, env)
4706 self.interned_items.append(
4707 (name, target, coerced_item))
4709 def generate_execution_code(self, code):
4710 self.module.generate_evaluation_code(code)
4711 if self.import_star:
4712 code.putln(
4713 'if (%s(%s) < 0) %s;' % (
4714 Naming.import_star,
4715 self.module.py_result(),
4716 code.error_goto(self.pos)))
4717 item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
4718 self.item.set_cname(item_temp)
4719 for name, target, coerced_item in self.interned_items:
4720 cname = code.intern_identifier(name)
4721 code.putln(
4722 '%s = PyObject_GetAttr(%s, %s); %s' % (
4723 item_temp,
4724 self.module.py_result(),
4725 cname,
4726 code.error_goto_if_null(item_temp, self.pos)))
4727 code.put_gotref(item_temp)
4728 if coerced_item is None:
4729 target.generate_assignment_code(self.item, code)
4730 else:
4731 coerced_item.allocate_temp_result(code)
4732 coerced_item.generate_result_code(code)
4733 target.generate_assignment_code(coerced_item, code)
4734 code.put_decref_clear(item_temp, py_object_type)
4735 code.funcstate.release_temp(item_temp)
4736 self.module.generate_disposal_code(code)
4737 self.module.free_temps(code)
4741 #------------------------------------------------------------------------------------
4743 # Runtime support code
4745 #------------------------------------------------------------------------------------
4747 utility_function_predeclarations = \
4748 """
4749 #ifdef __GNUC__
4750 #define INLINE __inline__
4751 #elif _WIN32
4752 #define INLINE __inline
4753 #else
4754 #define INLINE
4755 #endif
4757 typedef struct {PyObject **p; char *s; const long n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; /*proto*/
4759 """
4761 if Options.gcc_branch_hints:
4762 branch_prediction_macros = \
4763 """
4764 #ifdef __GNUC__
4765 /* Test for GCC > 2.95 */
4766 #if __GNUC__ > 2 || \
4767 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4768 #define likely(x) __builtin_expect(!!(x), 1)
4769 #define unlikely(x) __builtin_expect(!!(x), 0)
4770 #else /* __GNUC__ > 2 ... */
4771 #define likely(x) (x)
4772 #define unlikely(x) (x)
4773 #endif /* __GNUC__ > 2 ... */
4774 #else /* __GNUC__ */
4775 #define likely(x) (x)
4776 #define unlikely(x) (x)
4777 #endif /* __GNUC__ */
4778 """
4779 else:
4780 branch_prediction_macros = \
4781 """
4782 #define likely(x) (x)
4783 #define unlikely(x) (x)
4784 """
4786 #get_name_predeclaration = \
4787 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4789 #get_name_interned_predeclaration = \
4790 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4792 #------------------------------------------------------------------------------------
4794 printing_utility_code = UtilityCode(
4795 proto = """
4796 static int __Pyx_Print(PyObject *, int); /*proto*/
4797 #if PY_MAJOR_VERSION >= 3
4798 static PyObject* %s = 0;
4799 static PyObject* %s = 0;
4800 #endif
4801 """ % (Naming.print_function, Naming.print_function_kwargs),
4802 impl = r"""
4803 #if PY_MAJOR_VERSION < 3
4804 static PyObject *__Pyx_GetStdout(void) {
4805 PyObject *f = PySys_GetObject((char *)"stdout");
4806 if (!f) {
4807 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4809 return f;
4812 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4813 PyObject *f;
4814 PyObject* v;
4815 int i;
4817 if (!(f = __Pyx_GetStdout()))
4818 return -1;
4819 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4820 if (PyFile_SoftSpace(f, 1)) {
4821 if (PyFile_WriteString(" ", f) < 0)
4822 return -1;
4824 v = PyTuple_GET_ITEM(arg_tuple, i);
4825 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4826 return -1;
4827 if (PyString_Check(v)) {
4828 char *s = PyString_AsString(v);
4829 Py_ssize_t len = PyString_Size(v);
4830 if (len > 0 &&
4831 isspace(Py_CHARMASK(s[len-1])) &&
4832 s[len-1] != ' ')
4833 PyFile_SoftSpace(f, 0);
4836 if (newline) {
4837 if (PyFile_WriteString("\n", f) < 0)
4838 return -1;
4839 PyFile_SoftSpace(f, 0);
4841 return 0;
4844 #else /* Python 3 has a print function */
4846 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4847 PyObject* kwargs = 0;
4848 PyObject* result = 0;
4849 PyObject* end_string;
4850 if (!%(PRINT_FUNCTION)s) {
4851 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4852 if (!%(PRINT_FUNCTION)s)
4853 return -1;
4855 if (!newline) {
4856 if (!%(PRINT_KWARGS)s) {
4857 %(PRINT_KWARGS)s = PyDict_New();
4858 if (!%(PRINT_KWARGS)s)
4859 return -1;
4860 end_string = PyUnicode_FromStringAndSize(" ", 1);
4861 if (!end_string)
4862 return -1;
4863 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4864 Py_DECREF(end_string);
4865 return -1;
4867 Py_DECREF(end_string);
4869 kwargs = %(PRINT_KWARGS)s;
4871 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4872 if (!result)
4873 return -1;
4874 Py_DECREF(result);
4875 return 0;
4878 #endif
4879 """ % {'BUILTINS' : Naming.builtins_cname,
4880 'PRINT_FUNCTION' : Naming.print_function,
4881 'PRINT_KWARGS' : Naming.print_function_kwargs}
4885 printing_one_utility_code = UtilityCode(
4886 proto = """
4887 static int __Pyx_PrintOne(PyObject *o); /*proto*/
4888 """,
4889 impl = r"""
4890 #if PY_MAJOR_VERSION < 3
4892 static int __Pyx_PrintOne(PyObject *o) {
4893 PyObject *f;
4894 if (!(f = __Pyx_GetStdout()))
4895 return -1;
4896 if (PyFile_SoftSpace(f, 0)) {
4897 if (PyFile_WriteString(" ", f) < 0)
4898 return -1;
4900 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
4901 return -1;
4902 if (PyFile_WriteString("\n", f) < 0)
4903 return -1;
4904 return 0;
4905 /* the line below is just to avoid compiler
4906 * compiler warnings about unused functions */
4907 return __Pyx_Print(NULL, 0);
4910 #else /* Python 3 has a print function */
4912 static int __Pyx_PrintOne(PyObject *o) {
4913 int res;
4914 PyObject* arg_tuple = PyTuple_New(1);
4915 if (unlikely(!arg_tuple))
4916 return -1;
4917 Py_INCREF(o);
4918 PyTuple_SET_ITEM(arg_tuple, 0, o);
4919 res = __Pyx_Print(arg_tuple, 1);
4920 Py_DECREF(arg_tuple);
4921 return res;
4924 #endif
4925 """,
4926 requires=[printing_utility_code])
4930 #------------------------------------------------------------------------------------
4932 # Exception raising code
4934 # Exceptions are raised by __Pyx_Raise() and stored as plain
4935 # type/value/tb in PyThreadState->curexc_*. When being caught by an
4936 # 'except' statement, curexc_* is moved over to exc_* by
4937 # __Pyx_GetException()
4939 restore_exception_utility_code = UtilityCode(
4940 proto = """
4941 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4942 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
4943 """,
4944 impl = """
4945 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
4946 PyObject *tmp_type, *tmp_value, *tmp_tb;
4947 PyThreadState *tstate = PyThreadState_GET();
4949 tmp_type = tstate->curexc_type;
4950 tmp_value = tstate->curexc_value;
4951 tmp_tb = tstate->curexc_traceback;
4952 tstate->curexc_type = type;
4953 tstate->curexc_value = value;
4954 tstate->curexc_traceback = tb;
4955 Py_XDECREF(tmp_type);
4956 Py_XDECREF(tmp_value);
4957 Py_XDECREF(tmp_tb);
4960 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
4961 PyThreadState *tstate = PyThreadState_GET();
4962 *type = tstate->curexc_type;
4963 *value = tstate->curexc_value;
4964 *tb = tstate->curexc_traceback;
4966 tstate->curexc_type = 0;
4967 tstate->curexc_value = 0;
4968 tstate->curexc_traceback = 0;
4971 """)
4973 # The following function is based on do_raise() from ceval.c. There
4974 # are separate versions for Python2 and Python3 as exception handling
4975 # has changed quite a lot between the two versions.
4977 raise_utility_code = UtilityCode(
4978 proto = """
4979 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4980 """,
4981 impl = """
4982 #if PY_MAJOR_VERSION < 3
4983 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4984 Py_XINCREF(type);
4985 Py_XINCREF(value);
4986 Py_XINCREF(tb);
4987 /* First, check the traceback argument, replacing None with NULL. */
4988 if (tb == Py_None) {
4989 Py_DECREF(tb);
4990 tb = 0;
4992 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4993 PyErr_SetString(PyExc_TypeError,
4994 "raise: arg 3 must be a traceback or None");
4995 goto raise_error;
4997 /* Next, replace a missing value with None */
4998 if (value == NULL) {
4999 value = Py_None;
5000 Py_INCREF(value);
5002 #if PY_VERSION_HEX < 0x02050000
5003 if (!PyClass_Check(type))
5004 #else
5005 if (!PyType_Check(type))
5006 #endif
5008 /* Raising an instance. The value should be a dummy. */
5009 if (value != Py_None) {
5010 PyErr_SetString(PyExc_TypeError,
5011 "instance exception may not have a separate value");
5012 goto raise_error;
5014 /* Normalize to raise <class>, <instance> */
5015 Py_DECREF(value);
5016 value = type;
5017 #if PY_VERSION_HEX < 0x02050000
5018 if (PyInstance_Check(type)) {
5019 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
5020 Py_INCREF(type);
5022 else {
5023 type = 0;
5024 PyErr_SetString(PyExc_TypeError,
5025 "raise: exception must be an old-style class or instance");
5026 goto raise_error;
5028 #else
5029 type = (PyObject*) Py_TYPE(type);
5030 Py_INCREF(type);
5031 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
5032 PyErr_SetString(PyExc_TypeError,
5033 "raise: exception class must be a subclass of BaseException");
5034 goto raise_error;
5036 #endif
5039 __Pyx_ErrRestore(type, value, tb);
5040 return;
5041 raise_error:
5042 Py_XDECREF(value);
5043 Py_XDECREF(type);
5044 Py_XDECREF(tb);
5045 return;
5048 #else /* Python 3+ */
5050 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5051 if (tb == Py_None) {
5052 tb = 0;
5053 } else if (tb && !PyTraceBack_Check(tb)) {
5054 PyErr_SetString(PyExc_TypeError,
5055 "raise: arg 3 must be a traceback or None");
5056 goto bad;
5058 if (value == Py_None)
5059 value = 0;
5061 if (PyExceptionInstance_Check(type)) {
5062 if (value) {
5063 PyErr_SetString(PyExc_TypeError,
5064 "instance exception may not have a separate value");
5065 goto bad;
5067 value = type;
5068 type = (PyObject*) Py_TYPE(value);
5069 } else if (!PyExceptionClass_Check(type)) {
5070 PyErr_SetString(PyExc_TypeError,
5071 "raise: exception class must be a subclass of BaseException");
5072 goto bad;
5075 PyErr_SetObject(type, value);
5077 if (tb) {
5078 PyThreadState *tstate = PyThreadState_GET();
5079 PyObject* tmp_tb = tstate->curexc_traceback;
5080 if (tb != tmp_tb) {
5081 Py_INCREF(tb);
5082 tstate->curexc_traceback = tb;
5083 Py_XDECREF(tmp_tb);
5087 bad:
5088 return;
5090 #endif
5091 """,
5092 requires=[restore_exception_utility_code])
5094 #------------------------------------------------------------------------------------
5096 get_exception_utility_code = UtilityCode(
5097 proto = """
5098 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5099 """,
5100 impl = """
5101 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5102 PyObject *local_type, *local_value, *local_tb;
5103 PyObject *tmp_type, *tmp_value, *tmp_tb;
5104 PyThreadState *tstate = PyThreadState_GET();
5105 local_type = tstate->curexc_type;
5106 local_value = tstate->curexc_value;
5107 local_tb = tstate->curexc_traceback;
5108 tstate->curexc_type = 0;
5109 tstate->curexc_value = 0;
5110 tstate->curexc_traceback = 0;
5111 PyErr_NormalizeException(&local_type, &local_value, &local_tb);
5112 if (unlikely(tstate->curexc_type))
5113 goto bad;
5114 #if PY_MAJOR_VERSION >= 3
5115 if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
5116 goto bad;
5117 #endif
5118 *type = local_type;
5119 *value = local_value;
5120 *tb = local_tb;
5121 Py_INCREF(local_type);
5122 Py_INCREF(local_value);
5123 Py_INCREF(local_tb);
5124 tmp_type = tstate->exc_type;
5125 tmp_value = tstate->exc_value;
5126 tmp_tb = tstate->exc_traceback;
5127 tstate->exc_type = local_type;
5128 tstate->exc_value = local_value;
5129 tstate->exc_traceback = local_tb;
5130 /* Make sure tstate is in a consistent state when we XDECREF
5131 these objects (XDECREF may run arbitrary code). */
5132 Py_XDECREF(tmp_type);
5133 Py_XDECREF(tmp_value);
5134 Py_XDECREF(tmp_tb);
5135 return 0;
5136 bad:
5137 *type = 0;
5138 *value = 0;
5139 *tb = 0;
5140 Py_XDECREF(local_type);
5141 Py_XDECREF(local_value);
5142 Py_XDECREF(local_tb);
5143 return -1;
5146 """)
5148 #------------------------------------------------------------------------------------
5150 get_exception_tuple_utility_code = UtilityCode(proto="""
5151 static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
5152 """,
5153 # I doubt that calling __Pyx_GetException() here is correct as it moves
5154 # the exception from tstate->curexc_* to tstate->exc_*, which prevents
5155 # exception handlers later on from receiving it.
5156 impl = """
5157 static PyObject *__Pyx_GetExceptionTuple(void) {
5158 PyObject *type = NULL, *value = NULL, *tb = NULL;
5159 if (__Pyx_GetException(&type, &value, &tb) == 0) {
5160 PyObject* exc_info = PyTuple_New(3);
5161 if (exc_info) {
5162 Py_INCREF(type);
5163 Py_INCREF(value);
5164 Py_INCREF(tb);
5165 PyTuple_SET_ITEM(exc_info, 0, type);
5166 PyTuple_SET_ITEM(exc_info, 1, value);
5167 PyTuple_SET_ITEM(exc_info, 2, tb);
5168 return exc_info;
5171 return NULL;
5173 """,
5174 requires=[get_exception_utility_code])
5176 #------------------------------------------------------------------------------------
5178 reset_exception_utility_code = UtilityCode(
5179 proto = """
5180 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5181 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5182 """,
5183 impl = """
5184 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5185 PyThreadState *tstate = PyThreadState_GET();
5186 *type = tstate->exc_type;
5187 *value = tstate->exc_value;
5188 *tb = tstate->exc_traceback;
5189 Py_XINCREF(*type);
5190 Py_XINCREF(*value);
5191 Py_XINCREF(*tb);
5194 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5195 PyObject *tmp_type, *tmp_value, *tmp_tb;
5196 PyThreadState *tstate = PyThreadState_GET();
5197 tmp_type = tstate->exc_type;
5198 tmp_value = tstate->exc_value;
5199 tmp_tb = tstate->exc_traceback;
5200 tstate->exc_type = type;
5201 tstate->exc_value = value;
5202 tstate->exc_traceback = tb;
5203 Py_XDECREF(tmp_type);
5204 Py_XDECREF(tmp_value);
5205 Py_XDECREF(tmp_tb);
5207 """)
5209 #------------------------------------------------------------------------------------
5211 arg_type_test_utility_code = UtilityCode(
5212 proto = """
5213 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5214 const char *name, int exact); /*proto*/
5215 """,
5216 impl = """
5217 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5218 const char *name, int exact)
5220 if (!type) {
5221 PyErr_Format(PyExc_SystemError, "Missing type object");
5222 return 0;
5224 if (none_allowed && obj == Py_None) return 1;
5225 else if (exact) {
5226 if (Py_TYPE(obj) == type) return 1;
5228 else {
5229 if (PyObject_TypeCheck(obj, type)) return 1;
5231 PyErr_Format(PyExc_TypeError,
5232 "Argument '%s' has incorrect type (expected %s, got %s)",
5233 name, type->tp_name, Py_TYPE(obj)->tp_name);
5234 return 0;
5236 """)
5238 #------------------------------------------------------------------------------------
5240 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5241 # many or too few positional arguments were found. This handles
5242 # Py_ssize_t formatting correctly.
5244 raise_argtuple_invalid_utility_code = UtilityCode(
5245 proto = """
5246 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5247 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5248 """,
5249 impl = """
5250 static void __Pyx_RaiseArgtupleInvalid(
5251 const char* func_name,
5252 int exact,
5253 Py_ssize_t num_min,
5254 Py_ssize_t num_max,
5255 Py_ssize_t num_found)
5257 Py_ssize_t num_expected;
5258 const char *number, *more_or_less;
5260 if (num_found < num_min) {
5261 num_expected = num_min;
5262 more_or_less = "at least";
5263 } else {
5264 num_expected = num_max;
5265 more_or_less = "at most";
5267 if (exact) {
5268 more_or_less = "exactly";
5270 number = (num_expected == 1) ? "" : "s";
5271 PyErr_Format(PyExc_TypeError,
5272 #if PY_VERSION_HEX < 0x02050000
5273 "%s() takes %s %d positional argument%s (%d given)",
5274 #else
5275 "%s() takes %s %zd positional argument%s (%zd given)",
5276 #endif
5277 func_name, more_or_less, num_expected, number, num_found);
5279 """)
5281 raise_keyword_required_utility_code = UtilityCode(
5282 proto = """
5283 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5284 """,
5285 impl = """
5286 static INLINE void __Pyx_RaiseKeywordRequired(
5287 const char* func_name,
5288 PyObject* kw_name)
5290 PyErr_Format(PyExc_TypeError,
5291 #if PY_MAJOR_VERSION >= 3
5292 "%s() needs keyword-only argument %U", func_name, kw_name);
5293 #else
5294 "%s() needs keyword-only argument %s", func_name,
5295 PyString_AS_STRING(kw_name));
5296 #endif
5298 """)
5300 raise_double_keywords_utility_code = UtilityCode(
5301 proto = """
5302 static void __Pyx_RaiseDoubleKeywordsError(
5303 const char* func_name, PyObject* kw_name); /*proto*/
5304 """,
5305 impl = """
5306 static void __Pyx_RaiseDoubleKeywordsError(
5307 const char* func_name,
5308 PyObject* kw_name)
5310 PyErr_Format(PyExc_TypeError,
5311 #if PY_MAJOR_VERSION >= 3
5312 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5313 #else
5314 "%s() got multiple values for keyword argument '%s'", func_name,
5315 PyString_AS_STRING(kw_name));
5316 #endif
5318 """)
5320 #------------------------------------------------------------------------------------
5322 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5323 # were passed to a function, or if any keywords were passed to a
5324 # function that does not accept them.
5326 keyword_string_check_utility_code = UtilityCode(
5327 proto = """
5328 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5329 const char* function_name, int kw_allowed); /*proto*/
5330 """,
5331 impl = """
5332 static INLINE int __Pyx_CheckKeywordStrings(
5333 PyObject *kwdict,
5334 const char* function_name,
5335 int kw_allowed)
5337 PyObject* key = 0;
5338 Py_ssize_t pos = 0;
5339 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5340 #if PY_MAJOR_VERSION < 3
5341 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5342 #else
5343 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5344 #endif
5345 goto invalid_keyword_type;
5347 if ((!kw_allowed) && unlikely(key))
5348 goto invalid_keyword;
5349 return 1;
5350 invalid_keyword_type:
5351 PyErr_Format(PyExc_TypeError,
5352 "%s() keywords must be strings", function_name);
5353 return 0;
5354 invalid_keyword:
5355 PyErr_Format(PyExc_TypeError,
5356 #if PY_MAJOR_VERSION < 3
5357 "%s() got an unexpected keyword argument '%s'",
5358 function_name, PyString_AsString(key));
5359 #else
5360 "%s() got an unexpected keyword argument '%U'",
5361 function_name, key);
5362 #endif
5363 return 0;
5365 """)
5367 #------------------------------------------------------------------------------------
5369 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5370 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5371 # keywords will raise an invalid keyword error.
5373 # Three kinds of errors are checked: 1) non-string keywords, 2)
5374 # unexpected keywords and 3) overlap with positional arguments.
5376 # If num_posargs is greater 0, it denotes the number of positional
5377 # arguments that were passed and that must therefore not appear
5378 # amongst the keywords as well.
5380 # This method does not check for required keyword arguments.
5383 parse_keywords_utility_code = UtilityCode(
5384 proto = """
5385 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5386 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5387 const char* function_name); /*proto*/
5388 """,
5389 impl = """
5390 static int __Pyx_ParseOptionalKeywords(
5391 PyObject *kwds,
5392 PyObject **argnames[],
5393 PyObject *kwds2,
5394 PyObject *values[],
5395 Py_ssize_t num_pos_args,
5396 const char* function_name)
5398 PyObject *key = 0, *value = 0;
5399 Py_ssize_t pos = 0;
5400 PyObject*** name;
5401 PyObject*** first_kw_arg = argnames + num_pos_args;
5403 while (PyDict_Next(kwds, &pos, &key, &value)) {
5404 name = first_kw_arg;
5405 while (*name && (**name != key)) name++;
5406 if (*name) {
5407 values[name-argnames] = value;
5408 } else {
5409 #if PY_MAJOR_VERSION < 3
5410 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5411 #else
5412 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5413 #endif
5414 goto invalid_keyword_type;
5415 } else {
5416 for (name = first_kw_arg; *name; name++) {
5417 #if PY_MAJOR_VERSION >= 3
5418 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5419 PyUnicode_Compare(**name, key) == 0) break;
5420 #else
5421 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5422 _PyString_Eq(**name, key)) break;
5423 #endif
5425 if (*name) {
5426 values[name-argnames] = value;
5427 } else {
5428 /* unexpected keyword found */
5429 for (name=argnames; name != first_kw_arg; name++) {
5430 if (**name == key) goto arg_passed_twice;
5431 #if PY_MAJOR_VERSION >= 3
5432 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5433 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5434 #else
5435 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5436 _PyString_Eq(**name, key)) goto arg_passed_twice;
5437 #endif
5439 if (kwds2) {
5440 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5441 } else {
5442 goto invalid_keyword;
5448 return 0;
5449 arg_passed_twice:
5450 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5451 goto bad;
5452 invalid_keyword_type:
5453 PyErr_Format(PyExc_TypeError,
5454 "%s() keywords must be strings", function_name);
5455 goto bad;
5456 invalid_keyword:
5457 PyErr_Format(PyExc_TypeError,
5458 #if PY_MAJOR_VERSION < 3
5459 "%s() got an unexpected keyword argument '%s'",
5460 function_name, PyString_AsString(key));
5461 #else
5462 "%s() got an unexpected keyword argument '%U'",
5463 function_name, key);
5464 #endif
5465 bad:
5466 return -1;
5468 """)
5470 #------------------------------------------------------------------------------------
5472 traceback_utility_code = UtilityCode(
5473 proto = """
5474 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5475 """,
5476 impl = """
5477 #include "compile.h"
5478 #include "frameobject.h"
5479 #include "traceback.h"
5481 static void __Pyx_AddTraceback(const char *funcname) {
5482 PyObject *py_srcfile = 0;
5483 PyObject *py_funcname = 0;
5484 PyObject *py_globals = 0;
5485 PyCodeObject *py_code = 0;
5486 PyFrameObject *py_frame = 0;
5488 #if PY_MAJOR_VERSION < 3
5489 py_srcfile = PyString_FromString(%(FILENAME)s);
5490 #else
5491 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5492 #endif
5493 if (!py_srcfile) goto bad;
5494 if (%(CLINENO)s) {
5495 #if PY_MAJOR_VERSION < 3
5496 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5497 #else
5498 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5499 #endif
5501 else {
5502 #if PY_MAJOR_VERSION < 3
5503 py_funcname = PyString_FromString(funcname);
5504 #else
5505 py_funcname = PyUnicode_FromString(funcname);
5506 #endif
5508 if (!py_funcname) goto bad;
5509 py_globals = PyModule_GetDict(%(GLOBALS)s);
5510 if (!py_globals) goto bad;
5511 py_code = PyCode_New(
5512 0, /*int argcount,*/
5513 #if PY_MAJOR_VERSION >= 3
5514 0, /*int kwonlyargcount,*/
5515 #endif
5516 0, /*int nlocals,*/
5517 0, /*int stacksize,*/
5518 0, /*int flags,*/
5519 %(EMPTY_BYTES)s, /*PyObject *code,*/
5520 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5521 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5522 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5523 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5524 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5525 py_srcfile, /*PyObject *filename,*/
5526 py_funcname, /*PyObject *name,*/
5527 %(LINENO)s, /*int firstlineno,*/
5528 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5529 );
5530 if (!py_code) goto bad;
5531 py_frame = PyFrame_New(
5532 PyThreadState_GET(), /*PyThreadState *tstate,*/
5533 py_code, /*PyCodeObject *code,*/
5534 py_globals, /*PyObject *globals,*/
5535 0 /*PyObject *locals*/
5536 );
5537 if (!py_frame) goto bad;
5538 py_frame->f_lineno = %(LINENO)s;
5539 PyTraceBack_Here(py_frame);
5540 bad:
5541 Py_XDECREF(py_srcfile);
5542 Py_XDECREF(py_funcname);
5543 Py_XDECREF(py_code);
5544 Py_XDECREF(py_frame);
5546 """ % {
5547 'FILENAME': Naming.filename_cname,
5548 'LINENO': Naming.lineno_cname,
5549 'CFILENAME': Naming.cfilenm_cname,
5550 'CLINENO': Naming.clineno_cname,
5551 'GLOBALS': Naming.module_cname,
5552 'EMPTY_TUPLE' : Naming.empty_tuple,
5553 'EMPTY_BYTES' : Naming.empty_bytes,
5554 })
5556 #------------------------------------------------------------------------------------
5558 unraisable_exception_utility_code = UtilityCode(
5559 proto = """
5560 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5561 """,
5562 impl = """
5563 static void __Pyx_WriteUnraisable(const char *name) {
5564 PyObject *old_exc, *old_val, *old_tb;
5565 PyObject *ctx;
5566 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5567 #if PY_MAJOR_VERSION < 3
5568 ctx = PyString_FromString(name);
5569 #else
5570 ctx = PyUnicode_FromString(name);
5571 #endif
5572 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5573 if (!ctx) {
5574 PyErr_WriteUnraisable(Py_None);
5575 } else {
5576 PyErr_WriteUnraisable(ctx);
5577 Py_DECREF(ctx);
5580 """,
5581 requires=[restore_exception_utility_code])
5583 #------------------------------------------------------------------------------------
5585 set_vtable_utility_code = UtilityCode(
5586 proto = """
5587 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5588 """,
5589 impl = """
5590 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5591 #if PY_VERSION_HEX < 0x03010000
5592 PyObject *ob = PyCObject_FromVoidPtr(vtable, 0);
5593 #else
5594 PyObject *ob = PyCapsule_New(vtable, 0, 0);
5595 #endif
5596 if (!ob)
5597 goto bad;
5598 if (PyDict_SetItemString(dict, "__pyx_vtable__", ob) < 0)
5599 goto bad;
5600 Py_DECREF(ob);
5601 return 0;
5602 bad:
5603 Py_XDECREF(ob);
5604 return -1;
5606 """)
5608 #------------------------------------------------------------------------------------
5610 get_vtable_utility_code = UtilityCode(
5611 proto = """
5612 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5613 """,
5614 impl = r"""
5615 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5616 PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5617 if (!ob)
5618 goto bad;
5619 #if PY_VERSION_HEX < 0x03010000
5620 *(void **)vtabptr = PyCObject_AsVoidPtr(ob);
5621 #else
5622 *(void **)vtabptr = PyCapsule_GetPointer(ob, 0);
5623 #endif
5624 if (!*(void **)vtabptr)
5625 goto bad;
5626 Py_DECREF(ob);
5627 return 0;
5628 bad:
5629 Py_XDECREF(ob);
5630 return -1;
5632 """)
5634 #------------------------------------------------------------------------------------
5636 init_string_tab_utility_code = UtilityCode(
5637 proto = """
5638 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5639 """,
5640 impl = """
5641 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5642 while (t->p) {
5643 #if PY_MAJOR_VERSION < 3
5644 if (t->is_unicode) {
5645 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5646 } else if (t->intern) {
5647 *t->p = PyString_InternFromString(t->s);
5648 } else {
5649 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5651 #else /* Python 3+ has unicode identifiers */
5652 if (t->is_unicode | t->is_str) {
5653 if (t->intern) {
5654 *t->p = PyUnicode_InternFromString(t->s);
5655 } else if (t->encoding) {
5656 *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
5657 } else {
5658 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5660 } else {
5661 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5663 #endif
5664 if (!*t->p)
5665 return -1;
5666 ++t;
5668 return 0;
5670 """)
5672 #------------------------------------------------------------------------------------
5674 force_init_threads_utility_code = UtilityCode(
5675 proto="""
5676 #ifndef __PYX_FORCE_INIT_THREADS
5677 #if PY_VERSION_HEX < 0x02040200
5678 #define __PYX_FORCE_INIT_THREADS 1
5679 #else
5680 #define __PYX_FORCE_INIT_THREADS 0
5681 #endif
5682 #endif
5683 """)
5685 #------------------------------------------------------------------------------------
5687 # Note that cPython ignores PyTrace_EXCEPTION,
5688 # but maybe some other profilers don't.
5690 profile_utility_code = UtilityCode(proto="""
5691 #ifndef CYTHON_PROFILE
5692 #define CYTHON_PROFILE 1
5693 #endif
5695 #ifndef CYTHON_PROFILE_REUSE_FRAME
5696 #define CYTHON_PROFILE_REUSE_FRAME 0
5697 #endif
5699 #if CYTHON_PROFILE
5701 #include "compile.h"
5702 #include "frameobject.h"
5703 #include "traceback.h"
5705 #if CYTHON_PROFILE_REUSE_FRAME
5706 #define CYTHON_FRAME_MODIFIER static
5707 #define CYTHON_FRAME_DEL
5708 #else
5709 #define CYTHON_FRAME_MODIFIER
5710 #define CYTHON_FRAME_DEL Py_DECREF(%(FRAME)s)
5711 #endif
5713 #define __Pyx_TraceCall(funcname, srcfile, firstlineno) \\
5714 static PyCodeObject *%(FRAME_CODE)s = NULL; \\
5715 CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL; \\
5716 int __Pyx_use_tracing = 0; \\
5717 if (unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc)) { \\
5718 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&%(FRAME_CODE)s, &%(FRAME)s, funcname, srcfile, firstlineno); \\
5721 #define __Pyx_TraceException() \\
5722 if (unlikely(__Pyx_use_tracing( && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5723 PyObject *exc_info = __Pyx_GetExceptionTuple(); \\
5724 if (exc_info) { \\
5725 PyThreadState_GET()->c_profilefunc( \\
5726 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_EXCEPTION, exc_info); \\
5727 Py_DECREF(exc_info); \\
5728 } \\
5731 #define __Pyx_TraceReturn(result) \\
5732 if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5733 PyThreadState_GET()->c_profilefunc( \\
5734 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_RETURN, (PyObject*)result); \\
5735 CYTHON_FRAME_DEL; \\
5738 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
5739 static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
5741 #else
5742 #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
5743 #define __Pyx_TraceException()
5744 #define __Pyx_TraceReturn(result)
5745 #endif /* CYTHON_PROFILE */
5746 """
5747 % {
5748 "FRAME": Naming.frame_cname,
5749 "FRAME_CODE": Naming.frame_code_cname,
5750 },
5751 impl = """
5753 #if CYTHON_PROFILE
5755 static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
5756 PyFrameObject** frame,
5757 const char *funcname,
5758 const char *srcfile,
5759 int firstlineno) {
5760 if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) {
5761 if (*code == NULL) {
5762 *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
5763 if (*code == NULL) return 0;
5765 *frame = PyFrame_New(
5766 PyThreadState_GET(), /*PyThreadState *tstate*/
5767 *code, /*PyCodeObject *code*/
5768 PyModule_GetDict(%(MODULE)s), /*PyObject *globals*/
5769 0 /*PyObject *locals*/
5770 );
5771 if (*frame == NULL) return 0;
5773 else {
5774 (*frame)->f_tstate = PyThreadState_GET();
5776 return PyThreadState_GET()->c_profilefunc(PyThreadState_GET()->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
5779 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
5780 PyObject *py_srcfile = 0;
5781 PyObject *py_funcname = 0;
5782 PyCodeObject *py_code = 0;
5784 #if PY_MAJOR_VERSION < 3
5785 py_funcname = PyString_FromString(funcname);
5786 py_srcfile = PyString_FromString(srcfile);
5787 #else
5788 py_funcname = PyUnicode_FromString(funcname);
5789 py_srcfile = PyUnicode_FromString(srcfile);
5790 #endif
5791 if (!py_funcname | !py_srcfile) goto bad;
5793 py_code = PyCode_New(
5794 0, /*int argcount,*/
5795 #if PY_MAJOR_VERSION >= 3
5796 0, /*int kwonlyargcount,*/
5797 #endif
5798 0, /*int nlocals,*/
5799 0, /*int stacksize,*/
5800 0, /*int flags,*/
5801 %(EMPTY_BYTES)s, /*PyObject *code,*/
5802 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5803 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5804 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5805 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5806 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5807 py_srcfile, /*PyObject *filename,*/
5808 py_funcname, /*PyObject *name,*/
5809 firstlineno, /*int firstlineno,*/
5810 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5811 );
5813 bad:
5814 Py_XDECREF(py_srcfile);
5815 Py_XDECREF(py_funcname);
5817 return py_code;
5820 #endif /* CYTHON_PROFILE */
5821 """ % {
5822 'EMPTY_TUPLE' : Naming.empty_tuple,
5823 'EMPTY_BYTES' : Naming.empty_bytes,
5824 "MODULE": Naming.module_cname,
5825 })