Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 2658:4208042ceeae

Fix bug #252, mangle illegal optional c argument names.
author Robert Bradshaw <robertwb@math.washington.edu>
date Wed Nov 04 21:41:14 2009 -0800 (2 years ago)
parents e3d0bc7a39fa
children 5a87e3f5706c b9710187b2c8
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 profile:
1091 code.put_trace_call(self.entry.name, self.pos)
1092 if not lenv.nogil:
1093 code.put_setup_refcount_context(self.entry.name)
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 code.put_finish_refcount_context()
1216 if self.entry.is_special and self.entry.name == "__hash__":
1217 # Returning -1 for __hash__ is supposed to signal an error
1218 # We do as Python instances and coerce -1 into -2.
1219 code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (Naming.retval_cname, Naming.retval_cname))
1221 if profile:
1222 if self.return_type.is_pyobject:
1223 code.put_trace_return(Naming.retval_cname)
1224 else:
1225 code.put_trace_return("Py_None")
1227 if acquire_gil:
1228 code.putln("PyGILState_Release(_save);")
1230 if not self.return_type.is_void:
1231 code.putln("return %s;" % Naming.retval_cname)
1233 code.putln("}")
1234 # ----- Go back and insert temp variable declarations
1235 tempvardecl_code.put_temp_declarations(code.funcstate)
1236 # ----- Python version
1237 code.exit_cfunc_scope()
1238 if self.py_func:
1239 self.py_func.generate_function_definitions(env, code)
1240 self.generate_wrapper_functions(code)
1242 def declare_argument(self, env, arg):
1243 if arg.type.is_void:
1244 error(arg.pos, "Invalid use of 'void'")
1245 elif not arg.type.is_complete() and not arg.type.is_array:
1246 error(arg.pos,
1247 "Argument type '%s' is incomplete" % arg.type)
1248 return env.declare_arg(arg.name, arg.type, arg.pos)
1250 def generate_wrapper_functions(self, code):
1251 pass
1253 def generate_execution_code(self, code):
1254 # Evaluate and store argument default values
1255 for arg in self.args:
1256 default = arg.default
1257 if default:
1258 if not default.is_literal:
1259 default.generate_evaluation_code(code)
1260 default.make_owned_reference(code)
1261 result = default.result_as(arg.type)
1262 code.putln(
1263 "%s = %s;" % (
1264 arg.calculate_default_value_code(code),
1265 result))
1266 if arg.type.is_pyobject:
1267 code.put_giveref(default.result())
1268 default.generate_post_assignment_code(code)
1269 default.free_temps(code)
1270 # For Python class methods, create and store function object
1271 if self.assmt:
1272 self.assmt.generate_execution_code(code)
1275 # Special code for the __getbuffer__ function
1277 def getbuffer_init(self, code):
1278 info = self.local_scope.arg_entries[1].cname
1279 # Python 3.0 betas have a bug in memoryview which makes it call
1280 # getbuffer with a NULL parameter. For now we work around this;
1281 # the following line should be removed when this bug is fixed.
1282 code.putln("if (%s == NULL) return 0;" % info)
1283 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1284 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1286 def getbuffer_error_cleanup(self, code):
1287 info = self.local_scope.arg_entries[1].cname
1288 code.put_gotref("%s->obj" % info)
1289 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1290 (info, info))
1292 def getbuffer_normal_cleanup(self, code):
1293 info = self.local_scope.arg_entries[1].cname
1294 code.putln("if (%s->obj == Py_None) {" % info)
1295 code.put_gotref("Py_None")
1296 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1297 code.putln("}")
1299 class CFuncDefNode(FuncDefNode):
1300 # C function definition.
1302 # modifiers ['inline']
1303 # visibility 'private' or 'public' or 'extern'
1304 # base_type CBaseTypeNode
1305 # declarator CDeclaratorNode
1306 # body StatListNode
1307 # api boolean
1308 # decorators [DecoratorNode] list of decorators
1310 # with_gil boolean Acquire GIL around body
1311 # type CFuncType
1312 # py_func wrapper for calling from Python
1313 # overridable whether or not this is a cpdef function
1314 # inline_in_pxd whether this is an inline function in a pxd file
1316 child_attrs = ["base_type", "declarator", "body", "py_func"]
1318 inline_in_pxd = False
1319 decorators = None
1320 directive_locals = {}
1322 def unqualified_name(self):
1323 return self.entry.name
1325 def analyse_declarations(self, env):
1326 self.directive_locals.update(env.directives['locals'])
1327 base_type = self.base_type.analyse(env)
1328 # The 2 here is because we need both function and argument names.
1329 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1330 if not type.is_cfunction:
1331 error(self.pos,
1332 "Suite attached to non-function declaration")
1333 # Remember the actual type according to the function header
1334 # written here, because the type in the symbol table entry
1335 # may be different if we're overriding a C method inherited
1336 # from the base type of an extension type.
1337 self.type = type
1338 type.is_overridable = self.overridable
1339 declarator = self.declarator
1340 while not hasattr(declarator, 'args'):
1341 declarator = declarator.base
1342 self.args = declarator.args
1343 for formal_arg, type_arg in zip(self.args, type.args):
1344 formal_arg.type = type_arg.type
1345 formal_arg.name = type_arg.name
1346 formal_arg.cname = type_arg.cname
1347 name = name_declarator.name
1348 cname = name_declarator.cname
1349 self.entry = env.declare_cfunction(
1350 name, type, self.pos,
1351 cname = cname, visibility = self.visibility,
1352 defining = self.body is not None,
1353 api = self.api, modifiers = self.modifiers)
1354 self.entry.inline_func_in_pxd = self.inline_in_pxd
1355 self.return_type = type.return_type
1357 if self.overridable and not env.is_module_scope:
1358 if len(self.args) < 1 or not self.args[0].type.is_pyobject:
1359 # An error will be produced in the cdef function
1360 self.overridable = False
1362 if self.overridable:
1363 import ExprNodes
1364 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1365 self.py_func = DefNode(pos = self.pos,
1366 name = self.entry.name,
1367 args = self.args,
1368 star_arg = None,
1369 starstar_arg = None,
1370 doc = self.doc,
1371 body = py_func_body,
1372 is_wrapper = 1)
1373 self.py_func.is_module_scope = env.is_module_scope
1374 self.py_func.analyse_declarations(env)
1375 self.entry.as_variable = self.py_func.entry
1376 # Reset scope entry the above cfunction
1377 env.entries[name] = self.entry
1378 if not env.is_module_scope or Options.lookup_module_cpdef:
1379 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1380 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1382 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1383 import ExprNodes
1384 args = self.type.args
1385 if omit_optional_args:
1386 args = args[:len(args) - self.type.optional_arg_count]
1387 arg_names = [arg.name for arg in args]
1388 if is_module_scope:
1389 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1390 else:
1391 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1392 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1393 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1394 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)
1395 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1397 def declare_arguments(self, env):
1398 for arg in self.type.args:
1399 if not arg.name:
1400 error(arg.pos, "Missing argument name")
1401 self.declare_argument(env, arg)
1403 def need_gil_acquisition(self, lenv):
1404 return self.type.with_gil
1406 def nogil_check(self, env):
1407 type = self.type
1408 with_gil = type.with_gil
1409 if type.nogil and not with_gil:
1410 if type.return_type.is_pyobject:
1411 error(self.pos,
1412 "Function with Python return type cannot be declared nogil")
1413 for entry in self.local_scope.var_entries:
1414 if entry.type.is_pyobject:
1415 error(self.pos, "Function declared nogil has Python locals or temporaries")
1417 def analyse_expressions(self, env):
1418 self.local_scope.directives = env.directives
1419 if self.py_func is not None:
1420 # this will also analyse the default values
1421 self.py_func.analyse_expressions(env)
1422 else:
1423 self.analyse_default_values(env)
1424 self.acquire_gil = self.need_gil_acquisition(self.local_scope)
1426 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1427 arg_decls = []
1428 type = self.type
1429 visibility = self.entry.visibility
1430 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1431 arg_decls.append(arg.declaration_code())
1432 if with_dispatch and self.overridable:
1433 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1434 if type.optional_arg_count and with_opt_args:
1435 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1436 if type.has_varargs:
1437 arg_decls.append("...")
1438 if not arg_decls:
1439 arg_decls = ["void"]
1440 if cname is None:
1441 cname = self.entry.func_cname
1442 entity = type.function_header_code(cname, ', '.join(arg_decls))
1443 if visibility == 'public':
1444 dll_linkage = "DL_EXPORT"
1445 else:
1446 dll_linkage = None
1447 header = self.return_type.declaration_code(entity,
1448 dll_linkage = dll_linkage)
1449 if visibility == 'extern':
1450 storage_class = "%s " % Naming.extern_c_macro
1451 elif visibility == 'public':
1452 storage_class = ""
1453 else:
1454 storage_class = "static "
1455 code.putln("%s%s %s {" % (
1456 storage_class,
1457 ' '.join(self.modifiers).upper(), # macro forms
1458 header))
1460 def generate_argument_declarations(self, env, code):
1461 for arg in self.args:
1462 if arg.default:
1463 result = arg.calculate_default_value_code(code)
1464 code.putln('%s = %s;' % (
1465 arg.type.declaration_code(arg.cname), result))
1467 def generate_keyword_list(self, code):
1468 pass
1470 def generate_argument_parsing_code(self, env, code):
1471 i = 0
1472 if self.type.optional_arg_count:
1473 code.putln('if (%s) {' % Naming.optional_args_cname)
1474 for arg in self.args:
1475 if arg.default:
1476 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1477 declarator = arg.declarator
1478 while not hasattr(declarator, 'name'):
1479 declarator = declarator.base
1480 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, self.type.opt_arg_cname(declarator.name)))
1481 i += 1
1482 for _ in range(self.type.optional_arg_count):
1483 code.putln('}')
1484 code.putln('}')
1486 def generate_argument_conversion_code(self, code):
1487 pass
1489 def generate_argument_type_tests(self, code):
1490 # Generate type tests for args whose type in a parent
1491 # class is a supertype of the declared type.
1492 for arg in self.type.args:
1493 if arg.needs_type_test:
1494 self.generate_arg_type_test(arg, code)
1496 def generate_arg_type_test(self, arg, code):
1497 # Generate type test for one argument.
1498 if arg.type.typeobj_is_available():
1499 typeptr_cname = arg.type.typeptr_cname
1500 arg_code = "((PyObject *)%s)" % arg.cname
1501 code.putln(
1502 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1503 arg_code,
1504 typeptr_cname,
1505 not arg.not_none,
1506 arg.name,
1507 type.is_builtin_type,
1508 code.error_goto(arg.pos)))
1509 else:
1510 error(arg.pos, "Cannot test type of extern C class "
1511 "without type object name specification")
1513 def error_value(self):
1514 if self.return_type.is_pyobject:
1515 return "0"
1516 else:
1517 #return None
1518 return self.entry.type.exception_value
1520 def caller_will_check_exceptions(self):
1521 return self.entry.type.exception_check
1523 def generate_wrapper_functions(self, code):
1524 # If the C signature of a function has changed, we need to generate
1525 # wrappers to put in the slots here.
1526 k = 0
1527 entry = self.entry
1528 func_type = entry.type
1529 while entry.prev_entry is not None:
1530 k += 1
1531 entry = entry.prev_entry
1532 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1533 code.putln()
1534 self.generate_function_header(code,
1535 0,
1536 with_dispatch = entry.type.is_overridable,
1537 with_opt_args = entry.type.optional_arg_count,
1538 cname = entry.func_cname)
1539 if not self.return_type.is_void:
1540 code.put('return ')
1541 args = self.type.args
1542 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1543 if entry.type.is_overridable:
1544 arglist.append(Naming.skip_dispatch_cname)
1545 elif func_type.is_overridable:
1546 arglist.append('0')
1547 if entry.type.optional_arg_count:
1548 arglist.append(Naming.optional_args_cname)
1549 elif func_type.optional_arg_count:
1550 arglist.append('NULL')
1551 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1552 code.putln('}')
1555 class PyArgDeclNode(Node):
1556 # Argument which must be a Python object (used
1557 # for * and ** arguments).
1559 # name string
1560 # entry Symtab.Entry
1561 child_attrs = []
1564 class DecoratorNode(Node):
1565 # A decorator
1567 # decorator NameNode or CallNode
1568 child_attrs = ['decorator']
1571 class DefNode(FuncDefNode):
1572 # A Python function definition.
1574 # name string the Python name of the function
1575 # decorators [DecoratorNode] list of decorators
1576 # args [CArgDeclNode] formal arguments
1577 # star_arg PyArgDeclNode or None * argument
1578 # starstar_arg PyArgDeclNode or None ** argument
1579 # doc EncodedString or None
1580 # body StatListNode
1582 # The following subnode is constructed internally
1583 # when the def statement is inside a Python class definition.
1585 # assmt AssignmentNode Function construction/assignment
1587 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1589 assmt = None
1590 num_kwonly_args = 0
1591 num_required_kw_args = 0
1592 reqd_kw_flags_cname = "0"
1593 is_wrapper = 0
1594 decorators = None
1595 entry = None
1596 acquire_gil = 0
1599 def __init__(self, pos, **kwds):
1600 FuncDefNode.__init__(self, pos, **kwds)
1601 k = rk = r = 0
1602 for arg in self.args:
1603 if arg.kw_only:
1604 k += 1
1605 if not arg.default:
1606 rk += 1
1607 if not arg.default:
1608 r += 1
1609 self.num_kwonly_args = k
1610 self.num_required_kw_args = rk
1611 self.num_required_args = r
1613 def as_cfunction(self, cfunc=None, scope=None):
1614 if self.star_arg:
1615 error(self.star_arg.pos, "cdef function cannot have star argument")
1616 if self.starstar_arg:
1617 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1618 if cfunc is None:
1619 cfunc_args = []
1620 for formal_arg in self.args:
1621 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1622 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1623 cname = None,
1624 type = py_object_type,
1625 pos = formal_arg.pos))
1626 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1627 args = cfunc_args,
1628 has_varargs = False,
1629 exception_value = None,
1630 exception_check = False,
1631 nogil = False,
1632 with_gil = False,
1633 is_overridable = True)
1634 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1635 else:
1636 cfunc_type = cfunc.type
1637 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1638 error(self.pos, "wrong number of arguments")
1639 error(declarator.pos, "previous declaration here")
1640 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1641 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1642 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1643 formal_arg.type = type_arg.type
1644 formal_arg.name_declarator = name_declarator
1645 import ExprNodes
1646 if cfunc_type.exception_value is None:
1647 exception_value = None
1648 else:
1649 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1650 declarator = CFuncDeclaratorNode(self.pos,
1651 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1652 args = self.args,
1653 has_varargs = False,
1654 exception_check = cfunc_type.exception_check,
1655 exception_value = exception_value,
1656 with_gil = cfunc_type.with_gil,
1657 nogil = cfunc_type.nogil)
1658 return CFuncDefNode(self.pos,
1659 modifiers = [],
1660 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1661 declarator = declarator,
1662 body = self.body,
1663 doc = self.doc,
1664 overridable = cfunc_type.is_overridable,
1665 type = cfunc_type,
1666 with_gil = cfunc_type.with_gil,
1667 nogil = cfunc_type.nogil,
1668 visibility = 'private',
1669 api = False,
1670 directive_locals = getattr(cfunc, 'directive_locals', {}))
1672 def analyse_declarations(self, env):
1673 directive_locals = self.directive_locals = env.directives['locals']
1674 for arg in self.args:
1675 if hasattr(arg, 'name'):
1676 type = arg.type
1677 name_declarator = None
1678 else:
1679 base_type = arg.base_type.analyse(env)
1680 name_declarator, type = \
1681 arg.declarator.analyse(base_type, env)
1682 arg.name = name_declarator.name
1683 if arg.name in directive_locals:
1684 type_node = directive_locals[arg.name]
1685 other_type = type_node.analyse_as_type(env)
1686 if other_type is None:
1687 error(type_node.pos, "Not a type")
1688 elif (type is not PyrexTypes.py_object_type
1689 and not type.same_as(other_type)):
1690 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1691 error(type_node.pos, "Previous declaration here")
1692 else:
1693 type = other_type
1694 if name_declarator and name_declarator.cname:
1695 error(self.pos,
1696 "Python function argument cannot have C name specification")
1697 arg.type = type.as_argument_type()
1698 arg.hdr_type = None
1699 arg.needs_conversion = 0
1700 arg.needs_type_test = 0
1701 arg.is_generic = 1
1702 if arg.not_none and not arg.type.is_extension_type:
1703 error(self.pos,
1704 "Only extension type arguments can have 'not None'")
1705 self.declare_pyfunction(env)
1706 self.analyse_signature(env)
1707 self.return_type = self.entry.signature.return_type()
1709 def analyse_signature(self, env):
1710 any_type_tests_needed = 0
1711 if self.entry.is_special:
1712 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1713 elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
1714 # Use the simpler calling signature for zero- and one-argument functions.
1715 if self.entry.signature is TypeSlots.pyfunction_signature:
1716 if len(self.args) == 0:
1717 self.entry.signature = TypeSlots.pyfunction_noargs
1718 elif len(self.args) == 1:
1719 if self.args[0].default is None and not self.args[0].kw_only:
1720 self.entry.signature = TypeSlots.pyfunction_onearg
1721 elif self.entry.signature is TypeSlots.pymethod_signature:
1722 if len(self.args) == 1:
1723 self.entry.signature = TypeSlots.unaryfunc
1724 elif len(self.args) == 2:
1725 if self.args[1].default is None and not self.args[1].kw_only:
1726 self.entry.signature = TypeSlots.ibinaryfunc
1727 sig = self.entry.signature
1728 nfixed = sig.num_fixed_args()
1729 for i in range(nfixed):
1730 if i < len(self.args):
1731 arg = self.args[i]
1732 arg.is_generic = 0
1733 if sig.is_self_arg(i):
1734 arg.is_self_arg = 1
1735 arg.hdr_type = arg.type = env.parent_type
1736 arg.needs_conversion = 0
1737 else:
1738 arg.hdr_type = sig.fixed_arg_type(i)
1739 if not arg.type.same_as(arg.hdr_type):
1740 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1741 arg.needs_type_test = 1
1742 any_type_tests_needed = 1
1743 else:
1744 arg.needs_conversion = 1
1745 if arg.needs_conversion:
1746 arg.hdr_cname = Naming.arg_prefix + arg.name
1747 else:
1748 arg.hdr_cname = Naming.var_prefix + arg.name
1749 else:
1750 self.bad_signature()
1751 return
1752 if nfixed < len(self.args):
1753 if not sig.has_generic_args:
1754 self.bad_signature()
1755 for arg in self.args:
1756 if arg.is_generic and \
1757 (arg.type.is_extension_type or arg.type.is_builtin_type):
1758 arg.needs_type_test = 1
1759 any_type_tests_needed = 1
1760 if any_type_tests_needed:
1761 env.use_utility_code(arg_type_test_utility_code)
1763 def bad_signature(self):
1764 sig = self.entry.signature
1765 expected_str = "%d" % sig.num_fixed_args()
1766 if sig.has_generic_args:
1767 expected_str = expected_str + " or more"
1768 name = self.name
1769 if name.startswith("__") and name.endswith("__"):
1770 desc = "Special method"
1771 else:
1772 desc = "Method"
1773 error(self.pos,
1774 "%s %s has wrong number of arguments "
1775 "(%d declared, %s expected)" % (
1776 desc, self.name, len(self.args), expected_str))
1778 def signature_has_nongeneric_args(self):
1779 argcount = len(self.args)
1780 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1781 return 0
1782 return 1
1784 def signature_has_generic_args(self):
1785 return self.entry.signature.has_generic_args
1787 def declare_pyfunction(self, env):
1788 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1789 name = self.name
1790 entry = env.lookup_here(self.name)
1791 if entry and entry.type.is_cfunction and not self.is_wrapper:
1792 warning(self.pos, "Overriding cdef method with def method.", 5)
1793 entry = env.declare_pyfunction(self.name, self.pos)
1794 self.entry = entry
1795 prefix = env.scope_prefix
1796 entry.func_cname = \
1797 Naming.pyfunc_prefix + prefix + name
1798 entry.pymethdef_cname = \
1799 Naming.pymethdef_prefix + prefix + name
1800 if Options.docstrings:
1801 entry.doc = embed_position(self.pos, self.doc)
1802 entry.doc_cname = \
1803 Naming.funcdoc_prefix + prefix + name
1804 else:
1805 entry.doc = None
1807 def declare_arguments(self, env):
1808 for arg in self.args:
1809 if not arg.name:
1810 error(arg.pos, "Missing argument name")
1811 if arg.needs_conversion:
1812 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1813 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1814 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1815 if arg.type.is_pyobject:
1816 arg.entry.init = "0"
1817 arg.entry.init_to_none = 0
1818 else:
1819 arg.entry = self.declare_argument(env, arg)
1820 arg.entry.used = 1
1821 arg.entry.is_self_arg = arg.is_self_arg
1822 if arg.hdr_type:
1823 if arg.is_self_arg or \
1824 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1825 arg.entry.is_declared_generic = 1
1826 self.declare_python_arg(env, self.star_arg)
1827 self.declare_python_arg(env, self.starstar_arg)
1829 def declare_python_arg(self, env, arg):
1830 if arg:
1831 entry = env.declare_var(arg.name,
1832 PyrexTypes.py_object_type, arg.pos)
1833 entry.used = 1
1834 entry.init = "0"
1835 entry.init_to_none = 0
1836 entry.xdecref_cleanup = 1
1837 arg.entry = entry
1838 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1840 def analyse_expressions(self, env):
1841 self.local_scope.directives = env.directives
1842 self.analyse_default_values(env)
1843 if env.is_py_class_scope:
1844 self.synthesize_assignment_node(env)
1846 def synthesize_assignment_node(self, env):
1847 import ExprNodes
1848 self.assmt = SingleAssignmentNode(self.pos,
1849 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1850 rhs = ExprNodes.UnboundMethodNode(self.pos,
1851 function = ExprNodes.PyCFunctionNode(self.pos,
1852 pymethdef_cname = self.entry.pymethdef_cname)))
1853 self.assmt.analyse_declarations(env)
1854 self.assmt.analyse_expressions(env)
1856 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1857 arg_code_list = []
1858 sig = self.entry.signature
1859 if sig.has_dummy_arg:
1860 arg_code_list.append(
1861 "PyObject *%s" % Naming.self_cname)
1862 for arg in self.args:
1863 if not arg.is_generic:
1864 if arg.is_self_arg:
1865 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1866 else:
1867 arg_code_list.append(
1868 arg.hdr_type.declaration_code(arg.hdr_cname))
1869 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1870 arg_code_list.append("PyObject *unused")
1871 if sig.has_generic_args:
1872 arg_code_list.append(
1873 "PyObject *%s, PyObject *%s"
1874 % (Naming.args_cname, Naming.kwds_cname))
1875 arg_code = ", ".join(arg_code_list)
1876 dc = self.return_type.declaration_code(self.entry.func_cname)
1877 header = "static %s(%s)" % (dc, arg_code)
1878 code.putln("%s; /*proto*/" % header)
1879 if proto_only:
1880 return
1881 if self.entry.doc and Options.docstrings:
1882 docstr = self.entry.doc
1883 if docstr.is_unicode:
1884 docstr = docstr.utf8encode()
1885 code.putln(
1886 'static char %s[] = "%s";' % (
1887 self.entry.doc_cname,
1888 split_docstring(escape_byte_string(docstr))))
1889 if with_pymethdef:
1890 code.put(
1891 "static PyMethodDef %s = " %
1892 self.entry.pymethdef_cname)
1893 code.put_pymethoddef(self.entry, ";")
1894 code.putln("%s {" % header)
1896 def generate_argument_declarations(self, env, code):
1897 for arg in self.args:
1898 if arg.is_generic: # or arg.needs_conversion:
1899 if arg.needs_conversion:
1900 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1901 else:
1902 code.put_var_declaration(arg.entry)
1904 def generate_keyword_list(self, code):
1905 if self.signature_has_generic_args() and \
1906 self.signature_has_nongeneric_args():
1907 code.put(
1908 "static PyObject **%s[] = {" %
1909 Naming.pykwdlist_cname)
1910 for arg in self.args:
1911 if arg.is_generic:
1912 pystring_cname = code.intern_identifier(arg.name)
1913 code.put('&%s,' % pystring_cname)
1914 code.putln("0};")
1916 def generate_argument_parsing_code(self, env, code):
1917 # Generate PyArg_ParseTuple call for generic
1918 # arguments, if any.
1919 if self.entry.signature.has_dummy_arg:
1920 # get rid of unused argument warning
1921 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1923 old_error_label = code.new_error_label()
1924 our_error_label = code.error_label
1925 end_label = code.new_label("argument_unpacking_done")
1927 has_kwonly_args = self.num_kwonly_args > 0
1928 has_star_or_kw_args = self.star_arg is not None \
1929 or self.starstar_arg is not None or has_kwonly_args
1931 for arg in self.args:
1932 if not arg.type.is_pyobject:
1933 done = arg.type.create_from_py_utility_code(env)
1934 if not done: pass # will fail later
1936 if not self.signature_has_generic_args():
1937 if has_star_or_kw_args:
1938 error(self.pos, "This method cannot have * or keyword arguments")
1939 self.generate_argument_conversion_code(code)
1941 elif not self.signature_has_nongeneric_args():
1942 # func(*args) or func(**kw) or func(*args, **kw)
1943 self.generate_stararg_copy_code(code)
1945 else:
1946 positional_args = []
1947 kw_only_args = []
1948 for arg in self.args:
1949 arg_entry = arg.entry
1950 if arg.is_generic:
1951 if arg.default:
1952 if not arg.is_self_arg:
1953 if arg.kw_only:
1954 kw_only_args.append(arg)
1955 else:
1956 positional_args.append(arg)
1957 elif arg.kw_only:
1958 kw_only_args.append(arg)
1959 elif not arg.is_self_arg:
1960 positional_args.append(arg)
1962 self.generate_tuple_and_keyword_parsing_code(
1963 positional_args, kw_only_args, end_label, code)
1965 code.error_label = old_error_label
1966 if code.label_used(our_error_label):
1967 if not code.label_used(end_label):
1968 code.put_goto(end_label)
1969 code.put_label(our_error_label)
1970 if has_star_or_kw_args:
1971 self.generate_arg_decref(self.star_arg, code)
1972 if self.starstar_arg:
1973 if self.starstar_arg.entry.xdecref_cleanup:
1974 code.put_var_xdecref(self.starstar_arg.entry)
1975 else:
1976 code.put_var_decref(self.starstar_arg.entry)
1977 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1978 code.putln("return %s;" % self.error_value())
1979 if code.label_used(end_label):
1980 code.put_label(end_label)
1982 def generate_arg_assignment(self, arg, item, code):
1983 if arg.type.is_pyobject:
1984 if arg.is_generic:
1985 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1986 code.putln("%s = %s;" % (arg.entry.cname, item))
1987 else:
1988 func = arg.type.from_py_function
1989 if func:
1990 code.putln("%s = %s(%s); %s" % (
1991 arg.entry.cname,
1992 func,
1993 item,
1994 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1995 else:
1996 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1998 def generate_arg_xdecref(self, arg, code):
1999 if arg:
2000 code.put_var_xdecref(arg.entry)
2002 def generate_arg_decref(self, arg, code):
2003 if arg:
2004 code.put_var_decref(arg.entry)
2006 def generate_stararg_copy_code(self, code):
2007 if not self.star_arg:
2008 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2009 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
2010 Naming.args_cname)
2011 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2012 self.name, Naming.args_cname, self.error_value()))
2013 code.putln("}")
2015 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2017 if self.starstar_arg:
2018 if self.star_arg:
2019 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2020 else:
2021 kwarg_check = "%s" % Naming.kwds_cname
2022 else:
2023 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2024 Naming.kwds_cname, Naming.kwds_cname)
2025 code.putln(
2026 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2027 kwarg_check, Naming.kwds_cname, self.name,
2028 bool(self.starstar_arg), self.error_value()))
2030 if self.starstar_arg:
2031 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2032 self.starstar_arg.entry.cname,
2033 Naming.kwds_cname,
2034 Naming.kwds_cname))
2035 code.putln("if (unlikely(!%s)) return %s;" % (
2036 self.starstar_arg.entry.cname, self.error_value()))
2037 self.starstar_arg.entry.xdecref_cleanup = 0
2038 code.put_gotref(self.starstar_arg.entry.cname)
2041 if self.star_arg:
2042 code.put_incref(Naming.args_cname, py_object_type)
2043 code.putln("%s = %s;" % (
2044 self.star_arg.entry.cname,
2045 Naming.args_cname))
2046 self.star_arg.entry.xdecref_cleanup = 0
2048 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2049 kw_only_args, success_label, code):
2050 argtuple_error_label = code.new_label("argtuple_error")
2052 min_positional_args = self.num_required_args - self.num_required_kw_args
2053 if len(self.args) > 0 and self.args[0].is_self_arg:
2054 min_positional_args -= 1
2055 max_positional_args = len(positional_args)
2056 has_fixed_positional_count = not self.star_arg and \
2057 min_positional_args == max_positional_args
2059 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2060 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2061 if self.num_required_kw_args:
2062 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2064 if self.starstar_arg or self.star_arg:
2065 self.generate_stararg_init_code(max_positional_args, code)
2067 # --- optimised code when we receive keyword arguments
2068 if self.num_required_kw_args:
2069 likely_hint = "likely"
2070 else:
2071 likely_hint = "unlikely"
2072 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2073 self.generate_keyword_unpacking_code(
2074 min_positional_args, max_positional_args,
2075 has_fixed_positional_count,
2076 positional_args, kw_only_args, argtuple_error_label, code)
2078 # --- optimised code when we do not receive any keyword arguments
2079 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2080 # Python raises arg tuple related errors first, so we must
2081 # check the length here
2082 if min_positional_args == max_positional_args and not self.star_arg:
2083 compare = '!='
2084 else:
2085 compare = '<'
2086 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2087 Naming.args_cname, compare, min_positional_args))
2088 code.put_goto(argtuple_error_label)
2090 if self.num_required_kw_args:
2091 # pure error case: keywords required but not passed
2092 if max_positional_args > min_positional_args and not self.star_arg:
2093 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2094 Naming.args_cname, max_positional_args))
2095 code.put_goto(argtuple_error_label)
2096 code.putln('} else {')
2097 for i, arg in enumerate(kw_only_args):
2098 if not arg.default:
2099 pystring_cname = code.intern_identifier(arg.name)
2100 # required keyword-only argument missing
2101 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2102 self.name,
2103 pystring_cname))
2104 code.putln(code.error_goto(self.pos))
2105 break
2107 elif min_positional_args == max_positional_args:
2108 # parse the exact number of positional arguments from the
2109 # args tuple
2110 code.putln('} else {')
2111 for i, arg in enumerate(positional_args):
2112 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2113 self.generate_arg_assignment(arg, item, code)
2114 self.generate_arg_default_assignments(code)
2116 else:
2117 # parse the positional arguments from the variable length
2118 # args tuple
2119 code.putln('} else {')
2120 self.generate_arg_default_assignments(code)
2121 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2122 if self.star_arg:
2123 code.putln('default:')
2124 reversed_args = list(enumerate(positional_args))[::-1]
2125 for i, arg in reversed_args:
2126 if i >= min_positional_args-1:
2127 if min_positional_args > 1:
2128 code.putln('case %2d:' % (i+1)) # pure code beautification
2129 else:
2130 code.put('case %2d: ' % (i+1))
2131 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2132 self.generate_arg_assignment(arg, item, code)
2133 if min_positional_args == 0:
2134 code.put('case 0: ')
2135 code.putln('break;')
2136 if self.star_arg:
2137 if min_positional_args:
2138 for i in range(min_positional_args-1, -1, -1):
2139 code.putln('case %2d:' % i)
2140 code.put_goto(argtuple_error_label)
2141 else:
2142 code.put('default: ')
2143 code.put_goto(argtuple_error_label)
2144 code.putln('}')
2146 code.putln('}')
2148 if code.label_used(argtuple_error_label):
2149 code.put_goto(success_label)
2150 code.put_label(argtuple_error_label)
2151 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2152 self.name, has_fixed_positional_count,
2153 min_positional_args, max_positional_args,
2154 Naming.args_cname))
2155 code.putln(code.error_goto(self.pos))
2157 def generate_arg_default_assignments(self, code):
2158 for arg in self.args:
2159 if arg.is_generic and arg.default:
2160 code.putln(
2161 "%s = %s;" % (
2162 arg.entry.cname,
2163 arg.calculate_default_value_code(code)))
2165 def generate_stararg_init_code(self, max_positional_args, code):
2166 if self.starstar_arg:
2167 self.starstar_arg.entry.xdecref_cleanup = 0
2168 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2169 self.starstar_arg.entry.cname,
2170 self.starstar_arg.entry.cname,
2171 self.error_value()))
2172 code.put_gotref(self.starstar_arg.entry.cname)
2173 if self.star_arg:
2174 self.star_arg.entry.xdecref_cleanup = 0
2175 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2176 Naming.args_cname,
2177 max_positional_args))
2178 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2179 self.star_arg.entry.cname, Naming.args_cname,
2180 max_positional_args, Naming.args_cname))
2181 code.put_gotref(self.star_arg.entry.cname)
2182 if self.starstar_arg:
2183 code.putln("")
2184 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2185 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2186 code.putln('return %s;' % self.error_value())
2187 code.putln('}')
2188 else:
2189 code.putln("if (unlikely(!%s)) return %s;" % (
2190 self.star_arg.entry.cname, self.error_value()))
2191 code.putln('} else {')
2192 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2193 code.put_incref(Naming.empty_tuple, py_object_type)
2194 code.putln('}')
2196 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2197 has_fixed_positional_count, positional_args,
2198 kw_only_args, argtuple_error_label, code):
2199 all_args = tuple(positional_args) + tuple(kw_only_args)
2200 max_args = len(all_args)
2202 default_args = []
2203 for i, arg in enumerate(all_args):
2204 if arg.default and arg.type.is_pyobject:
2205 default_value = arg.calculate_default_value_code(code)
2206 if arg.type is not PyrexTypes.py_object_type:
2207 default_value = "(PyObject*)"+default_value
2208 default_args.append((i, default_value))
2210 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2211 Naming.kwds_cname)
2212 # it looks funny to separate the init-to-0 from setting the
2213 # default value, but C89 needs this
2214 code.putln("PyObject* values[%d] = {%s};" % (
2215 max_args, ','.join(['0']*max_args)))
2216 for i, default_value in default_args:
2217 code.putln('values[%d] = %s;' % (i, default_value))
2219 # parse the tuple and check that it's not too long
2220 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2221 if self.star_arg:
2222 code.putln('default:')
2223 for i in range(max_positional_args-1, -1, -1):
2224 code.put('case %2d: ' % (i+1))
2225 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2226 i, Naming.args_cname, i))
2227 code.putln('case 0: break;')
2228 if not self.star_arg:
2229 code.put('default: ') # more arguments than allowed
2230 code.put_goto(argtuple_error_label)
2231 code.putln('}')
2233 # now fill up the positional/required arguments with values
2234 # from the kw dict
2235 if self.num_required_args or max_positional_args > 0:
2236 last_required_arg = -1
2237 for i, arg in enumerate(all_args):
2238 if not arg.default:
2239 last_required_arg = i
2240 if last_required_arg < max_positional_args:
2241 last_required_arg = max_positional_args-1
2242 num_required_args = self.num_required_args
2243 if max_positional_args > 0:
2244 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2245 for i, arg in enumerate(all_args[:last_required_arg+1]):
2246 if max_positional_args > 0 and i <= max_positional_args:
2247 if self.star_arg and i == max_positional_args:
2248 code.putln('default:')
2249 else:
2250 code.putln('case %2d:' % i)
2251 pystring_cname = code.intern_identifier(arg.name)
2252 if arg.default:
2253 if arg.kw_only:
2254 # handled separately below
2255 continue
2256 code.putln('if (kw_args > %d) {' % num_required_args)
2257 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2258 Naming.kwds_cname, pystring_cname))
2259 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2260 code.putln('}')
2261 else:
2262 num_required_args -= 1
2263 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2264 i, Naming.kwds_cname, pystring_cname))
2265 code.putln('if (likely(values[%d])) kw_args--;' % i);
2266 if i < min_positional_args:
2267 if i == 0:
2268 # special case: we know arg 0 is missing
2269 code.put('else ')
2270 code.put_goto(argtuple_error_label)
2271 else:
2272 # print the correct number of values (args or
2273 # kwargs) that were passed into positional
2274 # arguments up to this point
2275 code.putln('else {')
2276 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2277 self.name, has_fixed_positional_count,
2278 min_positional_args, max_positional_args, i))
2279 code.putln(code.error_goto(self.pos))
2280 code.putln('}')
2281 elif arg.kw_only:
2282 code.putln('else {')
2283 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2284 self.name, pystring_cname))
2285 code.putln(code.error_goto(self.pos))
2286 code.putln('}')
2287 if max_positional_args > 0:
2288 code.putln('}')
2290 if kw_only_args and not self.starstar_arg:
2291 # unpack optional keyword-only arguments
2292 # checking for interned strings in a dict is faster than iterating
2293 # but it's too likely that we must iterate if we expect **kwargs
2294 optional_args = []
2295 for i, arg in enumerate(all_args[max_positional_args:]):
2296 if not arg.kw_only or not arg.default:
2297 continue
2298 optional_args.append((i+max_positional_args, arg))
2299 if optional_args:
2300 # this mimics an unrolled loop so that we can "break" out of it
2301 code.putln('while (kw_args > 0) {')
2302 code.putln('PyObject* value;')
2303 for i, arg in optional_args:
2304 pystring_cname = code.intern_identifier(arg.name)
2305 code.putln(
2306 'value = PyDict_GetItem(%s, %s);' % (
2307 Naming.kwds_cname, pystring_cname))
2308 code.putln(
2309 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2310 code.putln('break;')
2311 code.putln('}')
2313 code.putln('if (unlikely(kw_args > 0)) {')
2314 # non-positional/-required kw args left in dict: default args,
2315 # kw-only args, **kwargs or error
2317 # This is sort of a catch-all: except for checking required
2318 # arguments, this will always do the right thing for unpacking
2319 # keyword arguments, so that we can concentrate on optimising
2320 # common cases above.
2321 if max_positional_args == 0:
2322 pos_arg_count = "0"
2323 elif self.star_arg:
2324 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2325 Naming.args_cname, max_positional_args,
2326 Naming.args_cname, max_positional_args))
2327 pos_arg_count = "used_pos_args"
2328 else:
2329 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2330 code.globalstate.use_utility_code(parse_keywords_utility_code)
2331 code.put(
2332 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2333 Naming.kwds_cname,
2334 Naming.pykwdlist_cname,
2335 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2336 pos_arg_count,
2337 self.name))
2338 code.putln(code.error_goto(self.pos))
2339 code.putln('}')
2341 # convert arg values to their final type and assign them
2342 for i, arg in enumerate(all_args):
2343 if arg.default and not arg.type.is_pyobject:
2344 code.putln("if (values[%d]) {" % i)
2345 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2346 if arg.default and not arg.type.is_pyobject:
2347 code.putln('} else {')
2348 code.putln(
2349 "%s = %s;" % (
2350 arg.entry.cname,
2351 arg.calculate_default_value_code(code)))
2352 code.putln('}')
2354 def generate_argument_conversion_code(self, code):
2355 # Generate code to convert arguments from
2356 # signature type to declared type, if needed.
2357 for arg in self.args:
2358 if arg.needs_conversion:
2359 self.generate_arg_conversion(arg, code)
2361 def generate_arg_conversion(self, arg, code):
2362 # Generate conversion code for one argument.
2363 old_type = arg.hdr_type
2364 new_type = arg.type
2365 if old_type.is_pyobject:
2366 if arg.default:
2367 code.putln("if (%s) {" % arg.hdr_cname)
2368 else:
2369 code.putln("assert(%s); {" % arg.hdr_cname)
2370 self.generate_arg_conversion_from_pyobject(arg, code)
2371 code.putln("}")
2372 elif new_type.is_pyobject:
2373 self.generate_arg_conversion_to_pyobject(arg, code)
2374 else:
2375 if new_type.assignable_from(old_type):
2376 code.putln(
2377 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2378 else:
2379 error(arg.pos,
2380 "Cannot convert 1 argument from '%s' to '%s'" %
2381 (old_type, new_type))
2383 def generate_arg_conversion_from_pyobject(self, arg, code):
2384 new_type = arg.type
2385 func = new_type.from_py_function
2386 # copied from CoerceFromPyTypeNode
2387 if func:
2388 code.putln("%s = %s(%s); %s" % (
2389 arg.entry.cname,
2390 func,
2391 arg.hdr_cname,
2392 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2393 else:
2394 error(arg.pos,
2395 "Cannot convert Python object argument to type '%s'"
2396 % new_type)
2398 def generate_arg_conversion_to_pyobject(self, arg, code):
2399 old_type = arg.hdr_type
2400 func = old_type.to_py_function
2401 if func:
2402 code.putln("%s = %s(%s); %s" % (
2403 arg.entry.cname,
2404 func,
2405 arg.hdr_cname,
2406 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2407 code.put_var_gotref(arg.entry)
2408 else:
2409 error(arg.pos,
2410 "Cannot convert argument of type '%s' to Python object"
2411 % old_type)
2413 def generate_argument_type_tests(self, code):
2414 # Generate type tests for args whose signature
2415 # type is PyObject * and whose declared type is
2416 # a subtype thereof.
2417 for arg in self.args:
2418 if arg.needs_type_test:
2419 self.generate_arg_type_test(arg, code)
2421 def generate_arg_type_test(self, arg, code):
2422 # Generate type test for one argument.
2423 if arg.type.typeobj_is_available():
2424 typeptr_cname = arg.type.typeptr_cname
2425 arg_code = "((PyObject *)%s)" % arg.entry.cname
2426 code.putln(
2427 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2428 arg_code,
2429 typeptr_cname,
2430 not arg.not_none,
2431 arg.name,
2432 arg.type.is_builtin_type,
2433 code.error_goto(arg.pos)))
2434 else:
2435 error(arg.pos, "Cannot test type of extern C class "
2436 "without type object name specification")
2438 def error_value(self):
2439 return self.entry.signature.error_value
2441 def caller_will_check_exceptions(self):
2442 return 1
2444 class OverrideCheckNode(StatNode):
2445 # A Node for dispatching to the def method if it
2446 # is overriden.
2448 # py_func
2450 # args
2451 # func_temp
2452 # body
2454 child_attrs = ['body']
2456 body = None
2458 def analyse_expressions(self, env):
2459 self.args = env.arg_entries
2460 if self.py_func.is_module_scope:
2461 first_arg = 0
2462 else:
2463 first_arg = 1
2464 import ExprNodes
2465 self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
2466 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2467 call_node = ExprNodes.SimpleCallNode(self.pos,
2468 function=self.func_node,
2469 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2470 self.body = ReturnStatNode(self.pos, value=call_node)
2471 self.body.analyse_expressions(env)
2473 def generate_execution_code(self, code):
2474 interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
2475 # Check to see if we are an extension type
2476 if self.py_func.is_module_scope:
2477 self_arg = "((PyObject *)%s)" % Naming.module_cname
2478 else:
2479 self_arg = "((PyObject *)%s)" % self.args[0].cname
2480 code.putln("/* Check if called by wrapper */")
2481 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2482 code.putln("/* Check if overriden in Python */")
2483 if self.py_func.is_module_scope:
2484 code.putln("else {")
2485 else:
2486 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2487 func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
2488 self.func_node.set_cname(func_node_temp)
2489 # need to get attribute manually--scope would return cdef method
2490 err = code.error_goto_if_null(func_node_temp, self.pos)
2491 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
2492 func_node_temp, self_arg, interned_attr_cname, err))
2493 code.put_gotref(func_node_temp)
2494 is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
2495 is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)" % (
2496 func_node_temp, self.py_func.entry.func_cname)
2497 code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
2498 self.body.generate_execution_code(code)
2499 code.putln("}")
2500 code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
2501 code.funcstate.release_temp(func_node_temp)
2502 code.putln("}")
2504 class ClassDefNode(StatNode, BlockNode):
2505 pass
2507 class PyClassDefNode(ClassDefNode):
2508 # A Python class definition.
2510 # name EncodedString Name of the class
2511 # doc string or None
2512 # body StatNode Attribute definition code
2513 # entry Symtab.Entry
2514 # scope PyClassScope
2515 # decorators [DecoratorNode] list of decorators or None
2517 # The following subnodes are constructed internally:
2519 # dict DictNode Class dictionary
2520 # classobj ClassNode Class object
2521 # target NameNode Variable to assign class object to
2523 child_attrs = ["body", "dict", "classobj", "target"]
2524 decorators = None
2526 def __init__(self, pos, name, bases, doc, body, decorators = None):
2527 StatNode.__init__(self, pos)
2528 self.name = name
2529 self.doc = doc
2530 self.body = body
2531 self.decorators = decorators
2532 import ExprNodes
2533 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2534 if self.doc and Options.docstrings:
2535 doc = embed_position(self.pos, self.doc)
2536 # FIXME: correct string node?
2537 doc_node = ExprNodes.StringNode(pos, value = doc)
2538 else:
2539 doc_node = None
2540 self.classobj = ExprNodes.ClassNode(pos, name = name,
2541 bases = bases, dict = self.dict, doc = doc_node)
2542 self.target = ExprNodes.NameNode(pos, name = name)
2544 def as_cclass(self):
2545 """
2546 Return this node as if it were declared as an extension class
2547 """
2548 bases = self.classobj.bases.args
2549 if len(bases) == 0:
2550 base_class_name = None
2551 base_class_module = None
2552 elif len(bases) == 1:
2553 base = bases[0]
2554 path = []
2555 from ExprNodes import AttributeNode, NameNode
2556 while isinstance(base, AttributeNode):
2557 path.insert(0, base.attribute)
2558 base = base.obj
2559 if isinstance(base, NameNode):
2560 path.insert(0, base.name)
2561 base_class_name = path[-1]
2562 if len(path) > 1:
2563 base_class_module = u'.'.join(path[:-1])
2564 else:
2565 base_class_module = None
2566 else:
2567 error(self.classobj.bases.args.pos, "Invalid base class")
2568 else:
2569 error(self.classobj.bases.args.pos, "C class may only have one base class")
2570 return None
2572 return CClassDefNode(self.pos,
2573 visibility = 'private',
2574 module_name = None,
2575 class_name = self.name,
2576 base_class_module = base_class_module,
2577 base_class_name = base_class_name,
2578 decorators = self.decorators,
2579 body = self.body,
2580 in_pxd = False,
2581 doc = self.doc)
2583 def create_scope(self, env):
2584 genv = env
2585 while env.is_py_class_scope or env.is_c_class_scope:
2586 env = env.outer_scope
2587 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2588 return cenv
2590 def analyse_declarations(self, env):
2591 self.target.analyse_target_declaration(env)
2592 cenv = self.create_scope(env)
2593 cenv.directives = env.directives
2594 cenv.class_obj_cname = self.target.entry.cname
2595 self.body.analyse_declarations(cenv)
2597 def analyse_expressions(self, env):
2598 self.dict.analyse_expressions(env)
2599 self.classobj.analyse_expressions(env)
2600 genv = env.global_scope()
2601 cenv = self.scope
2602 self.body.analyse_expressions(cenv)
2603 self.target.analyse_target_expression(env, self.classobj)
2605 def generate_function_definitions(self, env, code):
2606 self.body.generate_function_definitions(self.scope, code)
2608 def generate_execution_code(self, code):
2609 code.pyclass_stack.append(self)
2610 cenv = self.scope
2611 self.dict.generate_evaluation_code(code)
2612 self.classobj.generate_evaluation_code(code)
2613 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2614 self.body.generate_execution_code(code)
2615 self.target.generate_assignment_code(self.classobj, code)
2616 self.dict.generate_disposal_code(code)
2617 self.dict.free_temps(code)
2618 code.pyclass_stack.pop()
2621 class CClassDefNode(ClassDefNode):
2622 # An extension type definition.
2624 # visibility 'private' or 'public' or 'extern'
2625 # typedef_flag boolean
2626 # api boolean
2627 # module_name string or None For import of extern type objects
2628 # class_name string Unqualified name of class
2629 # as_name string or None Name to declare as in this scope
2630 # base_class_module string or None Module containing the base class
2631 # base_class_name string or None Name of the base class
2632 # objstruct_name string or None Specified C name of object struct
2633 # typeobj_name string or None Specified C name of type object
2634 # in_pxd boolean Is in a .pxd file
2635 # decorators [DecoratorNode] list of decorators or None
2636 # doc string or None
2637 # body StatNode or None
2638 # entry Symtab.Entry
2639 # base_type PyExtensionType or None
2640 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2641 # buffer_defaults_pos
2643 child_attrs = ["body"]
2644 buffer_defaults_node = None
2645 buffer_defaults_pos = None
2646 typedef_flag = False
2647 api = False
2648 objstruct_name = None
2649 typeobj_name = None
2650 decorators = None
2652 def analyse_declarations(self, env):
2653 #print "CClassDefNode.analyse_declarations:", self.class_name
2654 #print "...visibility =", self.visibility
2655 #print "...module_name =", self.module_name
2657 import Buffer
2658 if self.buffer_defaults_node:
2659 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2660 env, [], self.buffer_defaults_node,
2661 need_complete=False)
2662 else:
2663 buffer_defaults = None
2665 if env.in_cinclude and not self.objstruct_name:
2666 error(self.pos, "Object struct name specification required for "
2667 "C class defined in 'extern from' block")
2668 self.base_type = None
2669 # Now that module imports are cached, we need to
2670 # import the modules for extern classes.
2671 if self.module_name:
2672 self.module = None
2673 for module in env.cimported_modules:
2674 if module.name == self.module_name:
2675 self.module = module
2676 if self.module is None:
2677 self.module = ModuleScope(self.module_name, None, env.context)
2678 self.module.has_extern_class = 1
2679 env.add_imported_module(self.module)
2681 if self.base_class_name:
2682 if self.base_class_module:
2683 base_class_scope = env.find_module(self.base_class_module, self.pos)
2684 else:
2685 base_class_scope = env
2686 if self.base_class_name == 'object':
2687 # extension classes are special and don't need to inherit from object
2688 if base_class_scope is None or base_class_scope.lookup('object') is None:
2689 self.base_class_name = None
2690 self.base_class_module = None
2691 base_class_scope = None
2692 if base_class_scope:
2693 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2694 if base_class_entry:
2695 if not base_class_entry.is_type:
2696 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2697 elif not base_class_entry.type.is_extension_type:
2698 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2699 elif not base_class_entry.type.is_complete():
2700 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2701 else:
2702 self.base_type = base_class_entry.type
2703 has_body = self.body is not None
2704 if self.module_name and self.visibility != 'extern':
2705 module_path = self.module_name.split(".")
2706 home_scope = env.find_imported_module(module_path, self.pos)
2707 if not home_scope:
2708 return
2709 else:
2710 home_scope = env
2712 if self.visibility == 'extern':
2713 if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
2714 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
2716 self.entry = home_scope.declare_c_class(
2717 name = self.class_name,
2718 pos = self.pos,
2719 defining = has_body and self.in_pxd,
2720 implementing = has_body and not self.in_pxd,
2721 module_name = self.module_name,
2722 base_type = self.base_type,
2723 objstruct_cname = self.objstruct_name,
2724 typeobj_cname = self.typeobj_name,
2725 visibility = self.visibility,
2726 typedef_flag = self.typedef_flag,
2727 api = self.api,
2728 buffer_defaults = buffer_defaults)
2729 if home_scope is not env and self.visibility == 'extern':
2730 env.add_imported_entry(self.class_name, self.entry, pos)
2731 self.scope = scope = self.entry.type.scope
2732 if scope is not None:
2733 scope.directives = env.directives
2735 if self.doc and Options.docstrings:
2736 scope.doc = embed_position(self.pos, self.doc)
2738 if has_body:
2739 self.body.analyse_declarations(scope)
2740 if self.in_pxd:
2741 scope.defined = 1
2742 else:
2743 scope.implemented = 1
2744 env.allocate_vtable_names(self.entry)
2746 def analyse_expressions(self, env):
2747 if self.body:
2748 scope = self.entry.type.scope
2749 self.body.analyse_expressions(scope)
2751 def generate_function_definitions(self, env, code):
2752 if self.body:
2753 self.body.generate_function_definitions(
2754 self.entry.type.scope, code)
2756 def generate_execution_code(self, code):
2757 # This is needed to generate evaluation code for
2758 # default values of method arguments.
2759 if self.body:
2760 self.body.generate_execution_code(code)
2762 def annotate(self, code):
2763 if self.body:
2764 self.body.annotate(code)
2767 class PropertyNode(StatNode):
2768 # Definition of a property in an extension type.
2770 # name string
2771 # doc EncodedString or None Doc string
2772 # body StatListNode
2774 child_attrs = ["body"]
2776 def analyse_declarations(self, env):
2777 entry = env.declare_property(self.name, self.doc, self.pos)
2778 if entry:
2779 entry.scope.directives = env.directives
2780 self.body.analyse_declarations(entry.scope)
2782 def analyse_expressions(self, env):
2783 self.body.analyse_expressions(env)
2785 def generate_function_definitions(self, env, code):
2786 self.body.generate_function_definitions(env, code)
2788 def generate_execution_code(self, code):
2789 pass
2791 def annotate(self, code):
2792 self.body.annotate(code)
2795 class GlobalNode(StatNode):
2796 # Global variable declaration.
2798 # names [string]
2800 child_attrs = []
2802 def analyse_declarations(self, env):
2803 for name in self.names:
2804 env.declare_global(name, self.pos)
2806 def analyse_expressions(self, env):
2807 pass
2809 def generate_execution_code(self, code):
2810 pass
2813 class ExprStatNode(StatNode):
2814 # Expression used as a statement.
2816 # expr ExprNode
2818 child_attrs = ["expr"]
2820 def analyse_declarations(self, env):
2821 import ExprNodes
2822 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2823 func = self.expr.function.as_cython_attribute()
2824 if func == u'declare':
2825 args, kwds = self.expr.explicit_args_kwds()
2826 if len(args):
2827 error(self.expr.pos, "Variable names must be specified.")
2828 for var, type_node in kwds.key_value_pairs:
2829 type = type_node.analyse_as_type(env)
2830 if type is None:
2831 error(type_node.pos, "Unknown type")
2832 else:
2833 env.declare_var(var.value, type, var.pos, is_cdef = True)
2834 self.__class__ = PassStatNode
2836 def analyse_expressions(self, env):
2837 self.expr.analyse_expressions(env)
2839 def generate_execution_code(self, code):
2840 self.expr.generate_evaluation_code(code)
2841 if not self.expr.is_temp and self.expr.result():
2842 code.putln("%s;" % self.expr.result())
2843 self.expr.generate_disposal_code(code)
2844 self.expr.free_temps(code)
2846 def annotate(self, code):
2847 self.expr.annotate(code)
2850 class AssignmentNode(StatNode):
2851 # Abstract base class for assignment nodes.
2853 # The analyse_expressions and generate_execution_code
2854 # phases of assignments are split into two sub-phases
2855 # each, to enable all the right hand sides of a
2856 # parallel assignment to be evaluated before assigning
2857 # to any of the left hand sides.
2859 def analyse_expressions(self, env):
2860 self.analyse_types(env)
2862 # def analyse_expressions(self, env):
2863 # self.analyse_expressions_1(env)
2864 # self.analyse_expressions_2(env)
2866 def generate_execution_code(self, code):
2867 self.generate_rhs_evaluation_code(code)
2868 self.generate_assignment_code(code)
2871 class SingleAssignmentNode(AssignmentNode):
2872 # The simplest case:
2874 # a = b
2876 # lhs ExprNode Left hand side
2877 # rhs ExprNode Right hand side
2878 # first bool Is this guaranteed the first assignment to lhs?
2880 child_attrs = ["lhs", "rhs"]
2881 first = False
2882 declaration_only = False
2884 def analyse_declarations(self, env):
2885 import ExprNodes
2887 # handle declarations of the form x = cython.foo()
2888 if isinstance(self.rhs, ExprNodes.CallNode):
2889 func_name = self.rhs.function.as_cython_attribute()
2890 if func_name:
2891 args, kwds = self.rhs.explicit_args_kwds()
2893 if func_name in ['declare', 'typedef']:
2894 if len(args) > 2 or kwds is not None:
2895 error(rhs.pos, "Can only declare one type at a time.")
2896 return
2897 type = args[0].analyse_as_type(env)
2898 if type is None:
2899 error(args[0].pos, "Unknown type")
2900 return
2901 lhs = self.lhs
2902 if func_name == 'declare':
2903 if isinstance(lhs, ExprNodes.NameNode):
2904 vars = [(lhs.name, lhs.pos)]
2905 elif isinstance(lhs, ExprNodes.TupleNode):
2906 vars = [(var.name, var.pos) for var in lhs.args]
2907 else:
2908 error(lhs.pos, "Invalid declaration")
2909 return
2910 for var, pos in vars:
2911 env.declare_var(var, type, pos, is_cdef = True)
2912 if len(args) == 2:
2913 # we have a value
2914 self.rhs = args[1]
2915 else:
2916 self.declaration_only = True
2917 else:
2918 self.declaration_only = True
2919 if not isinstance(lhs, ExprNodes.NameNode):
2920 error(lhs.pos, "Invalid declaration.")
2921 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2923 elif func_name in ['struct', 'union']:
2924 self.declaration_only = True
2925 if len(args) > 0 or kwds is None:
2926 error(rhs.pos, "Struct or union members must be given by name.")
2927 return
2928 members = []
2929 for member, type_node in kwds.key_value_pairs:
2930 type = type_node.analyse_as_type(env)
2931 if type is None:
2932 error(type_node.pos, "Unknown type")
2933 else:
2934 members.append((member.value, type, member.pos))
2935 if len(members) < len(kwds.key_value_pairs):
2936 return
2937 if not isinstance(self.lhs, ExprNodes.NameNode):
2938 error(self.lhs.pos, "Invalid declaration.")
2939 name = self.lhs.name
2940 scope = StructOrUnionScope(name)
2941 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2942 for member, type, pos in members:
2943 scope.declare_var(member, type, pos)
2945 if self.declaration_only:
2946 return
2947 else:
2948 self.lhs.analyse_target_declaration(env)
2950 def analyse_types(self, env, use_temp = 0):
2951 self.rhs.analyse_types(env)
2952 self.lhs.analyse_target_types(env)
2953 self.lhs.gil_assignment_check(env)
2954 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2955 if use_temp:
2956 self.rhs = self.rhs.coerce_to_temp(env)
2958 def generate_rhs_evaluation_code(self, code):
2959 self.rhs.generate_evaluation_code(code)
2961 def generate_assignment_code(self, code):
2962 self.lhs.generate_assignment_code(self.rhs, code)
2964 def annotate(self, code):
2965 self.lhs.annotate(code)
2966 self.rhs.annotate(code)
2969 class CascadedAssignmentNode(AssignmentNode):
2970 # An assignment with multiple left hand sides:
2972 # a = b = c
2974 # lhs_list [ExprNode] Left hand sides
2975 # rhs ExprNode Right hand sides
2977 # Used internally:
2979 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2981 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2982 coerced_rhs_list = None
2984 def analyse_declarations(self, env):
2985 for lhs in self.lhs_list:
2986 lhs.analyse_target_declaration(env)
2988 def analyse_types(self, env, use_temp = 0):
2989 self.rhs.analyse_types(env)
2990 if use_temp:
2991 self.rhs = self.rhs.coerce_to_temp(env)
2992 else:
2993 self.rhs = self.rhs.coerce_to_simple(env)
2994 from ExprNodes import CloneNode
2995 self.coerced_rhs_list = []
2996 for lhs in self.lhs_list:
2997 lhs.analyse_target_types(env)
2998 lhs.gil_assignment_check(env)
2999 rhs = CloneNode(self.rhs)
3000 rhs = rhs.coerce_to(lhs.type, env)
3001 self.coerced_rhs_list.append(rhs)
3003 def generate_rhs_evaluation_code(self, code):
3004 self.rhs.generate_evaluation_code(code)
3006 def generate_assignment_code(self, code):
3007 for i in range(len(self.lhs_list)):
3008 lhs = self.lhs_list[i]
3009 rhs = self.coerced_rhs_list[i]
3010 rhs.generate_evaluation_code(code)
3011 lhs.generate_assignment_code(rhs, code)
3012 # Assignment has disposed of the cloned RHS
3013 self.rhs.generate_disposal_code(code)
3014 self.rhs.free_temps(code)
3016 def annotate(self, code):
3017 for i in range(len(self.lhs_list)):
3018 lhs = self.lhs_list[i].annotate(code)
3019 rhs = self.coerced_rhs_list[i].annotate(code)
3020 self.rhs.annotate(code)
3023 class ParallelAssignmentNode(AssignmentNode):
3024 # A combined packing/unpacking assignment:
3026 # a, b, c = d, e, f
3028 # This has been rearranged by the parser into
3030 # a = d ; b = e ; c = f
3032 # but we must evaluate all the right hand sides
3033 # before assigning to any of the left hand sides.
3035 # stats [AssignmentNode] The constituent assignments
3037 child_attrs = ["stats"]
3039 def analyse_declarations(self, env):
3040 for stat in self.stats:
3041 stat.analyse_declarations(env)
3043 def analyse_expressions(self, env):
3044 for stat in self.stats:
3045 stat.analyse_types(env, use_temp = 1)
3047 # def analyse_expressions(self, env):
3048 # for stat in self.stats:
3049 # stat.analyse_expressions_1(env, use_temp = 1)
3050 # for stat in self.stats:
3051 # stat.analyse_expressions_2(env)
3053 def generate_execution_code(self, code):
3054 for stat in self.stats:
3055 stat.generate_rhs_evaluation_code(code)
3056 for stat in self.stats:
3057 stat.generate_assignment_code(code)
3059 def annotate(self, code):
3060 for stat in self.stats:
3061 stat.annotate(code)
3064 class InPlaceAssignmentNode(AssignmentNode):
3065 # An in place arithmatic operand:
3067 # a += b
3068 # a -= b
3069 # ...
3071 # lhs ExprNode Left hand side
3072 # rhs ExprNode Right hand side
3073 # op char one of "+-*/%^&|"
3074 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3076 # This code is a bit tricky because in order to obey Python
3077 # semantics the sub-expressions (e.g. indices) of the lhs must
3078 # not be evaluated twice. So we must re-use the values calculated
3079 # in evaluation phase for the assignment phase as well.
3080 # Fortunately, the type of the lhs node is fairly constrained
3081 # (it must be a NameNode, AttributeNode, or IndexNode).
3083 child_attrs = ["lhs", "rhs"]
3084 dup = None
3086 def analyse_declarations(self, env):
3087 self.lhs.analyse_target_declaration(env)
3089 def analyse_types(self, env):
3090 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3091 self.rhs.analyse_types(env)
3092 self.lhs.analyse_target_types(env)
3093 import ExprNodes
3094 if self.lhs.type.is_pyobject:
3095 self.rhs = self.rhs.coerce_to_pyobject(env)
3096 elif self.rhs.type.is_pyobject:
3097 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3098 if self.lhs.type.is_pyobject:
3099 self.result_value_temp = ExprNodes.PyTempNode(self.pos, env)
3100 self.result_value = self.result_value_temp.coerce_to(self.lhs.type, env)
3102 def generate_execution_code(self, code):
3103 import ExprNodes
3104 self.rhs.generate_evaluation_code(code)
3105 self.dup.generate_subexpr_evaluation_code(code)
3106 if self.dup.is_temp:
3107 self.dup.allocate_temp_result(code)
3108 # self.dup.generate_result_code is run only if it is not buffer access
3109 if self.operator == "**":
3110 extra = ", Py_None"
3111 else:
3112 extra = ""
3113 if self.lhs.type.is_pyobject:
3114 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3115 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3116 self.dup.generate_result_code(code)
3117 self.result_value_temp.allocate(code)
3118 code.putln(
3119 "%s = %s(%s, %s%s); %s" % (
3120 self.result_value.result(),
3121 self.py_operation_function(),
3122 self.dup.py_result(),
3123 self.rhs.py_result(),
3124 extra,
3125 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3126 code.put_gotref(self.result_value.py_result())
3127 self.result_value.generate_evaluation_code(code) # May be a type check...
3128 self.rhs.generate_disposal_code(code)
3129 self.rhs.free_temps(code)
3130 self.dup.generate_disposal_code(code)
3131 self.dup.free_temps(code)
3132 self.lhs.generate_assignment_code(self.result_value, code)
3133 self.result_value_temp.release(code)
3134 else:
3135 c_op = self.operator
3136 if c_op == "//":
3137 c_op = "/"
3138 elif c_op == "**":
3139 error(self.pos, "No C inplace power operator")
3140 elif self.lhs.type.is_complex:
3141 error(self.pos, "Inplace operators not implemented for complex types.")
3143 # have to do assignment directly to avoid side-effects
3144 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3145 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3146 else:
3147 self.dup.generate_result_code(code)
3148 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3149 self.rhs.generate_disposal_code(code)
3150 self.rhs.free_temps(code)
3151 if self.dup.is_temp:
3152 self.dup.generate_subexpr_disposal_code(code)
3153 self.dup.free_subexpr_temps(code)
3155 def create_dup_node(self, env):
3156 import ExprNodes
3157 self.dup = self.lhs
3158 self.dup.analyse_types(env)
3159 if isinstance(self.lhs, ExprNodes.NameNode):
3160 target_lhs = ExprNodes.NameNode(self.dup.pos,
3161 name = self.dup.name,
3162 is_temp = self.dup.is_temp,
3163 entry = self.dup.entry)
3164 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3165 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3166 obj = ExprNodes.CloneNode(self.lhs.obj),
3167 attribute = self.dup.attribute,
3168 is_temp = self.dup.is_temp)
3169 elif isinstance(self.lhs, ExprNodes.IndexNode):
3170 if self.lhs.index:
3171 index = ExprNodes.CloneNode(self.lhs.index)
3172 else:
3173 index = None
3174 if self.lhs.indices:
3175 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3176 else:
3177 indices = []
3178 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3179 base = ExprNodes.CloneNode(self.dup.base),
3180 index = index,
3181 indices = indices,
3182 is_temp = self.dup.is_temp)
3183 else:
3184 assert False
3185 self.lhs = target_lhs
3186 return self.dup
3188 def py_operation_function(self):
3189 return self.py_functions[self.operator]
3191 py_functions = {
3192 "|": "PyNumber_InPlaceOr",
3193 "^": "PyNumber_InPlaceXor",
3194 "&": "PyNumber_InPlaceAnd",
3195 "+": "PyNumber_InPlaceAdd",
3196 "-": "PyNumber_InPlaceSubtract",
3197 "*": "PyNumber_InPlaceMultiply",
3198 "/": "__Pyx_PyNumber_InPlaceDivide",
3199 "%": "PyNumber_InPlaceRemainder",
3200 "<<": "PyNumber_InPlaceLshift",
3201 ">>": "PyNumber_InPlaceRshift",
3202 "**": "PyNumber_InPlacePower",
3203 "//": "PyNumber_InPlaceFloorDivide",
3206 def annotate(self, code):
3207 self.lhs.annotate(code)
3208 self.rhs.annotate(code)
3209 self.dup.annotate(code)
3211 def create_binop_node(self):
3212 import ExprNodes
3213 return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
3216 class PrintStatNode(StatNode):
3217 # print statement
3219 # arg_tuple TupleNode
3220 # append_newline boolean
3222 child_attrs = ["arg_tuple"]
3224 def analyse_expressions(self, env):
3225 self.arg_tuple.analyse_expressions(env)
3226 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3227 env.use_utility_code(printing_utility_code)
3228 if len(self.arg_tuple.args) == 1 and self.append_newline:
3229 env.use_utility_code(printing_one_utility_code)
3231 nogil_check = Node.gil_error
3232 gil_message = "Python print statement"
3234 def generate_execution_code(self, code):
3235 if len(self.arg_tuple.args) == 1 and self.append_newline:
3236 arg = self.arg_tuple.args[0]
3237 arg.generate_evaluation_code(code)
3239 code.putln(
3240 "if (__Pyx_PrintOne(%s) < 0) %s" % (
3241 arg.py_result(),
3242 code.error_goto(self.pos)))
3243 arg.generate_disposal_code(code)
3244 arg.free_temps(code)
3245 else:
3246 self.arg_tuple.generate_evaluation_code(code)
3247 code.putln(
3248 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3249 self.arg_tuple.py_result(),
3250 self.append_newline,
3251 code.error_goto(self.pos)))
3252 self.arg_tuple.generate_disposal_code(code)
3253 self.arg_tuple.free_temps(code)
3255 def annotate(self, code):
3256 self.arg_tuple.annotate(code)
3259 class ExecStatNode(StatNode):
3260 # exec statement
3262 # args [ExprNode]
3264 child_attrs = ["args"]
3266 def analyse_expressions(self, env):
3267 for i, arg in enumerate(self.args):
3268 arg.analyse_expressions(env)
3269 arg = arg.coerce_to_pyobject(env)
3270 self.args[i] = arg
3271 env.use_utility_code(Builtin.pyexec_utility_code)
3273 nogil_check = Node.gil_error
3274 gil_message = "Python exec statement"
3276 def generate_execution_code(self, code):
3277 args = []
3278 for arg in self.args:
3279 arg.generate_evaluation_code(code)
3280 args.append( arg.py_result() )
3281 args = tuple(args + ['0', '0'][:3-len(args)])
3282 temp_result = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
3283 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3284 (temp_result,) + args))
3285 for arg in self.args:
3286 arg.generate_disposal_code(code)
3287 arg.free_temps(code)
3288 code.putln(
3289 code.error_goto_if_null(temp_result, self.pos))
3290 code.put_gotref(temp_result)
3291 code.put_decref_clear(temp_result, py_object_type)
3292 code.funcstate.release_temp(temp_result)
3294 def annotate(self, code):
3295 for arg in self.args:
3296 arg.annotate(code)
3299 class DelStatNode(StatNode):
3300 # del statement
3302 # args [ExprNode]
3304 child_attrs = ["args"]
3306 def analyse_declarations(self, env):
3307 for arg in self.args:
3308 arg.analyse_target_declaration(env)
3310 def analyse_expressions(self, env):
3311 for arg in self.args:
3312 arg.analyse_target_expression(env, None)
3313 if not arg.type.is_pyobject:
3314 error(arg.pos, "Deletion of non-Python object")
3315 #arg.release_target_temp(env)
3317 def nogil_check(self, env):
3318 for arg in self.args:
3319 if arg.type.is_pyobject:
3320 self.gil_error()
3322 gil_message = "Deleting Python object"
3324 def generate_execution_code(self, code):
3325 for arg in self.args:
3326 if arg.type.is_pyobject:
3327 arg.generate_deletion_code(code)
3328 # else error reported earlier
3330 def annotate(self, code):
3331 for arg in self.args:
3332 arg.annotate(code)
3335 class PassStatNode(StatNode):
3336 # pass statement
3338 child_attrs = []
3340 def analyse_expressions(self, env):
3341 pass
3343 def generate_execution_code(self, code):
3344 pass
3347 class BreakStatNode(StatNode):
3349 child_attrs = []
3351 def analyse_expressions(self, env):
3352 pass
3354 def generate_execution_code(self, code):
3355 if not code.break_label:
3356 error(self.pos, "break statement not inside loop")
3357 else:
3358 code.put_goto(code.break_label)
3361 class ContinueStatNode(StatNode):
3363 child_attrs = []
3365 def analyse_expressions(self, env):
3366 pass
3368 def generate_execution_code(self, code):
3369 if code.funcstate.in_try_finally:
3370 error(self.pos, "continue statement inside try of try...finally")
3371 elif not code.continue_label:
3372 error(self.pos, "continue statement not inside loop")
3373 else:
3374 code.put_goto(code.continue_label)
3377 class ReturnStatNode(StatNode):
3378 # return statement
3380 # value ExprNode or None
3381 # return_type PyrexType
3383 child_attrs = ["value"]
3385 def analyse_expressions(self, env):
3386 return_type = env.return_type
3387 self.return_type = return_type
3388 if not return_type:
3389 error(self.pos, "Return not inside a function body")
3390 return
3391 if self.value:
3392 self.value.analyse_types(env)
3393 if return_type.is_void or return_type.is_returncode:
3394 error(self.value.pos,
3395 "Return with value in void function")
3396 else:
3397 self.value = self.value.coerce_to(env.return_type, env)
3398 else:
3399 if (not return_type.is_void
3400 and not return_type.is_pyobject
3401 and not return_type.is_returncode):
3402 error(self.pos, "Return value required")
3404 def nogil_check(self, env):
3405 if self.return_type.is_pyobject:
3406 self.gil_error()
3408 gil_message = "Returning Python object"
3410 def generate_execution_code(self, code):
3411 code.mark_pos(self.pos)
3412 if not self.return_type:
3413 # error reported earlier
3414 return
3415 if self.return_type.is_pyobject:
3416 code.put_xdecref(Naming.retval_cname,
3417 self.return_type)
3418 if self.value:
3419 self.value.generate_evaluation_code(code)
3420 self.value.make_owned_reference(code)
3421 code.putln(
3422 "%s = %s;" % (
3423 Naming.retval_cname,
3424 self.value.result_as(self.return_type)))
3425 self.value.generate_post_assignment_code(code)
3426 self.value.free_temps(code)
3427 else:
3428 if self.return_type.is_pyobject:
3429 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3430 elif self.return_type.is_returncode:
3431 code.putln(
3432 "%s = %s;" % (
3433 Naming.retval_cname,
3434 self.return_type.default_value))
3435 for cname, type in code.funcstate.temps_holding_reference():
3436 code.put_decref_clear(cname, type)
3437 code.put_goto(code.return_label)
3439 def annotate(self, code):
3440 if self.value:
3441 self.value.annotate(code)
3444 class RaiseStatNode(StatNode):
3445 # raise statement
3447 # exc_type ExprNode or None
3448 # exc_value ExprNode or None
3449 # exc_tb ExprNode or None
3451 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3453 def analyse_expressions(self, env):
3454 if self.exc_type:
3455 self.exc_type.analyse_types(env)
3456 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3457 if self.exc_value:
3458 self.exc_value.analyse_types(env)
3459 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3460 if self.exc_tb:
3461 self.exc_tb.analyse_types(env)
3462 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3463 env.use_utility_code(raise_utility_code)
3465 nogil_check = Node.gil_error
3466 gil_message = "Raising exception"
3468 def generate_execution_code(self, code):
3469 if self.exc_type:
3470 self.exc_type.generate_evaluation_code(code)
3471 type_code = self.exc_type.py_result()
3472 else:
3473 type_code = "0"
3474 if self.exc_value:
3475 self.exc_value.generate_evaluation_code(code)
3476 value_code = self.exc_value.py_result()
3477 else:
3478 value_code = "0"
3479 if self.exc_tb:
3480 self.exc_tb.generate_evaluation_code(code)
3481 tb_code = self.exc_tb.py_result()
3482 else:
3483 tb_code = "0"
3484 code.putln(
3485 "__Pyx_Raise(%s, %s, %s);" % (
3486 type_code,
3487 value_code,
3488 tb_code))
3489 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3490 if obj:
3491 obj.generate_disposal_code(code)
3492 obj.free_temps(code)
3493 code.putln(
3494 code.error_goto(self.pos))
3496 def annotate(self, code):
3497 if self.exc_type:
3498 self.exc_type.annotate(code)
3499 if self.exc_value:
3500 self.exc_value.annotate(code)
3501 if self.exc_tb:
3502 self.exc_tb.annotate(code)
3505 class ReraiseStatNode(StatNode):
3507 child_attrs = []
3509 def analyse_expressions(self, env):
3510 env.use_utility_code(restore_exception_utility_code)
3512 nogil_check = Node.gil_error
3513 gil_message = "Raising exception"
3515 def generate_execution_code(self, code):
3516 vars = code.funcstate.exc_vars
3517 if vars:
3518 for varname in vars:
3519 code.put_giveref(varname)
3520 code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars))
3521 for varname in vars:
3522 code.put("%s = 0; " % varname)
3523 code.putln()
3524 code.putln(code.error_goto(self.pos))
3525 else:
3526 error(self.pos, "Reraise not inside except clause")
3529 class AssertStatNode(StatNode):
3530 # assert statement
3532 # cond ExprNode
3533 # value ExprNode or None
3535 child_attrs = ["cond", "value"]
3537 def analyse_expressions(self, env):
3538 self.cond = self.cond.analyse_boolean_expression(env)
3539 if self.value:
3540 self.value.analyse_types(env)
3541 self.value = self.value.coerce_to_pyobject(env)
3543 nogil_check = Node.gil_error
3544 gil_message = "Raising exception"
3546 def generate_execution_code(self, code):
3547 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3548 self.cond.generate_evaluation_code(code)
3549 code.putln(
3550 "if (unlikely(!%s)) {" %
3551 self.cond.result())
3552 if self.value:
3553 self.value.generate_evaluation_code(code)
3554 code.putln(
3555 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3556 self.value.py_result())
3557 self.value.generate_disposal_code(code)
3558 self.value.free_temps(code)
3559 else:
3560 code.putln(
3561 "PyErr_SetNone(PyExc_AssertionError);")
3562 code.putln(
3563 code.error_goto(self.pos))
3564 code.putln(
3565 "}")
3566 self.cond.generate_disposal_code(code)
3567 self.cond.free_temps(code)
3568 code.putln("#endif")
3570 def annotate(self, code):
3571 self.cond.annotate(code)
3572 if self.value:
3573 self.value.annotate(code)
3576 class IfStatNode(StatNode):
3577 # if statement
3579 # if_clauses [IfClauseNode]
3580 # else_clause StatNode or None
3582 child_attrs = ["if_clauses", "else_clause"]
3584 def analyse_control_flow(self, env):
3585 env.start_branching(self.pos)
3586 for if_clause in self.if_clauses:
3587 if_clause.analyse_control_flow(env)
3588 env.next_branch(if_clause.end_pos())
3589 if self.else_clause:
3590 self.else_clause.analyse_control_flow(env)
3591 env.finish_branching(self.end_pos())
3593 def analyse_declarations(self, env):
3594 for if_clause in self.if_clauses:
3595 if_clause.analyse_declarations(env)
3596 if self.else_clause:
3597 self.else_clause.analyse_declarations(env)
3599 def analyse_expressions(self, env):
3600 for if_clause in self.if_clauses:
3601 if_clause.analyse_expressions(env)
3602 if self.else_clause:
3603 self.else_clause.analyse_expressions(env)
3605 def generate_execution_code(self, code):
3606 code.mark_pos(self.pos)
3607 end_label = code.new_label()
3608 for if_clause in self.if_clauses:
3609 if_clause.generate_execution_code(code, end_label)
3610 if self.else_clause:
3611 code.putln("/*else*/ {")
3612 self.else_clause.generate_execution_code(code)
3613 code.putln("}")
3614 code.put_label(end_label)
3616 def annotate(self, code):
3617 for if_clause in self.if_clauses:
3618 if_clause.annotate(code)
3619 if self.else_clause:
3620 self.else_clause.annotate(code)
3623 class IfClauseNode(Node):
3624 # if or elif clause in an if statement
3626 # condition ExprNode
3627 # body StatNode
3629 child_attrs = ["condition", "body"]
3631 def analyse_control_flow(self, env):
3632 self.body.analyse_control_flow(env)
3634 def analyse_declarations(self, env):
3635 self.condition.analyse_declarations(env)
3636 self.body.analyse_declarations(env)
3638 def analyse_expressions(self, env):
3639 self.condition = \
3640 self.condition.analyse_temp_boolean_expression(env)
3641 self.body.analyse_expressions(env)
3643 def generate_execution_code(self, code, end_label):
3644 self.condition.generate_evaluation_code(code)
3645 code.putln(
3646 "if (%s) {" %
3647 self.condition.result())
3648 self.condition.generate_disposal_code(code)
3649 self.condition.free_temps(code)
3650 self.body.generate_execution_code(code)
3651 #code.putln(
3652 # "goto %s;" %
3653 # end_label)
3654 code.put_goto(end_label)
3655 code.putln("}")
3657 def annotate(self, code):
3658 self.condition.annotate(code)
3659 self.body.annotate(code)
3662 class SwitchCaseNode(StatNode):
3663 # Generated in the optimization of an if-elif-else node
3665 # conditions [ExprNode]
3666 # body StatNode
3668 child_attrs = ['conditions', 'body']
3670 def generate_execution_code(self, code):
3671 for cond in self.conditions:
3672 code.mark_pos(cond.pos)
3673 cond.generate_evaluation_code(code)
3674 code.putln("case %s:" % cond.result())
3675 self.body.generate_execution_code(code)
3676 code.putln("break;")
3678 def annotate(self, code):
3679 for cond in self.conditions:
3680 cond.annotate(code)
3681 self.body.annotate(code)
3683 class SwitchStatNode(StatNode):
3684 # Generated in the optimization of an if-elif-else node
3686 # test ExprNode
3687 # cases [SwitchCaseNode]
3688 # else_clause StatNode or None
3690 child_attrs = ['test', 'cases', 'else_clause']
3692 def generate_execution_code(self, code):
3693 code.putln("switch (%s) {" % self.test.result())
3694 for case in self.cases:
3695 case.generate_execution_code(code)
3696 if self.else_clause is not None:
3697 code.putln("default:")
3698 self.else_clause.generate_execution_code(code)
3699 code.putln("break;")
3700 code.putln("}")
3702 def annotate(self, code):
3703 self.test.annotate(code)
3704 for case in self.cases:
3705 case.annotate(code)
3706 if self.else_clause is not None:
3707 self.else_clause.annotate(code)
3709 class LoopNode(object):
3711 def analyse_control_flow(self, env):
3712 env.start_branching(self.pos)
3713 self.body.analyse_control_flow(env)
3714 env.next_branch(self.body.end_pos())
3715 if self.else_clause:
3716 self.else_clause.analyse_control_flow(env)
3717 env.finish_branching(self.end_pos())
3720 class WhileStatNode(LoopNode, StatNode):
3721 # while statement
3723 # condition ExprNode
3724 # body StatNode
3725 # else_clause StatNode
3727 child_attrs = ["condition", "body", "else_clause"]
3729 def analyse_declarations(self, env):
3730 self.body.analyse_declarations(env)
3731 if self.else_clause:
3732 self.else_clause.analyse_declarations(env)
3734 def analyse_expressions(self, env):
3735 self.condition = \
3736 self.condition.analyse_temp_boolean_expression(env)
3737 self.body.analyse_expressions(env)
3738 if self.else_clause:
3739 self.else_clause.analyse_expressions(env)
3741 def generate_execution_code(self, code):
3742 old_loop_labels = code.new_loop_labels()
3743 code.putln(
3744 "while (1) {")
3745 self.condition.generate_evaluation_code(code)
3746 self.condition.generate_disposal_code(code)
3747 code.putln(
3748 "if (!%s) break;" %
3749 self.condition.result())
3750 self.condition.free_temps(code)
3751 self.body.generate_execution_code(code)
3752 code.put_label(code.continue_label)
3753 code.putln("}")
3754 break_label = code.break_label
3755 code.set_loop_labels(old_loop_labels)
3756 if self.else_clause:
3757 code.putln("/*else*/ {")
3758 self.else_clause.generate_execution_code(code)
3759 code.putln("}")
3760 code.put_label(break_label)
3762 def annotate(self, code):
3763 self.condition.annotate(code)
3764 self.body.annotate(code)
3765 if self.else_clause:
3766 self.else_clause.annotate(code)
3769 def ForStatNode(pos, **kw):
3770 if 'iterator' in kw:
3771 return ForInStatNode(pos, **kw)
3772 else:
3773 return ForFromStatNode(pos, **kw)
3775 class ForInStatNode(LoopNode, StatNode):
3776 # for statement
3778 # target ExprNode
3779 # iterator IteratorNode
3780 # body StatNode
3781 # else_clause StatNode
3782 # item NextNode used internally
3784 child_attrs = ["target", "iterator", "body", "else_clause"]
3785 item = None
3787 def analyse_declarations(self, env):
3788 self.target.analyse_target_declaration(env)
3789 self.body.analyse_declarations(env)
3790 if self.else_clause:
3791 self.else_clause.analyse_declarations(env)
3793 def analyse_expressions(self, env):
3794 import ExprNodes
3795 self.target.analyse_target_types(env)
3796 self.iterator.analyse_expressions(env)
3797 self.item = ExprNodes.NextNode(self.iterator, env)
3798 self.item = self.item.coerce_to(self.target.type, env)
3799 self.body.analyse_expressions(env)
3800 if self.else_clause:
3801 self.else_clause.analyse_expressions(env)
3803 def generate_execution_code(self, code):
3804 old_loop_labels = code.new_loop_labels()
3805 self.iterator.allocate_counter_temp(code)
3806 self.iterator.generate_evaluation_code(code)
3807 code.putln(
3808 "for (;;) {")
3809 self.item.generate_evaluation_code(code)
3810 self.target.generate_assignment_code(self.item, code)
3811 self.body.generate_execution_code(code)
3812 code.put_label(code.continue_label)
3813 code.putln(
3814 "}")
3815 break_label = code.break_label
3816 code.set_loop_labels(old_loop_labels)
3817 if self.else_clause:
3818 code.putln("/*else*/ {")
3819 self.else_clause.generate_execution_code(code)
3820 code.putln("}")
3821 code.put_label(break_label)
3822 self.iterator.release_counter_temp(code)
3823 self.iterator.generate_disposal_code(code)
3824 self.iterator.free_temps(code)
3826 def annotate(self, code):
3827 self.target.annotate(code)
3828 self.iterator.annotate(code)
3829 self.body.annotate(code)
3830 if self.else_clause:
3831 self.else_clause.annotate(code)
3832 self.item.annotate(code)
3835 class ForFromStatNode(LoopNode, StatNode):
3836 # for name from expr rel name rel expr
3838 # target NameNode
3839 # bound1 ExprNode
3840 # relation1 string
3841 # relation2 string
3842 # bound2 ExprNode
3843 # step ExprNode or None
3844 # body StatNode
3845 # else_clause StatNode or None
3847 # Used internally:
3849 # from_range bool
3850 # is_py_target bool
3851 # loopvar_node ExprNode (usually a NameNode or temp node)
3852 # py_loopvar_node PyTempNode or None
3853 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3855 is_py_target = False
3856 loopvar_node = None
3857 py_loopvar_node = None
3858 from_range = False
3860 gil_message = "For-loop using object bounds or target"
3862 def nogil_check(self, env):
3863 for x in (self.target, self.bound1, self.bound2):
3864 if x.type.is_pyobject:
3865 self.gil_error()
3867 def analyse_declarations(self, env):
3868 self.target.analyse_target_declaration(env)
3869 self.body.analyse_declarations(env)
3870 if self.else_clause:
3871 self.else_clause.analyse_declarations(env)
3873 def analyse_expressions(self, env):
3874 import ExprNodes
3875 self.target.analyse_target_types(env)
3876 self.bound1.analyse_types(env)
3877 self.bound2.analyse_types(env)
3878 if self.step is not None:
3879 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3880 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3881 self.step.analyse_types(env)
3883 target_type = self.target.type
3884 if self.target.type.is_numeric:
3885 loop_type = self.target.type
3886 else:
3887 loop_type = PyrexTypes.c_int_type
3888 if not self.bound1.type.is_pyobject:
3889 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
3890 if not self.bound2.type.is_pyobject:
3891 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
3892 if self.step is not None and not self.step.type.is_pyobject:
3893 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
3894 self.bound1 = self.bound1.coerce_to(loop_type, env)
3895 self.bound2 = self.bound2.coerce_to(loop_type, env)
3896 if not self.bound2.is_literal:
3897 self.bound2 = self.bound2.coerce_to_temp(env)
3898 if self.step is not None:
3899 self.step = self.step.coerce_to(loop_type, env)
3900 if not self.step.is_literal:
3901 self.step = self.step.coerce_to_temp(env)
3903 target_type = self.target.type
3904 if not (target_type.is_pyobject or target_type.is_numeric):
3905 error(self.target.pos,
3906 "for-from loop variable must be c numeric type or Python object")
3907 if target_type.is_numeric:
3908 self.is_py_target = False
3909 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3910 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3911 self.loopvar_node = self.target
3912 self.py_loopvar_node = None
3913 else:
3914 self.is_py_target = True
3915 c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
3916 self.loopvar_node = c_loopvar_node
3917 self.py_loopvar_node = \
3918 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3919 self.body.analyse_expressions(env)
3920 if self.else_clause:
3921 self.else_clause.analyse_expressions(env)
3923 def generate_execution_code(self, code):
3924 old_loop_labels = code.new_loop_labels()
3925 from_range = self.from_range
3926 self.bound1.generate_evaluation_code(code)
3927 self.bound2.generate_evaluation_code(code)
3928 offset, incop = self.relation_table[self.relation1]
3929 if self.step is not None:
3930 self.step.generate_evaluation_code(code)
3931 step = self.step.result()
3932 incop = "%s=%s" % (incop[0], step)
3933 import ExprNodes
3934 if isinstance(self.loopvar_node, ExprNodes.TempNode):
3935 self.loopvar_node.allocate(code)
3936 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
3937 self.py_loopvar_node.allocate(code)
3938 if from_range:
3939 loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
3940 else:
3941 loopvar_name = self.loopvar_node.result()
3942 code.putln(
3943 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3944 loopvar_name,
3945 self.bound1.result(), offset,
3946 loopvar_name, self.relation2, self.bound2.result(),
3947 loopvar_name, incop))
3948 if self.py_loopvar_node:
3949 self.py_loopvar_node.generate_evaluation_code(code)
3950 self.target.generate_assignment_code(self.py_loopvar_node, code)
3951 elif from_range:
3952 code.putln("%s = %s;" % (
3953 self.target.result(), loopvar_name))
3954 self.body.generate_execution_code(code)
3955 code.put_label(code.continue_label)
3956 if self.py_loopvar_node:
3957 # This mess is to make for..from loops with python targets behave
3958 # exactly like those with C targets with regards to re-assignment
3959 # of the loop variable.
3960 import ExprNodes
3961 if self.target.entry.is_pyglobal:
3962 # We know target is a NameNode, this is the only ugly case.
3963 target_node = ExprNodes.PyTempNode(self.target.pos, None)
3964 target_node.allocate(code)
3965 interned_cname = code.intern_identifier(self.target.entry.name)
3966 code.putln("/*here*/")
3967 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
3968 target_node.result(),
3969 Naming.module_cname,
3970 interned_cname,
3971 code.error_goto_if_null(target_node.result(), self.target.pos)))
3972 code.put_gotref(target_node.result())
3973 else:
3974 target_node = self.target
3975 from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
3976 from_py_node.temp_code = loopvar_name
3977 from_py_node.generate_result_code(code)
3978 if self.target.entry.is_pyglobal:
3979 code.put_decref(target_node.result(), target_node.type)
3980 target_node.release(code)
3981 code.putln("}")
3982 if self.py_loopvar_node:
3983 # This is potentially wasteful, but we don't want the semantics to
3984 # depend on whether or not the loop is a python type.
3985 self.py_loopvar_node.generate_evaluation_code(code)
3986 self.target.generate_assignment_code(self.py_loopvar_node, code)
3987 if from_range:
3988 code.funcstate.release_temp(loopvar_name)
3989 break_label = code.break_label
3990 code.set_loop_labels(old_loop_labels)
3991 if self.else_clause:
3992 code.putln("/*else*/ {")
3993 self.else_clause.generate_execution_code(code)
3994 code.putln("}")
3995 code.put_label(break_label)
3996 self.bound1.generate_disposal_code(code)
3997 self.bound1.free_temps(code)
3998 self.bound2.generate_disposal_code(code)
3999 self.bound2.free_temps(code)
4000 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4001 self.loopvar_node.release(code)
4002 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4003 self.py_loopvar_node.release(code)
4004 if self.step is not None:
4005 self.step.generate_disposal_code(code)
4006 self.step.free_temps(code)
4008 relation_table = {
4009 # {relop : (initial offset, increment op)}
4010 '<=': ("", "++"),
4011 '<' : ("+1", "++"),
4012 '>=': ("", "--"),
4013 '>' : ("-1", "--")
4016 def annotate(self, code):
4017 self.target.annotate(code)
4018 self.bound1.annotate(code)
4019 self.bound2.annotate(code)
4020 if self.step:
4021 self.bound2.annotate(code)
4022 self.body.annotate(code)
4023 if self.else_clause:
4024 self.else_clause.annotate(code)
4027 class WithStatNode(StatNode):
4028 """
4029 Represents a Python with statement.
4031 This is only used at parse tree level; and is not present in
4032 analysis or generation phases.
4033 """
4034 # manager The with statement manager object
4035 # target Node (lhs expression)
4036 # body StatNode
4037 child_attrs = ["manager", "target", "body"]
4039 class TryExceptStatNode(StatNode):
4040 # try .. except statement
4042 # body StatNode
4043 # except_clauses [ExceptClauseNode]
4044 # else_clause StatNode or None
4046 child_attrs = ["body", "except_clauses", "else_clause"]
4048 def analyse_control_flow(self, env):
4049 env.start_branching(self.pos)
4050 self.body.analyse_control_flow(env)
4051 successful_try = env.control_flow # grab this for later
4052 env.next_branch(self.body.end_pos())
4053 env.finish_branching(self.body.end_pos())
4055 env.start_branching(self.except_clauses[0].pos)
4056 for except_clause in self.except_clauses:
4057 except_clause.analyse_control_flow(env)
4058 env.next_branch(except_clause.end_pos())
4060 # the else cause it executed only when the try clause finishes
4061 env.control_flow.incoming = successful_try
4062 if self.else_clause:
4063 self.else_clause.analyse_control_flow(env)
4064 env.finish_branching(self.end_pos())
4066 def analyse_declarations(self, env):
4067 self.body.analyse_declarations(env)
4068 for except_clause in self.except_clauses:
4069 except_clause.analyse_declarations(env)
4070 if self.else_clause:
4071 self.else_clause.analyse_declarations(env)
4072 env.use_utility_code(reset_exception_utility_code)
4074 def analyse_expressions(self, env):
4075 self.body.analyse_expressions(env)
4076 default_clause_seen = 0
4077 for except_clause in self.except_clauses:
4078 except_clause.analyse_expressions(env)
4079 if default_clause_seen:
4080 error(except_clause.pos, "default 'except:' must be last")
4081 if not except_clause.pattern:
4082 default_clause_seen = 1
4083 self.has_default_clause = default_clause_seen
4084 if self.else_clause:
4085 self.else_clause.analyse_expressions(env)
4087 nogil_check = Node.gil_error
4088 gil_message = "Try-except statement"
4090 def generate_execution_code(self, code):
4091 old_return_label = code.return_label
4092 old_break_label = code.break_label
4093 old_continue_label = code.continue_label
4094 old_error_label = code.new_error_label()
4095 our_error_label = code.error_label
4096 except_end_label = code.new_label('exception_handled')
4097 except_error_label = code.new_label('except_error')
4098 except_return_label = code.new_label('except_return')
4099 try_return_label = code.new_label('try_return')
4100 try_break_label = code.new_label('try_break')
4101 try_continue_label = code.new_label('try_continue')
4102 try_end_label = code.new_label('try_end')
4104 code.putln("{")
4105 code.putln("PyObject %s;" %
4106 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4107 code.putln("__Pyx_ExceptionSave(%s);" %
4108 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4109 for var in Naming.exc_save_vars:
4110 code.put_xgotref(var)
4111 code.putln(
4112 "/*try:*/ {")
4113 code.return_label = try_return_label
4114 code.break_label = try_break_label
4115 code.continue_label = try_continue_label
4116 self.body.generate_execution_code(code)
4117 code.putln(
4118 "}")
4119 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4120 code.error_label = except_error_label
4121 code.return_label = except_return_label
4122 if self.else_clause:
4123 code.putln(
4124 "/*else:*/ {")
4125 self.else_clause.generate_execution_code(code)
4126 code.putln(
4127 "}")
4128 for var in Naming.exc_save_vars:
4129 code.put_xdecref_clear(var, py_object_type)
4130 code.put_goto(try_end_label)
4131 if code.label_used(try_return_label):
4132 code.put_label(try_return_label)
4133 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4134 code.putln("__Pyx_ExceptionReset(%s);" %
4135 ', '.join(Naming.exc_save_vars))
4136 code.put_goto(old_return_label)
4137 code.put_label(our_error_label)
4138 for temp_name, type in temps_to_clean_up:
4139 code.put_xdecref_clear(temp_name, type)
4140 for except_clause in self.except_clauses:
4141 except_clause.generate_handling_code(code, except_end_label)
4143 error_label_used = code.label_used(except_error_label)
4144 if error_label_used or not self.has_default_clause:
4145 if error_label_used:
4146 code.put_label(except_error_label)
4147 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4148 code.putln("__Pyx_ExceptionReset(%s);" %
4149 ', '.join(Naming.exc_save_vars))
4150 code.put_goto(old_error_label)
4152 for exit_label, old_label in zip(
4153 [try_break_label, try_continue_label, except_return_label],
4154 [old_break_label, old_continue_label, old_return_label]):
4156 if code.label_used(exit_label):
4157 code.put_label(exit_label)
4158 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4159 code.putln("__Pyx_ExceptionReset(%s);" %
4160 ', '.join(Naming.exc_save_vars))
4161 code.put_goto(old_label)
4163 if code.label_used(except_end_label):
4164 code.put_label(except_end_label)
4165 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4166 code.putln("__Pyx_ExceptionReset(%s);" %
4167 ', '.join(Naming.exc_save_vars))
4168 code.put_label(try_end_label)
4169 code.putln("}")
4171 code.return_label = old_return_label
4172 code.break_label = old_break_label
4173 code.continue_label = old_continue_label
4174 code.error_label = old_error_label
4176 def annotate(self, code):
4177 self.body.annotate(code)
4178 for except_node in self.except_clauses:
4179 except_node.annotate(code)
4180 if self.else_clause:
4181 self.else_clause.annotate(code)
4184 class ExceptClauseNode(Node):
4185 # Part of try ... except statement.
4187 # pattern ExprNode
4188 # target ExprNode or None
4189 # body StatNode
4190 # excinfo_target NameNode or None optional target for exception info
4191 # match_flag string result of exception match
4192 # exc_value ExcValueNode used internally
4193 # function_name string qualified name of enclosing function
4194 # exc_vars (string * 3) local exception variables
4196 # excinfo_target is never set by the parser, but can be set by a transform
4197 # in order to extract more extensive information about the exception as a
4198 # sys.exc_info()-style tuple into a target variable
4200 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4202 exc_value = None
4203 excinfo_target = None
4205 def analyse_declarations(self, env):
4206 if self.target:
4207 self.target.analyse_target_declaration(env)
4208 if self.excinfo_target is not None:
4209 self.excinfo_target.analyse_target_declaration(env)
4210 self.body.analyse_declarations(env)
4212 def analyse_expressions(self, env):
4213 import ExprNodes
4214 genv = env.global_scope()
4215 self.function_name = env.qualified_name
4216 if self.pattern:
4217 self.pattern.analyse_expressions(env)
4218 self.pattern = self.pattern.coerce_to_pyobject(env)
4220 if self.target:
4221 self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
4222 self.target.analyse_target_expression(env, self.exc_value)
4223 if self.excinfo_target is not None:
4224 import ExprNodes
4225 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4226 ExprNodes.ExcValueNode(pos=self.pos, env=env) for x in range(3)])
4227 self.excinfo_tuple.analyse_expressions(env)
4228 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4230 self.body.analyse_expressions(env)
4232 def generate_handling_code(self, code, end_label):
4233 code.mark_pos(self.pos)
4234 if self.pattern:
4235 self.pattern.generate_evaluation_code(code)
4237 match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
4238 code.putln(
4239 "%s = PyErr_ExceptionMatches(%s);" % (
4240 match_flag,
4241 self.pattern.py_result()))
4242 self.pattern.generate_disposal_code(code)
4243 self.pattern.free_temps(code)
4244 code.putln(
4245 "if (%s) {" %
4246 match_flag)
4247 code.funcstate.release_temp(match_flag)
4248 else:
4249 code.putln("/*except:*/ {")
4251 if not getattr(self.body, 'stats', True):
4252 # most simple case: no exception variable, empty body (pass)
4253 # => reset the exception state, done
4254 code.putln("PyErr_Restore(0,0,0);")
4255 code.put_goto(end_label)
4256 code.putln("}")
4257 return
4259 exc_vars = [code.funcstate.allocate_temp(py_object_type,
4260 manage_ref=True)
4261 for i in xrange(3)]
4262 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4263 # We always have to fetch the exception value even if
4264 # there is no target, because this also normalises the
4265 # exception and stores it in the thread state.
4266 code.globalstate.use_utility_code(get_exception_utility_code)
4267 exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4268 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4269 code.error_goto(self.pos)))
4270 for x in exc_vars:
4271 code.put_gotref(x)
4272 if self.target:
4273 self.exc_value.set_var(exc_vars[1])
4274 self.exc_value.generate_evaluation_code(code)
4275 self.target.generate_assignment_code(self.exc_value, code)
4276 if self.excinfo_target is not None:
4277 for tempvar, node in zip(exc_vars, self.excinfo_tuple.args):
4278 node.set_var(tempvar)
4279 self.excinfo_tuple.generate_evaluation_code(code)
4280 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4282 old_break_label, old_continue_label = code.break_label, code.continue_label
4283 code.break_label = code.new_label('except_break')
4284 code.continue_label = code.new_label('except_continue')
4286 old_exc_vars = code.funcstate.exc_vars
4287 code.funcstate.exc_vars = exc_vars
4288 self.body.generate_execution_code(code)
4289 code.funcstate.exc_vars = old_exc_vars
4290 for var in exc_vars:
4291 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4292 code.put_goto(end_label)
4294 if code.label_used(code.break_label):
4295 code.put_label(code.break_label)
4296 for var in exc_vars:
4297 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4298 code.put_goto(old_break_label)
4299 code.break_label = old_break_label
4301 if code.label_used(code.continue_label):
4302 code.put_label(code.continue_label)
4303 for var in exc_vars:
4304 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4305 code.put_goto(old_continue_label)
4306 code.continue_label = old_continue_label
4308 for temp in exc_vars:
4309 code.funcstate.release_temp(temp)
4311 code.putln(
4312 "}")
4314 def annotate(self, code):
4315 if self.pattern:
4316 self.pattern.annotate(code)
4317 if self.target:
4318 self.target.annotate(code)
4319 self.body.annotate(code)
4322 class TryFinallyStatNode(StatNode):
4323 # try ... finally statement
4325 # body StatNode
4326 # finally_clause StatNode
4328 # The plan is that we funnel all continue, break
4329 # return and error gotos into the beginning of the
4330 # finally block, setting a variable to remember which
4331 # one we're doing. At the end of the finally block, we
4332 # switch on the variable to figure out where to go.
4333 # In addition, if we're doing an error, we save the
4334 # exception on entry to the finally block and restore
4335 # it on exit.
4337 child_attrs = ["body", "finally_clause"]
4339 preserve_exception = 1
4341 disallow_continue_in_try_finally = 0
4342 # There doesn't seem to be any point in disallowing
4343 # continue in the try block, since we have no problem
4344 # handling it.
4346 def create_analysed(pos, env, body, finally_clause):
4347 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4348 return node
4349 create_analysed = staticmethod(create_analysed)
4351 def analyse_control_flow(self, env):
4352 env.start_branching(self.pos)
4353 self.body.analyse_control_flow(env)
4354 env.next_branch(self.body.end_pos())
4355 env.finish_branching(self.body.end_pos())
4356 self.finally_clause.analyse_control_flow(env)
4358 def analyse_declarations(self, env):
4359 self.body.analyse_declarations(env)
4360 self.finally_clause.analyse_declarations(env)
4362 def analyse_expressions(self, env):
4363 self.body.analyse_expressions(env)
4364 self.finally_clause.analyse_expressions(env)
4366 nogil_check = Node.gil_error
4367 gil_message = "Try-finally statement"
4369 def generate_execution_code(self, code):
4370 old_error_label = code.error_label
4371 old_labels = code.all_new_labels()
4372 new_labels = code.get_all_labels()
4373 new_error_label = code.error_label
4374 catch_label = code.new_label()
4375 code.putln(
4376 "/*try:*/ {")
4377 if self.disallow_continue_in_try_finally:
4378 was_in_try_finally = code.funcstate.in_try_finally
4379 code.funcstate.in_try_finally = 1
4380 self.body.generate_execution_code(code)
4381 if self.disallow_continue_in_try_finally:
4382 code.funcstate.in_try_finally = was_in_try_finally
4383 code.putln(
4384 "}")
4385 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4386 code.putln(
4387 "/*finally:*/ {")
4388 cases_used = []
4389 error_label_used = 0
4390 for i, new_label in enumerate(new_labels):
4391 if new_label in code.labels_used:
4392 cases_used.append(i)
4393 if new_label == new_error_label:
4394 error_label_used = 1
4395 error_label_case = i
4396 if cases_used:
4397 code.putln(
4398 "int __pyx_why;")
4399 if error_label_used and self.preserve_exception:
4400 code.putln(
4401 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4402 code.putln(
4403 "int %s;" % Naming.exc_lineno_name)
4404 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4405 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4406 code.putln(exc_var_init_zero)
4407 else:
4408 exc_var_init_zero = None
4409 code.use_label(catch_label)
4410 code.putln(
4411 "__pyx_why = 0; goto %s;" % catch_label)
4412 for i in cases_used:
4413 new_label = new_labels[i]
4414 #if new_label and new_label != "<try>":
4415 if new_label == new_error_label and self.preserve_exception:
4416 self.put_error_catcher(code,
4417 new_error_label, i+1, catch_label, temps_to_clean_up)
4418 else:
4419 code.put('%s: ' % new_label)
4420 if exc_var_init_zero:
4421 code.putln(exc_var_init_zero)
4422 code.putln("__pyx_why = %s; goto %s;" % (
4423 i+1,
4424 catch_label))
4425 code.put_label(catch_label)
4426 code.set_all_labels(old_labels)
4427 if error_label_used:
4428 code.new_error_label()
4429 finally_error_label = code.error_label
4430 self.finally_clause.generate_execution_code(code)
4431 if error_label_used:
4432 if finally_error_label in code.labels_used and self.preserve_exception:
4433 over_label = code.new_label()
4434 code.put_goto(over_label);
4435 code.put_label(finally_error_label)
4436 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4437 for var in Naming.exc_vars:
4438 code.putln("Py_XDECREF(%s);" % var)
4439 code.putln("}")
4440 code.put_goto(old_error_label)
4441 code.put_label(over_label)
4442 code.error_label = old_error_label
4443 if cases_used:
4444 code.putln(
4445 "switch (__pyx_why) {")
4446 for i in cases_used:
4447 old_label = old_labels[i]
4448 if old_label == old_error_label and self.preserve_exception:
4449 self.put_error_uncatcher(code, i+1, old_error_label)
4450 else:
4451 code.use_label(old_label)
4452 code.putln(
4453 "case %s: goto %s;" % (
4454 i+1,
4455 old_label))
4456 code.putln(
4457 "}")
4458 code.putln(
4459 "}")
4461 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4462 code.globalstate.use_utility_code(restore_exception_utility_code)
4463 code.putln(
4464 "%s: {" %
4465 error_label)
4466 code.putln(
4467 "__pyx_why = %s;" %
4468 i)
4469 for temp_name, type in temps_to_clean_up:
4470 code.put_xdecref_clear(temp_name, type)
4471 code.putln(
4472 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4473 Naming.exc_vars)
4474 code.putln(
4475 "%s = %s;" % (
4476 Naming.exc_lineno_name, Naming.lineno_cname))
4477 #code.putln(
4478 # "goto %s;" %
4479 # catch_label)
4480 code.put_goto(catch_label)
4481 code.putln(
4482 "}")
4484 def put_error_uncatcher(self, code, i, error_label):
4485 code.globalstate.use_utility_code(restore_exception_utility_code)
4486 code.putln(
4487 "case %s: {" %
4488 i)
4489 code.putln(
4490 "__Pyx_ErrRestore(%s, %s, %s);" %
4491 Naming.exc_vars)
4492 code.putln(
4493 "%s = %s;" % (
4494 Naming.lineno_cname, Naming.exc_lineno_name))
4495 for var in Naming.exc_vars:
4496 code.putln(
4497 "%s = 0;" %
4498 var)
4499 code.put_goto(error_label)
4500 code.putln(
4501 "}")
4503 def annotate(self, code):
4504 self.body.annotate(code)
4505 self.finally_clause.annotate(code)
4508 class GILStatNode(TryFinallyStatNode):
4509 # 'with gil' or 'with nogil' statement
4511 # state string 'gil' or 'nogil'
4513 # child_attrs = []
4515 preserve_exception = 0
4517 def __init__(self, pos, state, body):
4518 self.state = state
4519 TryFinallyStatNode.__init__(self, pos,
4520 body = body,
4521 finally_clause = GILExitNode(pos, state = state))
4523 def analyse_expressions(self, env):
4524 env.use_utility_code(force_init_threads_utility_code)
4525 was_nogil = env.nogil
4526 env.nogil = 1
4527 TryFinallyStatNode.analyse_expressions(self, env)
4528 env.nogil = was_nogil
4530 nogil_check = None
4532 def generate_execution_code(self, code):
4533 code.mark_pos(self.pos)
4534 if self.state == 'gil':
4535 code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4536 else:
4537 code.putln("{ PyThreadState *_save;")
4538 code.putln("Py_UNBLOCK_THREADS")
4539 TryFinallyStatNode.generate_execution_code(self, code)
4540 code.putln("}")
4543 class GILExitNode(StatNode):
4544 # Used as the 'finally' block in a GILStatNode
4546 # state string 'gil' or 'nogil'
4548 child_attrs = []
4550 def analyse_expressions(self, env):
4551 pass
4553 def generate_execution_code(self, code):
4554 if self.state == 'gil':
4555 code.putln("PyGILState_Release();")
4556 else:
4557 code.putln("Py_BLOCK_THREADS")
4560 class CImportStatNode(StatNode):
4561 # cimport statement
4563 # module_name string Qualified name of module being imported
4564 # as_name string or None Name specified in "as" clause, if any
4566 child_attrs = []
4568 def analyse_declarations(self, env):
4569 if not env.is_module_scope:
4570 error(self.pos, "cimport only allowed at module level")
4571 return
4572 module_scope = env.find_module(self.module_name, self.pos)
4573 if "." in self.module_name:
4574 names = [EncodedString(name) for name in self.module_name.split(".")]
4575 top_name = names[0]
4576 top_module_scope = env.context.find_submodule(top_name)
4577 module_scope = top_module_scope
4578 for name in names[1:]:
4579 submodule_scope = module_scope.find_submodule(name)
4580 module_scope.declare_module(name, submodule_scope, self.pos)
4581 module_scope = submodule_scope
4582 if self.as_name:
4583 env.declare_module(self.as_name, module_scope, self.pos)
4584 else:
4585 env.declare_module(top_name, top_module_scope, self.pos)
4586 else:
4587 name = self.as_name or self.module_name
4588 env.declare_module(name, module_scope, self.pos)
4590 def analyse_expressions(self, env):
4591 pass
4593 def generate_execution_code(self, code):
4594 pass
4597 class FromCImportStatNode(StatNode):
4598 # from ... cimport statement
4600 # module_name string Qualified name of module
4601 # imported_names [(pos, name, as_name, kind)] Names to be imported
4603 child_attrs = []
4605 def analyse_declarations(self, env):
4606 if not env.is_module_scope:
4607 error(self.pos, "cimport only allowed at module level")
4608 return
4609 module_scope = env.find_module(self.module_name, self.pos)
4610 env.add_imported_module(module_scope)
4611 for pos, name, as_name, kind in self.imported_names:
4612 if name == "*":
4613 for local_name, entry in module_scope.entries.items():
4614 env.add_imported_entry(local_name, entry, pos)
4615 else:
4616 entry = module_scope.lookup(name)
4617 if entry:
4618 if kind and not self.declaration_matches(entry, kind):
4619 entry.redeclared(pos)
4620 else:
4621 if kind == 'struct' or kind == 'union':
4622 entry = module_scope.declare_struct_or_union(name,
4623 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4624 elif kind == 'class':
4625 entry = module_scope.declare_c_class(name, pos = pos,
4626 module_name = self.module_name)
4627 else:
4628 submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
4629 if submodule_scope.parent_module is module_scope:
4630 env.declare_module(as_name or name, submodule_scope, self.pos)
4631 else:
4632 error(pos, "Name '%s' not declared in module '%s'"
4633 % (name, self.module_name))
4635 if entry:
4636 local_name = as_name or name
4637 env.add_imported_entry(local_name, entry, pos)
4639 def declaration_matches(self, entry, kind):
4640 if not entry.is_type:
4641 return 0
4642 type = entry.type
4643 if kind == 'class':
4644 if not type.is_extension_type:
4645 return 0
4646 else:
4647 if not type.is_struct_or_union:
4648 return 0
4649 if kind != type.kind:
4650 return 0
4651 return 1
4653 def analyse_expressions(self, env):
4654 pass
4656 def generate_execution_code(self, code):
4657 pass
4660 class FromImportStatNode(StatNode):
4661 # from ... import statement
4663 # module ImportNode
4664 # items [(string, NameNode)]
4665 # interned_items [(string, NameNode, ExprNode)]
4666 # item PyTempNode used internally
4667 # import_star boolean used internally
4669 child_attrs = ["module"]
4670 import_star = 0
4672 def analyse_declarations(self, env):
4673 for name, target in self.items:
4674 if name == "*":
4675 if not env.is_module_scope:
4676 error(self.pos, "import * only allowed at module level")
4677 return
4678 env.has_import_star = 1
4679 self.import_star = 1
4680 else:
4681 target.analyse_target_declaration(env)
4683 def analyse_expressions(self, env):
4684 import ExprNodes
4685 self.module.analyse_expressions(env)
4686 self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
4687 self.interned_items = []
4688 for name, target in self.items:
4689 if name == '*':
4690 for _, entry in env.entries.items():
4691 if not entry.is_type and entry.type.is_extension_type:
4692 env.use_utility_code(ExprNodes.type_test_utility_code)
4693 break
4694 else:
4695 entry = env.lookup(target.name)
4696 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4697 continue # already cimported
4698 target.analyse_target_expression(env, None)
4699 if target.type is py_object_type:
4700 coerced_item = None
4701 else:
4702 coerced_item = self.item.coerce_to(target.type, env)
4703 self.interned_items.append(
4704 (name, target, coerced_item))
4706 def generate_execution_code(self, code):
4707 self.module.generate_evaluation_code(code)
4708 if self.import_star:
4709 code.putln(
4710 'if (%s(%s) < 0) %s;' % (
4711 Naming.import_star,
4712 self.module.py_result(),
4713 code.error_goto(self.pos)))
4714 item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
4715 self.item.set_cname(item_temp)
4716 for name, target, coerced_item in self.interned_items:
4717 cname = code.intern_identifier(name)
4718 code.putln(
4719 '%s = PyObject_GetAttr(%s, %s); %s' % (
4720 item_temp,
4721 self.module.py_result(),
4722 cname,
4723 code.error_goto_if_null(item_temp, self.pos)))
4724 code.put_gotref(item_temp)
4725 if coerced_item is None:
4726 target.generate_assignment_code(self.item, code)
4727 else:
4728 coerced_item.allocate_temp_result(code)
4729 coerced_item.generate_result_code(code)
4730 target.generate_assignment_code(coerced_item, code)
4731 code.put_decref_clear(item_temp, py_object_type)
4732 code.funcstate.release_temp(item_temp)
4733 self.module.generate_disposal_code(code)
4734 self.module.free_temps(code)
4738 #------------------------------------------------------------------------------------
4740 # Runtime support code
4742 #------------------------------------------------------------------------------------
4744 utility_function_predeclarations = \
4745 """
4746 #ifdef __GNUC__
4747 #define INLINE __inline__
4748 #elif _WIN32
4749 #define INLINE __inline
4750 #else
4751 #define INLINE
4752 #endif
4754 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*/
4756 """
4758 if Options.gcc_branch_hints:
4759 branch_prediction_macros = \
4760 """
4761 #ifdef __GNUC__
4762 /* Test for GCC > 2.95 */
4763 #if __GNUC__ > 2 || \
4764 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4765 #define likely(x) __builtin_expect(!!(x), 1)
4766 #define unlikely(x) __builtin_expect(!!(x), 0)
4767 #else /* __GNUC__ > 2 ... */
4768 #define likely(x) (x)
4769 #define unlikely(x) (x)
4770 #endif /* __GNUC__ > 2 ... */
4771 #else /* __GNUC__ */
4772 #define likely(x) (x)
4773 #define unlikely(x) (x)
4774 #endif /* __GNUC__ */
4775 """
4776 else:
4777 branch_prediction_macros = \
4778 """
4779 #define likely(x) (x)
4780 #define unlikely(x) (x)
4781 """
4783 #get_name_predeclaration = \
4784 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4786 #get_name_interned_predeclaration = \
4787 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4789 #------------------------------------------------------------------------------------
4791 printing_utility_code = UtilityCode(
4792 proto = """
4793 static int __Pyx_Print(PyObject *, int); /*proto*/
4794 #if PY_MAJOR_VERSION >= 3
4795 static PyObject* %s = 0;
4796 static PyObject* %s = 0;
4797 #endif
4798 """ % (Naming.print_function, Naming.print_function_kwargs),
4799 impl = r"""
4800 #if PY_MAJOR_VERSION < 3
4801 static PyObject *__Pyx_GetStdout(void) {
4802 PyObject *f = PySys_GetObject((char *)"stdout");
4803 if (!f) {
4804 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4806 return f;
4809 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4810 PyObject *f;
4811 PyObject* v;
4812 int i;
4814 if (!(f = __Pyx_GetStdout()))
4815 return -1;
4816 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4817 if (PyFile_SoftSpace(f, 1)) {
4818 if (PyFile_WriteString(" ", f) < 0)
4819 return -1;
4821 v = PyTuple_GET_ITEM(arg_tuple, i);
4822 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4823 return -1;
4824 if (PyString_Check(v)) {
4825 char *s = PyString_AsString(v);
4826 Py_ssize_t len = PyString_Size(v);
4827 if (len > 0 &&
4828 isspace(Py_CHARMASK(s[len-1])) &&
4829 s[len-1] != ' ')
4830 PyFile_SoftSpace(f, 0);
4833 if (newline) {
4834 if (PyFile_WriteString("\n", f) < 0)
4835 return -1;
4836 PyFile_SoftSpace(f, 0);
4838 return 0;
4841 #else /* Python 3 has a print function */
4843 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4844 PyObject* kwargs = 0;
4845 PyObject* result = 0;
4846 PyObject* end_string;
4847 if (!%(PRINT_FUNCTION)s) {
4848 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4849 if (!%(PRINT_FUNCTION)s)
4850 return -1;
4852 if (!newline) {
4853 if (!%(PRINT_KWARGS)s) {
4854 %(PRINT_KWARGS)s = PyDict_New();
4855 if (!%(PRINT_KWARGS)s)
4856 return -1;
4857 end_string = PyUnicode_FromStringAndSize(" ", 1);
4858 if (!end_string)
4859 return -1;
4860 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4861 Py_DECREF(end_string);
4862 return -1;
4864 Py_DECREF(end_string);
4866 kwargs = %(PRINT_KWARGS)s;
4868 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4869 if (!result)
4870 return -1;
4871 Py_DECREF(result);
4872 return 0;
4875 #endif
4876 """ % {'BUILTINS' : Naming.builtins_cname,
4877 'PRINT_FUNCTION' : Naming.print_function,
4878 'PRINT_KWARGS' : Naming.print_function_kwargs}
4882 printing_one_utility_code = UtilityCode(
4883 proto = """
4884 static int __Pyx_PrintOne(PyObject *o); /*proto*/
4885 """,
4886 impl = r"""
4887 #if PY_MAJOR_VERSION < 3
4889 static int __Pyx_PrintOne(PyObject *o) {
4890 PyObject *f;
4891 if (!(f = __Pyx_GetStdout()))
4892 return -1;
4893 if (PyFile_SoftSpace(f, 0)) {
4894 if (PyFile_WriteString(" ", f) < 0)
4895 return -1;
4897 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
4898 return -1;
4899 if (PyFile_WriteString("\n", f) < 0)
4900 return -1;
4901 return 0;
4902 /* the line below is just to avoid compiler
4903 * compiler warnings about unused functions */
4904 return __Pyx_Print(NULL, 0);
4907 #else /* Python 3 has a print function */
4909 static int __Pyx_PrintOne(PyObject *o) {
4910 int res;
4911 PyObject* arg_tuple = PyTuple_New(1);
4912 if (unlikely(!arg_tuple))
4913 return -1;
4914 Py_INCREF(o);
4915 PyTuple_SET_ITEM(arg_tuple, 0, o);
4916 res = __Pyx_Print(arg_tuple, 1);
4917 Py_DECREF(arg_tuple);
4918 return res;
4921 #endif
4922 """,
4923 requires=[printing_utility_code])
4927 #------------------------------------------------------------------------------------
4929 # Exception raising code
4931 # Exceptions are raised by __Pyx_Raise() and stored as plain
4932 # type/value/tb in PyThreadState->curexc_*. When being caught by an
4933 # 'except' statement, curexc_* is moved over to exc_* by
4934 # __Pyx_GetException()
4936 restore_exception_utility_code = UtilityCode(
4937 proto = """
4938 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4939 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
4940 """,
4941 impl = """
4942 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
4943 PyObject *tmp_type, *tmp_value, *tmp_tb;
4944 PyThreadState *tstate = PyThreadState_GET();
4946 tmp_type = tstate->curexc_type;
4947 tmp_value = tstate->curexc_value;
4948 tmp_tb = tstate->curexc_traceback;
4949 tstate->curexc_type = type;
4950 tstate->curexc_value = value;
4951 tstate->curexc_traceback = tb;
4952 Py_XDECREF(tmp_type);
4953 Py_XDECREF(tmp_value);
4954 Py_XDECREF(tmp_tb);
4957 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
4958 PyThreadState *tstate = PyThreadState_GET();
4959 *type = tstate->curexc_type;
4960 *value = tstate->curexc_value;
4961 *tb = tstate->curexc_traceback;
4963 tstate->curexc_type = 0;
4964 tstate->curexc_value = 0;
4965 tstate->curexc_traceback = 0;
4968 """)
4970 # The following function is based on do_raise() from ceval.c. There
4971 # are separate versions for Python2 and Python3 as exception handling
4972 # has changed quite a lot between the two versions.
4974 raise_utility_code = UtilityCode(
4975 proto = """
4976 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4977 """,
4978 impl = """
4979 #if PY_MAJOR_VERSION < 3
4980 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4981 Py_XINCREF(type);
4982 Py_XINCREF(value);
4983 Py_XINCREF(tb);
4984 /* First, check the traceback argument, replacing None with NULL. */
4985 if (tb == Py_None) {
4986 Py_DECREF(tb);
4987 tb = 0;
4989 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4990 PyErr_SetString(PyExc_TypeError,
4991 "raise: arg 3 must be a traceback or None");
4992 goto raise_error;
4994 /* Next, replace a missing value with None */
4995 if (value == NULL) {
4996 value = Py_None;
4997 Py_INCREF(value);
4999 #if PY_VERSION_HEX < 0x02050000
5000 if (!PyClass_Check(type))
5001 #else
5002 if (!PyType_Check(type))
5003 #endif
5005 /* Raising an instance. The value should be a dummy. */
5006 if (value != Py_None) {
5007 PyErr_SetString(PyExc_TypeError,
5008 "instance exception may not have a separate value");
5009 goto raise_error;
5011 /* Normalize to raise <class>, <instance> */
5012 Py_DECREF(value);
5013 value = type;
5014 #if PY_VERSION_HEX < 0x02050000
5015 if (PyInstance_Check(type)) {
5016 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
5017 Py_INCREF(type);
5019 else {
5020 type = 0;
5021 PyErr_SetString(PyExc_TypeError,
5022 "raise: exception must be an old-style class or instance");
5023 goto raise_error;
5025 #else
5026 type = (PyObject*) Py_TYPE(type);
5027 Py_INCREF(type);
5028 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
5029 PyErr_SetString(PyExc_TypeError,
5030 "raise: exception class must be a subclass of BaseException");
5031 goto raise_error;
5033 #endif
5036 __Pyx_ErrRestore(type, value, tb);
5037 return;
5038 raise_error:
5039 Py_XDECREF(value);
5040 Py_XDECREF(type);
5041 Py_XDECREF(tb);
5042 return;
5045 #else // Python 3+
5047 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5048 if (tb == Py_None) {
5049 tb = 0;
5050 } else if (tb && !PyTraceBack_Check(tb)) {
5051 PyErr_SetString(PyExc_TypeError,
5052 "raise: arg 3 must be a traceback or None");
5053 goto bad;
5055 if (value == Py_None)
5056 value = 0;
5058 if (PyExceptionInstance_Check(type)) {
5059 if (value) {
5060 PyErr_SetString(PyExc_TypeError,
5061 "instance exception may not have a separate value");
5062 goto bad;
5064 value = type;
5065 type = (PyObject*) Py_TYPE(value);
5066 } else if (!PyExceptionClass_Check(type)) {
5067 PyErr_SetString(PyExc_TypeError,
5068 "raise: exception class must be a subclass of BaseException");
5069 goto bad;
5072 PyErr_SetObject(type, value);
5074 if (tb) {
5075 PyThreadState *tstate = PyThreadState_GET();
5076 PyObject* tmp_tb = tstate->curexc_traceback;
5077 if (tb != tmp_tb) {
5078 Py_INCREF(tb);
5079 tstate->curexc_traceback = tb;
5080 Py_XDECREF(tmp_tb);
5084 bad:
5085 return;
5087 #endif
5088 """,
5089 requires=[restore_exception_utility_code])
5091 #------------------------------------------------------------------------------------
5093 get_exception_utility_code = UtilityCode(
5094 proto = """
5095 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5096 """,
5097 impl = """
5098 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5099 PyObject *local_type, *local_value, *local_tb;
5100 PyObject *tmp_type, *tmp_value, *tmp_tb;
5101 PyThreadState *tstate = PyThreadState_GET();
5102 local_type = tstate->curexc_type;
5103 local_value = tstate->curexc_value;
5104 local_tb = tstate->curexc_traceback;
5105 tstate->curexc_type = 0;
5106 tstate->curexc_value = 0;
5107 tstate->curexc_traceback = 0;
5108 PyErr_NormalizeException(&local_type, &local_value, &local_tb);
5109 if (unlikely(tstate->curexc_type))
5110 goto bad;
5111 #if PY_MAJOR_VERSION >= 3
5112 if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
5113 goto bad;
5114 #endif
5115 *type = local_type;
5116 *value = local_value;
5117 *tb = local_tb;
5118 Py_INCREF(local_type);
5119 Py_INCREF(local_value);
5120 Py_INCREF(local_tb);
5121 tmp_type = tstate->exc_type;
5122 tmp_value = tstate->exc_value;
5123 tmp_tb = tstate->exc_traceback;
5124 tstate->exc_type = local_type;
5125 tstate->exc_value = local_value;
5126 tstate->exc_traceback = local_tb;
5127 /* Make sure tstate is in a consistent state when we XDECREF
5128 these objects (XDECREF may run arbitrary code). */
5129 Py_XDECREF(tmp_type);
5130 Py_XDECREF(tmp_value);
5131 Py_XDECREF(tmp_tb);
5132 return 0;
5133 bad:
5134 *type = 0;
5135 *value = 0;
5136 *tb = 0;
5137 Py_XDECREF(local_type);
5138 Py_XDECREF(local_value);
5139 Py_XDECREF(local_tb);
5140 return -1;
5143 """)
5145 #------------------------------------------------------------------------------------
5147 get_exception_tuple_utility_code = UtilityCode(proto="""
5148 static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
5149 """,
5150 # I doubt that calling __Pyx_GetException() here is correct as it moves
5151 # the exception from tstate->curexc_* to tstate->exc_*, which prevents
5152 # exception handlers later on from receiving it.
5153 impl = """
5154 static PyObject *__Pyx_GetExceptionTuple(void) {
5155 PyObject *type = NULL, *value = NULL, *tb = NULL;
5156 if (__Pyx_GetException(&type, &value, &tb) == 0) {
5157 PyObject* exc_info = PyTuple_New(3);
5158 if (exc_info) {
5159 Py_INCREF(type);
5160 Py_INCREF(value);
5161 Py_INCREF(tb);
5162 PyTuple_SET_ITEM(exc_info, 0, type);
5163 PyTuple_SET_ITEM(exc_info, 1, value);
5164 PyTuple_SET_ITEM(exc_info, 2, tb);
5165 return exc_info;
5168 return NULL;
5170 """,
5171 requires=[get_exception_utility_code])
5173 #------------------------------------------------------------------------------------
5175 reset_exception_utility_code = UtilityCode(
5176 proto = """
5177 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5178 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5179 """,
5180 impl = """
5181 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5182 PyThreadState *tstate = PyThreadState_GET();
5183 *type = tstate->exc_type;
5184 *value = tstate->exc_value;
5185 *tb = tstate->exc_traceback;
5186 Py_XINCREF(*type);
5187 Py_XINCREF(*value);
5188 Py_XINCREF(*tb);
5191 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5192 PyObject *tmp_type, *tmp_value, *tmp_tb;
5193 PyThreadState *tstate = PyThreadState_GET();
5194 tmp_type = tstate->exc_type;
5195 tmp_value = tstate->exc_value;
5196 tmp_tb = tstate->exc_traceback;
5197 tstate->exc_type = type;
5198 tstate->exc_value = value;
5199 tstate->exc_traceback = tb;
5200 Py_XDECREF(tmp_type);
5201 Py_XDECREF(tmp_value);
5202 Py_XDECREF(tmp_tb);
5204 """)
5206 #------------------------------------------------------------------------------------
5208 arg_type_test_utility_code = UtilityCode(
5209 proto = """
5210 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5211 const char *name, int exact); /*proto*/
5212 """,
5213 impl = """
5214 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5215 const char *name, int exact)
5217 if (!type) {
5218 PyErr_Format(PyExc_SystemError, "Missing type object");
5219 return 0;
5221 if (none_allowed && obj == Py_None) return 1;
5222 else if (exact) {
5223 if (Py_TYPE(obj) == type) return 1;
5225 else {
5226 if (PyObject_TypeCheck(obj, type)) return 1;
5228 PyErr_Format(PyExc_TypeError,
5229 "Argument '%s' has incorrect type (expected %s, got %s)",
5230 name, type->tp_name, Py_TYPE(obj)->tp_name);
5231 return 0;
5233 """)
5235 #------------------------------------------------------------------------------------
5237 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5238 # many or too few positional arguments were found. This handles
5239 # Py_ssize_t formatting correctly.
5241 raise_argtuple_invalid_utility_code = UtilityCode(
5242 proto = """
5243 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5244 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5245 """,
5246 impl = """
5247 static void __Pyx_RaiseArgtupleInvalid(
5248 const char* func_name,
5249 int exact,
5250 Py_ssize_t num_min,
5251 Py_ssize_t num_max,
5252 Py_ssize_t num_found)
5254 Py_ssize_t num_expected;
5255 const char *number, *more_or_less;
5257 if (num_found < num_min) {
5258 num_expected = num_min;
5259 more_or_less = "at least";
5260 } else {
5261 num_expected = num_max;
5262 more_or_less = "at most";
5264 if (exact) {
5265 more_or_less = "exactly";
5267 number = (num_expected == 1) ? "" : "s";
5268 PyErr_Format(PyExc_TypeError,
5269 #if PY_VERSION_HEX < 0x02050000
5270 "%s() takes %s %d positional argument%s (%d given)",
5271 #else
5272 "%s() takes %s %zd positional argument%s (%zd given)",
5273 #endif
5274 func_name, more_or_less, num_expected, number, num_found);
5276 """)
5278 raise_keyword_required_utility_code = UtilityCode(
5279 proto = """
5280 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5281 """,
5282 impl = """
5283 static INLINE void __Pyx_RaiseKeywordRequired(
5284 const char* func_name,
5285 PyObject* kw_name)
5287 PyErr_Format(PyExc_TypeError,
5288 #if PY_MAJOR_VERSION >= 3
5289 "%s() needs keyword-only argument %U", func_name, kw_name);
5290 #else
5291 "%s() needs keyword-only argument %s", func_name,
5292 PyString_AS_STRING(kw_name));
5293 #endif
5295 """)
5297 raise_double_keywords_utility_code = UtilityCode(
5298 proto = """
5299 static void __Pyx_RaiseDoubleKeywordsError(
5300 const char* func_name, PyObject* kw_name); /*proto*/
5301 """,
5302 impl = """
5303 static void __Pyx_RaiseDoubleKeywordsError(
5304 const char* func_name,
5305 PyObject* kw_name)
5307 PyErr_Format(PyExc_TypeError,
5308 #if PY_MAJOR_VERSION >= 3
5309 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5310 #else
5311 "%s() got multiple values for keyword argument '%s'", func_name,
5312 PyString_AS_STRING(kw_name));
5313 #endif
5315 """)
5317 #------------------------------------------------------------------------------------
5319 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5320 # were passed to a function, or if any keywords were passed to a
5321 # function that does not accept them.
5323 keyword_string_check_utility_code = UtilityCode(
5324 proto = """
5325 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5326 const char* function_name, int kw_allowed); /*proto*/
5327 """,
5328 impl = """
5329 static INLINE int __Pyx_CheckKeywordStrings(
5330 PyObject *kwdict,
5331 const char* function_name,
5332 int kw_allowed)
5334 PyObject* key = 0;
5335 Py_ssize_t pos = 0;
5336 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5337 #if PY_MAJOR_VERSION < 3
5338 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5339 #else
5340 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5341 #endif
5342 goto invalid_keyword_type;
5344 if ((!kw_allowed) && unlikely(key))
5345 goto invalid_keyword;
5346 return 1;
5347 invalid_keyword_type:
5348 PyErr_Format(PyExc_TypeError,
5349 "%s() keywords must be strings", function_name);
5350 return 0;
5351 invalid_keyword:
5352 PyErr_Format(PyExc_TypeError,
5353 #if PY_MAJOR_VERSION < 3
5354 "%s() got an unexpected keyword argument '%s'",
5355 function_name, PyString_AsString(key));
5356 #else
5357 "%s() got an unexpected keyword argument '%U'",
5358 function_name, key);
5359 #endif
5360 return 0;
5362 """)
5364 #------------------------------------------------------------------------------------
5366 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5367 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5368 # keywords will raise an invalid keyword error.
5370 # Three kinds of errors are checked: 1) non-string keywords, 2)
5371 # unexpected keywords and 3) overlap with positional arguments.
5373 # If num_posargs is greater 0, it denotes the number of positional
5374 # arguments that were passed and that must therefore not appear
5375 # amongst the keywords as well.
5377 # This method does not check for required keyword arguments.
5380 parse_keywords_utility_code = UtilityCode(
5381 proto = """
5382 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5383 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5384 const char* function_name); /*proto*/
5385 """,
5386 impl = """
5387 static int __Pyx_ParseOptionalKeywords(
5388 PyObject *kwds,
5389 PyObject **argnames[],
5390 PyObject *kwds2,
5391 PyObject *values[],
5392 Py_ssize_t num_pos_args,
5393 const char* function_name)
5395 PyObject *key = 0, *value = 0;
5396 Py_ssize_t pos = 0;
5397 PyObject*** name;
5398 PyObject*** first_kw_arg = argnames + num_pos_args;
5400 while (PyDict_Next(kwds, &pos, &key, &value)) {
5401 name = first_kw_arg;
5402 while (*name && (**name != key)) name++;
5403 if (*name) {
5404 values[name-argnames] = value;
5405 } else {
5406 #if PY_MAJOR_VERSION < 3
5407 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5408 #else
5409 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5410 #endif
5411 goto invalid_keyword_type;
5412 } else {
5413 for (name = first_kw_arg; *name; name++) {
5414 #if PY_MAJOR_VERSION >= 3
5415 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5416 PyUnicode_Compare(**name, key) == 0) break;
5417 #else
5418 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5419 _PyString_Eq(**name, key)) break;
5420 #endif
5422 if (*name) {
5423 values[name-argnames] = value;
5424 } else {
5425 /* unexpected keyword found */
5426 for (name=argnames; name != first_kw_arg; name++) {
5427 if (**name == key) goto arg_passed_twice;
5428 #if PY_MAJOR_VERSION >= 3
5429 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5430 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5431 #else
5432 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5433 _PyString_Eq(**name, key)) goto arg_passed_twice;
5434 #endif
5436 if (kwds2) {
5437 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5438 } else {
5439 goto invalid_keyword;
5445 return 0;
5446 arg_passed_twice:
5447 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5448 goto bad;
5449 invalid_keyword_type:
5450 PyErr_Format(PyExc_TypeError,
5451 "%s() keywords must be strings", function_name);
5452 goto bad;
5453 invalid_keyword:
5454 PyErr_Format(PyExc_TypeError,
5455 #if PY_MAJOR_VERSION < 3
5456 "%s() got an unexpected keyword argument '%s'",
5457 function_name, PyString_AsString(key));
5458 #else
5459 "%s() got an unexpected keyword argument '%U'",
5460 function_name, key);
5461 #endif
5462 bad:
5463 return -1;
5465 """)
5467 #------------------------------------------------------------------------------------
5469 traceback_utility_code = UtilityCode(
5470 proto = """
5471 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5472 """,
5473 impl = """
5474 #include "compile.h"
5475 #include "frameobject.h"
5476 #include "traceback.h"
5478 static void __Pyx_AddTraceback(const char *funcname) {
5479 PyObject *py_srcfile = 0;
5480 PyObject *py_funcname = 0;
5481 PyObject *py_globals = 0;
5482 PyCodeObject *py_code = 0;
5483 PyFrameObject *py_frame = 0;
5485 #if PY_MAJOR_VERSION < 3
5486 py_srcfile = PyString_FromString(%(FILENAME)s);
5487 #else
5488 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5489 #endif
5490 if (!py_srcfile) goto bad;
5491 if (%(CLINENO)s) {
5492 #if PY_MAJOR_VERSION < 3
5493 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5494 #else
5495 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5496 #endif
5498 else {
5499 #if PY_MAJOR_VERSION < 3
5500 py_funcname = PyString_FromString(funcname);
5501 #else
5502 py_funcname = PyUnicode_FromString(funcname);
5503 #endif
5505 if (!py_funcname) goto bad;
5506 py_globals = PyModule_GetDict(%(GLOBALS)s);
5507 if (!py_globals) goto bad;
5508 py_code = PyCode_New(
5509 0, /*int argcount,*/
5510 #if PY_MAJOR_VERSION >= 3
5511 0, /*int kwonlyargcount,*/
5512 #endif
5513 0, /*int nlocals,*/
5514 0, /*int stacksize,*/
5515 0, /*int flags,*/
5516 %(EMPTY_BYTES)s, /*PyObject *code,*/
5517 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5518 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5519 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5520 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5521 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5522 py_srcfile, /*PyObject *filename,*/
5523 py_funcname, /*PyObject *name,*/
5524 %(LINENO)s, /*int firstlineno,*/
5525 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5526 );
5527 if (!py_code) goto bad;
5528 py_frame = PyFrame_New(
5529 PyThreadState_GET(), /*PyThreadState *tstate,*/
5530 py_code, /*PyCodeObject *code,*/
5531 py_globals, /*PyObject *globals,*/
5532 0 /*PyObject *locals*/
5533 );
5534 if (!py_frame) goto bad;
5535 py_frame->f_lineno = %(LINENO)s;
5536 PyTraceBack_Here(py_frame);
5537 bad:
5538 Py_XDECREF(py_srcfile);
5539 Py_XDECREF(py_funcname);
5540 Py_XDECREF(py_code);
5541 Py_XDECREF(py_frame);
5543 """ % {
5544 'FILENAME': Naming.filename_cname,
5545 'LINENO': Naming.lineno_cname,
5546 'CFILENAME': Naming.cfilenm_cname,
5547 'CLINENO': Naming.clineno_cname,
5548 'GLOBALS': Naming.module_cname,
5549 'EMPTY_TUPLE' : Naming.empty_tuple,
5550 'EMPTY_BYTES' : Naming.empty_bytes,
5551 })
5553 #------------------------------------------------------------------------------------
5555 unraisable_exception_utility_code = UtilityCode(
5556 proto = """
5557 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5558 """,
5559 impl = """
5560 static void __Pyx_WriteUnraisable(const char *name) {
5561 PyObject *old_exc, *old_val, *old_tb;
5562 PyObject *ctx;
5563 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5564 #if PY_MAJOR_VERSION < 3
5565 ctx = PyString_FromString(name);
5566 #else
5567 ctx = PyUnicode_FromString(name);
5568 #endif
5569 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5570 if (!ctx) {
5571 PyErr_WriteUnraisable(Py_None);
5572 } else {
5573 PyErr_WriteUnraisable(ctx);
5574 Py_DECREF(ctx);
5577 """,
5578 requires=[restore_exception_utility_code])
5580 #------------------------------------------------------------------------------------
5582 set_vtable_utility_code = UtilityCode(
5583 proto = """
5584 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5585 """,
5586 impl = """
5587 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5588 #if PY_VERSION_HEX < 0x03010000
5589 PyObject *ob = PyCObject_FromVoidPtr(vtable, 0);
5590 #else
5591 PyObject *ob = PyCapsule_New(vtable, 0, 0);
5592 #endif
5593 if (!ob)
5594 goto bad;
5595 if (PyDict_SetItemString(dict, "__pyx_vtable__", ob) < 0)
5596 goto bad;
5597 Py_DECREF(ob);
5598 return 0;
5599 bad:
5600 Py_XDECREF(ob);
5601 return -1;
5603 """)
5605 #------------------------------------------------------------------------------------
5607 get_vtable_utility_code = UtilityCode(
5608 proto = """
5609 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5610 """,
5611 impl = r"""
5612 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5613 PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5614 if (!ob)
5615 goto bad;
5616 #if PY_VERSION_HEX < 0x03010000
5617 *(void **)vtabptr = PyCObject_AsVoidPtr(ob);
5618 #else
5619 *(void **)vtabptr = PyCapsule_GetPointer(ob, 0);
5620 #endif
5621 if (!*(void **)vtabptr)
5622 goto bad;
5623 Py_DECREF(ob);
5624 return 0;
5625 bad:
5626 Py_XDECREF(ob);
5627 return -1;
5629 """)
5631 #------------------------------------------------------------------------------------
5633 init_string_tab_utility_code = UtilityCode(
5634 proto = """
5635 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5636 """,
5637 impl = """
5638 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5639 while (t->p) {
5640 #if PY_MAJOR_VERSION < 3
5641 if (t->is_unicode) {
5642 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5643 } else if (t->intern) {
5644 *t->p = PyString_InternFromString(t->s);
5645 } else {
5646 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5648 #else /* Python 3+ has unicode identifiers */
5649 if (t->is_unicode | t->is_str) {
5650 if (t->intern) {
5651 *t->p = PyUnicode_InternFromString(t->s);
5652 } else if (t->encoding) {
5653 *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
5654 } else {
5655 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5657 } else {
5658 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5660 #endif
5661 if (!*t->p)
5662 return -1;
5663 ++t;
5665 return 0;
5667 """)
5669 #------------------------------------------------------------------------------------
5671 force_init_threads_utility_code = UtilityCode(
5672 proto="""
5673 #ifndef __PYX_FORCE_INIT_THREADS
5674 #if PY_VERSION_HEX < 0x02040200
5675 #define __PYX_FORCE_INIT_THREADS 1
5676 #else
5677 #define __PYX_FORCE_INIT_THREADS 0
5678 #endif
5679 #endif
5680 """)
5682 #------------------------------------------------------------------------------------
5684 # Note that cPython ignores PyTrace_EXCEPTION,
5685 # but maybe some other profilers don't.
5687 profile_utility_code = UtilityCode(proto="""
5688 #ifndef CYTHON_PROFILE
5689 #define CYTHON_PROFILE 1
5690 #endif
5692 #ifndef CYTHON_PROFILE_REUSE_FRAME
5693 #define CYTHON_PROFILE_REUSE_FRAME 0
5694 #endif
5696 #if CYTHON_PROFILE
5698 #include "compile.h"
5699 #include "frameobject.h"
5700 #include "traceback.h"
5702 #if CYTHON_PROFILE_REUSE_FRAME
5703 #define CYTHON_FRAME_MODIFIER static
5704 #define CYTHON_FRAME_DEL
5705 #else
5706 #define CYTHON_FRAME_MODIFIER
5707 #define CYTHON_FRAME_DEL Py_DECREF(%(FRAME)s)
5708 #endif
5710 #define __Pyx_TraceCall(funcname, srcfile, firstlineno) \\
5711 static PyCodeObject *%(FRAME_CODE)s = NULL; \\
5712 CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL; \\
5713 int __Pyx_use_tracing = 0; \\
5714 if (unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc)) { \\
5715 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&%(FRAME_CODE)s, &%(FRAME)s, funcname, srcfile, firstlineno); \\
5718 #define __Pyx_TraceException() \\
5719 if (unlikely(__Pyx_use_tracing( && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5720 PyObject *exc_info = __Pyx_GetExceptionTuple(); \\
5721 if (exc_info) { \\
5722 PyThreadState_GET()->c_profilefunc( \\
5723 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_EXCEPTION, exc_info); \\
5724 Py_DECREF(exc_info); \\
5725 } \\
5728 #define __Pyx_TraceReturn(result) \\
5729 if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5730 PyThreadState_GET()->c_profilefunc( \\
5731 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_RETURN, (PyObject*)result); \\
5732 CYTHON_FRAME_DEL; \\
5735 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
5736 static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
5738 #else
5739 #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
5740 #define __Pyx_TraceException()
5741 #define __Pyx_TraceReturn(result)
5742 #endif /* CYTHON_PROFILE */
5743 """
5744 % {
5745 "FRAME": Naming.frame_cname,
5746 "FRAME_CODE": Naming.frame_code_cname,
5747 },
5748 impl = """
5750 #if CYTHON_PROFILE
5752 static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
5753 PyFrameObject** frame,
5754 const char *funcname,
5755 const char *srcfile,
5756 int firstlineno) {
5757 if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) {
5758 if (*code == NULL) {
5759 *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
5760 if (*code == NULL) return 0;
5762 *frame = PyFrame_New(
5763 PyThreadState_GET(), /*PyThreadState *tstate*/
5764 *code, /*PyCodeObject *code*/
5765 PyModule_GetDict(%(MODULE)s), /*PyObject *globals*/
5766 0 /*PyObject *locals*/
5767 );
5768 if (*frame == NULL) return 0;
5770 else {
5771 (*frame)->f_tstate = PyThreadState_GET();
5773 return PyThreadState_GET()->c_profilefunc(PyThreadState_GET()->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
5776 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
5777 PyObject *py_srcfile = 0;
5778 PyObject *py_funcname = 0;
5779 PyCodeObject *py_code = 0;
5781 #if PY_MAJOR_VERSION < 3
5782 py_funcname = PyString_FromString(funcname);
5783 py_srcfile = PyString_FromString(srcfile);
5784 #else
5785 py_funcname = PyUnicode_FromString(funcname);
5786 py_srcfile = PyUnicode_FromString(srcfile);
5787 #endif
5788 if (!py_funcname | !py_srcfile) goto bad;
5790 py_code = PyCode_New(
5791 0, /*int argcount,*/
5792 #if PY_MAJOR_VERSION >= 3
5793 0, /*int kwonlyargcount,*/
5794 #endif
5795 0, /*int nlocals,*/
5796 0, /*int stacksize,*/
5797 0, /*int flags,*/
5798 %(EMPTY_BYTES)s, /*PyObject *code,*/
5799 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5800 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5801 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5802 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5803 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5804 py_srcfile, /*PyObject *filename,*/
5805 py_funcname, /*PyObject *name,*/
5806 firstlineno, /*int firstlineno,*/
5807 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5808 );
5810 bad:
5811 Py_XDECREF(py_srcfile);
5812 Py_XDECREF(py_funcname);
5814 return py_code;
5817 #endif /* CYTHON_PROFILE */
5818 """ % {
5819 'EMPTY_TUPLE' : Naming.empty_tuple,
5820 'EMPTY_BYTES' : Naming.empty_bytes,
5821 "MODULE": Naming.module_cname,
5822 })