Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 2563:e3c343d38eb8

Fix #250, Traceback method name is wrong for exceptions caught in methods
author Robert Bradshaw <robertwb@math.washington.edu>
date Thu Oct 22 23:21:40 2009 -0700 (2 years ago)
parents 4c1766b9f8e5
children cbb3d4cea18c c793d02d914b 9f839d0cbbf9
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 code.putln("%s;" % Buffer.get_release_buffer_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 code.putln("%s;" % Buffer.get_release_buffer_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 # FIXME: simple name prefixing doesn't work when
1477 # argument name mangling is in place
1478 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1479 declarator = arg.declarator
1480 while not hasattr(declarator, 'name'):
1481 declarator = declarator.base
1482 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1483 i += 1
1484 for _ in range(self.type.optional_arg_count):
1485 code.putln('}')
1486 code.putln('}')
1488 def generate_argument_conversion_code(self, code):
1489 pass
1491 def generate_argument_type_tests(self, code):
1492 # Generate type tests for args whose type in a parent
1493 # class is a supertype of the declared type.
1494 for arg in self.type.args:
1495 if arg.needs_type_test:
1496 self.generate_arg_type_test(arg, code)
1498 def generate_arg_type_test(self, arg, code):
1499 # Generate type test for one argument.
1500 if arg.type.typeobj_is_available():
1501 typeptr_cname = arg.type.typeptr_cname
1502 arg_code = "((PyObject *)%s)" % arg.cname
1503 code.putln(
1504 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1505 arg_code,
1506 typeptr_cname,
1507 not arg.not_none,
1508 arg.name,
1509 type.is_builtin_type,
1510 code.error_goto(arg.pos)))
1511 else:
1512 error(arg.pos, "Cannot test type of extern C class "
1513 "without type object name specification")
1515 def error_value(self):
1516 if self.return_type.is_pyobject:
1517 return "0"
1518 else:
1519 #return None
1520 return self.entry.type.exception_value
1522 def caller_will_check_exceptions(self):
1523 return self.entry.type.exception_check
1525 def generate_wrapper_functions(self, code):
1526 # If the C signature of a function has changed, we need to generate
1527 # wrappers to put in the slots here.
1528 k = 0
1529 entry = self.entry
1530 func_type = entry.type
1531 while entry.prev_entry is not None:
1532 k += 1
1533 entry = entry.prev_entry
1534 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1535 code.putln()
1536 self.generate_function_header(code,
1537 0,
1538 with_dispatch = entry.type.is_overridable,
1539 with_opt_args = entry.type.optional_arg_count,
1540 cname = entry.func_cname)
1541 if not self.return_type.is_void:
1542 code.put('return ')
1543 args = self.type.args
1544 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1545 if entry.type.is_overridable:
1546 arglist.append(Naming.skip_dispatch_cname)
1547 elif func_type.is_overridable:
1548 arglist.append('0')
1549 if entry.type.optional_arg_count:
1550 arglist.append(Naming.optional_args_cname)
1551 elif func_type.optional_arg_count:
1552 arglist.append('NULL')
1553 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1554 code.putln('}')
1557 class PyArgDeclNode(Node):
1558 # Argument which must be a Python object (used
1559 # for * and ** arguments).
1561 # name string
1562 # entry Symtab.Entry
1563 child_attrs = []
1566 class DecoratorNode(Node):
1567 # A decorator
1569 # decorator NameNode or CallNode
1570 child_attrs = ['decorator']
1573 class DefNode(FuncDefNode):
1574 # A Python function definition.
1576 # name string the Python name of the function
1577 # decorators [DecoratorNode] list of decorators
1578 # args [CArgDeclNode] formal arguments
1579 # star_arg PyArgDeclNode or None * argument
1580 # starstar_arg PyArgDeclNode or None ** argument
1581 # doc EncodedString or None
1582 # body StatListNode
1584 # The following subnode is constructed internally
1585 # when the def statement is inside a Python class definition.
1587 # assmt AssignmentNode Function construction/assignment
1589 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1591 assmt = None
1592 num_kwonly_args = 0
1593 num_required_kw_args = 0
1594 reqd_kw_flags_cname = "0"
1595 is_wrapper = 0
1596 decorators = None
1597 entry = None
1598 acquire_gil = 0
1601 def __init__(self, pos, **kwds):
1602 FuncDefNode.__init__(self, pos, **kwds)
1603 k = rk = r = 0
1604 for arg in self.args:
1605 if arg.kw_only:
1606 k += 1
1607 if not arg.default:
1608 rk += 1
1609 if not arg.default:
1610 r += 1
1611 self.num_kwonly_args = k
1612 self.num_required_kw_args = rk
1613 self.num_required_args = r
1615 def as_cfunction(self, cfunc=None, scope=None):
1616 if self.star_arg:
1617 error(self.star_arg.pos, "cdef function cannot have star argument")
1618 if self.starstar_arg:
1619 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1620 if cfunc is None:
1621 cfunc_args = []
1622 for formal_arg in self.args:
1623 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1624 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1625 cname = None,
1626 type = py_object_type,
1627 pos = formal_arg.pos))
1628 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1629 args = cfunc_args,
1630 has_varargs = False,
1631 exception_value = None,
1632 exception_check = False,
1633 nogil = False,
1634 with_gil = False,
1635 is_overridable = True)
1636 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1637 else:
1638 cfunc_type = cfunc.type
1639 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1640 error(self.pos, "wrong number of arguments")
1641 error(declarator.pos, "previous declaration here")
1642 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1643 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1644 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1645 formal_arg.type = type_arg.type
1646 formal_arg.name_declarator = name_declarator
1647 import ExprNodes
1648 if cfunc_type.exception_value is None:
1649 exception_value = None
1650 else:
1651 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1652 declarator = CFuncDeclaratorNode(self.pos,
1653 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1654 args = self.args,
1655 has_varargs = False,
1656 exception_check = cfunc_type.exception_check,
1657 exception_value = exception_value,
1658 with_gil = cfunc_type.with_gil,
1659 nogil = cfunc_type.nogil)
1660 return CFuncDefNode(self.pos,
1661 modifiers = [],
1662 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1663 declarator = declarator,
1664 body = self.body,
1665 doc = self.doc,
1666 overridable = cfunc_type.is_overridable,
1667 type = cfunc_type,
1668 with_gil = cfunc_type.with_gil,
1669 nogil = cfunc_type.nogil,
1670 visibility = 'private',
1671 api = False,
1672 directive_locals = getattr(cfunc, 'directive_locals', {}))
1674 def analyse_declarations(self, env):
1675 directive_locals = self.directive_locals = env.directives['locals']
1676 for arg in self.args:
1677 if hasattr(arg, 'name'):
1678 type = arg.type
1679 name_declarator = None
1680 else:
1681 base_type = arg.base_type.analyse(env)
1682 name_declarator, type = \
1683 arg.declarator.analyse(base_type, env)
1684 arg.name = name_declarator.name
1685 if arg.name in directive_locals:
1686 type_node = directive_locals[arg.name]
1687 other_type = type_node.analyse_as_type(env)
1688 if other_type is None:
1689 error(type_node.pos, "Not a type")
1690 elif (type is not PyrexTypes.py_object_type
1691 and not type.same_as(other_type)):
1692 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1693 error(type_node.pos, "Previous declaration here")
1694 else:
1695 type = other_type
1696 if name_declarator and name_declarator.cname:
1697 error(self.pos,
1698 "Python function argument cannot have C name specification")
1699 arg.type = type.as_argument_type()
1700 arg.hdr_type = None
1701 arg.needs_conversion = 0
1702 arg.needs_type_test = 0
1703 arg.is_generic = 1
1704 if arg.not_none and not arg.type.is_extension_type:
1705 error(self.pos,
1706 "Only extension type arguments can have 'not None'")
1707 self.declare_pyfunction(env)
1708 self.analyse_signature(env)
1709 self.return_type = self.entry.signature.return_type()
1711 def analyse_signature(self, env):
1712 any_type_tests_needed = 0
1713 if self.entry.is_special:
1714 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1715 elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
1716 # Use the simpler calling signature for zero- and one-argument functions.
1717 if self.entry.signature is TypeSlots.pyfunction_signature:
1718 if len(self.args) == 0:
1719 self.entry.signature = TypeSlots.pyfunction_noargs
1720 elif len(self.args) == 1:
1721 if self.args[0].default is None and not self.args[0].kw_only:
1722 self.entry.signature = TypeSlots.pyfunction_onearg
1723 elif self.entry.signature is TypeSlots.pymethod_signature:
1724 if len(self.args) == 1:
1725 self.entry.signature = TypeSlots.unaryfunc
1726 elif len(self.args) == 2:
1727 if self.args[1].default is None and not self.args[1].kw_only:
1728 self.entry.signature = TypeSlots.ibinaryfunc
1729 sig = self.entry.signature
1730 nfixed = sig.num_fixed_args()
1731 for i in range(nfixed):
1732 if i < len(self.args):
1733 arg = self.args[i]
1734 arg.is_generic = 0
1735 if sig.is_self_arg(i):
1736 arg.is_self_arg = 1
1737 arg.hdr_type = arg.type = env.parent_type
1738 arg.needs_conversion = 0
1739 else:
1740 arg.hdr_type = sig.fixed_arg_type(i)
1741 if not arg.type.same_as(arg.hdr_type):
1742 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1743 arg.needs_type_test = 1
1744 any_type_tests_needed = 1
1745 else:
1746 arg.needs_conversion = 1
1747 if arg.needs_conversion:
1748 arg.hdr_cname = Naming.arg_prefix + arg.name
1749 else:
1750 arg.hdr_cname = Naming.var_prefix + arg.name
1751 else:
1752 self.bad_signature()
1753 return
1754 if nfixed < len(self.args):
1755 if not sig.has_generic_args:
1756 self.bad_signature()
1757 for arg in self.args:
1758 if arg.is_generic and \
1759 (arg.type.is_extension_type or arg.type.is_builtin_type):
1760 arg.needs_type_test = 1
1761 any_type_tests_needed = 1
1762 if any_type_tests_needed:
1763 env.use_utility_code(arg_type_test_utility_code)
1765 def bad_signature(self):
1766 sig = self.entry.signature
1767 expected_str = "%d" % sig.num_fixed_args()
1768 if sig.has_generic_args:
1769 expected_str = expected_str + " or more"
1770 name = self.name
1771 if name.startswith("__") and name.endswith("__"):
1772 desc = "Special method"
1773 else:
1774 desc = "Method"
1775 error(self.pos,
1776 "%s %s has wrong number of arguments "
1777 "(%d declared, %s expected)" % (
1778 desc, self.name, len(self.args), expected_str))
1780 def signature_has_nongeneric_args(self):
1781 argcount = len(self.args)
1782 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1783 return 0
1784 return 1
1786 def signature_has_generic_args(self):
1787 return self.entry.signature.has_generic_args
1789 def declare_pyfunction(self, env):
1790 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1791 name = self.name
1792 entry = env.lookup_here(self.name)
1793 if entry and entry.type.is_cfunction and not self.is_wrapper:
1794 warning(self.pos, "Overriding cdef method with def method.", 5)
1795 entry = env.declare_pyfunction(self.name, self.pos)
1796 self.entry = entry
1797 prefix = env.scope_prefix
1798 entry.func_cname = \
1799 Naming.pyfunc_prefix + prefix + name
1800 entry.pymethdef_cname = \
1801 Naming.pymethdef_prefix + prefix + name
1802 if Options.docstrings:
1803 entry.doc = embed_position(self.pos, self.doc)
1804 entry.doc_cname = \
1805 Naming.funcdoc_prefix + prefix + name
1806 else:
1807 entry.doc = None
1809 def declare_arguments(self, env):
1810 for arg in self.args:
1811 if not arg.name:
1812 error(arg.pos, "Missing argument name")
1813 if arg.needs_conversion:
1814 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1815 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1816 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1817 if arg.type.is_pyobject:
1818 arg.entry.init = "0"
1819 arg.entry.init_to_none = 0
1820 else:
1821 arg.entry = self.declare_argument(env, arg)
1822 arg.entry.used = 1
1823 arg.entry.is_self_arg = arg.is_self_arg
1824 if arg.hdr_type:
1825 if arg.is_self_arg or \
1826 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1827 arg.entry.is_declared_generic = 1
1828 self.declare_python_arg(env, self.star_arg)
1829 self.declare_python_arg(env, self.starstar_arg)
1831 def declare_python_arg(self, env, arg):
1832 if arg:
1833 entry = env.declare_var(arg.name,
1834 PyrexTypes.py_object_type, arg.pos)
1835 entry.used = 1
1836 entry.init = "0"
1837 entry.init_to_none = 0
1838 entry.xdecref_cleanup = 1
1839 arg.entry = entry
1840 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1842 def analyse_expressions(self, env):
1843 self.local_scope.directives = env.directives
1844 self.analyse_default_values(env)
1845 if env.is_py_class_scope:
1846 self.synthesize_assignment_node(env)
1848 def synthesize_assignment_node(self, env):
1849 import ExprNodes
1850 self.assmt = SingleAssignmentNode(self.pos,
1851 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1852 rhs = ExprNodes.UnboundMethodNode(self.pos,
1853 function = ExprNodes.PyCFunctionNode(self.pos,
1854 pymethdef_cname = self.entry.pymethdef_cname)))
1855 self.assmt.analyse_declarations(env)
1856 self.assmt.analyse_expressions(env)
1858 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1859 arg_code_list = []
1860 sig = self.entry.signature
1861 if sig.has_dummy_arg:
1862 arg_code_list.append(
1863 "PyObject *%s" % Naming.self_cname)
1864 for arg in self.args:
1865 if not arg.is_generic:
1866 if arg.is_self_arg:
1867 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1868 else:
1869 arg_code_list.append(
1870 arg.hdr_type.declaration_code(arg.hdr_cname))
1871 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1872 arg_code_list.append("PyObject *unused")
1873 if sig.has_generic_args:
1874 arg_code_list.append(
1875 "PyObject *%s, PyObject *%s"
1876 % (Naming.args_cname, Naming.kwds_cname))
1877 arg_code = ", ".join(arg_code_list)
1878 dc = self.return_type.declaration_code(self.entry.func_cname)
1879 header = "static %s(%s)" % (dc, arg_code)
1880 code.putln("%s; /*proto*/" % header)
1881 if proto_only:
1882 return
1883 if self.entry.doc and Options.docstrings:
1884 docstr = self.entry.doc
1885 if docstr.is_unicode:
1886 docstr = docstr.utf8encode()
1887 code.putln(
1888 'static char %s[] = "%s";' % (
1889 self.entry.doc_cname,
1890 split_docstring(escape_byte_string(docstr))))
1891 if with_pymethdef:
1892 code.put(
1893 "static PyMethodDef %s = " %
1894 self.entry.pymethdef_cname)
1895 code.put_pymethoddef(self.entry, ";")
1896 code.putln("%s {" % header)
1898 def generate_argument_declarations(self, env, code):
1899 for arg in self.args:
1900 if arg.is_generic: # or arg.needs_conversion:
1901 if arg.needs_conversion:
1902 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1903 else:
1904 code.put_var_declaration(arg.entry)
1906 def generate_keyword_list(self, code):
1907 if self.signature_has_generic_args() and \
1908 self.signature_has_nongeneric_args():
1909 code.put(
1910 "static PyObject **%s[] = {" %
1911 Naming.pykwdlist_cname)
1912 for arg in self.args:
1913 if arg.is_generic:
1914 pystring_cname = code.intern_identifier(arg.name)
1915 code.put('&%s,' % pystring_cname)
1916 code.putln("0};")
1918 def generate_argument_parsing_code(self, env, code):
1919 # Generate PyArg_ParseTuple call for generic
1920 # arguments, if any.
1921 if self.entry.signature.has_dummy_arg:
1922 # get rid of unused argument warning
1923 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1925 old_error_label = code.new_error_label()
1926 our_error_label = code.error_label
1927 end_label = code.new_label("argument_unpacking_done")
1929 has_kwonly_args = self.num_kwonly_args > 0
1930 has_star_or_kw_args = self.star_arg is not None \
1931 or self.starstar_arg is not None or has_kwonly_args
1933 for arg in self.args:
1934 if not arg.type.is_pyobject:
1935 done = arg.type.create_from_py_utility_code(env)
1936 if not done: pass # will fail later
1938 if not self.signature_has_generic_args():
1939 if has_star_or_kw_args:
1940 error(self.pos, "This method cannot have * or keyword arguments")
1941 self.generate_argument_conversion_code(code)
1943 elif not self.signature_has_nongeneric_args():
1944 # func(*args) or func(**kw) or func(*args, **kw)
1945 self.generate_stararg_copy_code(code)
1947 else:
1948 positional_args = []
1949 kw_only_args = []
1950 for arg in self.args:
1951 arg_entry = arg.entry
1952 if arg.is_generic:
1953 if arg.default:
1954 if not arg.is_self_arg:
1955 if arg.kw_only:
1956 kw_only_args.append(arg)
1957 else:
1958 positional_args.append(arg)
1959 elif arg.kw_only:
1960 kw_only_args.append(arg)
1961 elif not arg.is_self_arg:
1962 positional_args.append(arg)
1964 self.generate_tuple_and_keyword_parsing_code(
1965 positional_args, kw_only_args, end_label, code)
1967 code.error_label = old_error_label
1968 if code.label_used(our_error_label):
1969 if not code.label_used(end_label):
1970 code.put_goto(end_label)
1971 code.put_label(our_error_label)
1972 if has_star_or_kw_args:
1973 self.generate_arg_decref(self.star_arg, code)
1974 if self.starstar_arg:
1975 if self.starstar_arg.entry.xdecref_cleanup:
1976 code.put_var_xdecref(self.starstar_arg.entry)
1977 else:
1978 code.put_var_decref(self.starstar_arg.entry)
1979 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1980 code.putln("return %s;" % self.error_value())
1981 if code.label_used(end_label):
1982 code.put_label(end_label)
1984 def generate_arg_assignment(self, arg, item, code):
1985 if arg.type.is_pyobject:
1986 if arg.is_generic:
1987 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1988 code.putln("%s = %s;" % (arg.entry.cname, item))
1989 else:
1990 func = arg.type.from_py_function
1991 if func:
1992 code.putln("%s = %s(%s); %s" % (
1993 arg.entry.cname,
1994 func,
1995 item,
1996 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1997 else:
1998 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
2000 def generate_arg_xdecref(self, arg, code):
2001 if arg:
2002 code.put_var_xdecref(arg.entry)
2004 def generate_arg_decref(self, arg, code):
2005 if arg:
2006 code.put_var_decref(arg.entry)
2008 def generate_stararg_copy_code(self, code):
2009 if not self.star_arg:
2010 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2011 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
2012 Naming.args_cname)
2013 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2014 self.name, Naming.args_cname, self.error_value()))
2015 code.putln("}")
2017 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2019 if self.starstar_arg:
2020 if self.star_arg:
2021 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2022 else:
2023 kwarg_check = "%s" % Naming.kwds_cname
2024 else:
2025 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2026 Naming.kwds_cname, Naming.kwds_cname)
2027 code.putln(
2028 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2029 kwarg_check, Naming.kwds_cname, self.name,
2030 bool(self.starstar_arg), self.error_value()))
2032 if self.starstar_arg:
2033 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2034 self.starstar_arg.entry.cname,
2035 Naming.kwds_cname,
2036 Naming.kwds_cname))
2037 code.putln("if (unlikely(!%s)) return %s;" % (
2038 self.starstar_arg.entry.cname, self.error_value()))
2039 self.starstar_arg.entry.xdecref_cleanup = 0
2040 code.put_gotref(self.starstar_arg.entry.cname)
2043 if self.star_arg:
2044 code.put_incref(Naming.args_cname, py_object_type)
2045 code.putln("%s = %s;" % (
2046 self.star_arg.entry.cname,
2047 Naming.args_cname))
2048 self.star_arg.entry.xdecref_cleanup = 0
2050 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2051 kw_only_args, success_label, code):
2052 argtuple_error_label = code.new_label("argtuple_error")
2054 min_positional_args = self.num_required_args - self.num_required_kw_args
2055 if len(self.args) > 0 and self.args[0].is_self_arg:
2056 min_positional_args -= 1
2057 max_positional_args = len(positional_args)
2058 has_fixed_positional_count = not self.star_arg and \
2059 min_positional_args == max_positional_args
2061 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2062 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2063 if self.num_required_kw_args:
2064 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2066 if self.starstar_arg or self.star_arg:
2067 self.generate_stararg_init_code(max_positional_args, code)
2069 # --- optimised code when we receive keyword arguments
2070 if self.num_required_kw_args:
2071 likely_hint = "likely"
2072 else:
2073 likely_hint = "unlikely"
2074 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2075 self.generate_keyword_unpacking_code(
2076 min_positional_args, max_positional_args,
2077 has_fixed_positional_count,
2078 positional_args, kw_only_args, argtuple_error_label, code)
2080 # --- optimised code when we do not receive any keyword arguments
2081 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2082 # Python raises arg tuple related errors first, so we must
2083 # check the length here
2084 if min_positional_args == max_positional_args and not self.star_arg:
2085 compare = '!='
2086 else:
2087 compare = '<'
2088 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2089 Naming.args_cname, compare, min_positional_args))
2090 code.put_goto(argtuple_error_label)
2092 if self.num_required_kw_args:
2093 # pure error case: keywords required but not passed
2094 if max_positional_args > min_positional_args and not self.star_arg:
2095 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2096 Naming.args_cname, max_positional_args))
2097 code.put_goto(argtuple_error_label)
2098 code.putln('} else {')
2099 for i, arg in enumerate(kw_only_args):
2100 if not arg.default:
2101 pystring_cname = code.intern_identifier(arg.name)
2102 # required keyword-only argument missing
2103 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2104 self.name,
2105 pystring_cname))
2106 code.putln(code.error_goto(self.pos))
2107 break
2109 elif min_positional_args == max_positional_args:
2110 # parse the exact number of positional arguments from the
2111 # args tuple
2112 code.putln('} else {')
2113 for i, arg in enumerate(positional_args):
2114 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2115 self.generate_arg_assignment(arg, item, code)
2116 self.generate_arg_default_assignments(code)
2118 else:
2119 # parse the positional arguments from the variable length
2120 # args tuple
2121 code.putln('} else {')
2122 self.generate_arg_default_assignments(code)
2123 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2124 if self.star_arg:
2125 code.putln('default:')
2126 reversed_args = list(enumerate(positional_args))[::-1]
2127 for i, arg in reversed_args:
2128 if i >= min_positional_args-1:
2129 if min_positional_args > 1:
2130 code.putln('case %2d:' % (i+1)) # pure code beautification
2131 else:
2132 code.put('case %2d: ' % (i+1))
2133 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2134 self.generate_arg_assignment(arg, item, code)
2135 if min_positional_args == 0:
2136 code.put('case 0: ')
2137 code.putln('break;')
2138 if self.star_arg:
2139 if min_positional_args:
2140 for i in range(min_positional_args-1, -1, -1):
2141 code.putln('case %2d:' % i)
2142 code.put_goto(argtuple_error_label)
2143 else:
2144 code.put('default: ')
2145 code.put_goto(argtuple_error_label)
2146 code.putln('}')
2148 code.putln('}')
2150 if code.label_used(argtuple_error_label):
2151 code.put_goto(success_label)
2152 code.put_label(argtuple_error_label)
2153 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2154 self.name, has_fixed_positional_count,
2155 min_positional_args, max_positional_args,
2156 Naming.args_cname))
2157 code.putln(code.error_goto(self.pos))
2159 def generate_arg_default_assignments(self, code):
2160 for arg in self.args:
2161 if arg.is_generic and arg.default:
2162 code.putln(
2163 "%s = %s;" % (
2164 arg.entry.cname,
2165 arg.calculate_default_value_code(code)))
2167 def generate_stararg_init_code(self, max_positional_args, code):
2168 if self.starstar_arg:
2169 self.starstar_arg.entry.xdecref_cleanup = 0
2170 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2171 self.starstar_arg.entry.cname,
2172 self.starstar_arg.entry.cname,
2173 self.error_value()))
2174 code.put_gotref(self.starstar_arg.entry.cname)
2175 if self.star_arg:
2176 self.star_arg.entry.xdecref_cleanup = 0
2177 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2178 Naming.args_cname,
2179 max_positional_args))
2180 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2181 self.star_arg.entry.cname, Naming.args_cname,
2182 max_positional_args, Naming.args_cname))
2183 code.put_gotref(self.star_arg.entry.cname)
2184 if self.starstar_arg:
2185 code.putln("")
2186 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2187 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2188 code.putln('return %s;' % self.error_value())
2189 code.putln('}')
2190 else:
2191 code.putln("if (unlikely(!%s)) return %s;" % (
2192 self.star_arg.entry.cname, self.error_value()))
2193 code.putln('} else {')
2194 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2195 code.put_incref(Naming.empty_tuple, py_object_type)
2196 code.putln('}')
2198 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2199 has_fixed_positional_count, positional_args,
2200 kw_only_args, argtuple_error_label, code):
2201 all_args = tuple(positional_args) + tuple(kw_only_args)
2202 max_args = len(all_args)
2204 default_args = []
2205 for i, arg in enumerate(all_args):
2206 if arg.default and arg.type.is_pyobject:
2207 default_value = arg.calculate_default_value_code(code)
2208 if arg.type is not PyrexTypes.py_object_type:
2209 default_value = "(PyObject*)"+default_value
2210 default_args.append((i, default_value))
2212 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2213 Naming.kwds_cname)
2214 # it looks funny to separate the init-to-0 from setting the
2215 # default value, but C89 needs this
2216 code.putln("PyObject* values[%d] = {%s};" % (
2217 max_args, ','.join(['0']*max_args)))
2218 for i, default_value in default_args:
2219 code.putln('values[%d] = %s;' % (i, default_value))
2221 # parse the tuple and check that it's not too long
2222 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2223 if self.star_arg:
2224 code.putln('default:')
2225 for i in range(max_positional_args-1, -1, -1):
2226 code.put('case %2d: ' % (i+1))
2227 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2228 i, Naming.args_cname, i))
2229 code.putln('case 0: break;')
2230 if not self.star_arg:
2231 code.put('default: ') # more arguments than allowed
2232 code.put_goto(argtuple_error_label)
2233 code.putln('}')
2235 # now fill up the positional/required arguments with values
2236 # from the kw dict
2237 if self.num_required_args or max_positional_args > 0:
2238 last_required_arg = -1
2239 for i, arg in enumerate(all_args):
2240 if not arg.default:
2241 last_required_arg = i
2242 if last_required_arg < max_positional_args:
2243 last_required_arg = max_positional_args-1
2244 num_required_args = self.num_required_args
2245 if max_positional_args > 0:
2246 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2247 for i, arg in enumerate(all_args[:last_required_arg+1]):
2248 if max_positional_args > 0 and i <= max_positional_args:
2249 if self.star_arg and i == max_positional_args:
2250 code.putln('default:')
2251 else:
2252 code.putln('case %2d:' % i)
2253 pystring_cname = code.intern_identifier(arg.name)
2254 if arg.default:
2255 if arg.kw_only:
2256 # handled separately below
2257 continue
2258 code.putln('if (kw_args > %d) {' % num_required_args)
2259 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2260 Naming.kwds_cname, pystring_cname))
2261 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2262 code.putln('}')
2263 else:
2264 num_required_args -= 1
2265 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2266 i, Naming.kwds_cname, pystring_cname))
2267 code.putln('if (likely(values[%d])) kw_args--;' % i);
2268 if i < min_positional_args:
2269 if i == 0:
2270 # special case: we know arg 0 is missing
2271 code.put('else ')
2272 code.put_goto(argtuple_error_label)
2273 else:
2274 # print the correct number of values (args or
2275 # kwargs) that were passed into positional
2276 # arguments up to this point
2277 code.putln('else {')
2278 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2279 self.name, has_fixed_positional_count,
2280 min_positional_args, max_positional_args, i))
2281 code.putln(code.error_goto(self.pos))
2282 code.putln('}')
2283 elif arg.kw_only:
2284 code.putln('else {')
2285 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2286 self.name, pystring_cname))
2287 code.putln(code.error_goto(self.pos))
2288 code.putln('}')
2289 if max_positional_args > 0:
2290 code.putln('}')
2292 if kw_only_args and not self.starstar_arg:
2293 # unpack optional keyword-only arguments
2294 # checking for interned strings in a dict is faster than iterating
2295 # but it's too likely that we must iterate if we expect **kwargs
2296 optional_args = []
2297 for i, arg in enumerate(all_args[max_positional_args:]):
2298 if not arg.kw_only or not arg.default:
2299 continue
2300 optional_args.append((i+max_positional_args, arg))
2301 if optional_args:
2302 # this mimics an unrolled loop so that we can "break" out of it
2303 code.putln('while (kw_args > 0) {')
2304 code.putln('PyObject* value;')
2305 for i, arg in optional_args:
2306 pystring_cname = code.intern_identifier(arg.name)
2307 code.putln(
2308 'value = PyDict_GetItem(%s, %s);' % (
2309 Naming.kwds_cname, pystring_cname))
2310 code.putln(
2311 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2312 code.putln('break;')
2313 code.putln('}')
2315 code.putln('if (unlikely(kw_args > 0)) {')
2316 # non-positional/-required kw args left in dict: default args,
2317 # kw-only args, **kwargs or error
2319 # This is sort of a catch-all: except for checking required
2320 # arguments, this will always do the right thing for unpacking
2321 # keyword arguments, so that we can concentrate on optimising
2322 # common cases above.
2323 if max_positional_args == 0:
2324 pos_arg_count = "0"
2325 elif self.star_arg:
2326 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2327 Naming.args_cname, max_positional_args,
2328 Naming.args_cname, max_positional_args))
2329 pos_arg_count = "used_pos_args"
2330 else:
2331 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2332 code.globalstate.use_utility_code(parse_keywords_utility_code)
2333 code.put(
2334 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2335 Naming.kwds_cname,
2336 Naming.pykwdlist_cname,
2337 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2338 pos_arg_count,
2339 self.name))
2340 code.putln(code.error_goto(self.pos))
2341 code.putln('}')
2343 # convert arg values to their final type and assign them
2344 for i, arg in enumerate(all_args):
2345 if arg.default and not arg.type.is_pyobject:
2346 code.putln("if (values[%d]) {" % i)
2347 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2348 if arg.default and not arg.type.is_pyobject:
2349 code.putln('} else {')
2350 code.putln(
2351 "%s = %s;" % (
2352 arg.entry.cname,
2353 arg.calculate_default_value_code(code)))
2354 code.putln('}')
2356 def generate_argument_conversion_code(self, code):
2357 # Generate code to convert arguments from
2358 # signature type to declared type, if needed.
2359 for arg in self.args:
2360 if arg.needs_conversion:
2361 self.generate_arg_conversion(arg, code)
2363 def generate_arg_conversion(self, arg, code):
2364 # Generate conversion code for one argument.
2365 old_type = arg.hdr_type
2366 new_type = arg.type
2367 if old_type.is_pyobject:
2368 if arg.default:
2369 code.putln("if (%s) {" % arg.hdr_cname)
2370 else:
2371 code.putln("assert(%s); {" % arg.hdr_cname)
2372 self.generate_arg_conversion_from_pyobject(arg, code)
2373 code.putln("}")
2374 elif new_type.is_pyobject:
2375 self.generate_arg_conversion_to_pyobject(arg, code)
2376 else:
2377 if new_type.assignable_from(old_type):
2378 code.putln(
2379 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2380 else:
2381 error(arg.pos,
2382 "Cannot convert 1 argument from '%s' to '%s'" %
2383 (old_type, new_type))
2385 def generate_arg_conversion_from_pyobject(self, arg, code):
2386 new_type = arg.type
2387 func = new_type.from_py_function
2388 # copied from CoerceFromPyTypeNode
2389 if func:
2390 code.putln("%s = %s(%s); %s" % (
2391 arg.entry.cname,
2392 func,
2393 arg.hdr_cname,
2394 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2395 else:
2396 error(arg.pos,
2397 "Cannot convert Python object argument to type '%s'"
2398 % new_type)
2400 def generate_arg_conversion_to_pyobject(self, arg, code):
2401 old_type = arg.hdr_type
2402 func = old_type.to_py_function
2403 if func:
2404 code.putln("%s = %s(%s); %s" % (
2405 arg.entry.cname,
2406 func,
2407 arg.hdr_cname,
2408 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2409 code.put_var_gotref(arg.entry)
2410 else:
2411 error(arg.pos,
2412 "Cannot convert argument of type '%s' to Python object"
2413 % old_type)
2415 def generate_argument_type_tests(self, code):
2416 # Generate type tests for args whose signature
2417 # type is PyObject * and whose declared type is
2418 # a subtype thereof.
2419 for arg in self.args:
2420 if arg.needs_type_test:
2421 self.generate_arg_type_test(arg, code)
2423 def generate_arg_type_test(self, arg, code):
2424 # Generate type test for one argument.
2425 if arg.type.typeobj_is_available():
2426 typeptr_cname = arg.type.typeptr_cname
2427 arg_code = "((PyObject *)%s)" % arg.entry.cname
2428 code.putln(
2429 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2430 arg_code,
2431 typeptr_cname,
2432 not arg.not_none,
2433 arg.name,
2434 arg.type.is_builtin_type,
2435 code.error_goto(arg.pos)))
2436 else:
2437 error(arg.pos, "Cannot test type of extern C class "
2438 "without type object name specification")
2440 def error_value(self):
2441 return self.entry.signature.error_value
2443 def caller_will_check_exceptions(self):
2444 return 1
2446 class OverrideCheckNode(StatNode):
2447 # A Node for dispatching to the def method if it
2448 # is overriden.
2450 # py_func
2452 # args
2453 # func_temp
2454 # body
2456 child_attrs = ['body']
2458 body = None
2460 def analyse_expressions(self, env):
2461 self.args = env.arg_entries
2462 if self.py_func.is_module_scope:
2463 first_arg = 0
2464 else:
2465 first_arg = 1
2466 import ExprNodes
2467 self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
2468 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2469 call_node = ExprNodes.SimpleCallNode(self.pos,
2470 function=self.func_node,
2471 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2472 self.body = ReturnStatNode(self.pos, value=call_node)
2473 self.body.analyse_expressions(env)
2475 def generate_execution_code(self, code):
2476 interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
2477 # Check to see if we are an extension type
2478 if self.py_func.is_module_scope:
2479 self_arg = "((PyObject *)%s)" % Naming.module_cname
2480 else:
2481 self_arg = "((PyObject *)%s)" % self.args[0].cname
2482 code.putln("/* Check if called by wrapper */")
2483 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2484 code.putln("/* Check if overriden in Python */")
2485 if self.py_func.is_module_scope:
2486 code.putln("else {")
2487 else:
2488 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2489 func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
2490 self.func_node.set_cname(func_node_temp)
2491 # need to get attribute manually--scope would return cdef method
2492 err = code.error_goto_if_null(func_node_temp, self.pos)
2493 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
2494 func_node_temp, self_arg, interned_attr_cname, err))
2495 code.put_gotref(func_node_temp)
2496 is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
2497 is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)" % (
2498 func_node_temp, self.py_func.entry.func_cname)
2499 code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
2500 self.body.generate_execution_code(code)
2501 code.putln("}")
2502 code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
2503 code.funcstate.release_temp(func_node_temp)
2504 code.putln("}")
2506 class ClassDefNode(StatNode, BlockNode):
2507 pass
2509 class PyClassDefNode(ClassDefNode):
2510 # A Python class definition.
2512 # name EncodedString Name of the class
2513 # doc string or None
2514 # body StatNode Attribute definition code
2515 # entry Symtab.Entry
2516 # scope PyClassScope
2517 # decorators [DecoratorNode] list of decorators or None
2519 # The following subnodes are constructed internally:
2521 # dict DictNode Class dictionary
2522 # classobj ClassNode Class object
2523 # target NameNode Variable to assign class object to
2525 child_attrs = ["body", "dict", "classobj", "target"]
2526 decorators = None
2528 def __init__(self, pos, name, bases, doc, body, decorators = None):
2529 StatNode.__init__(self, pos)
2530 self.name = name
2531 self.doc = doc
2532 self.body = body
2533 self.decorators = decorators
2534 import ExprNodes
2535 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2536 if self.doc and Options.docstrings:
2537 doc = embed_position(self.pos, self.doc)
2538 # FIXME: correct string node?
2539 doc_node = ExprNodes.StringNode(pos, value = doc)
2540 else:
2541 doc_node = None
2542 self.classobj = ExprNodes.ClassNode(pos, name = name,
2543 bases = bases, dict = self.dict, doc = doc_node)
2544 self.target = ExprNodes.NameNode(pos, name = name)
2546 def as_cclass(self):
2547 """
2548 Return this node as if it were declared as an extension class
2549 """
2550 bases = self.classobj.bases.args
2551 if len(bases) == 0:
2552 base_class_name = None
2553 base_class_module = None
2554 elif len(bases) == 1:
2555 base = bases[0]
2556 path = []
2557 from ExprNodes import AttributeNode, NameNode
2558 while isinstance(base, AttributeNode):
2559 path.insert(0, base.attribute)
2560 base = base.obj
2561 if isinstance(base, NameNode):
2562 path.insert(0, base.name)
2563 base_class_name = path[-1]
2564 if len(path) > 1:
2565 base_class_module = u'.'.join(path[:-1])
2566 else:
2567 base_class_module = None
2568 else:
2569 error(self.classobj.bases.args.pos, "Invalid base class")
2570 else:
2571 error(self.classobj.bases.args.pos, "C class may only have one base class")
2572 return None
2574 return CClassDefNode(self.pos,
2575 visibility = 'private',
2576 module_name = None,
2577 class_name = self.name,
2578 base_class_module = base_class_module,
2579 base_class_name = base_class_name,
2580 decorators = self.decorators,
2581 body = self.body,
2582 in_pxd = False,
2583 doc = self.doc)
2585 def create_scope(self, env):
2586 genv = env
2587 while env.is_py_class_scope or env.is_c_class_scope:
2588 env = env.outer_scope
2589 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2590 return cenv
2592 def analyse_declarations(self, env):
2593 self.target.analyse_target_declaration(env)
2594 cenv = self.create_scope(env)
2595 cenv.directives = env.directives
2596 cenv.class_obj_cname = self.target.entry.cname
2597 self.body.analyse_declarations(cenv)
2599 def analyse_expressions(self, env):
2600 self.dict.analyse_expressions(env)
2601 self.classobj.analyse_expressions(env)
2602 genv = env.global_scope()
2603 cenv = self.scope
2604 self.body.analyse_expressions(cenv)
2605 self.target.analyse_target_expression(env, self.classobj)
2607 def generate_function_definitions(self, env, code):
2608 self.body.generate_function_definitions(self.scope, code)
2610 def generate_execution_code(self, code):
2611 code.pyclass_stack.append(self)
2612 cenv = self.scope
2613 self.dict.generate_evaluation_code(code)
2614 self.classobj.generate_evaluation_code(code)
2615 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2616 self.body.generate_execution_code(code)
2617 self.target.generate_assignment_code(self.classobj, code)
2618 self.dict.generate_disposal_code(code)
2619 self.dict.free_temps(code)
2620 code.pyclass_stack.pop()
2623 class CClassDefNode(ClassDefNode):
2624 # An extension type definition.
2626 # visibility 'private' or 'public' or 'extern'
2627 # typedef_flag boolean
2628 # api boolean
2629 # module_name string or None For import of extern type objects
2630 # class_name string Unqualified name of class
2631 # as_name string or None Name to declare as in this scope
2632 # base_class_module string or None Module containing the base class
2633 # base_class_name string or None Name of the base class
2634 # objstruct_name string or None Specified C name of object struct
2635 # typeobj_name string or None Specified C name of type object
2636 # in_pxd boolean Is in a .pxd file
2637 # decorators [DecoratorNode] list of decorators or None
2638 # doc string or None
2639 # body StatNode or None
2640 # entry Symtab.Entry
2641 # base_type PyExtensionType or None
2642 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2643 # buffer_defaults_pos
2645 child_attrs = ["body"]
2646 buffer_defaults_node = None
2647 buffer_defaults_pos = None
2648 typedef_flag = False
2649 api = False
2650 objstruct_name = None
2651 typeobj_name = None
2652 decorators = None
2654 def analyse_declarations(self, env):
2655 #print "CClassDefNode.analyse_declarations:", self.class_name
2656 #print "...visibility =", self.visibility
2657 #print "...module_name =", self.module_name
2659 import Buffer
2660 if self.buffer_defaults_node:
2661 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2662 env, [], self.buffer_defaults_node,
2663 need_complete=False)
2664 else:
2665 buffer_defaults = None
2667 if env.in_cinclude and not self.objstruct_name:
2668 error(self.pos, "Object struct name specification required for "
2669 "C class defined in 'extern from' block")
2670 self.base_type = None
2671 # Now that module imports are cached, we need to
2672 # import the modules for extern classes.
2673 if self.module_name:
2674 self.module = None
2675 for module in env.cimported_modules:
2676 if module.name == self.module_name:
2677 self.module = module
2678 if self.module is None:
2679 self.module = ModuleScope(self.module_name, None, env.context)
2680 self.module.has_extern_class = 1
2681 env.add_imported_module(self.module)
2683 if self.base_class_name:
2684 if self.base_class_module:
2685 base_class_scope = env.find_module(self.base_class_module, self.pos)
2686 else:
2687 base_class_scope = env
2688 if self.base_class_name == 'object':
2689 # extension classes are special and don't need to inherit from object
2690 if base_class_scope is None or base_class_scope.lookup('object') is None:
2691 self.base_class_name = None
2692 self.base_class_module = None
2693 base_class_scope = None
2694 if base_class_scope:
2695 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2696 if base_class_entry:
2697 if not base_class_entry.is_type:
2698 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2699 elif not base_class_entry.type.is_extension_type:
2700 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2701 elif not base_class_entry.type.is_complete():
2702 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2703 else:
2704 self.base_type = base_class_entry.type
2705 has_body = self.body is not None
2706 if self.module_name and self.visibility != 'extern':
2707 module_path = self.module_name.split(".")
2708 home_scope = env.find_imported_module(module_path, self.pos)
2709 if not home_scope:
2710 return
2711 else:
2712 home_scope = env
2714 if self.visibility == 'extern':
2715 if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
2716 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
2718 self.entry = home_scope.declare_c_class(
2719 name = self.class_name,
2720 pos = self.pos,
2721 defining = has_body and self.in_pxd,
2722 implementing = has_body and not self.in_pxd,
2723 module_name = self.module_name,
2724 base_type = self.base_type,
2725 objstruct_cname = self.objstruct_name,
2726 typeobj_cname = self.typeobj_name,
2727 visibility = self.visibility,
2728 typedef_flag = self.typedef_flag,
2729 api = self.api,
2730 buffer_defaults = buffer_defaults)
2731 if home_scope is not env and self.visibility == 'extern':
2732 env.add_imported_entry(self.class_name, self.entry, pos)
2733 self.scope = scope = self.entry.type.scope
2734 if scope is not None:
2735 scope.directives = env.directives
2737 if self.doc and Options.docstrings:
2738 scope.doc = embed_position(self.pos, self.doc)
2740 if has_body:
2741 self.body.analyse_declarations(scope)
2742 if self.in_pxd:
2743 scope.defined = 1
2744 else:
2745 scope.implemented = 1
2746 env.allocate_vtable_names(self.entry)
2748 def analyse_expressions(self, env):
2749 if self.body:
2750 scope = self.entry.type.scope
2751 self.body.analyse_expressions(scope)
2753 def generate_function_definitions(self, env, code):
2754 if self.body:
2755 self.body.generate_function_definitions(
2756 self.entry.type.scope, code)
2758 def generate_execution_code(self, code):
2759 # This is needed to generate evaluation code for
2760 # default values of method arguments.
2761 if self.body:
2762 self.body.generate_execution_code(code)
2764 def annotate(self, code):
2765 if self.body:
2766 self.body.annotate(code)
2769 class PropertyNode(StatNode):
2770 # Definition of a property in an extension type.
2772 # name string
2773 # doc EncodedString or None Doc string
2774 # body StatListNode
2776 child_attrs = ["body"]
2778 def analyse_declarations(self, env):
2779 entry = env.declare_property(self.name, self.doc, self.pos)
2780 if entry:
2781 entry.scope.directives = env.directives
2782 self.body.analyse_declarations(entry.scope)
2784 def analyse_expressions(self, env):
2785 self.body.analyse_expressions(env)
2787 def generate_function_definitions(self, env, code):
2788 self.body.generate_function_definitions(env, code)
2790 def generate_execution_code(self, code):
2791 pass
2793 def annotate(self, code):
2794 self.body.annotate(code)
2797 class GlobalNode(StatNode):
2798 # Global variable declaration.
2800 # names [string]
2802 child_attrs = []
2804 def analyse_declarations(self, env):
2805 for name in self.names:
2806 env.declare_global(name, self.pos)
2808 def analyse_expressions(self, env):
2809 pass
2811 def generate_execution_code(self, code):
2812 pass
2815 class ExprStatNode(StatNode):
2816 # Expression used as a statement.
2818 # expr ExprNode
2820 child_attrs = ["expr"]
2822 def analyse_declarations(self, env):
2823 import ExprNodes
2824 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2825 func = self.expr.function.as_cython_attribute()
2826 if func == u'declare':
2827 args, kwds = self.expr.explicit_args_kwds()
2828 if len(args):
2829 error(self.expr.pos, "Variable names must be specified.")
2830 for var, type_node in kwds.key_value_pairs:
2831 type = type_node.analyse_as_type(env)
2832 if type is None:
2833 error(type_node.pos, "Unknown type")
2834 else:
2835 env.declare_var(var.value, type, var.pos, is_cdef = True)
2836 self.__class__ = PassStatNode
2838 def analyse_expressions(self, env):
2839 self.expr.analyse_expressions(env)
2841 def generate_execution_code(self, code):
2842 self.expr.generate_evaluation_code(code)
2843 if not self.expr.is_temp and self.expr.result():
2844 code.putln("%s;" % self.expr.result())
2845 self.expr.generate_disposal_code(code)
2846 self.expr.free_temps(code)
2848 def annotate(self, code):
2849 self.expr.annotate(code)
2852 class AssignmentNode(StatNode):
2853 # Abstract base class for assignment nodes.
2855 # The analyse_expressions and generate_execution_code
2856 # phases of assignments are split into two sub-phases
2857 # each, to enable all the right hand sides of a
2858 # parallel assignment to be evaluated before assigning
2859 # to any of the left hand sides.
2861 def analyse_expressions(self, env):
2862 self.analyse_types(env)
2864 # def analyse_expressions(self, env):
2865 # self.analyse_expressions_1(env)
2866 # self.analyse_expressions_2(env)
2868 def generate_execution_code(self, code):
2869 self.generate_rhs_evaluation_code(code)
2870 self.generate_assignment_code(code)
2873 class SingleAssignmentNode(AssignmentNode):
2874 # The simplest case:
2876 # a = b
2878 # lhs ExprNode Left hand side
2879 # rhs ExprNode Right hand side
2880 # first bool Is this guaranteed the first assignment to lhs?
2882 child_attrs = ["lhs", "rhs"]
2883 first = False
2884 declaration_only = False
2886 def analyse_declarations(self, env):
2887 import ExprNodes
2889 # handle declarations of the form x = cython.foo()
2890 if isinstance(self.rhs, ExprNodes.CallNode):
2891 func_name = self.rhs.function.as_cython_attribute()
2892 if func_name:
2893 args, kwds = self.rhs.explicit_args_kwds()
2895 if func_name in ['declare', 'typedef']:
2896 if len(args) > 2 or kwds is not None:
2897 error(rhs.pos, "Can only declare one type at a time.")
2898 return
2899 type = args[0].analyse_as_type(env)
2900 if type is None:
2901 error(args[0].pos, "Unknown type")
2902 return
2903 lhs = self.lhs
2904 if func_name == 'declare':
2905 if isinstance(lhs, ExprNodes.NameNode):
2906 vars = [(lhs.name, lhs.pos)]
2907 elif isinstance(lhs, ExprNodes.TupleNode):
2908 vars = [(var.name, var.pos) for var in lhs.args]
2909 else:
2910 error(lhs.pos, "Invalid declaration")
2911 return
2912 for var, pos in vars:
2913 env.declare_var(var, type, pos, is_cdef = True)
2914 if len(args) == 2:
2915 # we have a value
2916 self.rhs = args[1]
2917 else:
2918 self.declaration_only = True
2919 else:
2920 self.declaration_only = True
2921 if not isinstance(lhs, ExprNodes.NameNode):
2922 error(lhs.pos, "Invalid declaration.")
2923 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2925 elif func_name in ['struct', 'union']:
2926 self.declaration_only = True
2927 if len(args) > 0 or kwds is None:
2928 error(rhs.pos, "Struct or union members must be given by name.")
2929 return
2930 members = []
2931 for member, type_node in kwds.key_value_pairs:
2932 type = type_node.analyse_as_type(env)
2933 if type is None:
2934 error(type_node.pos, "Unknown type")
2935 else:
2936 members.append((member.value, type, member.pos))
2937 if len(members) < len(kwds.key_value_pairs):
2938 return
2939 if not isinstance(self.lhs, ExprNodes.NameNode):
2940 error(self.lhs.pos, "Invalid declaration.")
2941 name = self.lhs.name
2942 scope = StructOrUnionScope(name)
2943 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2944 for member, type, pos in members:
2945 scope.declare_var(member, type, pos)
2947 if self.declaration_only:
2948 return
2949 else:
2950 self.lhs.analyse_target_declaration(env)
2952 def analyse_types(self, env, use_temp = 0):
2953 self.rhs.analyse_types(env)
2954 self.lhs.analyse_target_types(env)
2955 self.lhs.gil_assignment_check(env)
2956 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2957 if use_temp:
2958 self.rhs = self.rhs.coerce_to_temp(env)
2960 def generate_rhs_evaluation_code(self, code):
2961 self.rhs.generate_evaluation_code(code)
2963 def generate_assignment_code(self, code):
2964 self.lhs.generate_assignment_code(self.rhs, code)
2966 def annotate(self, code):
2967 self.lhs.annotate(code)
2968 self.rhs.annotate(code)
2971 class CascadedAssignmentNode(AssignmentNode):
2972 # An assignment with multiple left hand sides:
2974 # a = b = c
2976 # lhs_list [ExprNode] Left hand sides
2977 # rhs ExprNode Right hand sides
2979 # Used internally:
2981 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2983 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2984 coerced_rhs_list = None
2986 def analyse_declarations(self, env):
2987 for lhs in self.lhs_list:
2988 lhs.analyse_target_declaration(env)
2990 def analyse_types(self, env, use_temp = 0):
2991 self.rhs.analyse_types(env)
2992 if use_temp:
2993 self.rhs = self.rhs.coerce_to_temp(env)
2994 else:
2995 self.rhs = self.rhs.coerce_to_simple(env)
2996 from ExprNodes import CloneNode
2997 self.coerced_rhs_list = []
2998 for lhs in self.lhs_list:
2999 lhs.analyse_target_types(env)
3000 lhs.gil_assignment_check(env)
3001 rhs = CloneNode(self.rhs)
3002 rhs = rhs.coerce_to(lhs.type, env)
3003 self.coerced_rhs_list.append(rhs)
3005 def generate_rhs_evaluation_code(self, code):
3006 self.rhs.generate_evaluation_code(code)
3008 def generate_assignment_code(self, code):
3009 for i in range(len(self.lhs_list)):
3010 lhs = self.lhs_list[i]
3011 rhs = self.coerced_rhs_list[i]
3012 rhs.generate_evaluation_code(code)
3013 lhs.generate_assignment_code(rhs, code)
3014 # Assignment has disposed of the cloned RHS
3015 self.rhs.generate_disposal_code(code)
3016 self.rhs.free_temps(code)
3018 def annotate(self, code):
3019 for i in range(len(self.lhs_list)):
3020 lhs = self.lhs_list[i].annotate(code)
3021 rhs = self.coerced_rhs_list[i].annotate(code)
3022 self.rhs.annotate(code)
3025 class ParallelAssignmentNode(AssignmentNode):
3026 # A combined packing/unpacking assignment:
3028 # a, b, c = d, e, f
3030 # This has been rearranged by the parser into
3032 # a = d ; b = e ; c = f
3034 # but we must evaluate all the right hand sides
3035 # before assigning to any of the left hand sides.
3037 # stats [AssignmentNode] The constituent assignments
3039 child_attrs = ["stats"]
3041 def analyse_declarations(self, env):
3042 for stat in self.stats:
3043 stat.analyse_declarations(env)
3045 def analyse_expressions(self, env):
3046 for stat in self.stats:
3047 stat.analyse_types(env, use_temp = 1)
3049 # def analyse_expressions(self, env):
3050 # for stat in self.stats:
3051 # stat.analyse_expressions_1(env, use_temp = 1)
3052 # for stat in self.stats:
3053 # stat.analyse_expressions_2(env)
3055 def generate_execution_code(self, code):
3056 for stat in self.stats:
3057 stat.generate_rhs_evaluation_code(code)
3058 for stat in self.stats:
3059 stat.generate_assignment_code(code)
3061 def annotate(self, code):
3062 for stat in self.stats:
3063 stat.annotate(code)
3066 class InPlaceAssignmentNode(AssignmentNode):
3067 # An in place arithmatic operand:
3069 # a += b
3070 # a -= b
3071 # ...
3073 # lhs ExprNode Left hand side
3074 # rhs ExprNode Right hand side
3075 # op char one of "+-*/%^&|"
3076 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3078 # This code is a bit tricky because in order to obey Python
3079 # semantics the sub-expressions (e.g. indices) of the lhs must
3080 # not be evaluated twice. So we must re-use the values calculated
3081 # in evaluation phase for the assignment phase as well.
3082 # Fortunately, the type of the lhs node is fairly constrained
3083 # (it must be a NameNode, AttributeNode, or IndexNode).
3085 child_attrs = ["lhs", "rhs"]
3086 dup = None
3088 def analyse_declarations(self, env):
3089 self.lhs.analyse_target_declaration(env)
3091 def analyse_types(self, env):
3092 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3093 self.rhs.analyse_types(env)
3094 self.lhs.analyse_target_types(env)
3095 if Options.incref_local_binop and self.dup.type.is_pyobject:
3096 self.dup = self.dup.coerce_to_temp(env)
3097 import ExprNodes
3098 if self.lhs.type.is_pyobject:
3099 self.rhs = self.rhs.coerce_to_pyobject(env)
3100 elif self.rhs.type.is_pyobject:
3101 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3102 if self.lhs.type.is_pyobject:
3103 self.result_value_temp = ExprNodes.PyTempNode(self.pos, env)
3104 self.result_value = self.result_value_temp.coerce_to(self.lhs.type, env)
3106 def generate_execution_code(self, code):
3107 import ExprNodes
3108 self.rhs.generate_evaluation_code(code)
3109 self.dup.generate_subexpr_evaluation_code(code)
3110 if self.dup.is_temp:
3111 self.dup.allocate_temp_result(code)
3112 # self.dup.generate_result_code is run only if it is not buffer access
3113 if self.operator == "**":
3114 extra = ", Py_None"
3115 else:
3116 extra = ""
3117 if self.lhs.type.is_pyobject:
3118 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3119 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3120 self.dup.generate_result_code(code)
3121 self.result_value_temp.allocate(code)
3122 code.putln(
3123 "%s = %s(%s, %s%s); %s" % (
3124 self.result_value.result(),
3125 self.py_operation_function(),
3126 self.dup.py_result(),
3127 self.rhs.py_result(),
3128 extra,
3129 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3130 code.put_gotref(self.result_value.py_result())
3131 self.result_value.generate_evaluation_code(code) # May be a type check...
3132 self.rhs.generate_disposal_code(code)
3133 self.rhs.free_temps(code)
3134 self.dup.generate_disposal_code(code)
3135 self.dup.free_temps(code)
3136 self.lhs.generate_assignment_code(self.result_value, code)
3137 self.result_value_temp.release(code)
3138 else:
3139 c_op = self.operator
3140 if c_op == "//":
3141 c_op = "/"
3142 elif c_op == "**":
3143 error(self.pos, "No C inplace power operator")
3144 elif self.lhs.type.is_complex:
3145 error(self.pos, "Inplace operators not implemented for complex types.")
3147 # have to do assignment directly to avoid side-effects
3148 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3149 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3150 else:
3151 self.dup.generate_result_code(code)
3152 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3153 self.rhs.generate_disposal_code(code)
3154 self.rhs.free_temps(code)
3155 if self.dup.is_temp:
3156 self.dup.generate_subexpr_disposal_code(code)
3157 self.dup.free_subexpr_temps(code)
3159 def create_dup_node(self, env):
3160 import ExprNodes
3161 self.dup = self.lhs
3162 self.dup.analyse_types(env)
3163 if isinstance(self.lhs, ExprNodes.NameNode):
3164 target_lhs = ExprNodes.NameNode(self.dup.pos,
3165 name = self.dup.name,
3166 is_temp = self.dup.is_temp,
3167 entry = self.dup.entry)
3168 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3169 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3170 obj = ExprNodes.CloneNode(self.lhs.obj),
3171 attribute = self.dup.attribute,
3172 is_temp = self.dup.is_temp)
3173 elif isinstance(self.lhs, ExprNodes.IndexNode):
3174 if self.lhs.index:
3175 index = ExprNodes.CloneNode(self.lhs.index)
3176 else:
3177 index = None
3178 if self.lhs.indices:
3179 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3180 else:
3181 indices = []
3182 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3183 base = ExprNodes.CloneNode(self.dup.base),
3184 index = index,
3185 indices = indices,
3186 is_temp = self.dup.is_temp)
3187 else:
3188 assert False
3189 self.lhs = target_lhs
3190 return self.dup
3192 def py_operation_function(self):
3193 return self.py_functions[self.operator]
3195 py_functions = {
3196 "|": "PyNumber_InPlaceOr",
3197 "^": "PyNumber_InPlaceXor",
3198 "&": "PyNumber_InPlaceAnd",
3199 "+": "PyNumber_InPlaceAdd",
3200 "-": "PyNumber_InPlaceSubtract",
3201 "*": "PyNumber_InPlaceMultiply",
3202 "/": "__Pyx_PyNumber_InPlaceDivide",
3203 "%": "PyNumber_InPlaceRemainder",
3204 "<<": "PyNumber_InPlaceLshift",
3205 ">>": "PyNumber_InPlaceRshift",
3206 "**": "PyNumber_InPlacePower",
3207 "//": "PyNumber_InPlaceFloorDivide",
3210 def annotate(self, code):
3211 self.lhs.annotate(code)
3212 self.rhs.annotate(code)
3213 self.dup.annotate(code)
3215 def create_binop_node(self):
3216 import ExprNodes
3217 return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
3220 class PrintStatNode(StatNode):
3221 # print statement
3223 # arg_tuple TupleNode
3224 # append_newline boolean
3226 child_attrs = ["arg_tuple"]
3228 def analyse_expressions(self, env):
3229 self.arg_tuple.analyse_expressions(env)
3230 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3231 env.use_utility_code(printing_utility_code)
3232 if len(self.arg_tuple.args) == 1 and self.append_newline:
3233 env.use_utility_code(printing_one_utility_code)
3235 nogil_check = Node.gil_error
3236 gil_message = "Python print statement"
3238 def generate_execution_code(self, code):
3239 if len(self.arg_tuple.args) == 1 and self.append_newline:
3240 arg = self.arg_tuple.args[0]
3241 arg.generate_evaluation_code(code)
3243 code.putln(
3244 "if (__Pyx_PrintOne(%s) < 0) %s" % (
3245 arg.py_result(),
3246 code.error_goto(self.pos)))
3247 arg.generate_disposal_code(code)
3248 arg.free_temps(code)
3249 else:
3250 self.arg_tuple.generate_evaluation_code(code)
3251 code.putln(
3252 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3253 self.arg_tuple.py_result(),
3254 self.append_newline,
3255 code.error_goto(self.pos)))
3256 self.arg_tuple.generate_disposal_code(code)
3257 self.arg_tuple.free_temps(code)
3259 def annotate(self, code):
3260 self.arg_tuple.annotate(code)
3263 class ExecStatNode(StatNode):
3264 # exec statement
3266 # args [ExprNode]
3268 child_attrs = ["args"]
3270 def analyse_expressions(self, env):
3271 for i, arg in enumerate(self.args):
3272 arg.analyse_expressions(env)
3273 arg = arg.coerce_to_pyobject(env)
3274 self.args[i] = arg
3275 env.use_utility_code(Builtin.pyexec_utility_code)
3277 nogil_check = Node.gil_error
3278 gil_message = "Python exec statement"
3280 def generate_execution_code(self, code):
3281 args = []
3282 for arg in self.args:
3283 arg.generate_evaluation_code(code)
3284 args.append( arg.py_result() )
3285 args = tuple(args + ['0', '0'][:3-len(args)])
3286 temp_result = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
3287 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3288 (temp_result,) + args))
3289 for arg in self.args:
3290 arg.generate_disposal_code(code)
3291 arg.free_temps(code)
3292 code.putln(
3293 code.error_goto_if_null(temp_result, self.pos))
3294 code.put_gotref(temp_result)
3295 code.put_decref_clear(temp_result, py_object_type)
3296 code.funcstate.release_temp(temp_result)
3298 def annotate(self, code):
3299 for arg in self.args:
3300 arg.annotate(code)
3303 class DelStatNode(StatNode):
3304 # del statement
3306 # args [ExprNode]
3308 child_attrs = ["args"]
3310 def analyse_declarations(self, env):
3311 for arg in self.args:
3312 arg.analyse_target_declaration(env)
3314 def analyse_expressions(self, env):
3315 for arg in self.args:
3316 arg.analyse_target_expression(env, None)
3317 if not arg.type.is_pyobject:
3318 error(arg.pos, "Deletion of non-Python object")
3319 #arg.release_target_temp(env)
3321 def nogil_check(self, env):
3322 for arg in self.args:
3323 if arg.type.is_pyobject:
3324 self.gil_error()
3326 gil_message = "Deleting Python object"
3328 def generate_execution_code(self, code):
3329 for arg in self.args:
3330 if arg.type.is_pyobject:
3331 arg.generate_deletion_code(code)
3332 # else error reported earlier
3334 def annotate(self, code):
3335 for arg in self.args:
3336 arg.annotate(code)
3339 class PassStatNode(StatNode):
3340 # pass statement
3342 child_attrs = []
3344 def analyse_expressions(self, env):
3345 pass
3347 def generate_execution_code(self, code):
3348 pass
3351 class BreakStatNode(StatNode):
3353 child_attrs = []
3355 def analyse_expressions(self, env):
3356 pass
3358 def generate_execution_code(self, code):
3359 if not code.break_label:
3360 error(self.pos, "break statement not inside loop")
3361 else:
3362 code.put_goto(code.break_label)
3365 class ContinueStatNode(StatNode):
3367 child_attrs = []
3369 def analyse_expressions(self, env):
3370 pass
3372 def generate_execution_code(self, code):
3373 if code.funcstate.in_try_finally:
3374 error(self.pos, "continue statement inside try of try...finally")
3375 elif not code.continue_label:
3376 error(self.pos, "continue statement not inside loop")
3377 else:
3378 code.put_goto(code.continue_label)
3381 class ReturnStatNode(StatNode):
3382 # return statement
3384 # value ExprNode or None
3385 # return_type PyrexType
3387 child_attrs = ["value"]
3389 def analyse_expressions(self, env):
3390 return_type = env.return_type
3391 self.return_type = return_type
3392 if not return_type:
3393 error(self.pos, "Return not inside a function body")
3394 return
3395 if self.value:
3396 self.value.analyse_types(env)
3397 if return_type.is_void or return_type.is_returncode:
3398 error(self.value.pos,
3399 "Return with value in void function")
3400 else:
3401 self.value = self.value.coerce_to(env.return_type, env)
3402 else:
3403 if (not return_type.is_void
3404 and not return_type.is_pyobject
3405 and not return_type.is_returncode):
3406 error(self.pos, "Return value required")
3408 def nogil_check(self, env):
3409 if self.return_type.is_pyobject:
3410 self.gil_error()
3412 gil_message = "Returning Python object"
3414 def generate_execution_code(self, code):
3415 code.mark_pos(self.pos)
3416 if not self.return_type:
3417 # error reported earlier
3418 return
3419 if self.return_type.is_pyobject:
3420 code.put_xdecref(Naming.retval_cname,
3421 self.return_type)
3422 if self.value:
3423 self.value.generate_evaluation_code(code)
3424 self.value.make_owned_reference(code)
3425 code.putln(
3426 "%s = %s;" % (
3427 Naming.retval_cname,
3428 self.value.result_as(self.return_type)))
3429 self.value.generate_post_assignment_code(code)
3430 self.value.free_temps(code)
3431 else:
3432 if self.return_type.is_pyobject:
3433 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3434 elif self.return_type.is_returncode:
3435 code.putln(
3436 "%s = %s;" % (
3437 Naming.retval_cname,
3438 self.return_type.default_value))
3439 for cname, type in code.funcstate.temps_holding_reference():
3440 code.put_decref_clear(cname, type)
3441 code.put_goto(code.return_label)
3443 def annotate(self, code):
3444 if self.value:
3445 self.value.annotate(code)
3448 class RaiseStatNode(StatNode):
3449 # raise statement
3451 # exc_type ExprNode or None
3452 # exc_value ExprNode or None
3453 # exc_tb ExprNode or None
3455 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3457 def analyse_expressions(self, env):
3458 if self.exc_type:
3459 self.exc_type.analyse_types(env)
3460 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3461 if self.exc_value:
3462 self.exc_value.analyse_types(env)
3463 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3464 if self.exc_tb:
3465 self.exc_tb.analyse_types(env)
3466 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3467 env.use_utility_code(raise_utility_code)
3469 nogil_check = Node.gil_error
3470 gil_message = "Raising exception"
3472 def generate_execution_code(self, code):
3473 if self.exc_type:
3474 self.exc_type.generate_evaluation_code(code)
3475 type_code = self.exc_type.py_result()
3476 else:
3477 type_code = "0"
3478 if self.exc_value:
3479 self.exc_value.generate_evaluation_code(code)
3480 value_code = self.exc_value.py_result()
3481 else:
3482 value_code = "0"
3483 if self.exc_tb:
3484 self.exc_tb.generate_evaluation_code(code)
3485 tb_code = self.exc_tb.py_result()
3486 else:
3487 tb_code = "0"
3488 code.putln(
3489 "__Pyx_Raise(%s, %s, %s);" % (
3490 type_code,
3491 value_code,
3492 tb_code))
3493 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3494 if obj:
3495 obj.generate_disposal_code(code)
3496 obj.free_temps(code)
3497 code.putln(
3498 code.error_goto(self.pos))
3500 def annotate(self, code):
3501 if self.exc_type:
3502 self.exc_type.annotate(code)
3503 if self.exc_value:
3504 self.exc_value.annotate(code)
3505 if self.exc_tb:
3506 self.exc_tb.annotate(code)
3509 class ReraiseStatNode(StatNode):
3511 child_attrs = []
3513 def analyse_expressions(self, env):
3514 env.use_utility_code(restore_exception_utility_code)
3516 nogil_check = Node.gil_error
3517 gil_message = "Raising exception"
3519 def generate_execution_code(self, code):
3520 vars = code.funcstate.exc_vars
3521 if vars:
3522 for varname in vars:
3523 code.put_giveref(varname)
3524 code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars))
3525 for varname in vars:
3526 code.put("%s = 0; " % varname)
3527 code.putln()
3528 code.putln(code.error_goto(self.pos))
3529 else:
3530 error(self.pos, "Reraise not inside except clause")
3533 class AssertStatNode(StatNode):
3534 # assert statement
3536 # cond ExprNode
3537 # value ExprNode or None
3539 child_attrs = ["cond", "value"]
3541 def analyse_expressions(self, env):
3542 self.cond = self.cond.analyse_boolean_expression(env)
3543 if self.value:
3544 self.value.analyse_types(env)
3545 self.value = self.value.coerce_to_pyobject(env)
3547 nogil_check = Node.gil_error
3548 gil_message = "Raising exception"
3550 def generate_execution_code(self, code):
3551 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3552 self.cond.generate_evaluation_code(code)
3553 code.putln(
3554 "if (unlikely(!%s)) {" %
3555 self.cond.result())
3556 if self.value:
3557 self.value.generate_evaluation_code(code)
3558 code.putln(
3559 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3560 self.value.py_result())
3561 self.value.generate_disposal_code(code)
3562 self.value.free_temps(code)
3563 else:
3564 code.putln(
3565 "PyErr_SetNone(PyExc_AssertionError);")
3566 code.putln(
3567 code.error_goto(self.pos))
3568 code.putln(
3569 "}")
3570 self.cond.generate_disposal_code(code)
3571 self.cond.free_temps(code)
3572 code.putln("#endif")
3574 def annotate(self, code):
3575 self.cond.annotate(code)
3576 if self.value:
3577 self.value.annotate(code)
3580 class IfStatNode(StatNode):
3581 # if statement
3583 # if_clauses [IfClauseNode]
3584 # else_clause StatNode or None
3586 child_attrs = ["if_clauses", "else_clause"]
3588 def analyse_control_flow(self, env):
3589 env.start_branching(self.pos)
3590 for if_clause in self.if_clauses:
3591 if_clause.analyse_control_flow(env)
3592 env.next_branch(if_clause.end_pos())
3593 if self.else_clause:
3594 self.else_clause.analyse_control_flow(env)
3595 env.finish_branching(self.end_pos())
3597 def analyse_declarations(self, env):
3598 for if_clause in self.if_clauses:
3599 if_clause.analyse_declarations(env)
3600 if self.else_clause:
3601 self.else_clause.analyse_declarations(env)
3603 def analyse_expressions(self, env):
3604 for if_clause in self.if_clauses:
3605 if_clause.analyse_expressions(env)
3606 if self.else_clause:
3607 self.else_clause.analyse_expressions(env)
3609 def generate_execution_code(self, code):
3610 code.mark_pos(self.pos)
3611 end_label = code.new_label()
3612 for if_clause in self.if_clauses:
3613 if_clause.generate_execution_code(code, end_label)
3614 if self.else_clause:
3615 code.putln("/*else*/ {")
3616 self.else_clause.generate_execution_code(code)
3617 code.putln("}")
3618 code.put_label(end_label)
3620 def annotate(self, code):
3621 for if_clause in self.if_clauses:
3622 if_clause.annotate(code)
3623 if self.else_clause:
3624 self.else_clause.annotate(code)
3627 class IfClauseNode(Node):
3628 # if or elif clause in an if statement
3630 # condition ExprNode
3631 # body StatNode
3633 child_attrs = ["condition", "body"]
3635 def analyse_control_flow(self, env):
3636 self.body.analyse_control_flow(env)
3638 def analyse_declarations(self, env):
3639 self.condition.analyse_declarations(env)
3640 self.body.analyse_declarations(env)
3642 def analyse_expressions(self, env):
3643 self.condition = \
3644 self.condition.analyse_temp_boolean_expression(env)
3645 self.body.analyse_expressions(env)
3647 def generate_execution_code(self, code, end_label):
3648 self.condition.generate_evaluation_code(code)
3649 code.putln(
3650 "if (%s) {" %
3651 self.condition.result())
3652 self.condition.generate_disposal_code(code)
3653 self.condition.free_temps(code)
3654 self.body.generate_execution_code(code)
3655 #code.putln(
3656 # "goto %s;" %
3657 # end_label)
3658 code.put_goto(end_label)
3659 code.putln("}")
3661 def annotate(self, code):
3662 self.condition.annotate(code)
3663 self.body.annotate(code)
3666 class SwitchCaseNode(StatNode):
3667 # Generated in the optimization of an if-elif-else node
3669 # conditions [ExprNode]
3670 # body StatNode
3672 child_attrs = ['conditions', 'body']
3674 def generate_execution_code(self, code):
3675 for cond in self.conditions:
3676 code.mark_pos(cond.pos)
3677 cond.generate_evaluation_code(code)
3678 code.putln("case %s:" % cond.result())
3679 self.body.generate_execution_code(code)
3680 code.putln("break;")
3682 def annotate(self, code):
3683 for cond in self.conditions:
3684 cond.annotate(code)
3685 self.body.annotate(code)
3687 class SwitchStatNode(StatNode):
3688 # Generated in the optimization of an if-elif-else node
3690 # test ExprNode
3691 # cases [SwitchCaseNode]
3692 # else_clause StatNode or None
3694 child_attrs = ['test', 'cases', 'else_clause']
3696 def generate_execution_code(self, code):
3697 code.putln("switch (%s) {" % self.test.result())
3698 for case in self.cases:
3699 case.generate_execution_code(code)
3700 if self.else_clause is not None:
3701 code.putln("default:")
3702 self.else_clause.generate_execution_code(code)
3703 code.putln("break;")
3704 code.putln("}")
3706 def annotate(self, code):
3707 self.test.annotate(code)
3708 for case in self.cases:
3709 case.annotate(code)
3710 if self.else_clause is not None:
3711 self.else_clause.annotate(code)
3713 class LoopNode(object):
3715 def analyse_control_flow(self, env):
3716 env.start_branching(self.pos)
3717 self.body.analyse_control_flow(env)
3718 env.next_branch(self.body.end_pos())
3719 if self.else_clause:
3720 self.else_clause.analyse_control_flow(env)
3721 env.finish_branching(self.end_pos())
3724 class WhileStatNode(LoopNode, StatNode):
3725 # while statement
3727 # condition ExprNode
3728 # body StatNode
3729 # else_clause StatNode
3731 child_attrs = ["condition", "body", "else_clause"]
3733 def analyse_declarations(self, env):
3734 self.body.analyse_declarations(env)
3735 if self.else_clause:
3736 self.else_clause.analyse_declarations(env)
3738 def analyse_expressions(self, env):
3739 self.condition = \
3740 self.condition.analyse_temp_boolean_expression(env)
3741 self.body.analyse_expressions(env)
3742 if self.else_clause:
3743 self.else_clause.analyse_expressions(env)
3745 def generate_execution_code(self, code):
3746 old_loop_labels = code.new_loop_labels()
3747 code.putln(
3748 "while (1) {")
3749 self.condition.generate_evaluation_code(code)
3750 self.condition.generate_disposal_code(code)
3751 code.putln(
3752 "if (!%s) break;" %
3753 self.condition.result())
3754 self.condition.free_temps(code)
3755 self.body.generate_execution_code(code)
3756 code.put_label(code.continue_label)
3757 code.putln("}")
3758 break_label = code.break_label
3759 code.set_loop_labels(old_loop_labels)
3760 if self.else_clause:
3761 code.putln("/*else*/ {")
3762 self.else_clause.generate_execution_code(code)
3763 code.putln("}")
3764 code.put_label(break_label)
3766 def annotate(self, code):
3767 self.condition.annotate(code)
3768 self.body.annotate(code)
3769 if self.else_clause:
3770 self.else_clause.annotate(code)
3773 def ForStatNode(pos, **kw):
3774 if 'iterator' in kw:
3775 return ForInStatNode(pos, **kw)
3776 else:
3777 return ForFromStatNode(pos, **kw)
3779 class ForInStatNode(LoopNode, StatNode):
3780 # for statement
3782 # target ExprNode
3783 # iterator IteratorNode
3784 # body StatNode
3785 # else_clause StatNode
3786 # item NextNode used internally
3788 child_attrs = ["target", "iterator", "body", "else_clause"]
3789 item = None
3791 def analyse_declarations(self, env):
3792 self.target.analyse_target_declaration(env)
3793 self.body.analyse_declarations(env)
3794 if self.else_clause:
3795 self.else_clause.analyse_declarations(env)
3797 def analyse_expressions(self, env):
3798 import ExprNodes
3799 self.target.analyse_target_types(env)
3800 self.iterator.analyse_expressions(env)
3801 self.item = ExprNodes.NextNode(self.iterator, env)
3802 self.item = self.item.coerce_to(self.target.type, env)
3803 self.body.analyse_expressions(env)
3804 if self.else_clause:
3805 self.else_clause.analyse_expressions(env)
3807 def generate_execution_code(self, code):
3808 old_loop_labels = code.new_loop_labels()
3809 self.iterator.allocate_counter_temp(code)
3810 self.iterator.generate_evaluation_code(code)
3811 code.putln(
3812 "for (;;) {")
3813 self.item.generate_evaluation_code(code)
3814 self.target.generate_assignment_code(self.item, code)
3815 self.body.generate_execution_code(code)
3816 code.put_label(code.continue_label)
3817 code.putln(
3818 "}")
3819 break_label = code.break_label
3820 code.set_loop_labels(old_loop_labels)
3821 if self.else_clause:
3822 code.putln("/*else*/ {")
3823 self.else_clause.generate_execution_code(code)
3824 code.putln("}")
3825 code.put_label(break_label)
3826 self.iterator.release_counter_temp(code)
3827 self.iterator.generate_disposal_code(code)
3828 self.iterator.free_temps(code)
3830 def annotate(self, code):
3831 self.target.annotate(code)
3832 self.iterator.annotate(code)
3833 self.body.annotate(code)
3834 if self.else_clause:
3835 self.else_clause.annotate(code)
3836 self.item.annotate(code)
3839 class ForFromStatNode(LoopNode, StatNode):
3840 # for name from expr rel name rel expr
3842 # target NameNode
3843 # bound1 ExprNode
3844 # relation1 string
3845 # relation2 string
3846 # bound2 ExprNode
3847 # step ExprNode or None
3848 # body StatNode
3849 # else_clause StatNode or None
3851 # Used internally:
3853 # from_range bool
3854 # is_py_target bool
3855 # loopvar_node ExprNode (usually a NameNode or temp node)
3856 # py_loopvar_node PyTempNode or None
3857 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3859 is_py_target = False
3860 loopvar_node = None
3861 py_loopvar_node = None
3862 from_range = False
3864 gil_message = "For-loop using object bounds or target"
3866 def nogil_check(self, env):
3867 for x in (self.target, self.bound1, self.bound2):
3868 if x.type.is_pyobject:
3869 self.gil_error()
3871 def analyse_declarations(self, env):
3872 self.target.analyse_target_declaration(env)
3873 self.body.analyse_declarations(env)
3874 if self.else_clause:
3875 self.else_clause.analyse_declarations(env)
3877 def analyse_expressions(self, env):
3878 import ExprNodes
3879 self.target.analyse_target_types(env)
3880 self.bound1.analyse_types(env)
3881 self.bound2.analyse_types(env)
3882 if self.step is not None:
3883 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3884 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3885 self.step.analyse_types(env)
3887 target_type = self.target.type
3888 if self.target.type.is_numeric:
3889 loop_type = self.target.type
3890 else:
3891 loop_type = PyrexTypes.c_int_type
3892 if not self.bound1.type.is_pyobject:
3893 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
3894 if not self.bound2.type.is_pyobject:
3895 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
3896 if self.step is not None and not self.step.type.is_pyobject:
3897 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
3898 self.bound1 = self.bound1.coerce_to(loop_type, env)
3899 self.bound2 = self.bound2.coerce_to(loop_type, env)
3900 if not self.bound2.is_literal:
3901 self.bound2 = self.bound2.coerce_to_temp(env)
3902 if self.step is not None:
3903 self.step = self.step.coerce_to(loop_type, env)
3904 if not self.step.is_literal:
3905 self.step = self.step.coerce_to_temp(env)
3907 target_type = self.target.type
3908 if not (target_type.is_pyobject or target_type.is_numeric):
3909 error(self.target.pos,
3910 "for-from loop variable must be c numeric type or Python object")
3911 if target_type.is_numeric:
3912 self.is_py_target = False
3913 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3914 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3915 self.loopvar_node = self.target
3916 self.py_loopvar_node = None
3917 else:
3918 self.is_py_target = True
3919 c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
3920 self.loopvar_node = c_loopvar_node
3921 self.py_loopvar_node = \
3922 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3923 self.body.analyse_expressions(env)
3924 if self.else_clause:
3925 self.else_clause.analyse_expressions(env)
3927 def generate_execution_code(self, code):
3928 old_loop_labels = code.new_loop_labels()
3929 from_range = self.from_range
3930 self.bound1.generate_evaluation_code(code)
3931 self.bound2.generate_evaluation_code(code)
3932 offset, incop = self.relation_table[self.relation1]
3933 if self.step is not None:
3934 self.step.generate_evaluation_code(code)
3935 step = self.step.result()
3936 incop = "%s=%s" % (incop[0], step)
3937 import ExprNodes
3938 if isinstance(self.loopvar_node, ExprNodes.TempNode):
3939 self.loopvar_node.allocate(code)
3940 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
3941 self.py_loopvar_node.allocate(code)
3942 if from_range:
3943 loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
3944 else:
3945 loopvar_name = self.loopvar_node.result()
3946 code.putln(
3947 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3948 loopvar_name,
3949 self.bound1.result(), offset,
3950 loopvar_name, self.relation2, self.bound2.result(),
3951 loopvar_name, incop))
3952 if self.py_loopvar_node:
3953 self.py_loopvar_node.generate_evaluation_code(code)
3954 self.target.generate_assignment_code(self.py_loopvar_node, code)
3955 elif from_range:
3956 code.putln("%s = %s;" % (
3957 self.target.result(), loopvar_name))
3958 self.body.generate_execution_code(code)
3959 code.put_label(code.continue_label)
3960 if self.py_loopvar_node:
3961 # This mess is to make for..from loops with python targets behave
3962 # exactly like those with C targets with regards to re-assignment
3963 # of the loop variable.
3964 import ExprNodes
3965 if self.target.entry.is_pyglobal:
3966 # We know target is a NameNode, this is the only ugly case.
3967 target_node = ExprNodes.PyTempNode(self.target.pos, None)
3968 target_node.allocate(code)
3969 interned_cname = code.intern_identifier(self.target.entry.name)
3970 code.putln("/*here*/")
3971 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
3972 target_node.result(),
3973 Naming.module_cname,
3974 interned_cname,
3975 code.error_goto_if_null(target_node.result(), self.target.pos)))
3976 code.put_gotref(target_node.result())
3977 else:
3978 target_node = self.target
3979 from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
3980 from_py_node.temp_code = loopvar_name
3981 from_py_node.generate_result_code(code)
3982 if self.target.entry.is_pyglobal:
3983 code.put_decref(target_node.result(), target_node.type)
3984 target_node.release(code)
3985 code.putln("}")
3986 if self.py_loopvar_node:
3987 # This is potentially wasteful, but we don't want the semantics to
3988 # depend on whether or not the loop is a python type.
3989 self.py_loopvar_node.generate_evaluation_code(code)
3990 self.target.generate_assignment_code(self.py_loopvar_node, code)
3991 if from_range:
3992 code.funcstate.release_temp(loopvar_name)
3993 break_label = code.break_label
3994 code.set_loop_labels(old_loop_labels)
3995 if self.else_clause:
3996 code.putln("/*else*/ {")
3997 self.else_clause.generate_execution_code(code)
3998 code.putln("}")
3999 code.put_label(break_label)
4000 self.bound1.generate_disposal_code(code)
4001 self.bound1.free_temps(code)
4002 self.bound2.generate_disposal_code(code)
4003 self.bound2.free_temps(code)
4004 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4005 self.loopvar_node.release(code)
4006 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4007 self.py_loopvar_node.release(code)
4008 if self.step is not None:
4009 self.step.generate_disposal_code(code)
4010 self.step.free_temps(code)
4012 relation_table = {
4013 # {relop : (initial offset, increment op)}
4014 '<=': ("", "++"),
4015 '<' : ("+1", "++"),
4016 '>=': ("", "--"),
4017 '>' : ("-1", "--")
4020 def annotate(self, code):
4021 self.target.annotate(code)
4022 self.bound1.annotate(code)
4023 self.bound2.annotate(code)
4024 if self.step:
4025 self.bound2.annotate(code)
4026 self.body.annotate(code)
4027 if self.else_clause:
4028 self.else_clause.annotate(code)
4031 class WithStatNode(StatNode):
4032 """
4033 Represents a Python with statement.
4035 This is only used at parse tree level; and is not present in
4036 analysis or generation phases.
4037 """
4038 # manager The with statement manager object
4039 # target Node (lhs expression)
4040 # body StatNode
4041 child_attrs = ["manager", "target", "body"]
4043 class TryExceptStatNode(StatNode):
4044 # try .. except statement
4046 # body StatNode
4047 # except_clauses [ExceptClauseNode]
4048 # else_clause StatNode or None
4050 child_attrs = ["body", "except_clauses", "else_clause"]
4052 def analyse_control_flow(self, env):
4053 env.start_branching(self.pos)
4054 self.body.analyse_control_flow(env)
4055 successful_try = env.control_flow # grab this for later
4056 env.next_branch(self.body.end_pos())
4057 env.finish_branching(self.body.end_pos())
4059 env.start_branching(self.except_clauses[0].pos)
4060 for except_clause in self.except_clauses:
4061 except_clause.analyse_control_flow(env)
4062 env.next_branch(except_clause.end_pos())
4064 # the else cause it executed only when the try clause finishes
4065 env.control_flow.incoming = successful_try
4066 if self.else_clause:
4067 self.else_clause.analyse_control_flow(env)
4068 env.finish_branching(self.end_pos())
4070 def analyse_declarations(self, env):
4071 self.body.analyse_declarations(env)
4072 for except_clause in self.except_clauses:
4073 except_clause.analyse_declarations(env)
4074 if self.else_clause:
4075 self.else_clause.analyse_declarations(env)
4076 env.use_utility_code(reset_exception_utility_code)
4078 def analyse_expressions(self, env):
4079 self.body.analyse_expressions(env)
4080 default_clause_seen = 0
4081 for except_clause in self.except_clauses:
4082 except_clause.analyse_expressions(env)
4083 if default_clause_seen:
4084 error(except_clause.pos, "default 'except:' must be last")
4085 if not except_clause.pattern:
4086 default_clause_seen = 1
4087 self.has_default_clause = default_clause_seen
4088 if self.else_clause:
4089 self.else_clause.analyse_expressions(env)
4091 nogil_check = Node.gil_error
4092 gil_message = "Try-except statement"
4094 def generate_execution_code(self, code):
4095 old_return_label = code.return_label
4096 old_break_label = code.break_label
4097 old_continue_label = code.continue_label
4098 old_error_label = code.new_error_label()
4099 our_error_label = code.error_label
4100 except_end_label = code.new_label('exception_handled')
4101 except_error_label = code.new_label('except_error')
4102 except_return_label = code.new_label('except_return')
4103 try_return_label = code.new_label('try_return')
4104 try_break_label = code.new_label('try_break')
4105 try_continue_label = code.new_label('try_continue')
4106 try_end_label = code.new_label('try_end')
4108 code.putln("{")
4109 code.putln("PyObject %s;" %
4110 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4111 code.putln("__Pyx_ExceptionSave(%s);" %
4112 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4113 for var in Naming.exc_save_vars:
4114 code.put_xgotref(var)
4115 code.putln(
4116 "/*try:*/ {")
4117 code.return_label = try_return_label
4118 code.break_label = try_break_label
4119 code.continue_label = try_continue_label
4120 self.body.generate_execution_code(code)
4121 code.putln(
4122 "}")
4123 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4124 code.error_label = except_error_label
4125 code.return_label = except_return_label
4126 if self.else_clause:
4127 code.putln(
4128 "/*else:*/ {")
4129 self.else_clause.generate_execution_code(code)
4130 code.putln(
4131 "}")
4132 for var in Naming.exc_save_vars:
4133 code.put_xdecref_clear(var, py_object_type)
4134 code.put_goto(try_end_label)
4135 if code.label_used(try_return_label):
4136 code.put_label(try_return_label)
4137 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4138 code.putln("__Pyx_ExceptionReset(%s);" %
4139 ', '.join(Naming.exc_save_vars))
4140 code.put_goto(old_return_label)
4141 code.put_label(our_error_label)
4142 for temp_name, type in temps_to_clean_up:
4143 code.put_xdecref_clear(temp_name, type)
4144 for except_clause in self.except_clauses:
4145 except_clause.generate_handling_code(code, except_end_label)
4147 error_label_used = code.label_used(except_error_label)
4148 if error_label_used or not self.has_default_clause:
4149 if error_label_used:
4150 code.put_label(except_error_label)
4151 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4152 code.putln("__Pyx_ExceptionReset(%s);" %
4153 ', '.join(Naming.exc_save_vars))
4154 code.put_goto(old_error_label)
4156 for exit_label, old_label in zip(
4157 [try_break_label, try_continue_label, except_return_label],
4158 [old_break_label, old_continue_label, old_return_label]):
4160 if code.label_used(exit_label):
4161 code.put_label(exit_label)
4162 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4163 code.putln("__Pyx_ExceptionReset(%s);" %
4164 ', '.join(Naming.exc_save_vars))
4165 code.put_goto(old_label)
4167 if code.label_used(except_end_label):
4168 code.put_label(except_end_label)
4169 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4170 code.putln("__Pyx_ExceptionReset(%s);" %
4171 ', '.join(Naming.exc_save_vars))
4172 code.put_label(try_end_label)
4173 code.putln("}")
4175 code.return_label = old_return_label
4176 code.break_label = old_break_label
4177 code.continue_label = old_continue_label
4178 code.error_label = old_error_label
4180 def annotate(self, code):
4181 self.body.annotate(code)
4182 for except_node in self.except_clauses:
4183 except_node.annotate(code)
4184 if self.else_clause:
4185 self.else_clause.annotate(code)
4188 class ExceptClauseNode(Node):
4189 # Part of try ... except statement.
4191 # pattern ExprNode
4192 # target ExprNode or None
4193 # body StatNode
4194 # excinfo_target NameNode or None optional target for exception info
4195 # match_flag string result of exception match
4196 # exc_value ExcValueNode used internally
4197 # function_name string qualified name of enclosing function
4198 # exc_vars (string * 3) local exception variables
4200 # excinfo_target is never set by the parser, but can be set by a transform
4201 # in order to extract more extensive information about the exception as a
4202 # sys.exc_info()-style tuple into a target variable
4204 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4206 exc_value = None
4207 excinfo_target = None
4209 def analyse_declarations(self, env):
4210 if self.target:
4211 self.target.analyse_target_declaration(env)
4212 if self.excinfo_target is not None:
4213 self.excinfo_target.analyse_target_declaration(env)
4214 self.body.analyse_declarations(env)
4216 def analyse_expressions(self, env):
4217 import ExprNodes
4218 genv = env.global_scope()
4219 self.function_name = env.qualified_name
4220 if self.pattern:
4221 self.pattern.analyse_expressions(env)
4222 self.pattern = self.pattern.coerce_to_pyobject(env)
4224 if self.target:
4225 self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
4226 self.target.analyse_target_expression(env, self.exc_value)
4227 if self.excinfo_target is not None:
4228 import ExprNodes
4229 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4230 ExprNodes.ExcValueNode(pos=self.pos, env=env) for x in range(3)])
4231 self.excinfo_tuple.analyse_expressions(env)
4232 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4234 self.body.analyse_expressions(env)
4236 def generate_handling_code(self, code, end_label):
4237 code.mark_pos(self.pos)
4238 if self.pattern:
4239 self.pattern.generate_evaluation_code(code)
4241 match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
4242 code.putln(
4243 "%s = PyErr_ExceptionMatches(%s);" % (
4244 match_flag,
4245 self.pattern.py_result()))
4246 self.pattern.generate_disposal_code(code)
4247 self.pattern.free_temps(code)
4248 code.putln(
4249 "if (%s) {" %
4250 match_flag)
4251 code.funcstate.release_temp(match_flag)
4252 else:
4253 code.putln("/*except:*/ {")
4255 if not getattr(self.body, 'stats', True):
4256 # most simple case: no exception variable, empty body (pass)
4257 # => reset the exception state, done
4258 code.putln("PyErr_Restore(0,0,0);")
4259 code.put_goto(end_label)
4260 code.putln("}")
4261 return
4263 exc_vars = [code.funcstate.allocate_temp(py_object_type,
4264 manage_ref=True)
4265 for i in xrange(3)]
4266 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4267 # We always have to fetch the exception value even if
4268 # there is no target, because this also normalises the
4269 # exception and stores it in the thread state.
4270 code.globalstate.use_utility_code(get_exception_utility_code)
4271 exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4272 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4273 code.error_goto(self.pos)))
4274 for x in exc_vars:
4275 code.put_gotref(x)
4276 if self.target:
4277 self.exc_value.set_var(exc_vars[1])
4278 self.exc_value.generate_evaluation_code(code)
4279 self.target.generate_assignment_code(self.exc_value, code)
4280 if self.excinfo_target is not None:
4281 for tempvar, node in zip(exc_vars, self.excinfo_tuple.args):
4282 node.set_var(tempvar)
4283 self.excinfo_tuple.generate_evaluation_code(code)
4284 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4286 old_break_label, old_continue_label = code.break_label, code.continue_label
4287 code.break_label = code.new_label('except_break')
4288 code.continue_label = code.new_label('except_continue')
4290 old_exc_vars = code.funcstate.exc_vars
4291 code.funcstate.exc_vars = exc_vars
4292 self.body.generate_execution_code(code)
4293 code.funcstate.exc_vars = old_exc_vars
4294 for var in exc_vars:
4295 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4296 code.put_goto(end_label)
4298 if code.label_used(code.break_label):
4299 code.put_label(code.break_label)
4300 for var in exc_vars:
4301 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4302 code.put_goto(old_break_label)
4303 code.break_label = old_break_label
4305 if code.label_used(code.continue_label):
4306 code.put_label(code.continue_label)
4307 for var in exc_vars:
4308 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4309 code.put_goto(old_continue_label)
4310 code.continue_label = old_continue_label
4312 for temp in exc_vars:
4313 code.funcstate.release_temp(temp)
4315 code.putln(
4316 "}")
4318 def annotate(self, code):
4319 if self.pattern:
4320 self.pattern.annotate(code)
4321 if self.target:
4322 self.target.annotate(code)
4323 self.body.annotate(code)
4326 class TryFinallyStatNode(StatNode):
4327 # try ... finally statement
4329 # body StatNode
4330 # finally_clause StatNode
4332 # The plan is that we funnel all continue, break
4333 # return and error gotos into the beginning of the
4334 # finally block, setting a variable to remember which
4335 # one we're doing. At the end of the finally block, we
4336 # switch on the variable to figure out where to go.
4337 # In addition, if we're doing an error, we save the
4338 # exception on entry to the finally block and restore
4339 # it on exit.
4341 child_attrs = ["body", "finally_clause"]
4343 preserve_exception = 1
4345 disallow_continue_in_try_finally = 0
4346 # There doesn't seem to be any point in disallowing
4347 # continue in the try block, since we have no problem
4348 # handling it.
4350 def create_analysed(pos, env, body, finally_clause):
4351 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4352 return node
4353 create_analysed = staticmethod(create_analysed)
4355 def analyse_control_flow(self, env):
4356 env.start_branching(self.pos)
4357 self.body.analyse_control_flow(env)
4358 env.next_branch(self.body.end_pos())
4359 env.finish_branching(self.body.end_pos())
4360 self.finally_clause.analyse_control_flow(env)
4362 def analyse_declarations(self, env):
4363 self.body.analyse_declarations(env)
4364 self.finally_clause.analyse_declarations(env)
4366 def analyse_expressions(self, env):
4367 self.body.analyse_expressions(env)
4368 self.finally_clause.analyse_expressions(env)
4370 nogil_check = Node.gil_error
4371 gil_message = "Try-finally statement"
4373 def generate_execution_code(self, code):
4374 old_error_label = code.error_label
4375 old_labels = code.all_new_labels()
4376 new_labels = code.get_all_labels()
4377 new_error_label = code.error_label
4378 catch_label = code.new_label()
4379 code.putln(
4380 "/*try:*/ {")
4381 if self.disallow_continue_in_try_finally:
4382 was_in_try_finally = code.funcstate.in_try_finally
4383 code.funcstate.in_try_finally = 1
4384 self.body.generate_execution_code(code)
4385 if self.disallow_continue_in_try_finally:
4386 code.funcstate.in_try_finally = was_in_try_finally
4387 code.putln(
4388 "}")
4389 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4390 code.putln(
4391 "/*finally:*/ {")
4392 cases_used = []
4393 error_label_used = 0
4394 for i, new_label in enumerate(new_labels):
4395 if new_label in code.labels_used:
4396 cases_used.append(i)
4397 if new_label == new_error_label:
4398 error_label_used = 1
4399 error_label_case = i
4400 if cases_used:
4401 code.putln(
4402 "int __pyx_why;")
4403 if error_label_used and self.preserve_exception:
4404 code.putln(
4405 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4406 code.putln(
4407 "int %s;" % Naming.exc_lineno_name)
4408 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4409 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4410 code.putln(exc_var_init_zero)
4411 else:
4412 exc_var_init_zero = None
4413 code.use_label(catch_label)
4414 code.putln(
4415 "__pyx_why = 0; goto %s;" % catch_label)
4416 for i in cases_used:
4417 new_label = new_labels[i]
4418 #if new_label and new_label != "<try>":
4419 if new_label == new_error_label and self.preserve_exception:
4420 self.put_error_catcher(code,
4421 new_error_label, i+1, catch_label, temps_to_clean_up)
4422 else:
4423 code.put('%s: ' % new_label)
4424 if exc_var_init_zero:
4425 code.putln(exc_var_init_zero)
4426 code.putln("__pyx_why = %s; goto %s;" % (
4427 i+1,
4428 catch_label))
4429 code.put_label(catch_label)
4430 code.set_all_labels(old_labels)
4431 if error_label_used:
4432 code.new_error_label()
4433 finally_error_label = code.error_label
4434 self.finally_clause.generate_execution_code(code)
4435 if error_label_used:
4436 if finally_error_label in code.labels_used and self.preserve_exception:
4437 over_label = code.new_label()
4438 code.put_goto(over_label);
4439 code.put_label(finally_error_label)
4440 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4441 for var in Naming.exc_vars:
4442 code.putln("Py_XDECREF(%s);" % var)
4443 code.putln("}")
4444 code.put_goto(old_error_label)
4445 code.put_label(over_label)
4446 code.error_label = old_error_label
4447 if cases_used:
4448 code.putln(
4449 "switch (__pyx_why) {")
4450 for i in cases_used:
4451 old_label = old_labels[i]
4452 if old_label == old_error_label and self.preserve_exception:
4453 self.put_error_uncatcher(code, i+1, old_error_label)
4454 else:
4455 code.use_label(old_label)
4456 code.putln(
4457 "case %s: goto %s;" % (
4458 i+1,
4459 old_label))
4460 code.putln(
4461 "}")
4462 code.putln(
4463 "}")
4465 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4466 code.globalstate.use_utility_code(restore_exception_utility_code)
4467 code.putln(
4468 "%s: {" %
4469 error_label)
4470 code.putln(
4471 "__pyx_why = %s;" %
4472 i)
4473 for temp_name, type in temps_to_clean_up:
4474 code.put_xdecref_clear(temp_name, type)
4475 code.putln(
4476 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4477 Naming.exc_vars)
4478 code.putln(
4479 "%s = %s;" % (
4480 Naming.exc_lineno_name, Naming.lineno_cname))
4481 #code.putln(
4482 # "goto %s;" %
4483 # catch_label)
4484 code.put_goto(catch_label)
4485 code.putln(
4486 "}")
4488 def put_error_uncatcher(self, code, i, error_label):
4489 code.globalstate.use_utility_code(restore_exception_utility_code)
4490 code.putln(
4491 "case %s: {" %
4492 i)
4493 code.putln(
4494 "__Pyx_ErrRestore(%s, %s, %s);" %
4495 Naming.exc_vars)
4496 code.putln(
4497 "%s = %s;" % (
4498 Naming.lineno_cname, Naming.exc_lineno_name))
4499 for var in Naming.exc_vars:
4500 code.putln(
4501 "%s = 0;" %
4502 var)
4503 code.put_goto(error_label)
4504 code.putln(
4505 "}")
4507 def annotate(self, code):
4508 self.body.annotate(code)
4509 self.finally_clause.annotate(code)
4512 class GILStatNode(TryFinallyStatNode):
4513 # 'with gil' or 'with nogil' statement
4515 # state string 'gil' or 'nogil'
4517 # child_attrs = []
4519 preserve_exception = 0
4521 def __init__(self, pos, state, body):
4522 self.state = state
4523 TryFinallyStatNode.__init__(self, pos,
4524 body = body,
4525 finally_clause = GILExitNode(pos, state = state))
4527 def analyse_expressions(self, env):
4528 env.use_utility_code(force_init_threads_utility_code)
4529 was_nogil = env.nogil
4530 env.nogil = 1
4531 TryFinallyStatNode.analyse_expressions(self, env)
4532 env.nogil = was_nogil
4534 nogil_check = None
4536 def generate_execution_code(self, code):
4537 code.mark_pos(self.pos)
4538 if self.state == 'gil':
4539 code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4540 else:
4541 code.putln("{ PyThreadState *_save;")
4542 code.putln("Py_UNBLOCK_THREADS")
4543 TryFinallyStatNode.generate_execution_code(self, code)
4544 code.putln("}")
4547 class GILExitNode(StatNode):
4548 # Used as the 'finally' block in a GILStatNode
4550 # state string 'gil' or 'nogil'
4552 child_attrs = []
4554 def analyse_expressions(self, env):
4555 pass
4557 def generate_execution_code(self, code):
4558 if self.state == 'gil':
4559 code.putln("PyGILState_Release();")
4560 else:
4561 code.putln("Py_BLOCK_THREADS")
4564 class CImportStatNode(StatNode):
4565 # cimport statement
4567 # module_name string Qualified name of module being imported
4568 # as_name string or None Name specified in "as" clause, if any
4570 child_attrs = []
4572 def analyse_declarations(self, env):
4573 if not env.is_module_scope:
4574 error(self.pos, "cimport only allowed at module level")
4575 return
4576 module_scope = env.find_module(self.module_name, self.pos)
4577 if "." in self.module_name:
4578 names = [EncodedString(name) for name in self.module_name.split(".")]
4579 top_name = names[0]
4580 top_module_scope = env.context.find_submodule(top_name)
4581 module_scope = top_module_scope
4582 for name in names[1:]:
4583 submodule_scope = module_scope.find_submodule(name)
4584 module_scope.declare_module(name, submodule_scope, self.pos)
4585 module_scope = submodule_scope
4586 if self.as_name:
4587 env.declare_module(self.as_name, module_scope, self.pos)
4588 else:
4589 env.declare_module(top_name, top_module_scope, self.pos)
4590 else:
4591 name = self.as_name or self.module_name
4592 env.declare_module(name, module_scope, self.pos)
4594 def analyse_expressions(self, env):
4595 pass
4597 def generate_execution_code(self, code):
4598 pass
4601 class FromCImportStatNode(StatNode):
4602 # from ... cimport statement
4604 # module_name string Qualified name of module
4605 # imported_names [(pos, name, as_name, kind)] Names to be imported
4607 child_attrs = []
4609 def analyse_declarations(self, env):
4610 if not env.is_module_scope:
4611 error(self.pos, "cimport only allowed at module level")
4612 return
4613 module_scope = env.find_module(self.module_name, self.pos)
4614 env.add_imported_module(module_scope)
4615 for pos, name, as_name, kind in self.imported_names:
4616 if name == "*":
4617 for local_name, entry in module_scope.entries.items():
4618 env.add_imported_entry(local_name, entry, pos)
4619 else:
4620 entry = module_scope.lookup(name)
4621 if entry:
4622 if kind and not self.declaration_matches(entry, kind):
4623 entry.redeclared(pos)
4624 else:
4625 if kind == 'struct' or kind == 'union':
4626 entry = module_scope.declare_struct_or_union(name,
4627 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4628 elif kind == 'class':
4629 entry = module_scope.declare_c_class(name, pos = pos,
4630 module_name = self.module_name)
4631 else:
4632 submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
4633 if submodule_scope.parent_module is module_scope:
4634 env.declare_module(as_name or name, submodule_scope, self.pos)
4635 else:
4636 error(pos, "Name '%s' not declared in module '%s'"
4637 % (name, self.module_name))
4639 if entry:
4640 local_name = as_name or name
4641 env.add_imported_entry(local_name, entry, pos)
4643 def declaration_matches(self, entry, kind):
4644 if not entry.is_type:
4645 return 0
4646 type = entry.type
4647 if kind == 'class':
4648 if not type.is_extension_type:
4649 return 0
4650 else:
4651 if not type.is_struct_or_union:
4652 return 0
4653 if kind != type.kind:
4654 return 0
4655 return 1
4657 def analyse_expressions(self, env):
4658 pass
4660 def generate_execution_code(self, code):
4661 pass
4664 class FromImportStatNode(StatNode):
4665 # from ... import statement
4667 # module ImportNode
4668 # items [(string, NameNode)]
4669 # interned_items [(string, NameNode, ExprNode)]
4670 # item PyTempNode used internally
4671 # import_star boolean used internally
4673 child_attrs = ["module"]
4674 import_star = 0
4676 def analyse_declarations(self, env):
4677 for name, target in self.items:
4678 if name == "*":
4679 if not env.is_module_scope:
4680 error(self.pos, "import * only allowed at module level")
4681 return
4682 env.has_import_star = 1
4683 self.import_star = 1
4684 else:
4685 target.analyse_target_declaration(env)
4687 def analyse_expressions(self, env):
4688 import ExprNodes
4689 self.module.analyse_expressions(env)
4690 self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
4691 self.interned_items = []
4692 for name, target in self.items:
4693 if name == '*':
4694 for _, entry in env.entries.items():
4695 if not entry.is_type and entry.type.is_extension_type:
4696 env.use_utility_code(ExprNodes.type_test_utility_code)
4697 break
4698 else:
4699 entry = env.lookup(target.name)
4700 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4701 continue # already cimported
4702 target.analyse_target_expression(env, None)
4703 if target.type is py_object_type:
4704 coerced_item = None
4705 else:
4706 coerced_item = self.item.coerce_to(target.type, env)
4707 self.interned_items.append(
4708 (name, target, coerced_item))
4710 def generate_execution_code(self, code):
4711 self.module.generate_evaluation_code(code)
4712 if self.import_star:
4713 code.putln(
4714 'if (%s(%s) < 0) %s;' % (
4715 Naming.import_star,
4716 self.module.py_result(),
4717 code.error_goto(self.pos)))
4718 item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
4719 self.item.set_cname(item_temp)
4720 for name, target, coerced_item in self.interned_items:
4721 cname = code.intern_identifier(name)
4722 code.putln(
4723 '%s = PyObject_GetAttr(%s, %s); %s' % (
4724 item_temp,
4725 self.module.py_result(),
4726 cname,
4727 code.error_goto_if_null(item_temp, self.pos)))
4728 code.put_gotref(item_temp)
4729 if coerced_item is None:
4730 target.generate_assignment_code(self.item, code)
4731 else:
4732 coerced_item.allocate_temp_result(code)
4733 coerced_item.generate_result_code(code)
4734 target.generate_assignment_code(coerced_item, code)
4735 code.put_decref_clear(item_temp, py_object_type)
4736 code.funcstate.release_temp(item_temp)
4737 self.module.generate_disposal_code(code)
4738 self.module.free_temps(code)
4742 #------------------------------------------------------------------------------------
4744 # Runtime support code
4746 #------------------------------------------------------------------------------------
4748 utility_function_predeclarations = \
4749 """
4750 #ifdef __GNUC__
4751 #define INLINE __inline__
4752 #elif _WIN32
4753 #define INLINE __inline
4754 #else
4755 #define INLINE
4756 #endif
4758 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*/
4760 """
4762 if Options.gcc_branch_hints:
4763 branch_prediction_macros = \
4764 """
4765 #ifdef __GNUC__
4766 /* Test for GCC > 2.95 */
4767 #if __GNUC__ > 2 || \
4768 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4769 #define likely(x) __builtin_expect(!!(x), 1)
4770 #define unlikely(x) __builtin_expect(!!(x), 0)
4771 #else /* __GNUC__ > 2 ... */
4772 #define likely(x) (x)
4773 #define unlikely(x) (x)
4774 #endif /* __GNUC__ > 2 ... */
4775 #else /* __GNUC__ */
4776 #define likely(x) (x)
4777 #define unlikely(x) (x)
4778 #endif /* __GNUC__ */
4779 """
4780 else:
4781 branch_prediction_macros = \
4782 """
4783 #define likely(x) (x)
4784 #define unlikely(x) (x)
4785 """
4787 #get_name_predeclaration = \
4788 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4790 #get_name_interned_predeclaration = \
4791 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4793 #------------------------------------------------------------------------------------
4795 printing_utility_code = UtilityCode(
4796 proto = """
4797 static int __Pyx_Print(PyObject *, int); /*proto*/
4798 #if PY_MAJOR_VERSION >= 3
4799 static PyObject* %s = 0;
4800 static PyObject* %s = 0;
4801 #endif
4802 """ % (Naming.print_function, Naming.print_function_kwargs),
4803 impl = r"""
4804 #if PY_MAJOR_VERSION < 3
4805 static PyObject *__Pyx_GetStdout(void) {
4806 PyObject *f = PySys_GetObject((char *)"stdout");
4807 if (!f) {
4808 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4810 return f;
4813 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4814 PyObject *f;
4815 PyObject* v;
4816 int i;
4818 if (!(f = __Pyx_GetStdout()))
4819 return -1;
4820 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4821 if (PyFile_SoftSpace(f, 1)) {
4822 if (PyFile_WriteString(" ", f) < 0)
4823 return -1;
4825 v = PyTuple_GET_ITEM(arg_tuple, i);
4826 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4827 return -1;
4828 if (PyString_Check(v)) {
4829 char *s = PyString_AsString(v);
4830 Py_ssize_t len = PyString_Size(v);
4831 if (len > 0 &&
4832 isspace(Py_CHARMASK(s[len-1])) &&
4833 s[len-1] != ' ')
4834 PyFile_SoftSpace(f, 0);
4837 if (newline) {
4838 if (PyFile_WriteString("\n", f) < 0)
4839 return -1;
4840 PyFile_SoftSpace(f, 0);
4842 return 0;
4845 #else /* Python 3 has a print function */
4847 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4848 PyObject* kwargs = 0;
4849 PyObject* result = 0;
4850 PyObject* end_string;
4851 if (!%(PRINT_FUNCTION)s) {
4852 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4853 if (!%(PRINT_FUNCTION)s)
4854 return -1;
4856 if (!newline) {
4857 if (!%(PRINT_KWARGS)s) {
4858 %(PRINT_KWARGS)s = PyDict_New();
4859 if (!%(PRINT_KWARGS)s)
4860 return -1;
4861 end_string = PyUnicode_FromStringAndSize(" ", 1);
4862 if (!end_string)
4863 return -1;
4864 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4865 Py_DECREF(end_string);
4866 return -1;
4868 Py_DECREF(end_string);
4870 kwargs = %(PRINT_KWARGS)s;
4872 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4873 if (!result)
4874 return -1;
4875 Py_DECREF(result);
4876 return 0;
4879 #endif
4880 """ % {'BUILTINS' : Naming.builtins_cname,
4881 'PRINT_FUNCTION' : Naming.print_function,
4882 'PRINT_KWARGS' : Naming.print_function_kwargs}
4886 printing_one_utility_code = UtilityCode(
4887 proto = """
4888 static int __Pyx_PrintOne(PyObject *o); /*proto*/
4889 """,
4890 impl = r"""
4891 #if PY_MAJOR_VERSION < 3
4893 static int __Pyx_PrintOne(PyObject *o) {
4894 PyObject *f;
4895 if (!(f = __Pyx_GetStdout()))
4896 return -1;
4897 if (PyFile_SoftSpace(f, 0)) {
4898 if (PyFile_WriteString(" ", f) < 0)
4899 return -1;
4901 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
4902 return -1;
4903 if (PyFile_WriteString("\n", f) < 0)
4904 return -1;
4905 return 0;
4906 /* the line below is just to avoid compiler
4907 * compiler warnings about unused functions */
4908 return __Pyx_Print(NULL, 0);
4911 #else /* Python 3 has a print function */
4913 static int __Pyx_PrintOne(PyObject *o) {
4914 int res;
4915 PyObject* arg_tuple = PyTuple_New(1);
4916 if (unlikely(!arg_tuple))
4917 return -1;
4918 Py_INCREF(o);
4919 PyTuple_SET_ITEM(arg_tuple, 0, o);
4920 res = __Pyx_Print(arg_tuple, 1);
4921 Py_DECREF(arg_tuple);
4922 return res;
4925 #endif
4926 """,
4927 requires=[printing_utility_code])
4931 #------------------------------------------------------------------------------------
4933 # Exception raising code
4935 # Exceptions are raised by __Pyx_Raise() and stored as plain
4936 # type/value/tb in PyThreadState->curexc_*. When being caught by an
4937 # 'except' statement, curexc_* is moved over to exc_* by
4938 # __Pyx_GetException()
4940 restore_exception_utility_code = UtilityCode(
4941 proto = """
4942 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4943 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
4944 """,
4945 impl = """
4946 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
4947 PyObject *tmp_type, *tmp_value, *tmp_tb;
4948 PyThreadState *tstate = PyThreadState_GET();
4950 tmp_type = tstate->curexc_type;
4951 tmp_value = tstate->curexc_value;
4952 tmp_tb = tstate->curexc_traceback;
4953 tstate->curexc_type = type;
4954 tstate->curexc_value = value;
4955 tstate->curexc_traceback = tb;
4956 Py_XDECREF(tmp_type);
4957 Py_XDECREF(tmp_value);
4958 Py_XDECREF(tmp_tb);
4961 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
4962 PyThreadState *tstate = PyThreadState_GET();
4963 *type = tstate->curexc_type;
4964 *value = tstate->curexc_value;
4965 *tb = tstate->curexc_traceback;
4967 tstate->curexc_type = 0;
4968 tstate->curexc_value = 0;
4969 tstate->curexc_traceback = 0;
4972 """)
4974 # The following function is based on do_raise() from ceval.c. There
4975 # are separate versions for Python2 and Python3 as exception handling
4976 # has changed quite a lot between the two versions.
4978 raise_utility_code = UtilityCode(
4979 proto = """
4980 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4981 """,
4982 impl = """
4983 #if PY_MAJOR_VERSION < 3
4984 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4985 Py_XINCREF(type);
4986 Py_XINCREF(value);
4987 Py_XINCREF(tb);
4988 /* First, check the traceback argument, replacing None with NULL. */
4989 if (tb == Py_None) {
4990 Py_DECREF(tb);
4991 tb = 0;
4993 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4994 PyErr_SetString(PyExc_TypeError,
4995 "raise: arg 3 must be a traceback or None");
4996 goto raise_error;
4998 /* Next, replace a missing value with None */
4999 if (value == NULL) {
5000 value = Py_None;
5001 Py_INCREF(value);
5003 #if PY_VERSION_HEX < 0x02050000
5004 if (!PyClass_Check(type))
5005 #else
5006 if (!PyType_Check(type))
5007 #endif
5009 /* Raising an instance. The value should be a dummy. */
5010 if (value != Py_None) {
5011 PyErr_SetString(PyExc_TypeError,
5012 "instance exception may not have a separate value");
5013 goto raise_error;
5015 /* Normalize to raise <class>, <instance> */
5016 Py_DECREF(value);
5017 value = type;
5018 #if PY_VERSION_HEX < 0x02050000
5019 if (PyInstance_Check(type)) {
5020 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
5021 Py_INCREF(type);
5023 else {
5024 type = 0;
5025 PyErr_SetString(PyExc_TypeError,
5026 "raise: exception must be an old-style class or instance");
5027 goto raise_error;
5029 #else
5030 type = (PyObject*) Py_TYPE(type);
5031 Py_INCREF(type);
5032 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
5033 PyErr_SetString(PyExc_TypeError,
5034 "raise: exception class must be a subclass of BaseException");
5035 goto raise_error;
5037 #endif
5040 __Pyx_ErrRestore(type, value, tb);
5041 return;
5042 raise_error:
5043 Py_XDECREF(value);
5044 Py_XDECREF(type);
5045 Py_XDECREF(tb);
5046 return;
5049 #else // Python 3+
5051 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5052 if (tb == Py_None) {
5053 tb = 0;
5054 } else if (tb && !PyTraceBack_Check(tb)) {
5055 PyErr_SetString(PyExc_TypeError,
5056 "raise: arg 3 must be a traceback or None");
5057 goto bad;
5059 if (value == Py_None)
5060 value = 0;
5062 if (PyExceptionInstance_Check(type)) {
5063 if (value) {
5064 PyErr_SetString(PyExc_TypeError,
5065 "instance exception may not have a separate value");
5066 goto bad;
5068 value = type;
5069 type = (PyObject*) Py_TYPE(value);
5070 } else if (!PyExceptionClass_Check(type)) {
5071 PyErr_SetString(PyExc_TypeError,
5072 "raise: exception class must be a subclass of BaseException");
5073 goto bad;
5076 PyErr_SetObject(type, value);
5078 if (tb) {
5079 PyThreadState *tstate = PyThreadState_GET();
5080 PyObject* tmp_tb = tstate->curexc_traceback;
5081 if (tb != tmp_tb) {
5082 Py_INCREF(tb);
5083 tstate->curexc_traceback = tb;
5084 Py_XDECREF(tmp_tb);
5088 bad:
5089 return;
5091 #endif
5092 """,
5093 requires=[restore_exception_utility_code])
5095 #------------------------------------------------------------------------------------
5097 get_exception_utility_code = UtilityCode(
5098 proto = """
5099 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5100 """,
5101 impl = """
5102 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5103 PyObject *local_type, *local_value, *local_tb;
5104 PyObject *tmp_type, *tmp_value, *tmp_tb;
5105 PyThreadState *tstate = PyThreadState_GET();
5106 local_type = tstate->curexc_type;
5107 local_value = tstate->curexc_value;
5108 local_tb = tstate->curexc_traceback;
5109 tstate->curexc_type = 0;
5110 tstate->curexc_value = 0;
5111 tstate->curexc_traceback = 0;
5112 PyErr_NormalizeException(&local_type, &local_value, &local_tb);
5113 if (unlikely(tstate->curexc_type))
5114 goto bad;
5115 #if PY_MAJOR_VERSION >= 3
5116 if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
5117 goto bad;
5118 #endif
5119 *type = local_type;
5120 *value = local_value;
5121 *tb = local_tb;
5122 Py_INCREF(local_type);
5123 Py_INCREF(local_value);
5124 Py_INCREF(local_tb);
5125 tmp_type = tstate->exc_type;
5126 tmp_value = tstate->exc_value;
5127 tmp_tb = tstate->exc_traceback;
5128 tstate->exc_type = local_type;
5129 tstate->exc_value = local_value;
5130 tstate->exc_traceback = local_tb;
5131 /* Make sure tstate is in a consistent state when we XDECREF
5132 these objects (XDECREF may run arbitrary code). */
5133 Py_XDECREF(tmp_type);
5134 Py_XDECREF(tmp_value);
5135 Py_XDECREF(tmp_tb);
5136 return 0;
5137 bad:
5138 *type = 0;
5139 *value = 0;
5140 *tb = 0;
5141 Py_XDECREF(local_type);
5142 Py_XDECREF(local_value);
5143 Py_XDECREF(local_tb);
5144 return -1;
5147 """)
5149 #------------------------------------------------------------------------------------
5151 get_exception_tuple_utility_code = UtilityCode(proto="""
5152 static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
5153 """,
5154 # I doubt that calling __Pyx_GetException() here is correct as it moves
5155 # the exception from tstate->curexc_* to tstate->exc_*, which prevents
5156 # exception handlers later on from receiving it.
5157 impl = """
5158 static PyObject *__Pyx_GetExceptionTuple(void) {
5159 PyObject *type = NULL, *value = NULL, *tb = NULL;
5160 if (__Pyx_GetException(&type, &value, &tb) == 0) {
5161 PyObject* exc_info = PyTuple_New(3);
5162 if (exc_info) {
5163 Py_INCREF(type);
5164 Py_INCREF(value);
5165 Py_INCREF(tb);
5166 PyTuple_SET_ITEM(exc_info, 0, type);
5167 PyTuple_SET_ITEM(exc_info, 1, value);
5168 PyTuple_SET_ITEM(exc_info, 2, tb);
5169 return exc_info;
5172 return NULL;
5174 """,
5175 requires=[get_exception_utility_code])
5177 #------------------------------------------------------------------------------------
5179 reset_exception_utility_code = UtilityCode(
5180 proto = """
5181 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5182 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5183 """,
5184 impl = """
5185 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5186 PyThreadState *tstate = PyThreadState_GET();
5187 *type = tstate->exc_type;
5188 *value = tstate->exc_value;
5189 *tb = tstate->exc_traceback;
5190 Py_XINCREF(*type);
5191 Py_XINCREF(*value);
5192 Py_XINCREF(*tb);
5195 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5196 PyObject *tmp_type, *tmp_value, *tmp_tb;
5197 PyThreadState *tstate = PyThreadState_GET();
5198 tmp_type = tstate->exc_type;
5199 tmp_value = tstate->exc_value;
5200 tmp_tb = tstate->exc_traceback;
5201 tstate->exc_type = type;
5202 tstate->exc_value = value;
5203 tstate->exc_traceback = tb;
5204 Py_XDECREF(tmp_type);
5205 Py_XDECREF(tmp_value);
5206 Py_XDECREF(tmp_tb);
5208 """)
5210 #------------------------------------------------------------------------------------
5212 arg_type_test_utility_code = UtilityCode(
5213 proto = """
5214 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5215 const char *name, int exact); /*proto*/
5216 """,
5217 impl = """
5218 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5219 const char *name, int exact)
5221 if (!type) {
5222 PyErr_Format(PyExc_SystemError, "Missing type object");
5223 return 0;
5225 if (none_allowed && obj == Py_None) return 1;
5226 else if (exact) {
5227 if (Py_TYPE(obj) == type) return 1;
5229 else {
5230 if (PyObject_TypeCheck(obj, type)) return 1;
5232 PyErr_Format(PyExc_TypeError,
5233 "Argument '%s' has incorrect type (expected %s, got %s)",
5234 name, type->tp_name, Py_TYPE(obj)->tp_name);
5235 return 0;
5237 """)
5239 #------------------------------------------------------------------------------------
5241 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5242 # many or too few positional arguments were found. This handles
5243 # Py_ssize_t formatting correctly.
5245 raise_argtuple_invalid_utility_code = UtilityCode(
5246 proto = """
5247 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5248 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5249 """,
5250 impl = """
5251 static void __Pyx_RaiseArgtupleInvalid(
5252 const char* func_name,
5253 int exact,
5254 Py_ssize_t num_min,
5255 Py_ssize_t num_max,
5256 Py_ssize_t num_found)
5258 Py_ssize_t num_expected;
5259 const char *number, *more_or_less;
5261 if (num_found < num_min) {
5262 num_expected = num_min;
5263 more_or_less = "at least";
5264 } else {
5265 num_expected = num_max;
5266 more_or_less = "at most";
5268 if (exact) {
5269 more_or_less = "exactly";
5271 number = (num_expected == 1) ? "" : "s";
5272 PyErr_Format(PyExc_TypeError,
5273 #if PY_VERSION_HEX < 0x02050000
5274 "%s() takes %s %d positional argument%s (%d given)",
5275 #else
5276 "%s() takes %s %zd positional argument%s (%zd given)",
5277 #endif
5278 func_name, more_or_less, num_expected, number, num_found);
5280 """)
5282 raise_keyword_required_utility_code = UtilityCode(
5283 proto = """
5284 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5285 """,
5286 impl = """
5287 static INLINE void __Pyx_RaiseKeywordRequired(
5288 const char* func_name,
5289 PyObject* kw_name)
5291 PyErr_Format(PyExc_TypeError,
5292 #if PY_MAJOR_VERSION >= 3
5293 "%s() needs keyword-only argument %U", func_name, kw_name);
5294 #else
5295 "%s() needs keyword-only argument %s", func_name,
5296 PyString_AS_STRING(kw_name));
5297 #endif
5299 """)
5301 raise_double_keywords_utility_code = UtilityCode(
5302 proto = """
5303 static void __Pyx_RaiseDoubleKeywordsError(
5304 const char* func_name, PyObject* kw_name); /*proto*/
5305 """,
5306 impl = """
5307 static void __Pyx_RaiseDoubleKeywordsError(
5308 const char* func_name,
5309 PyObject* kw_name)
5311 PyErr_Format(PyExc_TypeError,
5312 #if PY_MAJOR_VERSION >= 3
5313 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5314 #else
5315 "%s() got multiple values for keyword argument '%s'", func_name,
5316 PyString_AS_STRING(kw_name));
5317 #endif
5319 """)
5321 #------------------------------------------------------------------------------------
5323 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5324 # were passed to a function, or if any keywords were passed to a
5325 # function that does not accept them.
5327 keyword_string_check_utility_code = UtilityCode(
5328 proto = """
5329 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5330 const char* function_name, int kw_allowed); /*proto*/
5331 """,
5332 impl = """
5333 static INLINE int __Pyx_CheckKeywordStrings(
5334 PyObject *kwdict,
5335 const char* function_name,
5336 int kw_allowed)
5338 PyObject* key = 0;
5339 Py_ssize_t pos = 0;
5340 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5341 #if PY_MAJOR_VERSION < 3
5342 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5343 #else
5344 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5345 #endif
5346 goto invalid_keyword_type;
5348 if ((!kw_allowed) && unlikely(key))
5349 goto invalid_keyword;
5350 return 1;
5351 invalid_keyword_type:
5352 PyErr_Format(PyExc_TypeError,
5353 "%s() keywords must be strings", function_name);
5354 return 0;
5355 invalid_keyword:
5356 PyErr_Format(PyExc_TypeError,
5357 #if PY_MAJOR_VERSION < 3
5358 "%s() got an unexpected keyword argument '%s'",
5359 function_name, PyString_AsString(key));
5360 #else
5361 "%s() got an unexpected keyword argument '%U'",
5362 function_name, key);
5363 #endif
5364 return 0;
5366 """)
5368 #------------------------------------------------------------------------------------
5370 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5371 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5372 # keywords will raise an invalid keyword error.
5374 # Three kinds of errors are checked: 1) non-string keywords, 2)
5375 # unexpected keywords and 3) overlap with positional arguments.
5377 # If num_posargs is greater 0, it denotes the number of positional
5378 # arguments that were passed and that must therefore not appear
5379 # amongst the keywords as well.
5381 # This method does not check for required keyword arguments.
5384 parse_keywords_utility_code = UtilityCode(
5385 proto = """
5386 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5387 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5388 const char* function_name); /*proto*/
5389 """,
5390 impl = """
5391 static int __Pyx_ParseOptionalKeywords(
5392 PyObject *kwds,
5393 PyObject **argnames[],
5394 PyObject *kwds2,
5395 PyObject *values[],
5396 Py_ssize_t num_pos_args,
5397 const char* function_name)
5399 PyObject *key = 0, *value = 0;
5400 Py_ssize_t pos = 0;
5401 PyObject*** name;
5402 PyObject*** first_kw_arg = argnames + num_pos_args;
5404 while (PyDict_Next(kwds, &pos, &key, &value)) {
5405 name = first_kw_arg;
5406 while (*name && (**name != key)) name++;
5407 if (*name) {
5408 values[name-argnames] = value;
5409 } else {
5410 #if PY_MAJOR_VERSION < 3
5411 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5412 #else
5413 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5414 #endif
5415 goto invalid_keyword_type;
5416 } else {
5417 for (name = first_kw_arg; *name; name++) {
5418 #if PY_MAJOR_VERSION >= 3
5419 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5420 PyUnicode_Compare(**name, key) == 0) break;
5421 #else
5422 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5423 _PyString_Eq(**name, key)) break;
5424 #endif
5426 if (*name) {
5427 values[name-argnames] = value;
5428 } else {
5429 /* unexpected keyword found */
5430 for (name=argnames; name != first_kw_arg; name++) {
5431 if (**name == key) goto arg_passed_twice;
5432 #if PY_MAJOR_VERSION >= 3
5433 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5434 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5435 #else
5436 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5437 _PyString_Eq(**name, key)) goto arg_passed_twice;
5438 #endif
5440 if (kwds2) {
5441 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5442 } else {
5443 goto invalid_keyword;
5449 return 0;
5450 arg_passed_twice:
5451 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5452 goto bad;
5453 invalid_keyword_type:
5454 PyErr_Format(PyExc_TypeError,
5455 "%s() keywords must be strings", function_name);
5456 goto bad;
5457 invalid_keyword:
5458 PyErr_Format(PyExc_TypeError,
5459 #if PY_MAJOR_VERSION < 3
5460 "%s() got an unexpected keyword argument '%s'",
5461 function_name, PyString_AsString(key));
5462 #else
5463 "%s() got an unexpected keyword argument '%U'",
5464 function_name, key);
5465 #endif
5466 bad:
5467 return -1;
5469 """)
5471 #------------------------------------------------------------------------------------
5473 traceback_utility_code = UtilityCode(
5474 proto = """
5475 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5476 """,
5477 impl = """
5478 #include "compile.h"
5479 #include "frameobject.h"
5480 #include "traceback.h"
5482 static void __Pyx_AddTraceback(const char *funcname) {
5483 PyObject *py_srcfile = 0;
5484 PyObject *py_funcname = 0;
5485 PyObject *py_globals = 0;
5486 PyCodeObject *py_code = 0;
5487 PyFrameObject *py_frame = 0;
5489 #if PY_MAJOR_VERSION < 3
5490 py_srcfile = PyString_FromString(%(FILENAME)s);
5491 #else
5492 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5493 #endif
5494 if (!py_srcfile) goto bad;
5495 if (%(CLINENO)s) {
5496 #if PY_MAJOR_VERSION < 3
5497 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5498 #else
5499 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5500 #endif
5502 else {
5503 #if PY_MAJOR_VERSION < 3
5504 py_funcname = PyString_FromString(funcname);
5505 #else
5506 py_funcname = PyUnicode_FromString(funcname);
5507 #endif
5509 if (!py_funcname) goto bad;
5510 py_globals = PyModule_GetDict(%(GLOBALS)s);
5511 if (!py_globals) goto bad;
5512 py_code = PyCode_New(
5513 0, /*int argcount,*/
5514 #if PY_MAJOR_VERSION >= 3
5515 0, /*int kwonlyargcount,*/
5516 #endif
5517 0, /*int nlocals,*/
5518 0, /*int stacksize,*/
5519 0, /*int flags,*/
5520 %(EMPTY_BYTES)s, /*PyObject *code,*/
5521 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5522 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5523 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5524 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5525 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5526 py_srcfile, /*PyObject *filename,*/
5527 py_funcname, /*PyObject *name,*/
5528 %(LINENO)s, /*int firstlineno,*/
5529 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5530 );
5531 if (!py_code) goto bad;
5532 py_frame = PyFrame_New(
5533 PyThreadState_GET(), /*PyThreadState *tstate,*/
5534 py_code, /*PyCodeObject *code,*/
5535 py_globals, /*PyObject *globals,*/
5536 0 /*PyObject *locals*/
5537 );
5538 if (!py_frame) goto bad;
5539 py_frame->f_lineno = %(LINENO)s;
5540 PyTraceBack_Here(py_frame);
5541 bad:
5542 Py_XDECREF(py_srcfile);
5543 Py_XDECREF(py_funcname);
5544 Py_XDECREF(py_code);
5545 Py_XDECREF(py_frame);
5547 """ % {
5548 'FILENAME': Naming.filename_cname,
5549 'LINENO': Naming.lineno_cname,
5550 'CFILENAME': Naming.cfilenm_cname,
5551 'CLINENO': Naming.clineno_cname,
5552 'GLOBALS': Naming.module_cname,
5553 'EMPTY_TUPLE' : Naming.empty_tuple,
5554 'EMPTY_BYTES' : Naming.empty_bytes,
5555 })
5557 #------------------------------------------------------------------------------------
5559 unraisable_exception_utility_code = UtilityCode(
5560 proto = """
5561 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5562 """,
5563 impl = """
5564 static void __Pyx_WriteUnraisable(const char *name) {
5565 PyObject *old_exc, *old_val, *old_tb;
5566 PyObject *ctx;
5567 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5568 #if PY_MAJOR_VERSION < 3
5569 ctx = PyString_FromString(name);
5570 #else
5571 ctx = PyUnicode_FromString(name);
5572 #endif
5573 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5574 if (!ctx) {
5575 PyErr_WriteUnraisable(Py_None);
5576 } else {
5577 PyErr_WriteUnraisable(ctx);
5578 Py_DECREF(ctx);
5581 """,
5582 requires=[restore_exception_utility_code])
5584 #------------------------------------------------------------------------------------
5586 set_vtable_utility_code = UtilityCode(
5587 proto = """
5588 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5589 """,
5590 impl = """
5591 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5592 #if PY_VERSION_HEX < 0x03010000
5593 PyObject *ob = PyCObject_FromVoidPtr(vtable, 0);
5594 #else
5595 PyObject *ob = PyCapsule_New(vtable, 0, 0);
5596 #endif
5597 if (!ob)
5598 goto bad;
5599 if (PyDict_SetItemString(dict, "__pyx_vtable__", ob) < 0)
5600 goto bad;
5601 Py_DECREF(ob);
5602 return 0;
5603 bad:
5604 Py_XDECREF(ob);
5605 return -1;
5607 """)
5609 #------------------------------------------------------------------------------------
5611 get_vtable_utility_code = UtilityCode(
5612 proto = """
5613 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5614 """,
5615 impl = r"""
5616 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5617 PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5618 if (!ob)
5619 goto bad;
5620 #if PY_VERSION_HEX < 0x03010000
5621 *(void **)vtabptr = PyCObject_AsVoidPtr(ob);
5622 #else
5623 *(void **)vtabptr = PyCapsule_GetPointer(ob, 0);
5624 #endif
5625 if (!*(void **)vtabptr)
5626 goto bad;
5627 Py_DECREF(ob);
5628 return 0;
5629 bad:
5630 Py_XDECREF(ob);
5631 return -1;
5633 """)
5635 #------------------------------------------------------------------------------------
5637 init_string_tab_utility_code = UtilityCode(
5638 proto = """
5639 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5640 """,
5641 impl = """
5642 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5643 while (t->p) {
5644 #if PY_MAJOR_VERSION < 3
5645 if (t->is_unicode) {
5646 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5647 } else if (t->intern) {
5648 *t->p = PyString_InternFromString(t->s);
5649 } else {
5650 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5652 #else /* Python 3+ has unicode identifiers */
5653 if (t->is_unicode | t->is_str) {
5654 if (t->intern) {
5655 *t->p = PyUnicode_InternFromString(t->s);
5656 } else if (t->encoding) {
5657 *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
5658 } else {
5659 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5661 } else {
5662 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5664 #endif
5665 if (!*t->p)
5666 return -1;
5667 ++t;
5669 return 0;
5671 """)
5673 #------------------------------------------------------------------------------------
5675 force_init_threads_utility_code = UtilityCode(
5676 proto="""
5677 #ifndef __PYX_FORCE_INIT_THREADS
5678 #if PY_VERSION_HEX < 0x02040200
5679 #define __PYX_FORCE_INIT_THREADS 1
5680 #else
5681 #define __PYX_FORCE_INIT_THREADS 0
5682 #endif
5683 #endif
5684 """)
5686 #------------------------------------------------------------------------------------
5688 # Note that cPython ignores PyTrace_EXCEPTION,
5689 # but maybe some other profilers don't.
5691 profile_utility_code = UtilityCode(proto="""
5692 #ifndef CYTHON_PROFILE
5693 #define CYTHON_PROFILE 1
5694 #endif
5696 #ifndef CYTHON_PROFILE_REUSE_FRAME
5697 #define CYTHON_PROFILE_REUSE_FRAME 0
5698 #endif
5700 #if CYTHON_PROFILE
5702 #include "compile.h"
5703 #include "frameobject.h"
5704 #include "traceback.h"
5706 #if CYTHON_PROFILE_REUSE_FRAME
5707 #define CYTHON_FRAME_MODIFIER static
5708 #define CYTHON_FRAME_DEL
5709 #else
5710 #define CYTHON_FRAME_MODIFIER
5711 #define CYTHON_FRAME_DEL Py_DECREF(%(FRAME)s)
5712 #endif
5714 #define __Pyx_TraceCall(funcname, srcfile, firstlineno) \\
5715 static PyCodeObject *%(FRAME_CODE)s = NULL; \\
5716 CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL; \\
5717 int __Pyx_use_tracing = 0; \\
5718 if (unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc)) { \\
5719 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&%(FRAME_CODE)s, &%(FRAME)s, funcname, srcfile, firstlineno); \\
5722 #define __Pyx_TraceException() \\
5723 if (unlikely(__Pyx_use_tracing( && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5724 PyObject *exc_info = __Pyx_GetExceptionTuple(); \\
5725 if (exc_info) { \\
5726 PyThreadState_GET()->c_profilefunc( \\
5727 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_EXCEPTION, exc_info); \\
5728 Py_DECREF(exc_info); \\
5729 } \\
5732 #define __Pyx_TraceReturn(result) \\
5733 if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5734 PyThreadState_GET()->c_profilefunc( \\
5735 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_RETURN, (PyObject*)result); \\
5736 CYTHON_FRAME_DEL; \\
5739 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
5740 static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
5742 #else
5743 #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
5744 #define __Pyx_TraceException()
5745 #define __Pyx_TraceReturn(result)
5746 #endif /* CYTHON_PROFILE */
5747 """
5748 % {
5749 "FRAME": Naming.frame_cname,
5750 "FRAME_CODE": Naming.frame_code_cname,
5751 },
5752 impl = """
5754 #if CYTHON_PROFILE
5756 static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
5757 PyFrameObject** frame,
5758 const char *funcname,
5759 const char *srcfile,
5760 int firstlineno) {
5761 if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) {
5762 if (*code == NULL) {
5763 *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
5764 if (*code == NULL) return 0;
5766 *frame = PyFrame_New(
5767 PyThreadState_GET(), /*PyThreadState *tstate*/
5768 *code, /*PyCodeObject *code*/
5769 PyModule_GetDict(%(MODULE)s), /*PyObject *globals*/
5770 0 /*PyObject *locals*/
5771 );
5772 if (*frame == NULL) return 0;
5774 else {
5775 (*frame)->f_tstate = PyThreadState_GET();
5777 return PyThreadState_GET()->c_profilefunc(PyThreadState_GET()->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
5780 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
5781 PyObject *py_srcfile = 0;
5782 PyObject *py_funcname = 0;
5783 PyCodeObject *py_code = 0;
5785 #if PY_MAJOR_VERSION < 3
5786 py_funcname = PyString_FromString(funcname);
5787 py_srcfile = PyString_FromString(srcfile);
5788 #else
5789 py_funcname = PyUnicode_FromString(funcname);
5790 py_srcfile = PyUnicode_FromString(srcfile);
5791 #endif
5792 if (!py_funcname | !py_srcfile) goto bad;
5794 py_code = PyCode_New(
5795 0, /*int argcount,*/
5796 #if PY_MAJOR_VERSION >= 3
5797 0, /*int kwonlyargcount,*/
5798 #endif
5799 0, /*int nlocals,*/
5800 0, /*int stacksize,*/
5801 0, /*int flags,*/
5802 %(EMPTY_BYTES)s, /*PyObject *code,*/
5803 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5804 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5805 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5806 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5807 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5808 py_srcfile, /*PyObject *filename,*/
5809 py_funcname, /*PyObject *name,*/
5810 firstlineno, /*int firstlineno,*/
5811 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5812 );
5814 bad:
5815 Py_XDECREF(py_srcfile);
5816 Py_XDECREF(py_funcname);
5818 return py_code;
5821 #endif /* CYTHON_PROFILE */
5822 """ % {
5823 'EMPTY_TUPLE' : Naming.empty_tuple,
5824 'EMPTY_BYTES' : Naming.empty_bytes,
5825 "MODULE": Naming.module_cname,
5826 })