Cython has moved to github.

cython

view Cython/Compiler/Nodes.py @ 1383:92baafe0edf3

Fix gcc crash on recursive typedef struct
Won't break existing code, only makes bad code compile now.
author Robert Bradshaw <robertwb@math.washington.edu>
date Tue Nov 25 14:04:41 2008 -0800 (3 years ago)
parents 04e83ffd8ea2
children 9953e9438922 afb41228c587
line source
1 #
2 # Pyrex - Parse tree nodes
3 #
5 import string, sys, os, time, copy
7 import Code
8 from Errors import error, warning, InternalError
9 import Naming
10 import PyrexTypes
11 import TypeSlots
12 from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType
13 from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
14 StructOrUnionScope, PyClassScope, CClassScope
15 from Cython.Utils import open_new_file, replace_suffix, UtilityCode
16 from StringEncoding import EncodedString, escape_byte_string, split_docstring
17 import Options
18 import ControlFlow
20 from DebugFlags import debug_disposal_code
22 absolute_path_length = 0
24 def relative_position(pos):
25 """
26 We embed the relative filename in the generated C file, since we
27 don't want to have to regnerate and compile all the source code
28 whenever the Python install directory moves (which could happen,
29 e.g,. when distributing binaries.)
31 INPUT:
32 a position tuple -- (absolute filename, line number column position)
34 OUTPUT:
35 relative filename
36 line number
38 AUTHOR: William Stein
39 """
40 global absolute_path_length
41 if absolute_path_length==0:
42 absolute_path_length = len(os.path.abspath(os.getcwd()))
43 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
45 def embed_position(pos, docstring):
46 if not Options.embed_pos_in_docstring:
47 return docstring
48 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
49 if docstring is None:
50 # unicode string
51 return EncodedString(pos_line)
53 # make sure we can encode the filename in the docstring encoding
54 # otherwise make the docstring a unicode string
55 encoding = docstring.encoding
56 if encoding is not None:
57 try:
58 encoded_bytes = pos_line.encode(encoding)
59 except UnicodeEncodeError:
60 encoding = None
62 if not docstring:
63 # reuse the string encoding of the original docstring
64 doc = EncodedString(pos_line)
65 else:
66 doc = EncodedString(pos_line + u'\n' + docstring)
67 doc.encoding = encoding
68 return doc
70 class Node(object):
71 # pos (string, int, int) Source file position
72 # is_name boolean Is a NameNode
73 # is_literal boolean Is a ConstNode
75 is_name = 0
76 is_literal = 0
77 temps = None
79 # All descandants should set child_attrs to a list of the attributes
80 # containing nodes considered "children" in the tree. Each such attribute
81 # can either contain a single node or a list of nodes. See Visitor.py.
82 child_attrs = None
84 def __init__(self, pos, **kw):
85 self.pos = pos
86 self.__dict__.update(kw)
88 gil_message = "Operation"
90 def gil_check(self, env):
91 if env.nogil:
92 self.gil_error()
94 def gil_error(self):
95 error(self.pos, "%s not allowed without gil" % self.gil_message)
97 def clone_node(self):
98 """Clone the node. This is defined as a shallow copy, except for member lists
99 amongst the child attributes (from get_child_accessors) which are also
100 copied. Lists containing child nodes are thus seen as a way for the node
101 to hold multiple children directly; the list is not treated as a seperate
102 level in the tree."""
103 result = copy.copy(self)
104 for attrname in result.child_attrs:
105 value = getattr(result, attrname)
106 if isinstance(value, list):
107 setattr(result, attrname, [x for x in value])
108 return result
111 #
112 # There are 4 phases of parse tree processing, applied in order to
113 # all the statements in a given scope-block:
114 #
115 # (0) analyse_control_flow
116 # Create the control flow tree into which state can be asserted and
117 # queried.
118 #
119 # (1) analyse_declarations
120 # Make symbol table entries for all declarations at the current
121 # level, both explicit (def, cdef, etc.) and implicit (assignment
122 # to an otherwise undeclared name).
123 #
124 # (2) analyse_expressions
125 # Determine the result types of expressions and fill in the
126 # 'type' attribute of each ExprNode. Insert coercion nodes into the
127 # tree where needed to convert to and from Python objects.
128 # Allocate temporary locals for intermediate results. Fill
129 # in the 'result_code' attribute of each ExprNode with a C code
130 # fragment.
131 #
132 # (3) generate_code
133 # Emit C code for all declarations, statements and expressions.
134 # Recursively applies the 3 processing phases to the bodies of
135 # functions.
136 #
138 def analyse_control_flow(self, env):
139 pass
141 def analyse_declarations(self, env):
142 pass
144 def analyse_expressions(self, env):
145 raise InternalError("analyse_expressions not implemented for %s" % \
146 self.__class__.__name__)
148 def generate_code(self, code):
149 raise InternalError("generate_code not implemented for %s" % \
150 self.__class__.__name__)
152 def annotate(self, code):
153 # mro does the wrong thing
154 if isinstance(self, BlockNode):
155 self.body.annotate(code)
157 def end_pos(self):
158 if not self.child_attrs:
159 return self.pos
160 try:
161 return self._end_pos
162 except AttributeError:
163 pos = self.pos
164 for attr in self.child_attrs:
165 child = getattr(self, attr)
166 # Sometimes lists, sometimes nodes
167 if child is None:
168 pass
169 elif isinstance(child, list):
170 for c in child:
171 pos = max(pos, c.end_pos())
172 else:
173 pos = max(pos, child.end_pos())
174 self._end_pos = pos
175 return pos
177 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
178 if cutoff == 0:
179 return "<...nesting level cutoff...>"
180 if encountered is None:
181 encountered = set()
182 if id(self) in encountered:
183 return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
184 encountered.add(id(self))
186 def dump_child(x, level):
187 if isinstance(x, Node):
188 return x.dump(level, filter_out, cutoff-1, encountered)
189 elif isinstance(x, list):
190 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
191 else:
192 return repr(x)
195 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
196 if len(attrs) == 0:
197 return "<%s (%d)>" % (self.__class__.__name__, id(self))
198 else:
199 indent = " " * level
200 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
201 for key, value in attrs:
202 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
203 res += "%s>" % indent
204 return res
206 class CompilerDirectivesNode(Node):
207 """
208 Sets compiler directives for the children nodes
209 """
210 # directives {string:value} A dictionary holding the right value for
211 # *all* possible directives.
212 # body Node
213 child_attrs = ["body"]
215 def analyse_control_flow(self, env):
216 old = env.directives
217 env.directives = self.directives
218 self.body.analyse_control_flow(env)
219 env.directives = old
221 def analyse_declarations(self, env):
222 old = env.directives
223 env.directives = self.directives
224 self.body.analyse_declarations(env)
225 env.directives = old
227 def analyse_expressions(self, env):
228 old = env.directives
229 env.directives = self.directives
230 self.body.analyse_expressions(env)
231 env.directives = old
233 def generate_function_definitions(self, env, code):
234 env_old = env.directives
235 code_old = code.globalstate.directives
236 code.globalstate.directives = self.directives
237 self.body.generate_function_definitions(env, code)
238 env.directives = env_old
239 code.globalstate.directives = code_old
241 def generate_execution_code(self, code):
242 old = code.globalstate.directives
243 code.globalstate.directives = self.directives
244 self.body.generate_execution_code(code)
245 code.globalstate.directives = old
247 def annotate(self, code):
248 old = code.globalstate.directives
249 code.globalstate.directives = self.directives
250 self.body.annotate(code)
251 code.globalstate.directives = old
253 class BlockNode:
254 # Mixin class for nodes representing a declaration block.
256 def generate_const_definitions(self, env, code):
257 if env.const_entries:
258 for entry in env.const_entries:
259 if not entry.is_interned:
260 code.globalstate.add_const_definition(entry)
262 def generate_interned_string_decls(self, env, code):
263 entries = env.global_scope().new_interned_string_entries
264 if entries:
265 for entry in entries:
266 code.globalstate.add_interned_string_decl(entry)
267 del entries[:]
269 def generate_py_string_decls(self, env, code):
270 if env is None:
271 return # earlier error
272 entries = env.pystring_entries
273 if entries:
274 for entry in entries:
275 if not entry.is_interned:
276 code.globalstate.add_py_string_decl(entry)
278 def generate_interned_num_decls(self, env, code):
279 # Flush accumulated interned nums from the global scope
280 # and generate declarations for them.
281 genv = env.global_scope()
282 entries = genv.interned_nums
283 if entries:
284 for entry in entries:
285 code.globalstate.add_interned_num_decl(entry)
286 del entries[:]
288 def generate_cached_builtins_decls(self, env, code):
289 entries = env.global_scope().undeclared_cached_builtins
290 for entry in entries:
291 code.globalstate.add_cached_builtin_decl(entry)
292 del entries[:]
295 class StatListNode(Node):
296 # stats a list of StatNode
298 child_attrs = ["stats"]
300 def create_analysed(pos, env, *args, **kw):
301 node = StatListNode(pos, *args, **kw)
302 return node # No node-specific analysis necesarry
303 create_analysed = staticmethod(create_analysed)
305 def analyse_control_flow(self, env):
306 for stat in self.stats:
307 stat.analyse_control_flow(env)
309 def analyse_declarations(self, env):
310 #print "StatListNode.analyse_declarations" ###
311 for stat in self.stats:
312 stat.analyse_declarations(env)
314 def analyse_expressions(self, env):
315 #print "StatListNode.analyse_expressions" ###
316 for stat in self.stats:
317 stat.analyse_expressions(env)
319 def generate_function_definitions(self, env, code):
320 #print "StatListNode.generate_function_definitions" ###
321 for stat in self.stats:
322 stat.generate_function_definitions(env, code)
324 def generate_execution_code(self, code):
325 #print "StatListNode.generate_execution_code" ###
326 for stat in self.stats:
327 code.mark_pos(stat.pos)
328 stat.generate_execution_code(code)
330 def annotate(self, code):
331 for stat in self.stats:
332 stat.annotate(code)
335 class StatNode(Node):
336 #
337 # Code generation for statements is split into the following subphases:
338 #
339 # (1) generate_function_definitions
340 # Emit C code for the definitions of any structs,
341 # unions, enums and functions defined in the current
342 # scope-block.
343 #
344 # (2) generate_execution_code
345 # Emit C code for executable statements.
346 #
348 def generate_function_definitions(self, env, code):
349 pass
351 def generate_execution_code(self, code):
352 raise InternalError("generate_execution_code not implemented for %s" % \
353 self.__class__.__name__)
356 class CDefExternNode(StatNode):
357 # include_file string or None
358 # body StatNode
360 child_attrs = ["body"]
362 def analyse_declarations(self, env):
363 if self.include_file:
364 env.add_include_file(self.include_file)
365 old_cinclude_flag = env.in_cinclude
366 env.in_cinclude = 1
367 self.body.analyse_declarations(env)
368 env.in_cinclude = old_cinclude_flag
370 def analyse_expressions(self, env):
371 pass
373 def generate_execution_code(self, code):
374 pass
376 def annotate(self, code):
377 self.body.annotate(code)
380 class CDeclaratorNode(Node):
381 # Part of a C declaration.
382 #
383 # Processing during analyse_declarations phase:
384 #
385 # analyse
386 # Returns (name, type) pair where name is the
387 # CNameDeclaratorNode of the name being declared
388 # and type is the type it is being declared as.
389 #
390 # calling_convention string Calling convention of CFuncDeclaratorNode
391 # for which this is a base
393 child_attrs = []
395 calling_convention = ""
398 class CNameDeclaratorNode(CDeclaratorNode):
399 # name string The Pyrex name being declared
400 # cname string or None C name, if specified
401 # default ExprNode or None the value assigned on declaration
403 child_attrs = ['default']
405 default = None
407 def analyse(self, base_type, env, nonempty = 0):
408 if nonempty and self.name == '':
409 # May have mistaken the name for the type.
410 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
411 error(self.pos, "Missing argument name")
412 elif base_type.is_void:
413 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
414 else:
415 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
416 base_type = py_object_type
417 self.type = base_type
418 return self, base_type
420 class CPtrDeclaratorNode(CDeclaratorNode):
421 # base CDeclaratorNode
423 child_attrs = ["base"]
425 def analyse(self, base_type, env, nonempty = 0):
426 if base_type.is_pyobject:
427 error(self.pos,
428 "Pointer base type cannot be a Python object")
429 ptr_type = PyrexTypes.c_ptr_type(base_type)
430 return self.base.analyse(ptr_type, env, nonempty = nonempty)
432 class CArrayDeclaratorNode(CDeclaratorNode):
433 # base CDeclaratorNode
434 # dimension ExprNode
436 child_attrs = ["base", "dimension"]
438 def analyse(self, base_type, env, nonempty = 0):
439 if self.dimension:
440 self.dimension.analyse_const_expression(env)
441 if not self.dimension.type.is_int:
442 error(self.dimension.pos, "Array dimension not integer")
443 size = self.dimension.result()
444 else:
445 size = None
446 if not base_type.is_complete():
447 error(self.pos,
448 "Array element type '%s' is incomplete" % base_type)
449 if base_type.is_pyobject:
450 error(self.pos,
451 "Array element cannot be a Python object")
452 if base_type.is_cfunction:
453 error(self.pos,
454 "Array element cannot be a function")
455 array_type = PyrexTypes.c_array_type(base_type, size)
456 return self.base.analyse(array_type, env, nonempty = nonempty)
459 class CFuncDeclaratorNode(CDeclaratorNode):
460 # base CDeclaratorNode
461 # args [CArgDeclNode]
462 # has_varargs boolean
463 # exception_value ConstNode
464 # exception_check boolean True if PyErr_Occurred check needed
465 # nogil boolean Can be called without gil
466 # with_gil boolean Acquire gil around function body
468 child_attrs = ["base", "args", "exception_value"]
470 overridable = 0
471 optional_arg_count = 0
473 def analyse(self, return_type, env, nonempty = 0):
474 if nonempty:
475 nonempty -= 1
476 func_type_args = []
477 for arg_node in self.args:
478 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
479 name = name_declarator.name
480 if name_declarator.cname:
481 error(self.pos,
482 "Function argument cannot have C name specification")
483 # Turn *[] argument into **
484 if type.is_array:
485 type = PyrexTypes.c_ptr_type(type.base_type)
486 # Catch attempted C-style func(void) decl
487 if type.is_void:
488 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
489 # if type.is_pyobject and self.nogil:
490 # error(self.pos,
491 # "Function with Python argument cannot be declared nogil")
492 func_type_args.append(
493 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
494 if arg_node.default:
495 self.optional_arg_count += 1
496 elif self.optional_arg_count:
497 error(self.pos, "Non-default argument follows default argument")
499 if self.optional_arg_count:
500 scope = StructOrUnionScope()
501 scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
502 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
503 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
504 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
505 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
506 kind = 'struct',
507 scope = scope,
508 typedef_flag = 0,
509 pos = self.pos,
510 cname = struct_cname)
511 self.op_args_struct.defined_in_pxd = 1
512 self.op_args_struct.used = 1
514 exc_val = None
515 exc_check = 0
516 if return_type.is_pyobject \
517 and (self.exception_value or self.exception_check) \
518 and self.exception_check != '+':
519 error(self.pos,
520 "Exception clause not allowed for function returning Python object")
521 else:
522 if self.exception_value:
523 self.exception_value.analyse_const_expression(env)
524 if self.exception_check == '+':
525 exc_val_type = self.exception_value.type
526 if not exc_val_type.is_error and \
527 not exc_val_type.is_pyobject and \
528 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
529 error(self.exception_value.pos,
530 "Exception value must be a Python exception or cdef function with no arguments.")
531 exc_val = self.exception_value
532 else:
533 exc_val = self.exception_value.result()
534 if not return_type.assignable_from(self.exception_value.type):
535 error(self.exception_value.pos,
536 "Exception value incompatible with function return type")
537 exc_check = self.exception_check
538 if return_type.is_array:
539 error(self.pos,
540 "Function cannot return an array")
541 if return_type.is_cfunction:
542 error(self.pos,
543 "Function cannot return a function")
544 func_type = PyrexTypes.CFuncType(
545 return_type, func_type_args, self.has_varargs,
546 optional_arg_count = self.optional_arg_count,
547 exception_value = exc_val, exception_check = exc_check,
548 calling_convention = self.base.calling_convention,
549 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
550 if self.optional_arg_count:
551 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
552 return self.base.analyse(func_type, env)
555 class CArgDeclNode(Node):
556 # Item in a function declaration argument list.
557 #
558 # base_type CBaseTypeNode
559 # declarator CDeclaratorNode
560 # not_none boolean Tagged with 'not None'
561 # default ExprNode or None
562 # default_entry Symtab.Entry Entry for the variable holding the default value
563 # default_result_code string cname or code fragment for default value
564 # is_self_arg boolean Is the "self" arg of an extension type method
565 # is_kw_only boolean Is a keyword-only argument
567 child_attrs = ["base_type", "declarator", "default"]
569 is_self_arg = 0
570 is_generic = 1
571 type = None
572 name_declarator = None
574 def analyse(self, env, nonempty = 0):
575 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
576 if self.type is None:
577 # The parser may missinterpret names as types...
578 # We fix that here.
579 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
580 if nonempty:
581 self.declarator.name = self.base_type.name
582 self.base_type.name = None
583 self.base_type.is_basic_c_type = False
584 could_be_name = True
585 else:
586 could_be_name = False
587 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
588 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
589 self.declarator.name = self.base_type.arg_name
590 return self.declarator.analyse(base_type, env, nonempty = nonempty)
591 else:
592 return self.name_declarator, self.type
594 def annotate(self, code):
595 if self.default:
596 self.default.annotate(code)
599 class CBaseTypeNode(Node):
600 # Abstract base class for C base type nodes.
601 #
602 # Processing during analyse_declarations phase:
603 #
604 # analyse
605 # Returns the type.
607 pass
609 class CAnalysedBaseTypeNode(Node):
610 # type type
612 child_attrs = []
614 def analyse(self, env, could_be_name = False):
615 return self.type
617 class CSimpleBaseTypeNode(CBaseTypeNode):
618 # name string
619 # module_path [string] Qualifying name components
620 # is_basic_c_type boolean
621 # signed boolean
622 # longness integer
623 # is_self_arg boolean Is self argument of C method
625 child_attrs = []
626 arg_name = None # in case the argument name was interpreted as a type
628 def analyse(self, env, could_be_name = False):
629 # Return type descriptor.
630 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
631 type = None
632 if self.is_basic_c_type:
633 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
634 if not type:
635 error(self.pos, "Unrecognised type modifier combination")
636 elif self.name == "object" and not self.module_path:
637 type = py_object_type
638 elif self.name is None:
639 if self.is_self_arg and env.is_c_class_scope:
640 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
641 type = env.parent_type
642 else:
643 type = py_object_type
644 else:
645 if self.module_path:
646 scope = env.find_imported_module(self.module_path, self.pos)
647 else:
648 scope = env
649 if scope:
650 if scope.is_c_class_scope:
651 scope = scope.global_scope()
652 entry = scope.lookup(self.name)
653 if entry and entry.is_type:
654 type = entry.type
655 elif could_be_name:
656 if self.is_self_arg and env.is_c_class_scope:
657 type = env.parent_type
658 else:
659 type = py_object_type
660 self.arg_name = self.name
661 else:
662 error(self.pos, "'%s' is not a type identifier" % self.name)
663 if type:
664 return type
665 else:
666 return PyrexTypes.error_type
668 class CBufferAccessTypeNode(CBaseTypeNode):
669 # After parsing:
670 # positional_args [ExprNode] List of positional arguments
671 # keyword_args DictNode Keyword arguments
672 # base_type_node CBaseTypeNode
674 # After analysis:
675 # type PyrexType.BufferType ...containing the right options
678 child_attrs = ["base_type_node", "positional_args",
679 "keyword_args", "dtype_node"]
681 dtype_node = None
683 def analyse(self, env, could_be_name = False):
684 base_type = self.base_type_node.analyse(env)
685 if base_type.is_error: return base_type
686 import Buffer
688 options = Buffer.analyse_buffer_options(
689 self.pos,
690 env,
691 self.positional_args,
692 self.keyword_args,
693 base_type.buffer_defaults)
695 self.type = PyrexTypes.BufferType(base_type, **options)
696 return self.type
698 class CComplexBaseTypeNode(CBaseTypeNode):
699 # base_type CBaseTypeNode
700 # declarator CDeclaratorNode
702 child_attrs = ["base_type", "declarator"]
704 def analyse(self, env, could_be_name = False):
705 base = self.base_type.analyse(env, could_be_name)
706 _, type = self.declarator.analyse(base, env)
707 return type
710 class CVarDefNode(StatNode):
711 # C variable definition or forward/extern function declaration.
712 #
713 # visibility 'private' or 'public' or 'extern'
714 # base_type CBaseTypeNode
715 # declarators [CDeclaratorNode]
716 # in_pxd boolean
717 # api boolean
718 # need_properties [entry]
720 child_attrs = ["base_type", "declarators"]
721 need_properties = ()
723 def analyse_declarations(self, env, dest_scope = None):
724 if not dest_scope:
725 dest_scope = env
726 self.dest_scope = dest_scope
727 base_type = self.base_type.analyse(env)
728 if (dest_scope.is_c_class_scope
729 and self.visibility == 'public'
730 and base_type.is_pyobject
731 and (base_type.is_builtin_type or base_type.is_extension_type)):
732 self.need_properties = []
733 need_property = True
734 visibility = 'private'
735 else:
736 need_property = False
737 visibility = self.visibility
739 for declarator in self.declarators:
740 name_declarator, type = declarator.analyse(base_type, env)
741 if not type.is_complete():
742 if not (self.visibility == 'extern' and type.is_array):
743 error(declarator.pos,
744 "Variable type '%s' is incomplete" % type)
745 if self.visibility == 'extern' and type.is_pyobject:
746 error(declarator.pos,
747 "Python object cannot be declared extern")
748 name = name_declarator.name
749 cname = name_declarator.cname
750 if name == '':
751 error(declarator.pos, "Missing name in declaration.")
752 return
753 if type.is_cfunction:
754 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
755 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
756 api = self.api)
757 else:
758 if self.in_pxd and self.visibility != 'extern':
759 error(self.pos,
760 "Only 'extern' C variable declaration allowed in .pxd file")
761 entry = dest_scope.declare_var(name, type, declarator.pos,
762 cname = cname, visibility = visibility, is_cdef = 1)
763 if need_property:
764 self.need_properties.append(entry)
765 entry.needs_property = 1
768 class CStructOrUnionDefNode(StatNode):
769 # name string
770 # cname string or None
771 # kind "struct" or "union"
772 # typedef_flag boolean
773 # visibility "public" or "private"
774 # in_pxd boolean
775 # attributes [CVarDefNode] or None
776 # entry Entry
778 child_attrs = ["attributes"]
780 def analyse_declarations(self, env):
781 scope = None
782 if self.attributes is not None:
783 scope = StructOrUnionScope(self.name)
784 self.entry = env.declare_struct_or_union(
785 self.name, self.kind, scope, self.typedef_flag, self.pos,
786 self.cname, visibility = self.visibility)
787 need_typedef_indirection = False
788 if self.attributes is not None:
789 if self.in_pxd and not env.in_cinclude:
790 self.entry.defined_in_pxd = 1
791 for attr in self.attributes:
792 attr.analyse_declarations(env, scope)
793 for attr in scope.var_entries:
794 type = attr.type
795 while type.is_array:
796 type = type.base_type
797 if type == self.entry.type:
798 error(attr.pos, "Struct cannot contain itself as a member.")
799 if self.typedef_flag:
800 while type.is_ptr:
801 type = type.base_type
802 if type == self.entry.type:
803 need_typedef_indirection = True
804 if need_typedef_indirection and self.visibility != 'extern':
805 # C can't handle typedef structs that refer to themselves.
806 struct_entry = self.entry
807 cname = env.new_const_cname()
808 self.entry = env.declare_typedef(self.name, struct_entry.type, self.pos, cname = self.cname, visibility='ignore')
809 struct_entry.type.typedef_flag = False
810 struct_entry.cname = struct_entry.type.cname = env.new_const_cname()
812 def analyse_expressions(self, env):
813 pass
815 def generate_execution_code(self, code):
816 pass
819 class CEnumDefNode(StatNode):
820 # name string or None
821 # cname string or None
822 # items [CEnumDefItemNode]
823 # typedef_flag boolean
824 # visibility "public" or "private"
825 # in_pxd boolean
826 # entry Entry
828 child_attrs = ["items"]
830 def analyse_declarations(self, env):
831 self.entry = env.declare_enum(self.name, self.pos,
832 cname = self.cname, typedef_flag = self.typedef_flag,
833 visibility = self.visibility)
834 if self.items is not None:
835 if self.in_pxd and not env.in_cinclude:
836 self.entry.defined_in_pxd = 1
837 for item in self.items:
838 item.analyse_declarations(env, self.entry)
840 def analyse_expressions(self, env):
841 if self.visibility == 'public':
842 self.temp = env.allocate_temp_pyobject()
843 env.release_temp(self.temp)
845 def generate_execution_code(self, code):
846 if self.visibility == 'public':
847 for item in self.entry.enum_values:
848 code.putln("%s = PyInt_FromLong(%s); %s" % (
849 self.temp,
850 item.cname,
851 code.error_goto_if_null(self.temp, item.pos)))
852 code.putln('if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
853 Naming.module_cname,
854 item.name,
855 self.temp,
856 code.error_goto(item.pos)))
857 code.putln("%s = 0;" % self.temp)
860 class CEnumDefItemNode(StatNode):
861 # name string
862 # cname string or None
863 # value ExprNode or None
865 child_attrs = ["value"]
867 def analyse_declarations(self, env, enum_entry):
868 if self.value:
869 self.value.analyse_const_expression(env)
870 if not self.value.type.is_int:
871 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
872 self.value.analyse_const_expression(env)
873 value = self.value.result()
874 else:
875 value = self.name
876 entry = env.declare_const(self.name, enum_entry.type,
877 value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
878 enum_entry.enum_values.append(entry)
881 class CTypeDefNode(StatNode):
882 # base_type CBaseTypeNode
883 # declarator CDeclaratorNode
884 # visibility "public" or "private"
885 # in_pxd boolean
887 child_attrs = ["base_type", "declarator"]
889 def analyse_declarations(self, env):
890 base = self.base_type.analyse(env)
891 name_declarator, type = self.declarator.analyse(base, env)
892 name = name_declarator.name
893 cname = name_declarator.cname
894 entry = env.declare_typedef(name, type, self.pos,
895 cname = cname, visibility = self.visibility)
896 if self.in_pxd and not env.in_cinclude:
897 entry.defined_in_pxd = 1
899 def analyse_expressions(self, env):
900 pass
901 def generate_execution_code(self, code):
902 pass
905 class FuncDefNode(StatNode, BlockNode):
906 # Base class for function definition nodes.
907 #
908 # return_type PyrexType
909 # #filename string C name of filename string const
910 # entry Symtab.Entry
911 # needs_closure boolean Whether or not this function has inner functions/classes/yield
913 py_func = None
914 assmt = None
915 needs_closure = False
917 def analyse_default_values(self, env):
918 genv = env.global_scope()
919 for arg in self.args:
920 if arg.default:
921 if arg.is_generic:
922 if not hasattr(arg, 'default_entry'):
923 arg.default.analyse_types(env)
924 arg.default = arg.default.coerce_to(arg.type, genv)
925 if arg.default.is_literal:
926 arg.default_entry = arg.default
927 arg.default_result_code = arg.default.calculate_result_code()
928 if arg.default.type != arg.type and not arg.type.is_int:
929 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
930 else:
931 arg.default.allocate_temps(genv)
932 arg.default_entry = genv.add_default_value(arg.type)
933 arg.default_entry.used = 1
934 arg.default_result_code = arg.default_entry.cname
935 else:
936 error(arg.pos,
937 "This argument cannot have a default value")
938 arg.default = None
940 def need_gil_acquisition(self, lenv):
941 return 0
943 def create_local_scope(self, env):
944 genv = env
945 while env.is_py_class_scope or env.is_c_class_scope:
946 env = env.outer_scope
947 if self.needs_closure:
948 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
949 else:
950 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
951 lenv.return_type = self.return_type
952 type = self.entry.type
953 if type.is_cfunction:
954 lenv.nogil = type.nogil and not type.with_gil
955 self.local_scope = lenv
956 return lenv
958 def generate_function_definitions(self, env, code):
959 import Buffer
961 lenv = self.local_scope
963 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
964 self.entry.scope.is_c_class_scope)
966 # Generate C code for header and body of function
967 code.enter_cfunc_scope()
968 code.return_from_error_cleanup_label = code.new_label()
970 # ----- Top-level constants used by this function
971 code.mark_pos(self.pos)
972 self.generate_interned_num_decls(lenv, code)
973 self.generate_interned_string_decls(lenv, code)
974 self.generate_py_string_decls(lenv, code)
975 self.generate_cached_builtins_decls(lenv, code)
976 #code.putln("")
977 #code.put_var_declarations(lenv.const_entries, static = 1)
978 self.generate_const_definitions(lenv, code)
979 # ----- Function header
980 code.putln("")
981 if self.py_func:
982 self.py_func.generate_function_header(code,
983 with_pymethdef = env.is_py_class_scope,
984 proto_only=True)
985 self.generate_function_header(code,
986 with_pymethdef = env.is_py_class_scope)
987 # ----- Local variable declarations
988 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
989 self.generate_argument_declarations(lenv, code)
990 if self.needs_closure:
991 code.putln("/* TODO: declare and create scope object */")
992 code.put_var_declarations(lenv.var_entries)
993 init = ""
994 if not self.return_type.is_void:
995 code.putln(
996 "%s%s;" %
997 (self.return_type.declaration_code(
998 Naming.retval_cname),
999 init))
1000 tempvardecl_code = code.insertion_point()
1001 self.generate_keyword_list(code)
1002 # ----- Extern library function declarations
1003 lenv.generate_library_function_declarations(code)
1004 # ----- GIL acquisition
1005 acquire_gil = self.need_gil_acquisition(lenv)
1006 if acquire_gil:
1007 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1008 # ----- Automatic lead-ins for certain special functions
1009 if is_getbuffer_slot:
1010 self.getbuffer_init(code)
1011 # ----- Fetch arguments
1012 self.generate_argument_parsing_code(env, code)
1013 # If an argument is assigned to in the body, we must
1014 # incref it to properly keep track of refcounts.
1015 for entry in lenv.arg_entries:
1016 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1017 code.put_var_incref(entry)
1018 # ----- Initialise local variables
1019 for entry in lenv.var_entries:
1020 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1021 code.put_init_var_to_py_none(entry)
1022 # ----- Initialise local buffer auxiliary variables
1023 for entry in lenv.var_entries + lenv.arg_entries:
1024 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1025 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1026 # ----- Check and convert arguments
1027 self.generate_argument_type_tests(code)
1028 # ----- Acquire buffer arguments
1029 for entry in lenv.arg_entries:
1030 if entry.type.is_buffer:
1031 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1032 # ----- Function body
1033 self.body.generate_execution_code(code)
1034 # ----- Default return value
1035 code.putln("")
1036 if self.return_type.is_pyobject:
1037 #if self.return_type.is_extension_type:
1038 # lhs = "(PyObject *)%s" % Naming.retval_cname
1039 #else:
1040 lhs = Naming.retval_cname
1041 code.put_init_to_py_none(lhs, self.return_type)
1042 else:
1043 val = self.return_type.default_value
1044 if val:
1045 code.putln("%s = %s;" % (Naming.retval_cname, val))
1046 # ----- Error cleanup
1047 if code.error_label in code.labels_used:
1048 code.put_goto(code.return_label)
1049 code.put_label(code.error_label)
1050 code.put_var_xdecrefs(lenv.temp_entries)
1052 # Clean up buffers -- this calls a Python function
1053 # so need to save and restore error state
1054 buffers_present = len(lenv.buffer_entries) > 0
1055 if buffers_present:
1056 code.globalstate.use_utility_code(restore_exception_utility_code)
1057 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1058 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1059 for entry in lenv.buffer_entries:
1060 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1061 #code.putln("%s = 0;" % entry.cname)
1062 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1064 err_val = self.error_value()
1065 exc_check = self.caller_will_check_exceptions()
1066 if err_val is not None or exc_check:
1067 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1068 else:
1069 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1070 % self.entry.qualified_name, 0)
1071 code.putln(
1072 '__Pyx_WriteUnraisable("%s");' %
1073 self.entry.qualified_name)
1074 env.use_utility_code(unraisable_exception_utility_code)
1075 env.use_utility_code(restore_exception_utility_code)
1076 default_retval = self.return_type.default_value
1077 if err_val is None and default_retval:
1078 err_val = default_retval
1079 if err_val is not None:
1080 code.putln(
1081 "%s = %s;" % (
1082 Naming.retval_cname,
1083 err_val))
1085 if is_getbuffer_slot:
1086 self.getbuffer_error_cleanup(code)
1088 # If we are using the non-error cleanup section we should
1089 # jump past it if we have an error. The if-test below determine
1090 # whether this section is used.
1091 if buffers_present or is_getbuffer_slot:
1092 code.put_goto(code.return_from_error_cleanup_label)
1095 # ----- Non-error return cleanup
1096 # If you add anything here, remember to add a condition to the
1097 # if-test above in the error block (so that it can jump past this
1098 # block).
1099 code.put_label(code.return_label)
1100 for entry in lenv.buffer_entries:
1101 if entry.used:
1102 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1103 if is_getbuffer_slot:
1104 self.getbuffer_normal_cleanup(code)
1105 # ----- Return cleanup for both error and no-error return
1106 code.put_label(code.return_from_error_cleanup_label)
1107 if not Options.init_local_none:
1108 for entry in lenv.var_entries:
1109 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1110 entry.xdecref_cleanup = 1
1111 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1112 # Decref any increfed args
1113 for entry in lenv.arg_entries:
1114 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1115 code.put_var_decref(entry)
1116 if acquire_gil:
1117 code.putln("PyGILState_Release(_save);")
1118 # code.putln("/* TODO: decref scope object */")
1119 # ----- Return
1120 if not self.return_type.is_void:
1121 code.putln("return %s;" % Naming.retval_cname)
1122 code.putln("}")
1123 # ----- Go back and insert temp variable declarations
1124 tempvardecl_code.put_var_declarations(lenv.temp_entries)
1125 tempvardecl_code.put_temp_declarations(code.funcstate)
1126 # ----- Python version
1127 code.exit_cfunc_scope()
1128 if self.py_func:
1129 self.py_func.generate_function_definitions(env, code)
1130 self.generate_wrapper_functions(code)
1132 def declare_argument(self, env, arg):
1133 if arg.type.is_void:
1134 error(arg.pos, "Invalid use of 'void'")
1135 elif not arg.type.is_complete() and not arg.type.is_array:
1136 error(arg.pos,
1137 "Argument type '%s' is incomplete" % arg.type)
1138 return env.declare_arg(arg.name, arg.type, arg.pos)
1140 def generate_wrapper_functions(self, code):
1141 pass
1143 def generate_execution_code(self, code):
1144 # Evaluate and store argument default values
1145 for arg in self.args:
1146 default = arg.default
1147 if default:
1148 if not default.is_literal:
1149 default.generate_evaluation_code(code)
1150 default.make_owned_reference(code)
1151 code.putln(
1152 "%s = %s;" % (
1153 arg.default_entry.cname,
1154 default.result_as(arg.default_entry.type)))
1155 if default.is_temp and default.type.is_pyobject:
1156 code.putln(
1157 "%s = 0;" %
1158 default.result())
1159 # For Python class methods, create and store function object
1160 if self.assmt:
1161 self.assmt.generate_execution_code(code)
1164 # Special code for the __getbuffer__ function
1166 def getbuffer_init(self, code):
1167 info = self.local_scope.arg_entries[1].cname
1168 # Python 3.0 betas have a bug in memoryview which makes it call
1169 # getbuffer with a NULL parameter. For now we work around this;
1170 # the following line should be removed when this bug is fixed.
1171 code.putln("if (%s == NULL) return 0;" % info)
1172 code.putln("%s->obj = Py_None; Py_INCREF(Py_None);" % info)
1174 def getbuffer_error_cleanup(self, code):
1175 info = self.local_scope.arg_entries[1].cname
1176 code.putln("Py_DECREF(%s->obj); %s->obj = NULL;" %
1177 (info, info))
1179 def getbuffer_normal_cleanup(self, code):
1180 info = self.local_scope.arg_entries[1].cname
1181 code.putln("if (%s->obj == Py_None) { Py_DECREF(Py_None); %s->obj = NULL; }" %
1182 (info, info))
1184 class CFuncDefNode(FuncDefNode):
1185 # C function definition.
1187 # modifiers ['inline']
1188 # visibility 'private' or 'public' or 'extern'
1189 # base_type CBaseTypeNode
1190 # declarator CDeclaratorNode
1191 # body StatListNode
1192 # api boolean
1194 # with_gil boolean Acquire GIL around body
1195 # type CFuncType
1196 # py_func wrapper for calling from Python
1197 # overridable whether or not this is a cpdef function
1199 child_attrs = ["base_type", "declarator", "body", "py_func"]
1201 def unqualified_name(self):
1202 return self.entry.name
1204 def analyse_declarations(self, env):
1205 if 'locals' in env.directives:
1206 directive_locals = env.directives['locals']
1207 else:
1208 directive_locals = {}
1209 self.directive_locals = directive_locals
1210 base_type = self.base_type.analyse(env)
1211 # The 2 here is because we need both function and argument names.
1212 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1213 if not type.is_cfunction:
1214 error(self.pos,
1215 "Suite attached to non-function declaration")
1216 # Remember the actual type according to the function header
1217 # written here, because the type in the symbol table entry
1218 # may be different if we're overriding a C method inherited
1219 # from the base type of an extension type.
1220 self.type = type
1221 type.is_overridable = self.overridable
1222 declarator = self.declarator
1223 while not hasattr(declarator, 'args'):
1224 declarator = declarator.base
1225 self.args = declarator.args
1226 for formal_arg, type_arg in zip(self.args, type.args):
1227 formal_arg.type = type_arg.type
1228 formal_arg.cname = type_arg.cname
1229 name = name_declarator.name
1230 cname = name_declarator.cname
1231 self.entry = env.declare_cfunction(
1232 name, type, self.pos,
1233 cname = cname, visibility = self.visibility,
1234 defining = self.body is not None,
1235 api = self.api)
1236 self.return_type = type.return_type
1238 if self.overridable:
1239 import ExprNodes
1240 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1241 self.py_func = DefNode(pos = self.pos,
1242 name = self.entry.name,
1243 args = self.args,
1244 star_arg = None,
1245 starstar_arg = None,
1246 doc = self.doc,
1247 body = py_func_body,
1248 is_wrapper = 1)
1249 self.py_func.is_module_scope = env.is_module_scope
1250 self.py_func.analyse_declarations(env)
1251 self.entry.as_variable = self.py_func.entry
1252 # Reset scope entry the above cfunction
1253 env.entries[name] = self.entry
1254 self.py_func.interned_attr_cname = env.intern_identifier(
1255 self.py_func.entry.name)
1256 if not env.is_module_scope or Options.lookup_module_cpdef:
1257 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1258 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1260 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1261 import ExprNodes
1262 args = self.type.args
1263 if omit_optional_args:
1264 args = args[:len(args) - self.type.optional_arg_count]
1265 arg_names = [arg.name for arg in args]
1266 if is_module_scope:
1267 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1268 else:
1269 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1270 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1271 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1272 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)
1273 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1275 def declare_arguments(self, env):
1276 for arg in self.type.args:
1277 if not arg.name:
1278 error(arg.pos, "Missing argument name")
1279 self.declare_argument(env, arg)
1281 def need_gil_acquisition(self, lenv):
1282 type = self.type
1283 with_gil = self.type.with_gil
1284 if type.nogil and not with_gil:
1285 if type.return_type.is_pyobject:
1286 error(self.pos,
1287 "Function with Python return type cannot be declared nogil")
1288 for entry in lenv.var_entries + lenv.temp_entries:
1289 if entry.type.is_pyobject:
1290 error(self.pos, "Function declared nogil has Python locals or temporaries")
1291 return with_gil
1293 def analyse_expressions(self, env):
1294 self.analyse_default_values(env)
1295 if self.overridable:
1296 self.py_func.analyse_expressions(env)
1298 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1299 arg_decls = []
1300 type = self.type
1301 visibility = self.entry.visibility
1302 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1303 arg_decls.append(arg.declaration_code())
1304 if with_dispatch and self.overridable:
1305 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1306 if type.optional_arg_count and with_opt_args:
1307 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1308 if type.has_varargs:
1309 arg_decls.append("...")
1310 if not arg_decls:
1311 arg_decls = ["void"]
1312 if cname is None:
1313 cname = self.entry.func_cname
1314 entity = type.function_header_code(cname, string.join(arg_decls, ", "))
1315 if visibility == 'public':
1316 dll_linkage = "DL_EXPORT"
1317 else:
1318 dll_linkage = None
1319 header = self.return_type.declaration_code(entity,
1320 dll_linkage = dll_linkage)
1321 if visibility == 'extern':
1322 storage_class = "%s " % Naming.extern_c_macro
1323 elif visibility == 'public':
1324 storage_class = ""
1325 else:
1326 storage_class = "static "
1327 code.putln("%s%s %s {" % (
1328 storage_class,
1329 ' '.join(self.modifiers).upper(), # macro forms
1330 header))
1332 def generate_argument_declarations(self, env, code):
1333 for arg in self.args:
1334 if arg.default:
1335 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1337 def generate_keyword_list(self, code):
1338 pass
1340 def generate_argument_parsing_code(self, env, code):
1341 i = 0
1342 if self.type.optional_arg_count:
1343 code.putln('if (%s) {' % Naming.optional_args_cname)
1344 for arg in self.args:
1345 if arg.default:
1346 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1347 declarator = arg.declarator
1348 while not hasattr(declarator, 'name'):
1349 declarator = declarator.base
1350 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1351 i += 1
1352 for _ in range(self.type.optional_arg_count):
1353 code.putln('}')
1354 code.putln('}')
1356 def generate_argument_conversion_code(self, code):
1357 pass
1359 def generate_argument_type_tests(self, code):
1360 # Generate type tests for args whose type in a parent
1361 # class is a supertype of the declared type.
1362 for arg in self.type.args:
1363 if arg.needs_type_test:
1364 self.generate_arg_type_test(arg, code)
1366 def generate_arg_type_test(self, arg, code):
1367 # Generate type test for one argument.
1368 if arg.type.typeobj_is_available():
1369 typeptr_cname = arg.type.typeptr_cname
1370 arg_code = "((PyObject *)%s)" % arg.cname
1371 code.putln(
1372 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1373 arg_code,
1374 typeptr_cname,
1375 not arg.not_none,
1376 arg.name,
1377 type.is_builtin_type,
1378 code.error_goto(arg.pos)))
1379 else:
1380 error(arg.pos, "Cannot test type of extern C class "
1381 "without type object name specification")
1383 def error_value(self):
1384 if self.return_type.is_pyobject:
1385 return "0"
1386 else:
1387 #return None
1388 return self.entry.type.exception_value
1390 def caller_will_check_exceptions(self):
1391 return self.entry.type.exception_check
1393 def generate_wrapper_functions(self, code):
1394 # If the C signature of a function has changed, we need to generate
1395 # wrappers to put in the slots here.
1396 k = 0
1397 entry = self.entry
1398 func_type = entry.type
1399 while entry.prev_entry is not None:
1400 k += 1
1401 entry = entry.prev_entry
1402 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1403 code.putln()
1404 self.generate_function_header(code,
1405 0,
1406 with_dispatch = entry.type.is_overridable,
1407 with_opt_args = entry.type.optional_arg_count,
1408 cname = entry.func_cname)
1409 if not self.return_type.is_void:
1410 code.put('return ')
1411 args = self.type.args
1412 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1413 if entry.type.is_overridable:
1414 arglist.append(Naming.skip_dispatch_cname)
1415 elif func_type.is_overridable:
1416 arglist.append('0')
1417 if entry.type.optional_arg_count:
1418 arglist.append(Naming.optional_args_cname)
1419 elif func_type.optional_arg_count:
1420 arglist.append('NULL')
1421 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1422 code.putln('}')
1425 class PyArgDeclNode(Node):
1426 # Argument which must be a Python object (used
1427 # for * and ** arguments).
1429 # name string
1430 # entry Symtab.Entry
1431 child_attrs = []
1434 class DecoratorNode(Node):
1435 # A decorator
1437 # decorator NameNode or CallNode
1438 child_attrs = ['decorator']
1441 class DefNode(FuncDefNode):
1442 # A Python function definition.
1444 # name string the Python name of the function
1445 # decorators [DecoratorNode] list of decorators
1446 # args [CArgDeclNode] formal arguments
1447 # star_arg PyArgDeclNode or None * argument
1448 # starstar_arg PyArgDeclNode or None ** argument
1449 # doc EncodedString or None
1450 # body StatListNode
1452 # The following subnode is constructed internally
1453 # when the def statement is inside a Python class definition.
1455 # assmt AssignmentNode Function construction/assignment
1457 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1459 assmt = None
1460 num_kwonly_args = 0
1461 num_required_kw_args = 0
1462 reqd_kw_flags_cname = "0"
1463 is_wrapper = 0
1464 decorators = None
1465 entry = None
1468 def __init__(self, pos, **kwds):
1469 FuncDefNode.__init__(self, pos, **kwds)
1470 k = rk = r = 0
1471 for arg in self.args:
1472 if arg.kw_only:
1473 k += 1
1474 if not arg.default:
1475 rk += 1
1476 if not arg.default:
1477 r += 1
1478 self.num_kwonly_args = k
1479 self.num_required_kw_args = rk
1480 self.num_required_args = r
1482 def as_cfunction(self, cfunc):
1483 if self.star_arg:
1484 error(self.star_arg.pos, "cdef function cannot have star argument")
1485 if self.starstar_arg:
1486 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1487 if len(self.args) != len(cfunc.type.args) or cfunc.type.has_varargs:
1488 error(self.pos, "wrong number of arguments")
1489 error(declarator.pos, "previous declaration here")
1490 for formal_arg, type_arg in zip(self.args, cfunc.type.args):
1491 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1492 if type is PyrexTypes.py_object_type or formal_arg.is_self:
1493 formal_arg.type = type_arg.type
1494 formal_arg.name_declarator = name_declarator
1495 import ExprNodes
1496 if cfunc.type.exception_value is None:
1497 exception_value = None
1498 else:
1499 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc.type.exception_value, type=cfunc.type.return_type)
1500 declarator = CFuncDeclaratorNode(self.pos,
1501 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1502 args = self.args,
1503 has_varargs = False,
1504 exception_check = cfunc.type.exception_check,
1505 exception_value = exception_value,
1506 with_gil = cfunc.type.with_gil,
1507 nogil = cfunc.type.nogil)
1508 return CFuncDefNode(self.pos,
1509 modifiers = [],
1510 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc.type.return_type),
1511 declarator = declarator,
1512 body = self.body,
1513 doc = self.doc,
1514 overridable = cfunc.type.is_overridable,
1515 type = cfunc.type,
1516 with_gil = cfunc.type.with_gil,
1517 nogil = cfunc.type.nogil,
1518 visibility = 'private',
1519 api = False)
1521 def analyse_declarations(self, env):
1522 if 'locals' in env.directives:
1523 directive_locals = env.directives['locals']
1524 else:
1525 directive_locals = {}
1526 self.directive_locals = directive_locals
1527 for arg in self.args:
1528 base_type = arg.base_type.analyse(env)
1529 name_declarator, type = \
1530 arg.declarator.analyse(base_type, env)
1531 arg.name = name_declarator.name
1532 if arg.name in directive_locals:
1533 type_node = directive_locals[arg.name]
1534 other_type = type_node.analyse_as_type(env)
1535 if other_type is None:
1536 error(type_node.pos, "Not a type")
1537 elif (type is not PyrexTypes.py_object_type
1538 and not type.same_as(other_type)):
1539 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1540 error(type_node.pos, "Previous declaration here")
1541 else:
1542 type = other_type
1543 if name_declarator.cname:
1544 error(self.pos,
1545 "Python function argument cannot have C name specification")
1546 arg.type = type.as_argument_type()
1547 arg.hdr_type = None
1548 arg.needs_conversion = 0
1549 arg.needs_type_test = 0
1550 arg.is_generic = 1
1551 if arg.not_none and not arg.type.is_extension_type:
1552 error(self.pos,
1553 "Only extension type arguments can have 'not None'")
1554 self.declare_pyfunction(env)
1555 self.analyse_signature(env)
1556 self.return_type = self.entry.signature.return_type()
1558 def analyse_signature(self, env):
1559 any_type_tests_needed = 0
1560 # Use the simpler calling signature for zero- and one-argument functions.
1561 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1562 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1563 if len(self.args) == 0:
1564 self.entry.signature = TypeSlots.pyfunction_noargs
1565 elif len(self.args) == 1:
1566 if self.args[0].default is None and not self.args[0].kw_only:
1567 self.entry.signature = TypeSlots.pyfunction_onearg
1568 elif self.entry.signature is TypeSlots.pymethod_signature:
1569 if len(self.args) == 1:
1570 self.entry.signature = TypeSlots.unaryfunc
1571 elif len(self.args) == 2:
1572 if self.args[1].default is None and not self.args[1].kw_only:
1573 self.entry.signature = TypeSlots.ibinaryfunc
1574 elif self.entry.is_special:
1575 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1576 sig = self.entry.signature
1577 nfixed = sig.num_fixed_args()
1578 for i in range(nfixed):
1579 if i < len(self.args):
1580 arg = self.args[i]
1581 arg.is_generic = 0
1582 if sig.is_self_arg(i):
1583 arg.is_self_arg = 1
1584 arg.hdr_type = arg.type = env.parent_type
1585 arg.needs_conversion = 0
1586 else:
1587 arg.hdr_type = sig.fixed_arg_type(i)
1588 if not arg.type.same_as(arg.hdr_type):
1589 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1590 arg.needs_type_test = 1
1591 any_type_tests_needed = 1
1592 else:
1593 arg.needs_conversion = 1
1594 if arg.needs_conversion:
1595 arg.hdr_cname = Naming.arg_prefix + arg.name
1596 else:
1597 arg.hdr_cname = Naming.var_prefix + arg.name
1598 else:
1599 self.bad_signature()
1600 return
1601 if nfixed < len(self.args):
1602 if not sig.has_generic_args:
1603 self.bad_signature()
1604 for arg in self.args:
1605 if arg.is_generic and \
1606 (arg.type.is_extension_type or arg.type.is_builtin_type):
1607 arg.needs_type_test = 1
1608 any_type_tests_needed = 1
1609 elif arg.type is PyrexTypes.c_py_ssize_t_type:
1610 # Want to use __index__ rather than __int__ method
1611 # that PyArg_ParseTupleAndKeywords calls
1612 arg.needs_conversion = 1
1613 arg.hdr_type = PyrexTypes.py_object_type
1614 arg.hdr_cname = Naming.arg_prefix + arg.name
1615 if any_type_tests_needed:
1616 env.use_utility_code(arg_type_test_utility_code)
1618 def bad_signature(self):
1619 sig = self.entry.signature
1620 expected_str = "%d" % sig.num_fixed_args()
1621 if sig.has_generic_args:
1622 expected_str = expected_str + " or more"
1623 name = self.name
1624 if name.startswith("__") and name.endswith("__"):
1625 desc = "Special method"
1626 else:
1627 desc = "Method"
1628 error(self.pos,
1629 "%s %s has wrong number of arguments "
1630 "(%d declared, %s expected)" % (
1631 desc, self.name, len(self.args), expected_str))
1633 def signature_has_nongeneric_args(self):
1634 argcount = len(self.args)
1635 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1636 return 0
1637 return 1
1639 def signature_has_generic_args(self):
1640 return self.entry.signature.has_generic_args
1642 def declare_pyfunction(self, env):
1643 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1644 name = self.name
1645 entry = env.lookup_here(self.name)
1646 if entry and entry.type.is_cfunction and not self.is_wrapper:
1647 warning(self.pos, "Overriding cdef method with def method.", 5)
1648 entry = env.declare_pyfunction(self.name, self.pos)
1649 self.entry = entry
1650 prefix = env.scope_prefix
1651 entry.func_cname = \
1652 Naming.pyfunc_prefix + prefix + name
1653 entry.pymethdef_cname = \
1654 Naming.pymethdef_prefix + prefix + name
1655 if Options.docstrings:
1656 entry.doc = embed_position(self.pos, self.doc)
1657 entry.doc_cname = \
1658 Naming.funcdoc_prefix + prefix + name
1659 else:
1660 entry.doc = None
1662 def declare_arguments(self, env):
1663 for arg in self.args:
1664 if not arg.name:
1665 error(arg.pos, "Missing argument name")
1666 if arg.needs_conversion:
1667 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1668 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1669 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1670 if arg.type.is_pyobject:
1671 arg.entry.init = "0"
1672 arg.entry.init_to_none = 0
1673 else:
1674 arg.entry = self.declare_argument(env, arg)
1675 arg.entry.used = 1
1676 arg.entry.is_self_arg = arg.is_self_arg
1677 if not arg.is_self_arg:
1678 arg.name_entry = env.get_string_const(
1679 arg.name, identifier = True)
1680 env.add_py_string(arg.name_entry, identifier = True)
1681 if arg.hdr_type:
1682 if arg.is_self_arg or \
1683 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1684 arg.entry.is_declared_generic = 1
1685 self.declare_python_arg(env, self.star_arg)
1686 self.declare_python_arg(env, self.starstar_arg)
1688 def declare_python_arg(self, env, arg):
1689 if arg:
1690 entry = env.declare_var(arg.name,
1691 PyrexTypes.py_object_type, arg.pos)
1692 entry.used = 1
1693 entry.init = "0"
1694 entry.init_to_none = 0
1695 entry.xdecref_cleanup = 1
1696 arg.entry = entry
1697 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1699 def analyse_expressions(self, env):
1700 self.analyse_default_values(env)
1701 if env.is_py_class_scope:
1702 self.synthesize_assignment_node(env)
1704 def synthesize_assignment_node(self, env):
1705 import ExprNodes
1706 self.assmt = SingleAssignmentNode(self.pos,
1707 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1708 rhs = ExprNodes.UnboundMethodNode(self.pos,
1709 class_cname = env.class_obj_cname,
1710 function = ExprNodes.PyCFunctionNode(self.pos,
1711 pymethdef_cname = self.entry.pymethdef_cname)))
1712 self.assmt.analyse_declarations(env)
1713 self.assmt.analyse_expressions(env)
1715 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1716 arg_code_list = []
1717 sig = self.entry.signature
1718 if sig.has_dummy_arg:
1719 arg_code_list.append(
1720 "PyObject *%s" % Naming.self_cname)
1721 for arg in self.args:
1722 if not arg.is_generic:
1723 if arg.is_self_arg:
1724 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1725 else:
1726 arg_code_list.append(
1727 arg.hdr_type.declaration_code(arg.hdr_cname))
1728 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1729 arg_code_list.append("PyObject *unused")
1730 if sig.has_generic_args:
1731 arg_code_list.append(
1732 "PyObject *%s, PyObject *%s"
1733 % (Naming.args_cname, Naming.kwds_cname))
1734 arg_code = ", ".join(arg_code_list)
1735 dc = self.return_type.declaration_code(self.entry.func_cname)
1736 header = "static %s(%s)" % (dc, arg_code)
1737 code.putln("%s; /*proto*/" % header)
1738 if proto_only:
1739 return
1740 if self.entry.doc and Options.docstrings:
1741 docstr = self.entry.doc
1742 if not isinstance(docstr, str):
1743 docstr = docstr.utf8encode()
1744 code.putln(
1745 'static char %s[] = "%s";' % (
1746 self.entry.doc_cname,
1747 split_docstring(escape_byte_string(docstr))))
1748 if with_pymethdef:
1749 code.put(
1750 "static PyMethodDef %s = " %
1751 self.entry.pymethdef_cname)
1752 code.put_pymethoddef(self.entry, ";")
1753 code.putln("%s {" % header)
1755 def generate_argument_declarations(self, env, code):
1756 for arg in self.args:
1757 if arg.is_generic: # or arg.needs_conversion:
1758 if arg.needs_conversion:
1759 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1760 else:
1761 code.put_var_declaration(arg.entry)
1763 def generate_keyword_list(self, code):
1764 if self.signature_has_generic_args() and \
1765 self.signature_has_nongeneric_args():
1766 code.put(
1767 "static PyObject **%s[] = {" %
1768 Naming.pykwdlist_cname)
1769 for arg in self.args:
1770 if arg.is_generic:
1771 code.put('&%s,' % arg.name_entry.pystring_cname)
1772 code.putln("0};")
1774 def generate_argument_parsing_code(self, env, code):
1775 # Generate PyArg_ParseTuple call for generic
1776 # arguments, if any.
1777 if self.entry.signature.has_dummy_arg:
1778 # get rid of unused argument warning
1779 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1781 old_error_label = code.new_error_label()
1782 our_error_label = code.error_label
1783 end_label = code.new_label("argument_unpacking_done")
1785 has_kwonly_args = self.num_kwonly_args > 0
1786 has_star_or_kw_args = self.star_arg is not None \
1787 or self.starstar_arg is not None or has_kwonly_args
1789 if not self.signature_has_generic_args():
1790 if has_star_or_kw_args:
1791 error(self.pos, "This method cannot have * or keyword arguments")
1792 self.generate_argument_conversion_code(code)
1794 elif not self.signature_has_nongeneric_args():
1795 # func(*args) or func(**kw) or func(*args, **kw)
1796 self.generate_stararg_copy_code(code)
1798 else:
1799 positional_args = []
1800 kw_only_args = []
1801 default_seen = 0
1802 for arg in self.args:
1803 arg_entry = arg.entry
1804 if arg.is_generic:
1805 if arg.default:
1806 code.putln(
1807 "%s = %s;" % (
1808 arg_entry.cname,
1809 arg.default_result_code))
1810 default_seen = 1
1811 if not arg.is_self_arg:
1812 if arg.kw_only:
1813 kw_only_args.append(arg)
1814 else:
1815 positional_args.append(arg)
1816 elif arg.kw_only:
1817 kw_only_args.append(arg)
1818 default_seen = 1
1819 elif default_seen:
1820 error(arg.pos, "Non-default argument following default argument")
1821 elif not arg.is_self_arg:
1822 positional_args.append(arg)
1823 if arg.needs_conversion:
1824 format = arg.hdr_type.parsetuple_format
1825 else:
1826 format = arg_entry.type.parsetuple_format
1827 if not format:
1828 error(arg.pos,
1829 "Cannot convert Python object argument to type '%s' (when parsing input arguments)"
1830 % arg.type)
1832 self.generate_tuple_and_keyword_parsing_code(
1833 positional_args, kw_only_args, end_label, code)
1835 code.error_label = old_error_label
1836 if code.label_used(our_error_label):
1837 if not code.label_used(end_label):
1838 code.put_goto(end_label)
1839 code.put_label(our_error_label)
1840 if has_star_or_kw_args:
1841 self.generate_arg_decref(self.star_arg, code)
1842 if self.starstar_arg:
1843 if self.starstar_arg.entry.xdecref_cleanup:
1844 code.put_var_xdecref(self.starstar_arg.entry)
1845 else:
1846 code.put_var_decref(self.starstar_arg.entry)
1847 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1848 code.putln("return %s;" % self.error_value())
1849 if code.label_used(end_label):
1850 code.put_label(end_label)
1852 def generate_arg_assignment(self, arg, item, code):
1853 if arg.type.is_pyobject:
1854 if arg.is_generic:
1855 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1856 code.putln("%s = %s;" % (arg.entry.cname, item))
1857 else:
1858 func = arg.type.from_py_function
1859 if func:
1860 code.putln("%s = %s(%s); %s" % (
1861 arg.entry.cname,
1862 func,
1863 item,
1864 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1865 else:
1866 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1868 def generate_arg_xdecref(self, arg, code):
1869 if arg:
1870 code.put_var_xdecref(arg.entry)
1872 def generate_arg_decref(self, arg, code):
1873 if arg:
1874 code.put_var_decref(arg.entry)
1876 def generate_stararg_copy_code(self, code):
1877 if not self.star_arg:
1878 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1879 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1880 Naming.args_cname)
1881 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
1882 self.name.utf8encode(), Naming.args_cname, self.error_value()))
1883 code.putln("}")
1885 code.globalstate.use_utility_code(keyword_string_check_utility_code)
1887 if self.starstar_arg:
1888 if self.star_arg:
1889 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
1890 else:
1891 kwarg_check = "%s" % Naming.kwds_cname
1892 else:
1893 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
1894 Naming.kwds_cname, Naming.kwds_cname)
1895 code.putln(
1896 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
1897 kwarg_check, Naming.kwds_cname, self.name,
1898 bool(self.starstar_arg), self.error_value()))
1900 if self.starstar_arg:
1901 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
1902 self.starstar_arg.entry.cname,
1903 Naming.kwds_cname,
1904 Naming.kwds_cname))
1905 code.putln("if (unlikely(!%s)) return %s;" % (
1906 self.starstar_arg.entry.cname, self.error_value()))
1907 self.starstar_arg.entry.xdecref_cleanup = 0
1909 if self.star_arg:
1910 code.put_incref(Naming.args_cname, py_object_type)
1911 code.putln("%s = %s;" % (
1912 self.star_arg.entry.cname,
1913 Naming.args_cname))
1914 self.star_arg.entry.xdecref_cleanup = 0
1916 def generate_tuple_and_keyword_parsing_code(self, positional_args,
1917 kw_only_args, success_label, code):
1918 argtuple_error_label = code.new_label("argtuple_error")
1920 min_positional_args = self.num_required_args - self.num_required_kw_args
1921 if len(self.args) > 0 and self.args[0].is_self_arg:
1922 min_positional_args -= 1
1923 max_positional_args = len(positional_args)
1924 has_fixed_positional_count = not self.star_arg and \
1925 min_positional_args == max_positional_args
1927 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
1928 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1929 if self.num_required_kw_args:
1930 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
1932 if self.starstar_arg or self.star_arg:
1933 self.generate_stararg_init_code(max_positional_args, code)
1935 # --- optimised code when we receive keyword arguments
1936 if self.num_required_kw_args:
1937 likely_hint = "likely"
1938 else:
1939 likely_hint = "unlikely"
1940 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
1941 self.generate_keyword_unpacking_code(
1942 min_positional_args, max_positional_args,
1943 has_fixed_positional_count,
1944 positional_args, kw_only_args, argtuple_error_label, code)
1946 # --- optimised code when we do not receive any keyword arguments
1947 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
1948 # Python raises arg tuple related errors first, so we must
1949 # check the length here
1950 if min_positional_args == max_positional_args and not self.star_arg:
1951 compare = '!='
1952 else:
1953 compare = '<'
1954 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
1955 Naming.args_cname, compare, min_positional_args))
1956 code.put_goto(argtuple_error_label)
1958 if self.num_required_kw_args:
1959 # pure error case: keywords required but not passed
1960 if max_positional_args > min_positional_args and not self.star_arg:
1961 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
1962 Naming.args_cname, max_positional_args))
1963 code.put_goto(argtuple_error_label)
1964 code.putln('} else {')
1965 for i, arg in enumerate(kw_only_args):
1966 if not arg.default:
1967 # required keyword-only argument missing
1968 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
1969 self.name.utf8encode(),
1970 arg.name_entry.pystring_cname))
1971 code.putln(code.error_goto(self.pos))
1972 break
1974 elif min_positional_args == max_positional_args:
1975 # parse the exact number of positional arguments from the
1976 # args tuple
1977 code.putln('} else {')
1978 for i, arg in enumerate(positional_args):
1979 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
1980 self.generate_arg_assignment(arg, item, code)
1982 else:
1983 # parse the positional arguments from the variable length
1984 # args tuple
1985 code.putln('} else {')
1986 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
1987 if self.star_arg:
1988 code.putln('default:')
1989 reversed_args = list(enumerate(positional_args))[::-1]
1990 for i, arg in reversed_args:
1991 if i >= min_positional_args-1:
1992 if min_positional_args > 1:
1993 code.putln('case %2d:' % (i+1)) # pure code beautification
1994 else:
1995 code.put('case %2d: ' % (i+1))
1996 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
1997 self.generate_arg_assignment(arg, item, code)
1998 if min_positional_args == 0:
1999 code.put('case 0: ')
2000 code.putln('break;')
2001 if self.star_arg:
2002 if min_positional_args:
2003 for i in range(min_positional_args-1, -1, -1):
2004 code.putln('case %2d:' % i)
2005 code.put_goto(argtuple_error_label)
2006 else:
2007 code.put('default: ')
2008 code.put_goto(argtuple_error_label)
2009 code.putln('}')
2011 code.putln('}')
2013 if code.label_used(argtuple_error_label):
2014 code.put_goto(success_label)
2015 code.put_label(argtuple_error_label)
2016 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2017 self.name.utf8encode(), has_fixed_positional_count,
2018 min_positional_args, max_positional_args,
2019 Naming.args_cname))
2020 code.putln(code.error_goto(self.pos))
2022 def generate_stararg_init_code(self, max_positional_args, code):
2023 if self.starstar_arg:
2024 self.starstar_arg.entry.xdecref_cleanup = 0
2025 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2026 self.starstar_arg.entry.cname,
2027 self.starstar_arg.entry.cname,
2028 self.error_value()))
2029 if self.star_arg:
2030 self.star_arg.entry.xdecref_cleanup = 0
2031 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2032 Naming.args_cname,
2033 max_positional_args))
2034 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2035 self.star_arg.entry.cname, Naming.args_cname,
2036 max_positional_args, Naming.args_cname))
2037 if self.starstar_arg:
2038 code.putln("")
2039 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2040 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2041 code.putln('return %s;' % self.error_value())
2042 code.putln('}')
2043 else:
2044 code.putln("if (unlikely(!%s)) return %s;" % (
2045 self.star_arg.entry.cname, self.error_value()))
2046 code.putln('} else {')
2047 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2048 code.put_incref(Naming.empty_tuple, py_object_type)
2049 code.putln('}')
2051 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2052 has_fixed_positional_count, positional_args,
2053 kw_only_args, argtuple_error_label, code):
2054 all_args = tuple(positional_args) + tuple(kw_only_args)
2055 max_args = len(all_args)
2057 code.putln("PyObject* values[%d] = {%s};" % (
2058 max_args, ('0,'*max_args)[:-1]))
2059 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2060 Naming.kwds_cname)
2062 # parse the tuple and check that it's not too long
2063 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2064 if self.star_arg:
2065 code.putln('default:')
2066 for i in range(max_positional_args-1, -1, -1):
2067 code.put('case %2d: ' % (i+1))
2068 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2069 i, Naming.args_cname, i))
2070 code.putln('case 0: break;')
2071 if not self.star_arg:
2072 code.put('default: ') # more arguments than allowed
2073 code.put_goto(argtuple_error_label)
2074 code.putln('}')
2076 # now fill up the required arguments with values from the kw dict
2077 last_required_arg = -1
2078 for i, arg in enumerate(all_args):
2079 if not arg.default:
2080 last_required_arg = i
2081 if last_required_arg >= 0:
2082 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2083 for i, arg in enumerate(all_args[:last_required_arg+1]):
2084 if i <= max_positional_args:
2085 if self.star_arg and i == max_positional_args:
2086 code.putln('default:')
2087 else:
2088 code.putln('case %2d:' % i)
2089 if arg.default:
2090 # handled in ParseOptionalKeywords() below
2091 continue
2092 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2093 i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2094 if i < min_positional_args:
2095 code.putln('if (likely(values[%d])) kw_args--;' % i);
2096 if i == 0:
2097 # special case: we know arg 0 is missing
2098 code.put('else ')
2099 code.put_goto(argtuple_error_label)
2100 else:
2101 # print the correct number of values (args or
2102 # kwargs) that were passed into positional
2103 # arguments up to this point
2104 code.putln('else {')
2105 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2106 self.name.utf8encode(), has_fixed_positional_count,
2107 min_positional_args, max_positional_args, i))
2108 code.putln(code.error_goto(self.pos))
2109 code.putln('}')
2110 else:
2111 code.putln('if (values[%d]) kw_args--;' % i);
2112 if arg.kw_only and not arg.default:
2113 code.putln('else {')
2114 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2115 self.name.utf8encode(), arg.name_entry.pystring_cname))
2116 code.putln(code.error_goto(self.pos))
2117 code.putln('}')
2118 code.putln('}')
2120 code.putln('if (unlikely(kw_args > 0)) {')
2121 # non-positional kw args left in dict: default args, **kwargs or error
2122 if self.star_arg:
2123 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2124 Naming.args_cname, max_positional_args,
2125 Naming.args_cname, max_positional_args))
2126 pos_arg_count = "used_pos_args"
2127 else:
2128 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2129 code.globalstate.use_utility_code(parse_keywords_utility_code)
2130 code.put(
2131 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2132 Naming.kwds_cname,
2133 Naming.pykwdlist_cname,
2134 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2135 pos_arg_count,
2136 self.name.utf8encode()))
2137 code.putln(code.error_goto(self.pos))
2138 code.putln('}')
2140 # convert arg values to their final type and assign them
2141 for i, arg in enumerate(all_args):
2142 if arg.default:
2143 code.putln("if (values[%d]) {" % i)
2144 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2145 if arg.default:
2146 code.putln('}')
2148 def generate_argument_conversion_code(self, code):
2149 # Generate code to convert arguments from
2150 # signature type to declared type, if needed.
2151 for arg in self.args:
2152 if arg.needs_conversion:
2153 self.generate_arg_conversion(arg, code)
2155 def generate_arg_conversion(self, arg, code):
2156 # Generate conversion code for one argument.
2157 old_type = arg.hdr_type
2158 new_type = arg.type
2159 if old_type.is_pyobject:
2160 if arg.default:
2161 code.putln("if (%s) {" % arg.hdr_cname)
2162 else:
2163 code.putln("assert(%s); {" % arg.hdr_cname)
2164 self.generate_arg_conversion_from_pyobject(arg, code)
2165 code.putln("}")
2166 elif new_type.is_pyobject:
2167 self.generate_arg_conversion_to_pyobject(arg, code)
2168 else:
2169 if new_type.assignable_from(old_type):
2170 code.putln(
2171 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2172 else:
2173 error(arg.pos,
2174 "Cannot convert 1 argument from '%s' to '%s'" %
2175 (old_type, new_type))
2177 def generate_arg_conversion_from_pyobject(self, arg, code):
2178 new_type = arg.type
2179 func = new_type.from_py_function
2180 # copied from CoerceFromPyTypeNode
2181 if func:
2182 code.putln("%s = %s(%s); %s" % (
2183 arg.entry.cname,
2184 func,
2185 arg.hdr_cname,
2186 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2187 else:
2188 error(arg.pos,
2189 "Cannot convert Python object argument to type '%s'"
2190 % new_type)
2192 def generate_arg_conversion_to_pyobject(self, arg, code):
2193 old_type = arg.hdr_type
2194 func = old_type.to_py_function
2195 if func:
2196 code.putln("%s = %s(%s); %s" % (
2197 arg.entry.cname,
2198 func,
2199 arg.hdr_cname,
2200 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2201 else:
2202 error(arg.pos,
2203 "Cannot convert argument of type '%s' to Python object"
2204 % old_type)
2206 def generate_argument_type_tests(self, code):
2207 # Generate type tests for args whose signature
2208 # type is PyObject * and whose declared type is
2209 # a subtype thereof.
2210 for arg in self.args:
2211 if arg.needs_type_test:
2212 self.generate_arg_type_test(arg, code)
2214 def generate_arg_type_test(self, arg, code):
2215 # Generate type test for one argument.
2216 if arg.type.typeobj_is_available():
2217 typeptr_cname = arg.type.typeptr_cname
2218 arg_code = "((PyObject *)%s)" % arg.entry.cname
2219 code.putln(
2220 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2221 arg_code,
2222 typeptr_cname,
2223 not arg.not_none,
2224 arg.name,
2225 arg.type.is_builtin_type,
2226 code.error_goto(arg.pos)))
2227 else:
2228 error(arg.pos, "Cannot test type of extern C class "
2229 "without type object name specification")
2231 def error_value(self):
2232 return self.entry.signature.error_value
2234 def caller_will_check_exceptions(self):
2235 return 1
2237 class OverrideCheckNode(StatNode):
2238 # A Node for dispatching to the def method if it
2239 # is overriden.
2241 # py_func
2243 # args
2244 # func_temp
2245 # body
2247 child_attrs = ['body']
2249 body = None
2251 def analyse_expressions(self, env):
2252 self.args = env.arg_entries
2253 if self.py_func.is_module_scope:
2254 first_arg = 0
2255 else:
2256 first_arg = 1
2257 import ExprNodes
2258 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2259 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2260 call_node = ExprNodes.SimpleCallNode(self.pos,
2261 function=self.func_node,
2262 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2263 self.body = ReturnStatNode(self.pos, value=call_node)
2264 self.body.analyse_expressions(env)
2266 def generate_execution_code(self, code):
2267 # Check to see if we are an extension type
2268 if self.py_func.is_module_scope:
2269 self_arg = "((PyObject *)%s)" % Naming.module_cname
2270 else:
2271 self_arg = "((PyObject *)%s)" % self.args[0].cname
2272 code.putln("/* Check if called by wrapper */")
2273 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2274 code.putln("/* Check if overriden in Python */")
2275 if self.py_func.is_module_scope:
2276 code.putln("else {")
2277 else:
2278 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2279 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2280 # need to get attribute manually--scope would return cdef method
2281 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2282 # It appears that this type is not anywhere exposed in the Python/C API
2283 is_builtin_function_or_method = '(strcmp(Py_TYPE(%s)->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result()
2284 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2285 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2286 self.body.generate_execution_code(code)
2287 code.putln('}')
2288 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2289 code.putln("}")
2291 class ClassDefNode(StatNode, BlockNode):
2292 pass
2294 class PyClassDefNode(ClassDefNode):
2295 # A Python class definition.
2297 # name EncodedString Name of the class
2298 # doc string or None
2299 # body StatNode Attribute definition code
2300 # entry Symtab.Entry
2301 # scope PyClassScope
2303 # The following subnodes are constructed internally:
2305 # dict DictNode Class dictionary
2306 # classobj ClassNode Class object
2307 # target NameNode Variable to assign class object to
2309 child_attrs = ["body", "dict", "classobj", "target"]
2311 def __init__(self, pos, name, bases, doc, body):
2312 StatNode.__init__(self, pos)
2313 self.name = name
2314 self.doc = doc
2315 self.body = body
2316 import ExprNodes
2317 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2318 if self.doc and Options.docstrings:
2319 doc = embed_position(self.pos, self.doc)
2320 doc_node = ExprNodes.StringNode(pos, value = doc)
2321 else:
2322 doc_node = None
2323 self.classobj = ExprNodes.ClassNode(pos, name = name,
2324 bases = bases, dict = self.dict, doc = doc_node)
2325 self.target = ExprNodes.NameNode(pos, name = name)
2327 def as_cclass(self):
2328 """
2329 Return this node as if it were declared as an extension class"
2330 """
2331 bases = self.classobj.bases.args
2332 if len(bases) == 0:
2333 base_class_name = None
2334 base_class_module = None
2335 elif len(bases) == 1:
2336 base = bases[0]
2337 path = []
2338 while isinstance(base, ExprNodes.AttributeNode):
2339 path.insert(0, base.attribute)
2340 base = base.obj
2341 if isinstance(base, ExprNodes.NameNode):
2342 path.insert(0, base.name)
2343 base_class_name = path[-1]
2344 if len(path) > 1:
2345 base_class_module = u'.'.join(path[:-1])
2346 else:
2347 base_class_module = None
2348 else:
2349 error(self.classobj.bases.args.pos, "Invalid base class")
2350 else:
2351 error(self.classobj.bases.args.pos, "C class may only have one base class")
2352 return None
2354 return CClassDefNode(self.pos,
2355 visibility = 'private',
2356 module_name = None,
2357 class_name = self.name,
2358 base_class_module = base_class_module,
2359 base_class_name = base_class_name,
2360 body = self.body,
2361 in_pxd = False,
2362 doc = self.doc)
2364 def create_scope(self, env):
2365 genv = env
2366 while env.is_py_class_scope or env.is_c_class_scope:
2367 env = env.outer_scope
2368 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2369 return cenv
2371 def analyse_declarations(self, env):
2372 self.target.analyse_target_declaration(env)
2373 cenv = self.create_scope(env)
2374 cenv.class_obj_cname = self.target.entry.cname
2375 self.body.analyse_declarations(cenv)
2377 def analyse_expressions(self, env):
2378 self.dict.analyse_expressions(env)
2379 self.classobj.analyse_expressions(env)
2380 genv = env.global_scope()
2381 cenv = self.scope
2382 cenv.class_dict_cname = self.dict.result()
2383 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2384 self.body.analyse_expressions(cenv)
2385 self.target.analyse_target_expression(env, self.classobj)
2386 self.dict.release_temp(env)
2387 #self.classobj.release_temp(env)
2388 #self.target.release_target_temp(env)
2390 def generate_function_definitions(self, env, code):
2391 self.generate_py_string_decls(self.scope, code)
2392 self.body.generate_function_definitions(self.scope, code)
2394 def generate_execution_code(self, code):
2395 self.dict.generate_evaluation_code(code)
2396 self.classobj.generate_evaluation_code(code)
2397 self.body.generate_execution_code(code)
2398 self.target.generate_assignment_code(self.classobj, code)
2399 self.dict.generate_disposal_code(code)
2402 class CClassDefNode(ClassDefNode):
2403 # An extension type definition.
2405 # visibility 'private' or 'public' or 'extern'
2406 # typedef_flag boolean
2407 # api boolean
2408 # module_name string or None For import of extern type objects
2409 # class_name string Unqualified name of class
2410 # as_name string or None Name to declare as in this scope
2411 # base_class_module string or None Module containing the base class
2412 # base_class_name string or None Name of the base class
2413 # objstruct_name string or None Specified C name of object struct
2414 # typeobj_name string or None Specified C name of type object
2415 # in_pxd boolean Is in a .pxd file
2416 # doc string or None
2417 # body StatNode or None
2418 # entry Symtab.Entry
2419 # base_type PyExtensionType or None
2420 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2421 # buffer_defaults_pos
2423 child_attrs = ["body"]
2424 buffer_defaults_node = None
2425 buffer_defaults_pos = None
2426 typedef_flag = False
2427 api = False
2428 objstruct_name = None
2429 typeobj_name = None
2431 def analyse_declarations(self, env):
2432 #print "CClassDefNode.analyse_declarations:", self.class_name
2433 #print "...visibility =", self.visibility
2434 #print "...module_name =", self.module_name
2436 import Buffer
2437 if self.buffer_defaults_node:
2438 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2439 env, [], self.buffer_defaults_node,
2440 need_complete=False)
2441 else:
2442 buffer_defaults = None
2444 if env.in_cinclude and not self.objstruct_name:
2445 error(self.pos, "Object struct name specification required for "
2446 "C class defined in 'extern from' block")
2447 self.base_type = None
2448 # Now that module imports are cached, we need to
2449 # import the modules for extern classes.
2450 if self.module_name:
2451 self.module = None
2452 for module in env.cimported_modules:
2453 if module.name == self.module_name:
2454 self.module = module
2455 if self.module is None:
2456 self.module = ModuleScope(self.module_name, None, env.context)
2457 self.module.has_extern_class = 1
2458 env.cimported_modules.append(self.module)
2460 if self.base_class_name:
2461 if self.base_class_module:
2462 base_class_scope = env.find_module(self.base_class_module, self.pos)
2463 else:
2464 base_class_scope = env
2465 if base_class_scope:
2466 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2467 if base_class_entry:
2468 if not base_class_entry.is_type:
2469 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2470 elif not base_class_entry.type.is_extension_type:
2471 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2472 elif not base_class_entry.type.is_complete():
2473 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2474 else:
2475 self.base_type = base_class_entry.type
2476 has_body = self.body is not None
2477 if self.module_name and self.visibility != 'extern':
2478 module_path = self.module_name.split(".")
2479 home_scope = env.find_imported_module(module_path, self.pos)
2480 if not home_scope:
2481 return
2482 else:
2483 home_scope = env
2484 self.entry = home_scope.declare_c_class(
2485 name = self.class_name,
2486 pos = self.pos,
2487 defining = has_body and self.in_pxd,
2488 implementing = has_body and not self.in_pxd,
2489 module_name = self.module_name,
2490 base_type = self.base_type,
2491 objstruct_cname = self.objstruct_name,
2492 typeobj_cname = self.typeobj_name,
2493 visibility = self.visibility,
2494 typedef_flag = self.typedef_flag,
2495 api = self.api,
2496 buffer_defaults = buffer_defaults)
2497 if home_scope is not env and self.visibility == 'extern':
2498 env.add_imported_entry(self.class_name, self.entry, pos)
2499 scope = self.entry.type.scope
2501 if self.doc and Options.docstrings:
2502 scope.doc = embed_position(self.pos, self.doc)
2504 if has_body:
2505 self.body.analyse_declarations(scope)
2506 if self.in_pxd:
2507 scope.defined = 1
2508 else:
2509 scope.implemented = 1
2510 env.allocate_vtable_names(self.entry)
2512 def analyse_expressions(self, env):
2513 if self.body:
2514 scope = self.entry.type.scope
2515 self.body.analyse_expressions(scope)
2517 def generate_function_definitions(self, env, code):
2518 self.generate_py_string_decls(self.entry.type.scope, code)
2519 if self.body:
2520 self.body.generate_function_definitions(
2521 self.entry.type.scope, code)
2523 def generate_execution_code(self, code):
2524 # This is needed to generate evaluation code for
2525 # default values of method arguments.
2526 if self.body:
2527 self.body.generate_execution_code(code)
2529 def annotate(self, code):
2530 if self.body:
2531 self.body.annotate(code)
2534 class PropertyNode(StatNode):
2535 # Definition of a property in an extension type.
2537 # name string
2538 # doc EncodedString or None Doc string
2539 # body StatListNode
2541 child_attrs = ["body"]
2543 def analyse_declarations(self, env):
2544 entry = env.declare_property(self.name, self.doc, self.pos)
2545 if entry:
2546 if self.doc and Options.docstrings:
2547 doc_entry = env.get_string_const(
2548 self.doc, identifier = False)
2549 entry.doc_cname = doc_entry.cname
2550 self.body.analyse_declarations(entry.scope)
2552 def analyse_expressions(self, env):
2553 self.body.analyse_expressions(env)
2555 def generate_function_definitions(self, env, code):
2556 self.body.generate_function_definitions(env, code)
2558 def generate_execution_code(self, code):
2559 pass
2561 def annotate(self, code):
2562 self.body.annotate(code)
2565 class GlobalNode(StatNode):
2566 # Global variable declaration.
2568 # names [string]
2570 child_attrs = []
2572 def analyse_declarations(self, env):
2573 for name in self.names:
2574 env.declare_global(name, self.pos)
2576 def analyse_expressions(self, env):
2577 pass
2579 def generate_execution_code(self, code):
2580 pass
2583 class ExprStatNode(StatNode):
2584 # Expression used as a statement.
2586 # expr ExprNode
2588 child_attrs = ["expr"]
2590 def analyse_declarations(self, env):
2591 import ExprNodes
2592 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2593 func = self.expr.function.as_cython_attribute()
2594 if func == u'declare':
2595 args, kwds = self.expr.explicit_args_kwds()
2596 if len(args):
2597 error(self.expr.pos, "Variable names must be specified.")
2598 for var, type_node in kwds.key_value_pairs:
2599 type = type_node.analyse_as_type(env)
2600 if type is None:
2601 error(type_node.pos, "Unknown type")
2602 else:
2603 env.declare_var(var.value, type, var.pos, is_cdef = True)
2604 self.__class__ = PassStatNode
2606 def analyse_expressions(self, env):
2607 self.expr.analyse_expressions(env)
2608 self.expr.release_temp(env)
2610 def generate_execution_code(self, code):
2611 self.expr.generate_evaluation_code(code)
2612 if not self.expr.is_temp and self.expr.result():
2613 code.putln("%s;" % self.expr.result())
2614 self.expr.generate_disposal_code(code)
2616 def annotate(self, code):
2617 self.expr.annotate(code)
2620 class AssignmentNode(StatNode):
2621 # Abstract base class for assignment nodes.
2623 # The analyse_expressions and generate_execution_code
2624 # phases of assignments are split into two sub-phases
2625 # each, to enable all the right hand sides of a
2626 # parallel assignment to be evaluated before assigning
2627 # to any of the left hand sides.
2629 def analyse_expressions(self, env):
2630 self.analyse_types(env)
2631 self.allocate_rhs_temps(env)
2632 self.allocate_lhs_temps(env)
2634 # def analyse_expressions(self, env):
2635 # self.analyse_expressions_1(env)
2636 # self.analyse_expressions_2(env)
2638 def generate_execution_code(self, code):
2639 self.generate_rhs_evaluation_code(code)
2640 self.generate_assignment_code(code)
2643 class SingleAssignmentNode(AssignmentNode):
2644 # The simplest case:
2646 # a = b
2648 # lhs ExprNode Left hand side
2649 # rhs ExprNode Right hand side
2650 # first bool Is this guaranteed the first assignment to lhs?
2652 child_attrs = ["lhs", "rhs"]
2653 first = False
2654 declaration_only = False
2656 def analyse_declarations(self, env):
2657 import ExprNodes
2659 # handle declarations of the form x = cython.foo()
2660 if isinstance(self.rhs, ExprNodes.CallNode):
2661 func_name = self.rhs.function.as_cython_attribute()
2662 if func_name:
2663 args, kwds = self.rhs.explicit_args_kwds()
2665 if func_name in ['declare', 'typedef']:
2666 if len(args) > 2 or kwds is not None:
2667 error(rhs.pos, "Can only declare one type at a time.")
2668 return
2669 type = args[0].analyse_as_type(env)
2670 if type is None:
2671 error(args[0].pos, "Unknown type")
2672 return
2673 lhs = self.lhs
2674 if func_name == 'declare':
2675 if isinstance(lhs, ExprNodes.NameNode):
2676 vars = [(lhs.name, lhs.pos)]
2677 elif isinstance(lhs, ExprNodes.TupleNode):
2678 vars = [(var.name, var.pos) for var in lhs.args]
2679 else:
2680 error(lhs.pos, "Invalid declaration")
2681 return
2682 for var, pos in vars:
2683 env.declare_var(var, type, pos, is_cdef = True)
2684 if len(args) == 2:
2685 # we have a value
2686 self.rhs = args[1]
2687 else:
2688 self.declaration_only = True
2689 else:
2690 self.declaration_only = True
2691 if not isinstance(lhs, ExprNodes.NameNode):
2692 error(lhs.pos, "Invalid declaration.")
2693 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2695 elif func_name in ['struct', 'union']:
2696 self.declaration_only = True
2697 if len(args) > 0 or kwds is None:
2698 error(rhs.pos, "Struct or union members must be given by name.")
2699 return
2700 members = []
2701 for member, type_node in kwds.key_value_pairs:
2702 type = type_node.analyse_as_type(env)
2703 if type is None:
2704 error(type_node.pos, "Unknown type")
2705 else:
2706 members.append((member.value, type, member.pos))
2707 if len(members) < len(kwds.key_value_pairs):
2708 return
2709 if not isinstance(self.lhs, ExprNodes.NameNode):
2710 error(self.lhs.pos, "Invalid declaration.")
2711 name = self.lhs.name
2712 scope = StructOrUnionScope(name)
2713 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2714 for member, type, pos in members:
2715 scope.declare_var(member, type, pos)
2717 if self.declaration_only:
2718 return
2719 else:
2720 self.lhs.analyse_target_declaration(env)
2722 def analyse_types(self, env, use_temp = 0):
2723 self.rhs.analyse_types(env)
2724 self.lhs.analyse_target_types(env)
2725 self.lhs.gil_assignment_check(env)
2726 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2727 if use_temp:
2728 self.rhs = self.rhs.coerce_to_temp(env)
2730 def allocate_rhs_temps(self, env):
2731 self.rhs.allocate_temps(env)
2733 def allocate_lhs_temps(self, env):
2734 self.lhs.allocate_target_temps(env, self.rhs)
2735 #self.lhs.release_target_temp(env)
2736 #self.rhs.release_temp(env)
2738 # def analyse_expressions_1(self, env, use_temp = 0):
2739 # self.rhs.analyse_types(env)
2740 # self.lhs.analyse_target_types(env)
2741 # self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2742 # if use_temp:
2743 # self.rhs = self.rhs.coerce_to_temp(env)
2744 # self.rhs.allocate_temps(env)
2746 # def analyse_expressions_2(self, env):
2747 # self.lhs.allocate_target_temps(env)
2748 # self.lhs.release_target_temp(env)
2749 # self.rhs.release_temp(env)
2751 def generate_rhs_evaluation_code(self, code):
2752 self.rhs.generate_evaluation_code(code)
2754 def generate_assignment_code(self, code):
2755 self.lhs.generate_assignment_code(self.rhs, code)
2757 def annotate(self, code):
2758 self.lhs.annotate(code)
2759 self.rhs.annotate(code)
2762 class CascadedAssignmentNode(AssignmentNode):
2763 # An assignment with multiple left hand sides:
2765 # a = b = c
2767 # lhs_list [ExprNode] Left hand sides
2768 # rhs ExprNode Right hand sides
2770 # Used internally:
2772 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2774 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2775 coerced_rhs_list = None
2777 def analyse_declarations(self, env):
2778 for lhs in self.lhs_list:
2779 lhs.analyse_target_declaration(env)
2781 def analyse_types(self, env, use_temp = 0):
2782 self.rhs.analyse_types(env)
2783 if use_temp:
2784 self.rhs = self.rhs.coerce_to_temp(env)
2785 else:
2786 self.rhs = self.rhs.coerce_to_simple(env)
2787 from ExprNodes import CloneNode
2788 self.coerced_rhs_list = []
2789 for lhs in self.lhs_list:
2790 lhs.analyse_target_types(env)
2791 lhs.gil_assignment_check(env)
2792 rhs = CloneNode(self.rhs)
2793 rhs = rhs.coerce_to(lhs.type, env)
2794 self.coerced_rhs_list.append(rhs)
2796 def allocate_rhs_temps(self, env):
2797 self.rhs.allocate_temps(env)
2799 def allocate_lhs_temps(self, env):
2800 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2801 rhs.allocate_temps(env)
2802 lhs.allocate_target_temps(env, rhs)
2803 #lhs.release_target_temp(env)
2804 #rhs.release_temp(env)
2805 self.rhs.release_temp(env)
2807 # def analyse_expressions_1(self, env, use_temp = 0):
2808 # self.rhs.analyse_types(env)
2809 # if use_temp:
2810 # self.rhs = self.rhs.coerce_to_temp(env)
2811 # else:
2812 # self.rhs = self.rhs.coerce_to_simple(env)
2813 # self.rhs.allocate_temps(env)
2815 # def analyse_expressions_2(self, env):
2816 # from ExprNodes import CloneNode
2817 # self.coerced_rhs_list = []
2818 # for lhs in self.lhs_list:
2819 # lhs.analyse_target_types(env)
2820 # rhs = CloneNode(self.rhs)
2821 # rhs = rhs.coerce_to(lhs.type, env)
2822 # self.coerced_rhs_list.append(rhs)
2823 # rhs.allocate_temps(env)
2824 # lhs.allocate_target_temps(env)
2825 # lhs.release_target_temp(env)
2826 # rhs.release_temp(env)
2827 # self.rhs.release_temp(env)
2829 def generate_rhs_evaluation_code(self, code):
2830 self.rhs.generate_evaluation_code(code)
2832 def generate_assignment_code(self, code):
2833 for i in range(len(self.lhs_list)):
2834 lhs = self.lhs_list[i]
2835 rhs = self.coerced_rhs_list[i]
2836 rhs.generate_evaluation_code(code)
2837 lhs.generate_assignment_code(rhs, code)
2838 # Assignment has disposed of the cloned RHS
2839 self.rhs.generate_disposal_code(code)
2841 def annotate(self, code):
2842 for i in range(len(self.lhs_list)):
2843 lhs = self.lhs_list[i].annotate(code)
2844 rhs = self.coerced_rhs_list[i].annotate(code)
2845 self.rhs.annotate(code)
2848 class ParallelAssignmentNode(AssignmentNode):
2849 # A combined packing/unpacking assignment:
2851 # a, b, c = d, e, f
2853 # This has been rearranged by the parser into
2855 # a = d ; b = e ; c = f
2857 # but we must evaluate all the right hand sides
2858 # before assigning to any of the left hand sides.
2860 # stats [AssignmentNode] The constituent assignments
2862 child_attrs = ["stats"]
2864 def analyse_declarations(self, env):
2865 for stat in self.stats:
2866 stat.analyse_declarations(env)
2868 def analyse_expressions(self, env):
2869 for stat in self.stats:
2870 stat.analyse_types(env, use_temp = 1)
2871 stat.allocate_rhs_temps(env)
2872 for stat in self.stats:
2873 stat.allocate_lhs_temps(env)
2875 # def analyse_expressions(self, env):
2876 # for stat in self.stats:
2877 # stat.analyse_expressions_1(env, use_temp = 1)
2878 # for stat in self.stats:
2879 # stat.analyse_expressions_2(env)
2881 def generate_execution_code(self, code):
2882 for stat in self.stats:
2883 stat.generate_rhs_evaluation_code(code)
2884 for stat in self.stats:
2885 stat.generate_assignment_code(code)
2887 def annotate(self, code):
2888 for stat in self.stats:
2889 stat.annotate(code)
2892 class InPlaceAssignmentNode(AssignmentNode):
2893 # An in place arithmatic operand:
2895 # a += b
2896 # a -= b
2897 # ...
2899 # lhs ExprNode Left hand side
2900 # rhs ExprNode Right hand side
2901 # op char one of "+-*/%^&|"
2902 # dup (ExprNode) copy of lhs used for operation (auto-generated)
2904 # This code is a bit tricky because in order to obey Python
2905 # semantics the sub-expressions (e.g. indices) of the lhs must
2906 # not be evaluated twice. So we must re-use the values calculated
2907 # in evaluation phase for the assignment phase as well.
2908 # Fortunately, the type of the lhs node is fairly constrained
2909 # (it must be a NameNode, AttributeNode, or IndexNode).
2911 child_attrs = ["lhs", "rhs"]
2912 dup = None
2914 def analyse_declarations(self, env):
2915 self.lhs.analyse_target_declaration(env)
2917 def analyse_types(self, env):
2918 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
2919 self.rhs.analyse_types(env)
2920 self.lhs.analyse_target_types(env)
2921 if Options.incref_local_binop and self.dup.type.is_pyobject:
2922 self.dup = self.dup.coerce_to_temp(env)
2924 def allocate_rhs_temps(self, env):
2925 import ExprNodes
2926 if self.lhs.type.is_pyobject:
2927 self.rhs = self.rhs.coerce_to_pyobject(env)
2928 elif self.rhs.type.is_pyobject:
2929 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2930 if self.lhs.type.is_pyobject:
2931 self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
2932 self.result_value.allocate_temps(env)
2933 # if use_temp:
2934 # self.rhs = self.rhs.coerce_to_temp(env)
2935 self.rhs.allocate_temps(env)
2936 self.dup.allocate_subexpr_temps(env)
2937 self.dup.allocate_temp(env)
2939 def allocate_lhs_temps(self, env):
2940 self.lhs.allocate_target_temps(env, self.rhs)
2941 # self.lhs.release_target_temp(env)
2942 self.dup.release_temp(env)
2943 if self.dup.is_temp:
2944 self.dup.release_subexpr_temps(env)
2945 # self.rhs.release_temp(env)
2946 if self.lhs.type.is_pyobject:
2947 self.result_value.release_temp(env)
2949 def generate_execution_code(self, code):
2950 self.rhs.generate_evaluation_code(code)
2951 self.dup.generate_subexpr_evaluation_code(code)
2952 # self.dup.generate_result_code is run only if it is not buffer access
2953 if self.operator == "**":
2954 extra = ", Py_None"
2955 else:
2956 extra = ""
2957 import ExprNodes
2958 if self.lhs.type.is_pyobject:
2959 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
2960 error(self.pos, "In-place operators not allowed on object buffers in this release.")
2961 self.dup.generate_result_code(code)
2962 code.putln(
2963 "%s = %s(%s, %s%s); %s" % (
2964 self.result_value.result(),
2965 self.py_operation_function(),
2966 self.dup.py_result(),
2967 self.rhs.py_result(),
2968 extra,
2969 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
2970 self.result_value.generate_evaluation_code(code) # May be a type check...
2971 self.rhs.generate_disposal_code(code)
2972 self.dup.generate_disposal_code(code)
2973 self.lhs.generate_assignment_code(self.result_value, code)
2974 else:
2975 c_op = self.operator
2976 if c_op == "//":
2977 c_op = "/"
2978 elif c_op == "**":
2979 if self.lhs.type.is_int and self.rhs.type.is_int:
2980 error(self.pos, "** with two C int types is ambiguous")
2981 else:
2982 error(self.pos, "No C inplace power operator")
2983 # have to do assignment directly to avoid side-effects
2984 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
2985 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
2986 else:
2987 self.dup.generate_result_code(code)
2988 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
2989 self.rhs.generate_disposal_code(code)
2990 if self.dup.is_temp:
2991 self.dup.generate_subexpr_disposal_code(code)
2993 def create_dup_node(self, env):
2994 import ExprNodes
2995 self.dup = self.lhs
2996 self.dup.analyse_types(env)
2997 if isinstance(self.lhs, ExprNodes.NameNode):
2998 target_lhs = ExprNodes.NameNode(self.dup.pos,
2999 name = self.dup.name,
3000 is_temp = self.dup.is_temp,
3001 entry = self.dup.entry)
3002 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3003 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3004 obj = ExprNodes.CloneNode(self.lhs.obj),
3005 attribute = self.dup.attribute,
3006 is_temp = self.dup.is_temp)
3007 elif isinstance(self.lhs, ExprNodes.IndexNode):
3008 if self.lhs.index:
3009 index = ExprNodes.CloneNode(self.lhs.index)
3010 else:
3011 index = None
3012 if self.lhs.indices:
3013 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3014 else:
3015 indices = []
3016 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3017 base = ExprNodes.CloneNode(self.dup.base),
3018 index = index,
3019 indices = indices,
3020 is_temp = self.dup.is_temp)
3021 self.lhs = target_lhs
3022 return self.dup
3024 def py_operation_function(self):
3025 return self.py_functions[self.operator]
3027 py_functions = {
3028 "|": "PyNumber_InPlaceOr",
3029 "^": "PyNumber_InPlaceXor",
3030 "&": "PyNumber_InPlaceAnd",
3031 "+": "PyNumber_InPlaceAdd",
3032 "-": "PyNumber_InPlaceSubtract",
3033 "*": "PyNumber_InPlaceMultiply",
3034 "/": "PyNumber_InPlaceDivide",
3035 "%": "PyNumber_InPlaceRemainder",
3036 "<<": "PyNumber_InPlaceLshift",
3037 ">>": "PyNumber_InPlaceRshift",
3038 "**": "PyNumber_InPlacePower",
3039 "//": "PyNumber_InPlaceFloorDivide",
3042 def annotate(self, code):
3043 self.lhs.annotate(code)
3044 self.rhs.annotate(code)
3045 self.dup.annotate(code)
3048 class PrintStatNode(StatNode):
3049 # print statement
3051 # arg_tuple TupleNode
3052 # append_newline boolean
3054 child_attrs = ["arg_tuple"]
3056 def analyse_expressions(self, env):
3057 self.arg_tuple.analyse_expressions(env)
3058 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3059 self.arg_tuple.release_temp(env)
3060 env.use_utility_code(printing_utility_code)
3061 self.gil_check(env)
3063 gil_message = "Python print statement"
3065 def generate_execution_code(self, code):
3066 self.arg_tuple.generate_evaluation_code(code)
3067 code.putln(
3068 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3069 self.arg_tuple.py_result(),
3070 self.append_newline,
3071 code.error_goto(self.pos)))
3072 self.arg_tuple.generate_disposal_code(code)
3074 def annotate(self, code):
3075 self.arg_tuple.annotate(code)
3078 class DelStatNode(StatNode):
3079 # del statement
3081 # args [ExprNode]
3083 child_attrs = ["args"]
3085 def analyse_declarations(self, env):
3086 for arg in self.args:
3087 arg.analyse_target_declaration(env)
3089 def analyse_expressions(self, env):
3090 for arg in self.args:
3091 arg.analyse_target_expression(env, None)
3092 if arg.type.is_pyobject:
3093 self.gil_check(env)
3094 else:
3095 error(arg.pos, "Deletion of non-Python object")
3096 #arg.release_target_temp(env)
3098 gil_message = "Deleting Python object"
3100 def generate_execution_code(self, code):
3101 for arg in self.args:
3102 if arg.type.is_pyobject:
3103 arg.generate_deletion_code(code)
3104 # else error reported earlier
3106 def annotate(self, code):
3107 for arg in self.args:
3108 arg.annotate(code)
3111 class PassStatNode(StatNode):
3112 # pass statement
3114 child_attrs = []
3116 def analyse_expressions(self, env):
3117 pass
3119 def generate_execution_code(self, code):
3120 pass
3123 class BreakStatNode(StatNode):
3125 child_attrs = []
3127 def analyse_expressions(self, env):
3128 pass
3130 def generate_execution_code(self, code):
3131 if not code.break_label:
3132 error(self.pos, "break statement not inside loop")
3133 else:
3134 #code.putln(
3135 # "goto %s;" %
3136 # code.break_label)
3137 code.put_goto(code.break_label)
3140 class ContinueStatNode(StatNode):
3142 child_attrs = []
3144 def analyse_expressions(self, env):
3145 pass
3147 def generate_execution_code(self, code):
3148 if code.funcstate.in_try_finally:
3149 error(self.pos, "continue statement inside try of try...finally")
3150 elif not code.continue_label:
3151 error(self.pos, "continue statement not inside loop")
3152 else:
3153 code.put_goto(code.continue_label)
3156 class ReturnStatNode(StatNode):
3157 # return statement
3159 # value ExprNode or None
3160 # return_type PyrexType
3161 # temps_in_use [Entry] Temps in use at time of return
3163 child_attrs = ["value"]
3165 def analyse_expressions(self, env):
3166 return_type = env.return_type
3167 self.return_type = return_type
3168 self.temps_in_use = env.temps_in_use()
3169 if not return_type:
3170 error(self.pos, "Return not inside a function body")
3171 return
3172 if self.value:
3173 self.value.analyse_types(env)
3174 if return_type.is_void or return_type.is_returncode:
3175 error(self.value.pos,
3176 "Return with value in void function")
3177 else:
3178 self.value = self.value.coerce_to(env.return_type, env)
3179 self.value.allocate_temps(env)
3180 self.value.release_temp(env)
3181 else:
3182 if (not return_type.is_void
3183 and not return_type.is_pyobject
3184 and not return_type.is_returncode):
3185 error(self.pos, "Return value required")
3186 if return_type.is_pyobject:
3187 self.gil_check(env)
3189 gil_message = "Returning Python object"
3191 def generate_execution_code(self, code):
3192 code.mark_pos(self.pos)
3193 if not self.return_type:
3194 # error reported earlier
3195 return
3196 if self.value:
3197 self.value.generate_evaluation_code(code)
3198 self.value.make_owned_reference(code)
3199 code.putln(
3200 "%s = %s;" % (
3201 Naming.retval_cname,
3202 self.value.result_as(self.return_type)))
3203 self.value.generate_post_assignment_code(code)
3204 else:
3205 if self.return_type.is_pyobject:
3206 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3207 elif self.return_type.is_returncode:
3208 code.putln(
3209 "%s = %s;" % (
3210 Naming.retval_cname,
3211 self.return_type.default_value))
3212 for entry in self.temps_in_use:
3213 code.put_var_decref_clear(entry)
3214 #code.putln(
3215 # "goto %s;" %
3216 # code.return_label)
3217 code.put_goto(code.return_label)
3219 def annotate(self, code):
3220 if self.value:
3221 self.value.annotate(code)
3224 class RaiseStatNode(StatNode):
3225 # raise statement
3227 # exc_type ExprNode or None
3228 # exc_value ExprNode or None
3229 # exc_tb ExprNode or None
3231 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3233 def analyse_expressions(self, env):
3234 if self.exc_type:
3235 self.exc_type.analyse_types(env)
3236 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3237 self.exc_type.allocate_temps(env)
3238 if self.exc_value:
3239 self.exc_value.analyse_types(env)
3240 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3241 self.exc_value.allocate_temps(env)
3242 if self.exc_tb:
3243 self.exc_tb.analyse_types(env)
3244 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3245 self.exc_tb.allocate_temps(env)
3246 if self.exc_type:
3247 self.exc_type.release_temp(env)
3248 if self.exc_value:
3249 self.exc_value.release_temp(env)
3250 if self.exc_tb:
3251 self.exc_tb.release_temp(env)
3252 env.use_utility_code(raise_utility_code)
3253 env.use_utility_code(restore_exception_utility_code)
3254 self.gil_check(env)
3256 gil_message = "Raising exception"
3258 def generate_execution_code(self, code):
3259 if self.exc_type:
3260 self.exc_type.generate_evaluation_code(code)
3261 type_code = self.exc_type.py_result()
3262 else:
3263 type_code = 0
3264 if self.exc_value:
3265 self.exc_value.generate_evaluation_code(code)
3266 value_code = self.exc_value.py_result()
3267 else:
3268 value_code = "0"
3269 if self.exc_tb:
3270 self.exc_tb.generate_evaluation_code(code)
3271 tb_code = self.exc_tb.py_result()
3272 else:
3273 tb_code = "0"
3274 if self.exc_type or self.exc_value or self.exc_tb:
3275 code.putln(
3276 "__Pyx_Raise(%s, %s, %s);" % (
3277 type_code,
3278 value_code,
3279 tb_code))
3280 else:
3281 code.putln(
3282 "__Pyx_ReRaise();")
3283 if self.exc_type:
3284 self.exc_type.generate_disposal_code(code)
3285 if self.exc_value:
3286 self.exc_value.generate_disposal_code(code)
3287 if self.exc_tb:
3288 self.exc_tb.generate_disposal_code(code)
3289 code.putln(
3290 code.error_goto(self.pos))
3292 def annotate(self, code):
3293 if self.exc_type:
3294 self.exc_type.annotate(code)
3295 if self.exc_value:
3296 self.exc_value.annotate(code)
3297 if self.exc_tb:
3298 self.exc_tb.annotate(code)
3301 class ReraiseStatNode(StatNode):
3303 child_attrs = []
3305 def analyse_expressions(self, env):
3306 self.gil_check(env)
3307 env.use_utility_code(raise_utility_code)
3308 env.use_utility_code(restore_exception_utility_code)
3310 gil_message = "Raising exception"
3312 def generate_execution_code(self, code):
3313 vars = code.funcstate.exc_vars
3314 if vars:
3315 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3316 code.putln(code.error_goto(self.pos))
3317 else:
3318 error(self.pos, "Reraise not inside except clause")
3321 class AssertStatNode(StatNode):
3322 # assert statement
3324 # cond ExprNode
3325 # value ExprNode or None
3327 child_attrs = ["cond", "value"]
3329 def analyse_expressions(self, env):
3330 self.cond = self.cond.analyse_boolean_expression(env)
3331 if self.value:
3332 self.value.analyse_types(env)
3333 self.value = self.value.coerce_to_pyobject(env)
3334 self.value.allocate_temps(env)
3335 self.cond.release_temp(env)
3336 if self.value:
3337 self.value.release_temp(env)
3338 self.gil_check(env)
3339 #env.recycle_pending_temps() # TEMPORARY
3341 gil_message = "Raising exception"
3343 def generate_execution_code(self, code):
3344 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3345 self.cond.generate_evaluation_code(code)
3346 code.putln(
3347 "if (unlikely(!%s)) {" %
3348 self.cond.result())
3349 if self.value:
3350 self.value.generate_evaluation_code(code)
3351 code.putln(
3352 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3353 self.value.py_result())
3354 self.value.generate_disposal_code(code)
3355 else:
3356 code.putln(
3357 "PyErr_SetNone(PyExc_AssertionError);")
3358 code.putln(
3359 code.error_goto(self.pos))
3360 code.putln(
3361 "}")
3362 self.cond.generate_disposal_code(code)
3363 code.putln("#endif")
3365 def annotate(self, code):
3366 self.cond.annotate(code)
3367 if self.value:
3368 self.value.annotate(code)
3371 class IfStatNode(StatNode):
3372 # if statement
3374 # if_clauses [IfClauseNode]
3375 # else_clause StatNode or None
3377 child_attrs = ["if_clauses", "else_clause"]
3379 def analyse_control_flow(self, env):
3380 env.start_branching(self.pos)
3381 for if_clause in self.if_clauses:
3382 if_clause.analyse_control_flow(env)
3383 env.next_branch(if_clause.end_pos())
3384 if self.else_clause:
3385 self.else_clause.analyse_control_flow(env)
3386 env.finish_branching(self.end_pos())
3388 def analyse_declarations(self, env):
3389 for if_clause in self.if_clauses:
3390 if_clause.analyse_declarations(env)
3391 if self.else_clause:
3392 self.else_clause.analyse_declarations(env)
3394 def analyse_expressions(self, env):
3395 for if_clause in self.if_clauses:
3396 if_clause.analyse_expressions(env)
3397 if self.else_clause:
3398 self.else_clause.analyse_expressions(env)
3400 def generate_execution_code(self, code):
3401 code.mark_pos(self.pos)
3402 end_label = code.new_label()
3403 for if_clause in self.if_clauses:
3404 if_clause.generate_execution_code(code, end_label)
3405 if self.else_clause:
3406 code.putln("/*else*/ {")
3407 self.else_clause.generate_execution_code(code)
3408 code.putln("}")
3409 code.put_label(end_label)
3411 def annotate(self, code):
3412 for if_clause in self.if_clauses:
3413 if_clause.annotate(code)
3414 if self.else_clause:
3415 self.else_clause.annotate(code)
3418 class IfClauseNode(Node):
3419 # if or elif clause in an if statement
3421 # condition ExprNode
3422 # body StatNode
3424 child_attrs = ["condition", "body"]
3426 def analyse_control_flow(self, env):
3427 self.body.analyse_control_flow(env)
3429 def analyse_declarations(self, env):
3430 self.condition.analyse_declarations(env)
3431 self.body.analyse_declarations(env)
3433 def analyse_expressions(self, env):
3434 self.condition = \
3435 self.condition.analyse_temp_boolean_expression(env)
3436 self.condition.release_temp(env)
3437 self.body.analyse_expressions(env)
3439 def generate_execution_code(self, code, end_label):
3440 self.condition.generate_evaluation_code(code)
3441 code.putln(
3442 "if (%s) {" %
3443 self.condition.result())
3444 self.body.generate_execution_code(code)
3445 #code.putln(
3446 # "goto %s;" %
3447 # end_label)
3448 code.put_goto(end_label)
3449 code.putln("}")
3451 def annotate(self, code):
3452 self.condition.annotate(code)
3453 self.body.annotate(code)
3456 class SwitchCaseNode(StatNode):
3457 # Generated in the optimization of an if-elif-else node
3459 # conditions [ExprNode]
3460 # body StatNode
3462 child_attrs = ['conditions', 'body']
3464 def generate_execution_code(self, code):
3465 for cond in self.conditions:
3466 code.putln("case %s:" % cond.calculate_result_code())
3467 self.body.generate_execution_code(code)
3468 code.putln("break;")
3470 def annotate(self, code):
3471 for cond in self.conditions:
3472 cond.annotate(code)
3473 self.body.annotate(code)
3475 class SwitchStatNode(StatNode):
3476 # Generated in the optimization of an if-elif-else node
3478 # test ExprNode
3479 # cases [SwitchCaseNode]
3480 # else_clause StatNode or None
3482 child_attrs = ['test', 'cases', 'else_clause']
3484 def generate_execution_code(self, code):
3485 code.putln("switch (%s) {" % self.test.calculate_result_code())
3486 for case in self.cases:
3487 case.generate_execution_code(code)
3488 if self.else_clause is not None:
3489 code.putln("default:")
3490 self.else_clause.generate_execution_code(code)
3491 code.putln("break;")
3492 code.putln("}")
3494 def annotate(self, code):
3495 self.test.annotate(code)
3496 for case in self.cases:
3497 case.annotate(code)
3498 if self.else_clause is not None:
3499 self.else_clause.annotate(code)
3501 class LoopNode:
3503 def analyse_control_flow(self, env):
3504 env.start_branching(self.pos)
3505 self.body.analyse_control_flow(env)
3506 env.next_branch(self.body.end_pos())
3507 if self.else_clause:
3508 self.else_clause.analyse_control_flow(env)
3509 env.finish_branching(self.end_pos())
3512 class WhileStatNode(LoopNode, StatNode):
3513 # while statement
3515 # condition ExprNode
3516 # body StatNode
3517 # else_clause StatNode
3519 child_attrs = ["condition", "body", "else_clause"]
3521 def analyse_declarations(self, env):
3522 self.body.analyse_declarations(env)
3523 if self.else_clause:
3524 self.else_clause.analyse_declarations(env)
3526 def analyse_expressions(self, env):
3527 self.condition = \
3528 self.condition.analyse_temp_boolean_expression(env)
3529 self.condition.release_temp(env)
3530 #env.recycle_pending_temps() # TEMPORARY
3531 self.body.analyse_expressions(env)
3532 if self.else_clause:
3533 self.else_clause.analyse_expressions(env)
3535 def generate_execution_code(self, code):
3536 old_loop_labels = code.new_loop_labels()
3537 code.putln(
3538 "while (1) {")
3539 self.condition.generate_evaluation_code(code)
3540 code.putln(
3541 "if (!%s) break;" %
3542 self.condition.result())
3543 self.body.generate_execution_code(code)
3544 code.put_label(code.continue_label)
3545 code.putln("}")
3546 break_label = code.break_label
3547 code.set_loop_labels(old_loop_labels)
3548 if self.else_clause:
3549 code.putln("/*else*/ {")
3550 self.else_clause.generate_execution_code(code)
3551 code.putln("}")
3552 code.put_label(break_label)
3554 def annotate(self, code):
3555 self.condition.annotate(code)
3556 self.body.annotate(code)
3557 if self.else_clause:
3558 self.else_clause.annotate(code)
3561 def ForStatNode(pos, **kw):
3562 if kw.has_key('iterator'):
3563 return ForInStatNode(pos, **kw)
3564 else:
3565 return ForFromStatNode(pos, **kw)
3567 class ForInStatNode(LoopNode, StatNode):
3568 # for statement
3570 # target ExprNode
3571 # iterator IteratorNode
3572 # body StatNode
3573 # else_clause StatNode
3574 # item NextNode used internally
3576 child_attrs = ["target", "iterator", "body", "else_clause"]
3577 item = None
3579 def analyse_declarations(self, env):
3580 self.target.analyse_target_declaration(env)
3581 self.body.analyse_declarations(env)
3582 if self.else_clause:
3583 self.else_clause.analyse_declarations(env)
3585 def analyse_range_step(self, args):
3586 import ExprNodes
3587 # The direction must be determined at compile time to set relations.
3588 # Otherwise, return False.
3589 if len(args) < 3:
3590 self.step = ExprNodes.IntNode(pos = args[0].pos, value='1')
3591 self.relation1 = '<='
3592 self.relation2 = '<'
3593 return True
3594 else:
3595 step = args[2]
3596 if isinstance(step, ExprNodes.UnaryMinusNode) and isinstance(step.operand, ExprNodes.IntNode):
3597 step = ExprNodes.IntNode(pos = step.pos, value=str(-int(step.operand.value, 0)))
3598 if isinstance(step, ExprNodes.IntNode):
3599 step_value = int(step.value, 0)
3600 if step_value > 0:
3601 self.step = step
3602 self.relation1 = '<='
3603 self.relation2 = '<'
3604 return True
3605 elif step_value < 0:
3606 self.step = ExprNodes.IntNode(pos = step.pos, value=str(-step_value))
3607 self.relation1 = '>='
3608 self.relation2 = '>'
3609 return True
3610 return False
3613 def analyse_expressions(self, env):
3614 import ExprNodes
3615 self.target.analyse_target_types(env)
3616 if Options.convert_range and self.target.type.is_int:
3617 sequence = self.iterator.sequence
3618 if isinstance(sequence, ExprNodes.SimpleCallNode) \
3619 and sequence.self is None \
3620 and isinstance(sequence.function, ExprNodes.NameNode) \
3621 and (sequence.function.name == 'range' or sequence.function.name == 'xrange'):
3622 args = sequence.args
3623 # Make sure we can determine direction from step
3624 if self.analyse_range_step(args):
3625 # Mutate to ForFrom loop type
3626 self.__class__ = ForFromStatNode
3627 if len(args) == 1:
3628 self.bound1 = ExprNodes.IntNode(pos = sequence.pos, value='0')
3629 self.bound2 = args[0]
3630 else:
3631 self.bound1 = args[0]
3632 self.bound2 = args[1]
3633 ForFromStatNode.analyse_expressions(self, env)
3634 return
3636 self.iterator.analyse_expressions(env)
3637 self.item = ExprNodes.NextNode(self.iterator, env)
3638 self.item = self.item.coerce_to(self.target.type, env)
3639 self.item.allocate_temps(env)
3640 self.target.allocate_target_temps(env, self.item)
3641 #self.item.release_temp(env)
3642 #self.target.release_target_temp(env)
3643 self.body.analyse_expressions(env)
3644 if self.else_clause:
3645 self.else_clause.analyse_expressions(env)
3646 self.iterator.release_temp(env)
3648 def generate_execution_code(self, code):
3649 old_loop_labels = code.new_loop_labels()
3650 self.iterator.generate_evaluation_code(code)
3651 code.putln(
3652 "for (;;) {")
3653 self.item.generate_evaluation_code(code)
3654 self.target.generate_assignment_code(self.item, code)
3655 self.body.generate_execution_code(code)
3656 code.put_label(code.continue_label)
3657 code.putln(
3658 "}")
3659 break_label = code.break_label
3660 code.set_loop_labels(old_loop_labels)
3661 if self.else_clause:
3662 code.putln("/*else*/ {")
3663 self.else_clause.generate_execution_code(code)
3664 code.putln("}")
3665 code.put_label(break_label)
3666 self.iterator.generate_disposal_code(code)
3668 def annotate(self, code):
3669 self.target.annotate(code)
3670 self.iterator.annotate(code)
3671 self.body.annotate(code)
3672 if self.else_clause:
3673 self.else_clause.annotate(code)
3674 self.item.annotate(code)
3677 class ForFromStatNode(LoopNode, StatNode):
3678 # for name from expr rel name rel expr
3680 # target NameNode
3681 # bound1 ExprNode
3682 # relation1 string
3683 # relation2 string
3684 # bound2 ExprNode
3685 # step ExprNode or None
3686 # body StatNode
3687 # else_clause StatNode or None
3689 # Used internally:
3691 # is_py_target bool
3692 # loopvar_name string
3693 # py_loopvar_node PyTempNode or None
3694 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3696 def analyse_declarations(self, env):
3697 self.target.analyse_target_declaration(env)
3698 self.body.analyse_declarations(env)
3699 if self.else_clause:
3700 self.else_clause.analyse_declarations(env)
3702 def analyse_expressions(self, env):
3703 import ExprNodes
3704 self.target.analyse_target_types(env)
3705 self.bound1.analyse_types(env)
3706 self.bound2.analyse_types(env)
3707 if self.target.type.is_numeric:
3708 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3709 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3710 else:
3711 self.bound1 = self.bound1.coerce_to_integer(env)
3712 self.bound2 = self.bound2.coerce_to_integer(env)
3713 if self.step is not None:
3714 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3715 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3716 self.step.analyse_types(env)
3717 self.step = self.step.coerce_to_integer(env)
3718 if not (self.bound2.is_name or self.bound2.is_literal):
3719 self.bound2 = self.bound2.coerce_to_temp(env)
3720 target_type = self.target.type
3721 if not (target_type.is_pyobject or target_type.is_numeric):
3722 error(self.target.pos,
3723 "Integer for-loop variable must be of type int or Python object")
3724 #if not (target_type.is_pyobject
3725 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3726 # error(self.target.pos,
3727 # "Cannot assign integer to variable of type '%s'" % target_type)
3728 if target_type.is_numeric:
3729 self.is_py_target = 0
3730 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3731 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3732 self.loopvar_name = self.target.entry.cname
3733 self.py_loopvar_node = None
3734 else:
3735 self.is_py_target = 1
3736 c_loopvar_node = ExprNodes.TempNode(self.pos,
3737 PyrexTypes.c_long_type, env)
3738 c_loopvar_node.allocate_temps(env)
3739 self.loopvar_name = c_loopvar_node.result()
3740 self.py_loopvar_node = \
3741 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3742 self.bound1.allocate_temps(env)
3743 self.bound2.allocate_temps(env)
3744 if self.step is not None:
3745 self.step.allocate_temps(env)
3746 if self.is_py_target:
3747 self.py_loopvar_node.allocate_temps(env)
3748 self.target.allocate_target_temps(env, self.py_loopvar_node)
3749 #self.target.release_target_temp(env)
3750 #self.py_loopvar_node.release_temp(env)
3751 self.body.analyse_expressions(env)
3752 if self.is_py_target:
3753 c_loopvar_node.release_temp(env)
3754 if self.else_clause:
3755 self.else_clause.analyse_expressions(env)
3756 self.bound1.release_temp(env)
3757 self.bound2.release_temp(env)
3758 if self.step is not None:
3759 self.step.release_temp(env)
3761 def generate_execution_code(self, code):
3762 old_loop_labels = code.new_loop_labels()
3763 self.bound1.generate_evaluation_code(code)
3764 self.bound2.generate_evaluation_code(code)
3765 offset, incop = self.relation_table[self.relation1]
3766 if self.step is not None:
3767 self.step.generate_evaluation_code(code)
3768 incop = "%s=%s" % (incop[0], self.step.result())
3769 code.putln(
3770 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3771 self.loopvar_name,
3772 self.bound1.result(), offset,
3773 self.loopvar_name, self.relation2, self.bound2.result(),
3774 self.loopvar_name, incop))
3775 if self.py_loopvar_node:
3776 self.py_loopvar_node.generate_evaluation_code(code)
3777 self.target.generate_assignment_code(self.py_loopvar_node, code)
3778 self.body.generate_execution_code(code)
3779 code.put_label(code.continue_label)
3780 code.putln("}")
3781 break_label = code.break_label
3782 code.set_loop_labels(old_loop_labels)
3783 if self.else_clause:
3784 code.putln("/*else*/ {")
3785 self.else_clause.generate_execution_code(code)
3786 code.putln("}")
3787 code.put_label(break_label)
3788 self.bound1.generate_disposal_code(code)
3789 self.bound2.generate_disposal_code(code)
3790 if self.step is not None:
3791 self.step.generate_disposal_code(code)
3793 relation_table = {
3794 # {relop : (initial offset, increment op)}
3795 '<=': ("", "++"),
3796 '<' : ("+1", "++"),
3797 '>=': ("", "--"),
3798 '>' : ("-1", "--")
3801 def annotate(self, code):
3802 self.target.annotate(code)
3803 self.bound1.annotate(code)
3804 self.bound2.annotate(code)
3805 if self.step:
3806 self.bound2.annotate(code)
3807 self.body.annotate(code)
3808 if self.else_clause:
3809 self.else_clause.annotate(code)
3812 class WithStatNode(StatNode):
3813 """
3814 Represents a Python with statement.
3816 This is only used at parse tree level; and is not present in
3817 analysis or generation phases.
3818 """
3819 # manager The with statement manager object
3820 # target Node (lhs expression)
3821 # body StatNode
3822 child_attrs = ["manager", "target", "body"]
3824 class TryExceptStatNode(StatNode):
3825 # try .. except statement
3827 # body StatNode
3828 # except_clauses [ExceptClauseNode]
3829 # else_clause StatNode or None
3830 # cleanup_list [Entry] temps to clean up on error
3832 child_attrs = ["body", "except_clauses", "else_clause"]
3834 def analyse_control_flow(self, env):
3835 env.start_branching(self.pos)
3836 self.body.analyse_control_flow(env)
3837 successful_try = env.control_flow # grab this for later
3838 env.next_branch(self.body.end_pos())
3839 env.finish_branching(self.body.end_pos())
3841 env.start_branching(self.except_clauses[0].pos)
3842 for except_clause in self.except_clauses:
3843 except_clause.analyse_control_flow(env)
3844 env.next_branch(except_clause.end_pos())
3846 # the else cause it executed only when the try clause finishes
3847 env.control_flow.incoming = successful_try
3848 if self.else_clause:
3849 self.else_clause.analyse_control_flow(env)
3850 env.finish_branching(self.end_pos())
3852 def analyse_declarations(self, env):
3853 self.body.analyse_declarations(env)
3854 for except_clause in self.except_clauses:
3855 except_clause.analyse_declarations(env)
3856 if self.else_clause:
3857 self.else_clause.analyse_declarations(env)
3858 self.gil_check(env)
3859 env.use_utility_code(reset_exception_utility_code)
3861 def analyse_expressions(self, env):
3862 self.body.analyse_expressions(env)
3863 self.cleanup_list = env.free_temp_entries[:]
3864 default_clause_seen = 0
3865 for except_clause in self.except_clauses:
3866 except_clause.analyse_expressions(env)
3867 if default_clause_seen:
3868 error(except_clause.pos, "default 'except:' must be last")
3869 if not except_clause.pattern:
3870 default_clause_seen = 1
3871 self.has_default_clause = default_clause_seen
3872 if self.else_clause:
3873 self.else_clause.analyse_expressions(env)
3874 self.gil_check(env)
3876 gil_message = "Try-except statement"
3878 def generate_execution_code(self, code):
3879 old_return_label = code.return_label
3880 old_error_label = code.new_error_label()
3881 our_error_label = code.error_label
3882 except_end_label = code.new_label('exception_handled')
3883 except_error_label = code.new_label('except_error')
3884 except_return_label = code.new_label('except_return')
3885 try_end_label = code.new_label('try')
3887 code.putln("{")
3888 code.putln("PyObject %s;" %
3889 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
3890 code.putln("__Pyx_ExceptionSave(%s);" %
3891 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
3892 code.putln(
3893 "/*try:*/ {")
3894 self.body.generate_execution_code(code)
3895 code.putln(
3896 "}")
3897 code.error_label = except_error_label
3898 code.return_label = except_return_label
3899 if self.else_clause:
3900 code.putln(
3901 "/*else:*/ {")
3902 self.else_clause.generate_execution_code(code)
3903 code.putln(
3904 "}")
3905 for var in Naming.exc_save_vars:
3906 code.put_xdecref_clear(var, py_object_type)
3907 code.put_goto(try_end_label)
3908 code.put_label(our_error_label)
3909 code.put_var_xdecrefs_clear(self.cleanup_list)
3910 for except_clause in self.except_clauses:
3911 except_clause.generate_handling_code(code, except_end_label)
3913 error_label_used = code.label_used(except_error_label)
3914 if error_label_used or not self.has_default_clause:
3915 if error_label_used:
3916 code.put_label(except_error_label)
3917 for var in Naming.exc_save_vars:
3918 code.put_xdecref(var, py_object_type)
3919 code.put_goto(old_error_label)
3921 if code.label_used(except_return_label):
3922 code.put_label(except_return_label)
3923 code.putln("__Pyx_ExceptionReset(%s);" %
3924 ', '.join(Naming.exc_save_vars))
3925 code.put_goto(old_return_label)
3927 if code.label_used(except_end_label):
3928 code.put_label(except_end_label)
3929 code.putln("__Pyx_ExceptionReset(%s);" %
3930 ', '.join(Naming.exc_save_vars))
3931 code.put_label(try_end_label)
3932 code.putln("}")
3934 code.return_label = old_return_label
3935 code.error_label = old_error_label
3937 def annotate(self, code):
3938 self.body.annotate(code)
3939 for except_node in self.except_clauses:
3940 except_node.annotate(code)
3941 if self.else_clause:
3942 self.else_clause.annotate(code)
3945 class ExceptClauseNode(Node):
3946 # Part of try ... except statement.
3948 # pattern ExprNode
3949 # target ExprNode or None
3950 # body StatNode
3951 # excinfo_target NameNode or None optional target for exception info
3952 # match_flag string result of exception match
3953 # exc_value ExcValueNode used internally
3954 # function_name string qualified name of enclosing function
3955 # exc_vars (string * 3) local exception variables
3957 # excinfo_target is never set by the parser, but can be set by a transform
3958 # in order to extract more extensive information about the exception as a
3959 # sys.exc_info()-style tuple into a target variable
3961 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
3963 exc_value = None
3964 excinfo_target = None
3966 def analyse_declarations(self, env):
3967 if self.target:
3968 self.target.analyse_target_declaration(env)
3969 if self.excinfo_target is not None:
3970 self.excinfo_target.analyse_target_declaration(env)
3971 self.body.analyse_declarations(env)
3973 def analyse_expressions(self, env):
3974 import ExprNodes
3975 genv = env.global_scope()
3976 self.function_name = env.qualified_name
3977 if self.pattern:
3978 self.pattern.analyse_expressions(env)
3979 self.pattern = self.pattern.coerce_to_pyobject(env)
3980 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
3981 self.pattern.release_temp(env)
3982 env.release_temp(self.match_flag)
3983 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
3984 if self.target:
3985 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
3986 self.exc_value.allocate_temps(env)
3987 self.target.analyse_target_expression(env, self.exc_value)
3988 if self.excinfo_target is not None:
3989 import ExprNodes
3990 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
3991 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
3992 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
3993 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
3994 ])
3995 self.excinfo_tuple.analyse_expressions(env)
3996 self.excinfo_tuple.allocate_temps(env)
3997 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
3999 self.body.analyse_expressions(env)
4000 for var in self.exc_vars:
4001 env.release_temp(var)
4002 env.use_utility_code(get_exception_utility_code)
4003 env.use_utility_code(restore_exception_utility_code)
4005 def generate_handling_code(self, code, end_label):
4006 code.mark_pos(self.pos)
4007 if self.pattern:
4008 self.pattern.generate_evaluation_code(code)
4009 code.putln(
4010 "%s = PyErr_ExceptionMatches(%s);" % (
4011 self.match_flag,
4012 self.pattern.py_result()))
4013 self.pattern.generate_disposal_code(code)
4014 code.putln(
4015 "if (%s) {" %
4016 self.match_flag)
4017 else:
4018 code.putln("/*except:*/ {")
4019 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4020 # We always have to fetch the exception value even if
4021 # there is no target, because this also normalises the
4022 # exception and stores it in the thread state.
4023 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
4024 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4025 code.error_goto(self.pos)))
4026 if self.target:
4027 self.exc_value.generate_evaluation_code(code)
4028 self.target.generate_assignment_code(self.exc_value, code)
4029 if self.excinfo_target is not None:
4030 self.excinfo_tuple.generate_evaluation_code(code)
4031 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4033 old_exc_vars = code.funcstate.exc_vars
4034 code.funcstate.exc_vars = self.exc_vars
4035 self.body.generate_execution_code(code)
4036 code.funcstate.exc_vars = old_exc_vars
4037 for var in self.exc_vars:
4038 code.putln("Py_DECREF(%s); %s = 0;" % (var, var))
4039 code.put_goto(end_label)
4040 code.putln(
4041 "}")
4043 def annotate(self, code):
4044 if self.pattern:
4045 self.pattern.annotate(code)
4046 if self.target:
4047 self.target.annotate(code)
4048 self.body.annotate(code)
4051 class TryFinallyStatNode(StatNode):
4052 # try ... finally statement
4054 # body StatNode
4055 # finally_clause StatNode
4057 # cleanup_list [Entry] temps to clean up on error
4059 # The plan is that we funnel all continue, break
4060 # return and error gotos into the beginning of the
4061 # finally block, setting a variable to remember which
4062 # one we're doing. At the end of the finally block, we
4063 # switch on the variable to figure out where to go.
4064 # In addition, if we're doing an error, we save the
4065 # exception on entry to the finally block and restore
4066 # it on exit.
4068 child_attrs = ["body", "finally_clause"]
4070 preserve_exception = 1
4072 disallow_continue_in_try_finally = 0
4073 # There doesn't seem to be any point in disallowing
4074 # continue in the try block, since we have no problem
4075 # handling it.
4077 def create_analysed(pos, env, body, finally_clause):
4078 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4079 node.cleanup_list = []
4080 return node
4081 create_analysed = staticmethod(create_analysed)
4083 def analyse_control_flow(self, env):
4084 env.start_branching(self.pos)
4085 self.body.analyse_control_flow(env)
4086 env.next_branch(self.body.end_pos())
4087 env.finish_branching(self.body.end_pos())
4088 self.finally_clause.analyse_control_flow(env)
4090 def analyse_declarations(self, env):
4091 self.body.analyse_declarations(env)
4092 self.finally_clause.analyse_declarations(env)
4094 def analyse_expressions(self, env):
4095 self.body.analyse_expressions(env)
4096 self.cleanup_list = env.free_temp_entries[:]
4097 self.finally_clause.analyse_expressions(env)
4098 self.gil_check(env)
4100 gil_message = "Try-finally statement"
4102 def generate_execution_code(self, code):
4103 old_error_label = code.error_label
4104 old_labels = code.all_new_labels()
4105 new_labels = code.get_all_labels()
4106 new_error_label = code.error_label
4107 catch_label = code.new_label()
4108 code.putln(
4109 "/*try:*/ {")
4110 if self.disallow_continue_in_try_finally:
4111 was_in_try_finally = code.funcstate.in_try_finally
4112 code.funcstate.in_try_finally = 1
4113 self.body.generate_execution_code(code)
4114 if self.disallow_continue_in_try_finally:
4115 code.funcstate.in_try_finally = was_in_try_finally
4116 code.putln(
4117 "}")
4118 code.putln(
4119 "/*finally:*/ {")
4120 cases_used = []
4121 error_label_used = 0
4122 for i, new_label in enumerate(new_labels):
4123 if new_label in code.labels_used:
4124 cases_used.append(i)
4125 if new_label == new_error_label:
4126 error_label_used = 1
4127 error_label_case = i
4128 if cases_used:
4129 code.putln(
4130 "int __pyx_why;")
4131 if error_label_used and self.preserve_exception:
4132 code.putln(
4133 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4134 code.putln(
4135 "int %s;" % Naming.exc_lineno_name)
4136 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4137 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4138 code.putln(exc_var_init_zero)
4139 else:
4140 exc_var_init_zero = None
4141 code.use_label(catch_label)
4142 code.putln(
4143 "__pyx_why = 0; goto %s;" % catch_label)
4144 for i in cases_used:
4145 new_label = new_labels[i]
4146 #if new_label and new_label != "<try>":
4147 if new_label == new_error_label and self.preserve_exception:
4148 self.put_error_catcher(code,
4149 new_error_label, i+1, catch_label)
4150 else:
4151 code.put('%s: ' % new_label)
4152 if exc_var_init_zero:
4153 code.putln(exc_var_init_zero)
4154 code.putln("__pyx_why = %s; goto %s;" % (
4155 i+1,
4156 catch_label))
4157 code.put_label(catch_label)
4158 code.set_all_labels(old_labels)
4159 if error_label_used:
4160 code.new_error_label()
4161 finally_error_label = code.error_label
4162 self.finally_clause.generate_execution_code(code)
4163 if error_label_used:
4164 if finally_error_label in code.labels_used and self.preserve_exception:
4165 over_label = code.new_label()
4166 code.put_goto(over_label);
4167 code.put_label(finally_error_label)
4168 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4169 for var in Naming.exc_vars:
4170 code.putln("Py_XDECREF(%s);" % var)
4171 code.putln("}")
4172 code.put_goto(old_error_label)
4173 code.put_label(over_label)
4174 code.error_label = old_error_label
4175 if cases_used:
4176 code.putln(
4177 "switch (__pyx_why) {")
4178 for i in cases_used:
4179 old_label = old_labels[i]
4180 if old_label == old_error_label and self.preserve_exception:
4181 self.put_error_uncatcher(code, i+1, old_error_label)
4182 else:
4183 code.use_label(old_label)
4184 code.putln(
4185 "case %s: goto %s;" % (
4186 i+1,
4187 old_label))
4188 code.putln(
4189 "}")
4190 code.putln(
4191 "}")
4193 def put_error_catcher(self, code, error_label, i, catch_label):
4194 code.globalstate.use_utility_code(restore_exception_utility_code)
4195 code.putln(
4196 "%s: {" %
4197 error_label)
4198 code.putln(
4199 "__pyx_why = %s;" %
4200 i)
4201 code.put_var_xdecrefs_clear(self.cleanup_list)
4202 code.putln(
4203 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4204 Naming.exc_vars)
4205 code.putln(
4206 "%s = %s;" % (
4207 Naming.exc_lineno_name, Naming.lineno_cname))
4208 #code.putln(
4209 # "goto %s;" %
4210 # catch_label)
4211 code.put_goto(catch_label)
4212 code.putln(
4213 "}")
4215 def put_error_uncatcher(self, code, i, error_label):
4216 code.globalstate.use_utility_code(restore_exception_utility_code)
4217 code.putln(
4218 "case %s: {" %
4219 i)
4220 code.putln(
4221 "__Pyx_ErrRestore(%s, %s, %s);" %
4222 Naming.exc_vars)
4223 code.putln(
4224 "%s = %s;" % (
4225 Naming.lineno_cname, Naming.exc_lineno_name))
4226 for var in Naming.exc_vars:
4227 code.putln(
4228 "%s = 0;" %
4229 var)
4230 code.put_goto(error_label)
4231 code.putln(
4232 "}")
4234 def annotate(self, code):
4235 self.body.annotate(code)
4236 self.finally_clause.annotate(code)
4239 class GILStatNode(TryFinallyStatNode):
4240 # 'with gil' or 'with nogil' statement
4242 # state string 'gil' or 'nogil'
4244 child_attrs = []
4246 preserve_exception = 0
4248 def __init__(self, pos, state, body):
4249 self.state = state
4250 TryFinallyStatNode.__init__(self, pos,
4251 body = body,
4252 finally_clause = GILExitNode(pos, state = state))
4254 def analyse_expressions(self, env):
4255 was_nogil = env.nogil
4256 env.nogil = 1
4257 TryFinallyStatNode.analyse_expressions(self, env)
4258 env.nogil = was_nogil
4260 def gil_check(self, env):
4261 pass
4263 def generate_execution_code(self, code):
4264 code.putln("/*with %s:*/ {" % self.state)
4265 if self.state == 'gil':
4266 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
4267 else:
4268 code.putln("PyThreadState *_save;")
4269 code.putln("Py_UNBLOCK_THREADS")
4270 TryFinallyStatNode.generate_execution_code(self, code)
4271 code.putln("}")
4274 class GILExitNode(StatNode):
4275 # Used as the 'finally' block in a GILStatNode
4277 # state string 'gil' or 'nogil'
4279 child_attrs = []
4281 def analyse_expressions(self, env):
4282 pass
4284 def generate_execution_code(self, code):
4285 if self.state == 'gil':
4286 code.putln("PyGILState_Release();")
4287 else:
4288 code.putln("Py_BLOCK_THREADS")
4291 class CImportStatNode(StatNode):
4292 # cimport statement
4294 # module_name string Qualified name of module being imported
4295 # as_name string or None Name specified in "as" clause, if any
4297 child_attrs = []
4299 def analyse_declarations(self, env):
4300 if not env.is_module_scope:
4301 error(self.pos, "cimport only allowed at module level")
4302 return
4303 module_scope = env.find_module(self.module_name, self.pos)
4304 if "." in self.module_name:
4305 names = [EncodedString(name) for name in self.module_name.split(".")]
4306 top_name = names[0]
4307 top_module_scope = env.context.find_submodule(top_name)
4308 module_scope = top_module_scope
4309 for name in names[1:]:
4310 submodule_scope = module_scope.find_submodule(name)
4311 module_scope.declare_module(name, submodule_scope, self.pos)
4312 module_scope = submodule_scope
4313 if self.as_name:
4314 env.declare_module(self.as_name, module_scope, self.pos)
4315 else:
4316 env.declare_module(top_name, top_module_scope, self.pos)
4317 else:
4318 name = self.as_name or self.module_name
4319 env.declare_module(name, module_scope, self.pos)
4321 def analyse_expressions(self, env):
4322 pass
4324 def generate_execution_code(self, code):
4325 pass
4328 class FromCImportStatNode(StatNode):
4329 # from ... cimport statement
4331 # module_name string Qualified name of module
4332 # imported_names [(pos, name, as_name, kind)] Names to be imported
4334 child_attrs = []
4336 def analyse_declarations(self, env):
4337 if not env.is_module_scope:
4338 error(self.pos, "cimport only allowed at module level")
4339 return
4340 module_scope = env.find_module(self.module_name, self.pos)
4341 env.add_imported_module(module_scope)
4342 for pos, name, as_name, kind in self.imported_names:
4343 if name == "*":
4344 for local_name, entry in module_scope.entries.items():
4345 env.add_imported_entry(local_name, entry, pos)
4346 else:
4347 entry = module_scope.lookup(name)
4348 if entry:
4349 if kind and not self.declaration_matches(entry, kind):
4350 entry.redeclared(pos)
4351 else:
4352 if kind == 'struct' or kind == 'union':
4353 entry = module_scope.declare_struct_or_union(name,
4354 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4355 elif kind == 'class':
4356 entry = module_scope.declare_c_class(name, pos = pos,
4357 module_name = self.module_name)
4358 else:
4359 error(pos, "Name '%s' not declared in module '%s'"
4360 % (name, self.module_name))
4362 if entry:
4363 local_name = as_name or name
4364 env.add_imported_entry(local_name, entry, pos)
4366 def declaration_matches(self, entry, kind):
4367 if not entry.is_type:
4368 return 0
4369 type = entry.type
4370 if kind == 'class':
4371 if not type.is_extension_type:
4372 return 0
4373 else:
4374 if not type.is_struct_or_union:
4375 return 0
4376 if kind <> type.kind:
4377 return 0
4378 return 1
4380 def analyse_expressions(self, env):
4381 pass
4383 def generate_execution_code(self, code):
4384 pass
4387 class FromImportStatNode(StatNode):
4388 # from ... import statement
4390 # module ImportNode
4391 # items [(string, NameNode)]
4392 # interned_items [(string, NameNode)]
4393 # item PyTempNode used internally
4394 # import_star boolean used internally
4396 child_attrs = ["module"]
4397 import_star = 0
4399 def analyse_declarations(self, env):
4400 for name, target in self.items:
4401 if name == "*":
4402 if not env.is_module_scope:
4403 error(self.pos, "import * only allowed at module level")
4404 return
4405 env.has_import_star = 1
4406 self.import_star = 1
4407 else:
4408 target.analyse_target_declaration(env)
4410 def analyse_expressions(self, env):
4411 import ExprNodes
4412 self.module.analyse_expressions(env)
4413 self.item = ExprNodes.PyTempNode(self.pos, env)
4414 self.item.allocate_temp(env)
4415 self.interned_items = []
4416 for name, target in self.items:
4417 if name == '*':
4418 for _, entry in env.entries.items():
4419 if not entry.is_type and entry.type.is_extension_type:
4420 env.use_utility_code(ExprNodes.type_test_utility_code)
4421 break
4422 else:
4423 self.interned_items.append(
4424 (env.intern_identifier(name), target))
4425 target.analyse_target_expression(env, None)
4426 #target.release_target_temp(env) # was release_temp ?!?
4427 self.module.release_temp(env)
4428 self.item.release_temp(env)
4430 def generate_execution_code(self, code):
4431 self.module.generate_evaluation_code(code)
4432 if self.import_star:
4433 code.putln(
4434 'if (%s(%s) < 0) %s;' % (
4435 Naming.import_star,
4436 self.module.py_result(),
4437 code.error_goto(self.pos)))
4438 for cname, target in self.interned_items:
4439 code.putln(
4440 '%s = PyObject_GetAttr(%s, %s); %s' % (
4441 self.item.result(),
4442 self.module.py_result(),
4443 cname,
4444 code.error_goto_if_null(self.item.result(), self.pos)))
4445 target.generate_assignment_code(self.item, code)
4446 self.module.generate_disposal_code(code)
4450 #------------------------------------------------------------------------------------
4452 # Runtime support code
4454 #------------------------------------------------------------------------------------
4456 utility_function_predeclarations = \
4457 """
4458 #ifdef __GNUC__
4459 #define INLINE __inline__
4460 #elif _WIN32
4461 #define INLINE __inline
4462 #else
4463 #define INLINE
4464 #endif
4466 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4468 """ + """
4470 static int %(skip_dispatch_cname)s = 0;
4472 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4474 if Options.gcc_branch_hints:
4475 branch_prediction_macros = \
4476 """
4477 #ifdef __GNUC__
4478 /* Test for GCC > 2.95 */
4479 #if __GNUC__ > 2 || \
4480 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4481 #define likely(x) __builtin_expect(!!(x), 1)
4482 #define unlikely(x) __builtin_expect(!!(x), 0)
4483 #else /* __GNUC__ > 2 ... */
4484 #define likely(x) (x)
4485 #define unlikely(x) (x)
4486 #endif /* __GNUC__ > 2 ... */
4487 #else /* __GNUC__ */
4488 #define likely(x) (x)
4489 #define unlikely(x) (x)
4490 #endif /* __GNUC__ */
4491 """
4492 else:
4493 branch_prediction_macros = \
4494 """
4495 #define likely(x) (x)
4496 #define unlikely(x) (x)
4497 """
4499 #get_name_predeclaration = \
4500 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4502 #get_name_interned_predeclaration = \
4503 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4505 #------------------------------------------------------------------------------------
4507 printing_utility_code = UtilityCode(
4508 proto = """
4509 static int __Pyx_Print(PyObject *, int); /*proto*/
4510 #if PY_MAJOR_VERSION >= 3
4511 static PyObject* %s = 0;
4512 static PyObject* %s = 0;
4513 #endif
4514 """ % (Naming.print_function, Naming.print_function_kwargs),
4515 impl = r"""
4516 #if PY_MAJOR_VERSION < 3
4517 static PyObject *__Pyx_GetStdout(void) {
4518 PyObject *f = PySys_GetObject("stdout");
4519 if (!f) {
4520 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4522 return f;
4525 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4526 PyObject *f;
4527 PyObject* v;
4528 int i;
4530 if (!(f = __Pyx_GetStdout()))
4531 return -1;
4532 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4533 if (PyFile_SoftSpace(f, 1)) {
4534 if (PyFile_WriteString(" ", f) < 0)
4535 return -1;
4537 v = PyTuple_GET_ITEM(arg_tuple, i);
4538 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4539 return -1;
4540 if (PyString_Check(v)) {
4541 char *s = PyString_AsString(v);
4542 Py_ssize_t len = PyString_Size(v);
4543 if (len > 0 &&
4544 isspace(Py_CHARMASK(s[len-1])) &&
4545 s[len-1] != ' ')
4546 PyFile_SoftSpace(f, 0);
4549 if (newline) {
4550 if (PyFile_WriteString("\n", f) < 0)
4551 return -1;
4552 PyFile_SoftSpace(f, 0);
4554 return 0;
4557 #else /* Python 3 has a print function */
4558 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4559 PyObject* kwargs = 0;
4560 PyObject* result = 0;
4561 PyObject* end_string;
4562 if (!%(PRINT_FUNCTION)s) {
4563 %(PRINT_FUNCTION)s = PyObject_GetAttrString(%(BUILTINS)s, "print");
4564 if (!%(PRINT_FUNCTION)s)
4565 return -1;
4567 if (!newline) {
4568 if (!%(PRINT_KWARGS)s) {
4569 %(PRINT_KWARGS)s = PyDict_New();
4570 if (!%(PRINT_KWARGS)s)
4571 return -1;
4572 end_string = PyUnicode_FromStringAndSize(" ", 1);
4573 if (!end_string)
4574 return -1;
4575 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4576 Py_DECREF(end_string);
4577 return -1;
4579 Py_DECREF(end_string);
4581 kwargs = %(PRINT_KWARGS)s;
4583 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4584 if (!result)
4585 return -1;
4586 Py_DECREF(result);
4587 return 0;
4589 #endif
4590 """ % {'BUILTINS' : Naming.builtins_cname,
4591 'PRINT_FUNCTION' : Naming.print_function,
4592 'PRINT_KWARGS' : Naming.print_function_kwargs}
4595 #------------------------------------------------------------------------------------
4597 # The following function is based on do_raise() from ceval.c.
4599 raise_utility_code = UtilityCode(
4600 proto = """
4601 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4602 """,
4603 impl = """
4604 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4605 Py_XINCREF(type);
4606 Py_XINCREF(value);
4607 Py_XINCREF(tb);
4608 /* First, check the traceback argument, replacing None with NULL. */
4609 if (tb == Py_None) {
4610 Py_DECREF(tb);
4611 tb = 0;
4613 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4614 PyErr_SetString(PyExc_TypeError,
4615 "raise: arg 3 must be a traceback or None");
4616 goto raise_error;
4618 /* Next, replace a missing value with None */
4619 if (value == NULL) {
4620 value = Py_None;
4621 Py_INCREF(value);
4623 #if PY_VERSION_HEX < 0x02050000
4624 if (!PyClass_Check(type))
4625 #else
4626 if (!PyType_Check(type))
4627 #endif
4629 /* Raising an instance. The value should be a dummy. */
4630 if (value != Py_None) {
4631 PyErr_SetString(PyExc_TypeError,
4632 "instance exception may not have a separate value");
4633 goto raise_error;
4635 /* Normalize to raise <class>, <instance> */
4636 Py_DECREF(value);
4637 value = type;
4638 #if PY_VERSION_HEX < 0x02050000
4639 if (PyInstance_Check(type)) {
4640 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4641 Py_INCREF(type);
4643 else {
4644 type = 0;
4645 PyErr_SetString(PyExc_TypeError,
4646 "raise: exception must be an old-style class or instance");
4647 goto raise_error;
4649 #else
4650 type = (PyObject*) Py_TYPE(type);
4651 Py_INCREF(type);
4652 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4653 PyErr_SetString(PyExc_TypeError,
4654 "raise: exception class must be a subclass of BaseException");
4655 goto raise_error;
4657 #endif
4659 __Pyx_ErrRestore(type, value, tb);
4660 return;
4661 raise_error:
4662 Py_XDECREF(value);
4663 Py_XDECREF(type);
4664 Py_XDECREF(tb);
4665 return;
4667 """)
4669 #------------------------------------------------------------------------------------
4671 reraise_utility_code = UtilityCode(
4672 proto = """
4673 static void __Pyx_ReRaise(void); /*proto*/
4674 """,
4675 impl = """
4676 static void __Pyx_ReRaise(void) {
4677 PyThreadState *tstate = PyThreadState_Get();
4678 PyObject *type = tstate->exc_type;
4679 PyObject *value = tstate->exc_value;
4680 PyObject *tb = tstate->exc_traceback;
4681 Py_XINCREF(type);
4682 Py_XINCREF(value);
4683 Py_XINCREF(tb);
4684 __Pyx_ErrRestore(type, value, tb);
4686 """)
4688 #------------------------------------------------------------------------------------
4690 arg_type_test_utility_code = UtilityCode(
4691 proto = """
4692 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4693 const char *name, int exact); /*proto*/
4694 """,
4695 impl = """
4696 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4697 const char *name, int exact)
4699 if (!type) {
4700 PyErr_Format(PyExc_SystemError, "Missing type object");
4701 return 0;
4703 if (none_allowed && obj == Py_None) return 1;
4704 else if (exact) {
4705 if (Py_TYPE(obj) == type) return 1;
4707 else {
4708 if (PyObject_TypeCheck(obj, type)) return 1;
4710 PyErr_Format(PyExc_TypeError,
4711 "Argument '%s' has incorrect type (expected %s, got %s)",
4712 name, type->tp_name, Py_TYPE(obj)->tp_name);
4713 return 0;
4715 """)
4717 #------------------------------------------------------------------------------------
4719 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
4720 # many or too few positional arguments were found. This handles
4721 # Py_ssize_t formatting correctly.
4723 raise_argtuple_invalid_utility_code = UtilityCode(
4724 proto = """
4725 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
4726 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
4727 """,
4728 impl = """
4729 static void __Pyx_RaiseArgtupleInvalid(
4730 const char* func_name,
4731 int exact,
4732 Py_ssize_t num_min,
4733 Py_ssize_t num_max,
4734 Py_ssize_t num_found)
4736 Py_ssize_t num_expected;
4737 const char *number, *more_or_less;
4739 if (num_found < num_min) {
4740 num_expected = num_min;
4741 more_or_less = "at least";
4742 } else {
4743 num_expected = num_max;
4744 more_or_less = "at most";
4746 if (exact) {
4747 more_or_less = "exactly";
4749 number = (num_expected == 1) ? "" : "s";
4750 PyErr_Format(PyExc_TypeError,
4751 #if PY_VERSION_HEX < 0x02050000
4752 "%s() takes %s %d positional argument%s (%d given)",
4753 #else
4754 "%s() takes %s %zd positional argument%s (%zd given)",
4755 #endif
4756 func_name, more_or_less, num_expected, number, num_found);
4758 """)
4760 raise_keyword_required_utility_code = UtilityCode(
4761 proto = """
4762 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
4763 """,
4764 impl = """
4765 static INLINE void __Pyx_RaiseKeywordRequired(
4766 const char* func_name,
4767 PyObject* kw_name)
4769 PyErr_Format(PyExc_TypeError,
4770 #if PY_MAJOR_VERSION >= 3
4771 "%s() needs keyword-only argument %U", func_name, kw_name);
4772 #else
4773 "%s() needs keyword-only argument %s", func_name,
4774 PyString_AS_STRING(kw_name));
4775 #endif
4777 """)
4779 raise_double_keywords_utility_code = UtilityCode(
4780 proto = """
4781 static void __Pyx_RaiseDoubleKeywordsError(
4782 const char* func_name, PyObject* kw_name); /*proto*/
4783 """,
4784 impl = """
4785 static void __Pyx_RaiseDoubleKeywordsError(
4786 const char* func_name,
4787 PyObject* kw_name)
4789 PyErr_Format(PyExc_TypeError,
4790 #if PY_MAJOR_VERSION >= 3
4791 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
4792 #else
4793 "%s() got multiple values for keyword argument '%s'", func_name,
4794 PyString_AS_STRING(kw_name));
4795 #endif
4797 """)
4799 #------------------------------------------------------------------------------------
4801 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
4802 # were passed to a function, or if any keywords were passed to a
4803 # function that does not accept them.
4805 keyword_string_check_utility_code = UtilityCode(
4806 proto = """
4807 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
4808 const char* function_name, int kw_allowed); /*proto*/
4809 """,
4810 impl = """
4811 static INLINE int __Pyx_CheckKeywordStrings(
4812 PyObject *kwdict,
4813 const char* function_name,
4814 int kw_allowed)
4816 PyObject* key = 0;
4817 Py_ssize_t pos = 0;
4818 while (PyDict_Next(kwdict, &pos, &key, 0)) {
4819 #if PY_MAJOR_VERSION < 3
4820 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
4821 #else
4822 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
4823 #endif
4824 goto invalid_keyword_type;
4826 if ((!kw_allowed) && unlikely(key))
4827 goto invalid_keyword;
4828 return 1;
4829 invalid_keyword_type:
4830 PyErr_Format(PyExc_TypeError,
4831 "%s() keywords must be strings", function_name);
4832 return 0;
4833 invalid_keyword:
4834 PyErr_Format(PyExc_TypeError,
4835 #if PY_MAJOR_VERSION < 3
4836 "%s() got an unexpected keyword argument '%s'",
4837 function_name, PyString_AsString(key));
4838 #else
4839 "%s() got an unexpected keyword argument '%U'",
4840 function_name, key);
4841 #endif
4842 return 0;
4844 """)
4846 #------------------------------------------------------------------------------------
4848 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
4849 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
4850 # keywords will raise an invalid keyword error.
4852 # Three kinds of errors are checked: 1) non-string keywords, 2)
4853 # unexpected keywords and 3) overlap with positional arguments.
4855 # If num_posargs is greater 0, it denotes the number of positional
4856 # arguments that were passed and that must therefore not appear
4857 # amongst the keywords as well.
4859 # This method does not check for required keyword arguments.
4862 parse_keywords_utility_code = UtilityCode(
4863 proto = """
4864 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
4865 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
4866 const char* function_name); /*proto*/
4867 """,
4868 impl = """
4869 static int __Pyx_ParseOptionalKeywords(
4870 PyObject *kwds,
4871 PyObject **argnames[],
4872 PyObject *kwds2,
4873 PyObject *values[],
4874 Py_ssize_t num_pos_args,
4875 const char* function_name)
4877 PyObject *key = 0, *value = 0;
4878 Py_ssize_t pos = 0;
4879 PyObject*** name;
4880 PyObject*** first_kw_arg = argnames + num_pos_args;
4882 while (PyDict_Next(kwds, &pos, &key, &value)) {
4883 #if PY_MAJOR_VERSION < 3
4884 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
4885 #else
4886 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
4887 #endif
4888 goto invalid_keyword_type;
4889 } else {
4890 name = argnames;
4891 while (*name && (**name != key)) name++;
4892 if (*name) {
4893 if (name < first_kw_arg) goto arg_passed_twice;
4894 values[name-argnames] = value;
4895 } else {
4896 for (name = first_kw_arg; *name; name++) {
4897 #if PY_MAJOR_VERSION >= 3
4898 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
4899 PyUnicode_Compare(**name, key) == 0) break;
4900 #else
4901 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
4902 strcmp(PyString_AS_STRING(**name),
4903 PyString_AS_STRING(key)) == 0) break;
4904 #endif
4906 if (*name) {
4907 values[name-argnames] = value;
4908 } else {
4909 /* unexpected keyword found */
4910 for (name=argnames; name != first_kw_arg; name++) {
4911 if (**name == key) goto arg_passed_twice;
4912 #if PY_MAJOR_VERSION >= 3
4913 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
4914 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
4915 #else
4916 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
4917 strcmp(PyString_AS_STRING(**name),
4918 PyString_AS_STRING(key)) == 0) goto arg_passed_twice;
4919 #endif
4921 if (kwds2) {
4922 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
4923 } else {
4924 goto invalid_keyword;
4930 return 0;
4931 arg_passed_twice:
4932 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
4933 goto bad;
4934 invalid_keyword_type:
4935 PyErr_Format(PyExc_TypeError,
4936 "%s() keywords must be strings", function_name);
4937 goto bad;
4938 invalid_keyword:
4939 PyErr_Format(PyExc_TypeError,
4940 #if PY_MAJOR_VERSION < 3
4941 "%s() got an unexpected keyword argument '%s'",
4942 function_name, PyString_AsString(key));
4943 #else
4944 "%s() got an unexpected keyword argument '%U'",
4945 function_name, key);
4946 #endif
4947 bad:
4948 return -1;
4950 """)
4952 #------------------------------------------------------------------------------------
4954 unraisable_exception_utility_code = UtilityCode(
4955 proto = """
4956 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
4957 """,
4958 impl = """
4959 static void __Pyx_WriteUnraisable(const char *name) {
4960 PyObject *old_exc, *old_val, *old_tb;
4961 PyObject *ctx;
4962 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
4963 #if PY_MAJOR_VERSION < 3
4964 ctx = PyString_FromString(name);
4965 #else
4966 ctx = PyUnicode_FromString(name);
4967 #endif
4968 __Pyx_ErrRestore(old_exc, old_val, old_tb);
4969 if (!ctx) {
4970 PyErr_WriteUnraisable(Py_None);
4971 } else {
4972 PyErr_WriteUnraisable(ctx);
4973 Py_DECREF(ctx);
4976 """)
4978 #------------------------------------------------------------------------------------
4980 traceback_utility_code = UtilityCode(
4981 proto = """
4982 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
4983 """,
4984 impl = """
4985 #include "compile.h"
4986 #include "frameobject.h"
4987 #include "traceback.h"
4989 static void __Pyx_AddTraceback(const char *funcname) {
4990 PyObject *py_srcfile = 0;
4991 PyObject *py_funcname = 0;
4992 PyObject *py_globals = 0;
4993 PyObject *empty_string = 0;
4994 PyCodeObject *py_code = 0;
4995 PyFrameObject *py_frame = 0;
4997 #if PY_MAJOR_VERSION < 3
4998 py_srcfile = PyString_FromString(%(FILENAME)s);
4999 #else
5000 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5001 #endif
5002 if (!py_srcfile) goto bad;
5003 if (%(CLINENO)s) {
5004 #if PY_MAJOR_VERSION < 3
5005 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5006 #else
5007 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5008 #endif
5010 else {
5011 #if PY_MAJOR_VERSION < 3
5012 py_funcname = PyString_FromString(funcname);
5013 #else
5014 py_funcname = PyUnicode_FromString(funcname);
5015 #endif
5017 if (!py_funcname) goto bad;
5018 py_globals = PyModule_GetDict(%(GLOBALS)s);
5019 if (!py_globals) goto bad;
5020 #if PY_MAJOR_VERSION < 3
5021 empty_string = PyString_FromStringAndSize("", 0);
5022 #else
5023 empty_string = PyBytes_FromStringAndSize("", 0);
5024 #endif
5025 if (!empty_string) goto bad;
5026 py_code = PyCode_New(
5027 0, /*int argcount,*/
5028 #if PY_MAJOR_VERSION >= 3
5029 0, /*int kwonlyargcount,*/
5030 #endif
5031 0, /*int nlocals,*/
5032 0, /*int stacksize,*/
5033 0, /*int flags,*/
5034 empty_string, /*PyObject *code,*/
5035 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5036 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5037 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5038 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5039 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5040 py_srcfile, /*PyObject *filename,*/
5041 py_funcname, /*PyObject *name,*/
5042 %(LINENO)s, /*int firstlineno,*/
5043 empty_string /*PyObject *lnotab*/
5044 );
5045 if (!py_code) goto bad;
5046 py_frame = PyFrame_New(
5047 PyThreadState_GET(), /*PyThreadState *tstate,*/
5048 py_code, /*PyCodeObject *code,*/
5049 py_globals, /*PyObject *globals,*/
5050 0 /*PyObject *locals*/
5051 );
5052 if (!py_frame) goto bad;
5053 py_frame->f_lineno = %(LINENO)s;
5054 PyTraceBack_Here(py_frame);
5055 bad:
5056 Py_XDECREF(py_srcfile);
5057 Py_XDECREF(py_funcname);
5058 Py_XDECREF(empty_string);
5059 Py_XDECREF(py_code);
5060 Py_XDECREF(py_frame);
5062 """ % {
5063 'FILENAME': Naming.filename_cname,
5064 'LINENO': Naming.lineno_cname,
5065 'CFILENAME': Naming.cfilenm_cname,
5066 'CLINENO': Naming.clineno_cname,
5067 'GLOBALS': Naming.module_cname,
5068 'EMPTY_TUPLE' : Naming.empty_tuple,
5069 })
5071 restore_exception_utility_code = UtilityCode(
5072 proto = """
5073 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5074 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5075 """,
5076 impl = """
5077 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5078 PyObject *tmp_type, *tmp_value, *tmp_tb;
5079 PyThreadState *tstate = PyThreadState_GET();
5081 tmp_type = tstate->curexc_type;
5082 tmp_value = tstate->curexc_value;
5083 tmp_tb = tstate->curexc_traceback;
5084 tstate->curexc_type = type;
5085 tstate->curexc_value = value;
5086 tstate->curexc_traceback = tb;
5087 Py_XDECREF(tmp_type);
5088 Py_XDECREF(tmp_value);
5089 Py_XDECREF(tmp_tb);
5092 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5093 PyThreadState *tstate = PyThreadState_GET();
5094 *type = tstate->curexc_type;
5095 *value = tstate->curexc_value;
5096 *tb = tstate->curexc_traceback;
5098 tstate->curexc_type = 0;
5099 tstate->curexc_value = 0;
5100 tstate->curexc_traceback = 0;
5103 """)
5105 #------------------------------------------------------------------------------------
5107 set_vtable_utility_code = UtilityCode(
5108 proto = """
5109 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5110 """,
5111 impl = """
5112 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5113 PyObject *pycobj = 0;
5114 int result;
5116 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5117 if (!pycobj)
5118 goto bad;
5119 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5120 goto bad;
5121 result = 0;
5122 goto done;
5124 bad:
5125 result = -1;
5126 done:
5127 Py_XDECREF(pycobj);
5128 return result;
5130 """)
5132 #------------------------------------------------------------------------------------
5134 get_vtable_utility_code = UtilityCode(
5135 proto = """
5136 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5137 """,
5138 impl = r"""
5139 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5140 int result;
5141 PyObject *pycobj;
5143 pycobj = PyMapping_GetItemString(dict, "__pyx_vtable__");
5144 if (!pycobj)
5145 goto bad;
5146 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5147 if (!*(void **)vtabptr)
5148 goto bad;
5149 result = 0;
5150 goto done;
5152 bad:
5153 result = -1;
5154 done:
5155 Py_XDECREF(pycobj);
5156 return result;
5158 """)
5160 #------------------------------------------------------------------------------------
5162 init_string_tab_utility_code = UtilityCode(
5163 proto = """
5164 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5165 """,
5166 impl = """
5167 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5168 while (t->p) {
5169 #if PY_MAJOR_VERSION < 3
5170 if (t->is_unicode && (!t->is_identifier)) {
5171 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5172 } else if (t->intern) {
5173 *t->p = PyString_InternFromString(t->s);
5174 } else {
5175 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5177 #else /* Python 3+ has unicode identifiers */
5178 if (t->is_identifier || (t->is_unicode && t->intern)) {
5179 *t->p = PyUnicode_InternFromString(t->s);
5180 } else if (t->is_unicode) {
5181 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5182 } else {
5183 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5185 #endif
5186 if (!*t->p)
5187 return -1;
5188 ++t;
5190 return 0;
5192 """)
5194 #------------------------------------------------------------------------------------
5196 get_exception_utility_code = UtilityCode(
5197 proto = """
5198 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5199 """,
5200 impl = """
5201 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5202 PyObject *tmp_type, *tmp_value, *tmp_tb;
5203 PyThreadState *tstate = PyThreadState_GET();
5204 __Pyx_ErrFetch(type, value, tb);
5205 PyErr_NormalizeException(type, value, tb);
5206 if (PyErr_Occurred())
5207 goto bad;
5208 Py_INCREF(*type);
5209 Py_INCREF(*value);
5210 Py_INCREF(*tb);
5211 tmp_type = tstate->exc_type;
5212 tmp_value = tstate->exc_value;
5213 tmp_tb = tstate->exc_traceback;
5214 tstate->exc_type = *type;
5215 tstate->exc_value = *value;
5216 tstate->exc_traceback = *tb;
5217 /* Make sure tstate is in a consistent state when we XDECREF
5218 these objects (XDECREF may run arbitrary code). */
5219 Py_XDECREF(tmp_type);
5220 Py_XDECREF(tmp_value);
5221 Py_XDECREF(tmp_tb);
5222 return 0;
5223 bad:
5224 Py_XDECREF(*type);
5225 Py_XDECREF(*value);
5226 Py_XDECREF(*tb);
5227 return -1;
5230 """)
5232 #------------------------------------------------------------------------------------
5234 reset_exception_utility_code = UtilityCode(
5235 proto = """
5236 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5237 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5238 """,
5239 impl = """
5240 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5241 PyThreadState *tstate = PyThreadState_GET();
5242 *type = tstate->exc_type;
5243 *value = tstate->exc_value;
5244 *tb = tstate->exc_traceback;
5245 Py_XINCREF(*type);
5246 Py_XINCREF(*value);
5247 Py_XINCREF(*tb);
5250 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5251 PyObject *tmp_type, *tmp_value, *tmp_tb;
5252 PyThreadState *tstate = PyThreadState_GET();
5253 tmp_type = tstate->exc_type;
5254 tmp_value = tstate->exc_value;
5255 tmp_tb = tstate->exc_traceback;
5256 tstate->exc_type = type;
5257 tstate->exc_value = value;
5258 tstate->exc_traceback = tb;
5259 Py_XDECREF(tmp_type);
5260 Py_XDECREF(tmp_value);
5261 Py_XDECREF(tmp_tb);
5263 """)
5265 #------------------------------------------------------------------------------------