Cython has moved to github.

cython

view Cython/Compiler/Nodes.py @ 1380:04e83ffd8ea2

conservative fix for empty switch statements
author Stefan Behnel <scoder@users.berlios.de>
date Fri Nov 07 06:55:37 2008 +0100 (3 years ago)
parents ef9d2c680684
children 92baafe0edf3
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 if self.attributes is not None:
788 if self.in_pxd and not env.in_cinclude:
789 self.entry.defined_in_pxd = 1
790 for attr in self.attributes:
791 attr.analyse_declarations(env, scope)
793 def analyse_expressions(self, env):
794 pass
796 def generate_execution_code(self, code):
797 pass
800 class CEnumDefNode(StatNode):
801 # name string or None
802 # cname string or None
803 # items [CEnumDefItemNode]
804 # typedef_flag boolean
805 # visibility "public" or "private"
806 # in_pxd boolean
807 # entry Entry
809 child_attrs = ["items"]
811 def analyse_declarations(self, env):
812 self.entry = env.declare_enum(self.name, self.pos,
813 cname = self.cname, typedef_flag = self.typedef_flag,
814 visibility = self.visibility)
815 if self.items is not None:
816 if self.in_pxd and not env.in_cinclude:
817 self.entry.defined_in_pxd = 1
818 for item in self.items:
819 item.analyse_declarations(env, self.entry)
821 def analyse_expressions(self, env):
822 if self.visibility == 'public':
823 self.temp = env.allocate_temp_pyobject()
824 env.release_temp(self.temp)
826 def generate_execution_code(self, code):
827 if self.visibility == 'public':
828 for item in self.entry.enum_values:
829 code.putln("%s = PyInt_FromLong(%s); %s" % (
830 self.temp,
831 item.cname,
832 code.error_goto_if_null(self.temp, item.pos)))
833 code.putln('if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
834 Naming.module_cname,
835 item.name,
836 self.temp,
837 code.error_goto(item.pos)))
838 code.putln("%s = 0;" % self.temp)
841 class CEnumDefItemNode(StatNode):
842 # name string
843 # cname string or None
844 # value ExprNode or None
846 child_attrs = ["value"]
848 def analyse_declarations(self, env, enum_entry):
849 if self.value:
850 self.value.analyse_const_expression(env)
851 if not self.value.type.is_int:
852 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
853 self.value.analyse_const_expression(env)
854 value = self.value.result()
855 else:
856 value = self.name
857 entry = env.declare_const(self.name, enum_entry.type,
858 value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
859 enum_entry.enum_values.append(entry)
862 class CTypeDefNode(StatNode):
863 # base_type CBaseTypeNode
864 # declarator CDeclaratorNode
865 # visibility "public" or "private"
866 # in_pxd boolean
868 child_attrs = ["base_type", "declarator"]
870 def analyse_declarations(self, env):
871 base = self.base_type.analyse(env)
872 name_declarator, type = self.declarator.analyse(base, env)
873 name = name_declarator.name
874 cname = name_declarator.cname
875 entry = env.declare_typedef(name, type, self.pos,
876 cname = cname, visibility = self.visibility)
877 if self.in_pxd and not env.in_cinclude:
878 entry.defined_in_pxd = 1
880 def analyse_expressions(self, env):
881 pass
882 def generate_execution_code(self, code):
883 pass
886 class FuncDefNode(StatNode, BlockNode):
887 # Base class for function definition nodes.
888 #
889 # return_type PyrexType
890 # #filename string C name of filename string const
891 # entry Symtab.Entry
892 # needs_closure boolean Whether or not this function has inner functions/classes/yield
894 py_func = None
895 assmt = None
896 needs_closure = False
898 def analyse_default_values(self, env):
899 genv = env.global_scope()
900 for arg in self.args:
901 if arg.default:
902 if arg.is_generic:
903 if not hasattr(arg, 'default_entry'):
904 arg.default.analyse_types(env)
905 arg.default = arg.default.coerce_to(arg.type, genv)
906 if arg.default.is_literal:
907 arg.default_entry = arg.default
908 arg.default_result_code = arg.default.calculate_result_code()
909 if arg.default.type != arg.type and not arg.type.is_int:
910 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
911 else:
912 arg.default.allocate_temps(genv)
913 arg.default_entry = genv.add_default_value(arg.type)
914 arg.default_entry.used = 1
915 arg.default_result_code = arg.default_entry.cname
916 else:
917 error(arg.pos,
918 "This argument cannot have a default value")
919 arg.default = None
921 def need_gil_acquisition(self, lenv):
922 return 0
924 def create_local_scope(self, env):
925 genv = env
926 while env.is_py_class_scope or env.is_c_class_scope:
927 env = env.outer_scope
928 if self.needs_closure:
929 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
930 else:
931 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
932 lenv.return_type = self.return_type
933 type = self.entry.type
934 if type.is_cfunction:
935 lenv.nogil = type.nogil and not type.with_gil
936 self.local_scope = lenv
937 return lenv
939 def generate_function_definitions(self, env, code):
940 import Buffer
942 lenv = self.local_scope
944 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
945 self.entry.scope.is_c_class_scope)
947 # Generate C code for header and body of function
948 code.enter_cfunc_scope()
949 code.return_from_error_cleanup_label = code.new_label()
951 # ----- Top-level constants used by this function
952 code.mark_pos(self.pos)
953 self.generate_interned_num_decls(lenv, code)
954 self.generate_interned_string_decls(lenv, code)
955 self.generate_py_string_decls(lenv, code)
956 self.generate_cached_builtins_decls(lenv, code)
957 #code.putln("")
958 #code.put_var_declarations(lenv.const_entries, static = 1)
959 self.generate_const_definitions(lenv, code)
960 # ----- Function header
961 code.putln("")
962 if self.py_func:
963 self.py_func.generate_function_header(code,
964 with_pymethdef = env.is_py_class_scope,
965 proto_only=True)
966 self.generate_function_header(code,
967 with_pymethdef = env.is_py_class_scope)
968 # ----- Local variable declarations
969 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
970 self.generate_argument_declarations(lenv, code)
971 if self.needs_closure:
972 code.putln("/* TODO: declare and create scope object */")
973 code.put_var_declarations(lenv.var_entries)
974 init = ""
975 if not self.return_type.is_void:
976 code.putln(
977 "%s%s;" %
978 (self.return_type.declaration_code(
979 Naming.retval_cname),
980 init))
981 tempvardecl_code = code.insertion_point()
982 self.generate_keyword_list(code)
983 # ----- Extern library function declarations
984 lenv.generate_library_function_declarations(code)
985 # ----- GIL acquisition
986 acquire_gil = self.need_gil_acquisition(lenv)
987 if acquire_gil:
988 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
989 # ----- Automatic lead-ins for certain special functions
990 if is_getbuffer_slot:
991 self.getbuffer_init(code)
992 # ----- Fetch arguments
993 self.generate_argument_parsing_code(env, code)
994 # If an argument is assigned to in the body, we must
995 # incref it to properly keep track of refcounts.
996 for entry in lenv.arg_entries:
997 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
998 code.put_var_incref(entry)
999 # ----- Initialise local variables
1000 for entry in lenv.var_entries:
1001 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1002 code.put_init_var_to_py_none(entry)
1003 # ----- Initialise local buffer auxiliary variables
1004 for entry in lenv.var_entries + lenv.arg_entries:
1005 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1006 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1007 # ----- Check and convert arguments
1008 self.generate_argument_type_tests(code)
1009 # ----- Acquire buffer arguments
1010 for entry in lenv.arg_entries:
1011 if entry.type.is_buffer:
1012 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1013 # ----- Function body
1014 self.body.generate_execution_code(code)
1015 # ----- Default return value
1016 code.putln("")
1017 if self.return_type.is_pyobject:
1018 #if self.return_type.is_extension_type:
1019 # lhs = "(PyObject *)%s" % Naming.retval_cname
1020 #else:
1021 lhs = Naming.retval_cname
1022 code.put_init_to_py_none(lhs, self.return_type)
1023 else:
1024 val = self.return_type.default_value
1025 if val:
1026 code.putln("%s = %s;" % (Naming.retval_cname, val))
1027 # ----- Error cleanup
1028 if code.error_label in code.labels_used:
1029 code.put_goto(code.return_label)
1030 code.put_label(code.error_label)
1031 code.put_var_xdecrefs(lenv.temp_entries)
1033 # Clean up buffers -- this calls a Python function
1034 # so need to save and restore error state
1035 buffers_present = len(lenv.buffer_entries) > 0
1036 if buffers_present:
1037 code.globalstate.use_utility_code(restore_exception_utility_code)
1038 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1039 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1040 for entry in lenv.buffer_entries:
1041 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1042 #code.putln("%s = 0;" % entry.cname)
1043 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1045 err_val = self.error_value()
1046 exc_check = self.caller_will_check_exceptions()
1047 if err_val is not None or exc_check:
1048 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1049 else:
1050 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1051 % self.entry.qualified_name, 0)
1052 code.putln(
1053 '__Pyx_WriteUnraisable("%s");' %
1054 self.entry.qualified_name)
1055 env.use_utility_code(unraisable_exception_utility_code)
1056 env.use_utility_code(restore_exception_utility_code)
1057 default_retval = self.return_type.default_value
1058 if err_val is None and default_retval:
1059 err_val = default_retval
1060 if err_val is not None:
1061 code.putln(
1062 "%s = %s;" % (
1063 Naming.retval_cname,
1064 err_val))
1066 if is_getbuffer_slot:
1067 self.getbuffer_error_cleanup(code)
1069 # If we are using the non-error cleanup section we should
1070 # jump past it if we have an error. The if-test below determine
1071 # whether this section is used.
1072 if buffers_present or is_getbuffer_slot:
1073 code.put_goto(code.return_from_error_cleanup_label)
1076 # ----- Non-error return cleanup
1077 # If you add anything here, remember to add a condition to the
1078 # if-test above in the error block (so that it can jump past this
1079 # block).
1080 code.put_label(code.return_label)
1081 for entry in lenv.buffer_entries:
1082 if entry.used:
1083 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1084 if is_getbuffer_slot:
1085 self.getbuffer_normal_cleanup(code)
1086 # ----- Return cleanup for both error and no-error return
1087 code.put_label(code.return_from_error_cleanup_label)
1088 if not Options.init_local_none:
1089 for entry in lenv.var_entries:
1090 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1091 entry.xdecref_cleanup = 1
1092 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1093 # Decref any increfed args
1094 for entry in lenv.arg_entries:
1095 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1096 code.put_var_decref(entry)
1097 if acquire_gil:
1098 code.putln("PyGILState_Release(_save);")
1099 # code.putln("/* TODO: decref scope object */")
1100 # ----- Return
1101 if not self.return_type.is_void:
1102 code.putln("return %s;" % Naming.retval_cname)
1103 code.putln("}")
1104 # ----- Go back and insert temp variable declarations
1105 tempvardecl_code.put_var_declarations(lenv.temp_entries)
1106 tempvardecl_code.put_temp_declarations(code.funcstate)
1107 # ----- Python version
1108 code.exit_cfunc_scope()
1109 if self.py_func:
1110 self.py_func.generate_function_definitions(env, code)
1111 self.generate_wrapper_functions(code)
1113 def declare_argument(self, env, arg):
1114 if arg.type.is_void:
1115 error(arg.pos, "Invalid use of 'void'")
1116 elif not arg.type.is_complete() and not arg.type.is_array:
1117 error(arg.pos,
1118 "Argument type '%s' is incomplete" % arg.type)
1119 return env.declare_arg(arg.name, arg.type, arg.pos)
1121 def generate_wrapper_functions(self, code):
1122 pass
1124 def generate_execution_code(self, code):
1125 # Evaluate and store argument default values
1126 for arg in self.args:
1127 default = arg.default
1128 if default:
1129 if not default.is_literal:
1130 default.generate_evaluation_code(code)
1131 default.make_owned_reference(code)
1132 code.putln(
1133 "%s = %s;" % (
1134 arg.default_entry.cname,
1135 default.result_as(arg.default_entry.type)))
1136 if default.is_temp and default.type.is_pyobject:
1137 code.putln(
1138 "%s = 0;" %
1139 default.result())
1140 # For Python class methods, create and store function object
1141 if self.assmt:
1142 self.assmt.generate_execution_code(code)
1145 # Special code for the __getbuffer__ function
1147 def getbuffer_init(self, code):
1148 info = self.local_scope.arg_entries[1].cname
1149 # Python 3.0 betas have a bug in memoryview which makes it call
1150 # getbuffer with a NULL parameter. For now we work around this;
1151 # the following line should be removed when this bug is fixed.
1152 code.putln("if (%s == NULL) return 0;" % info)
1153 code.putln("%s->obj = Py_None; Py_INCREF(Py_None);" % info)
1155 def getbuffer_error_cleanup(self, code):
1156 info = self.local_scope.arg_entries[1].cname
1157 code.putln("Py_DECREF(%s->obj); %s->obj = NULL;" %
1158 (info, info))
1160 def getbuffer_normal_cleanup(self, code):
1161 info = self.local_scope.arg_entries[1].cname
1162 code.putln("if (%s->obj == Py_None) { Py_DECREF(Py_None); %s->obj = NULL; }" %
1163 (info, info))
1165 class CFuncDefNode(FuncDefNode):
1166 # C function definition.
1168 # modifiers ['inline']
1169 # visibility 'private' or 'public' or 'extern'
1170 # base_type CBaseTypeNode
1171 # declarator CDeclaratorNode
1172 # body StatListNode
1173 # api boolean
1175 # with_gil boolean Acquire GIL around body
1176 # type CFuncType
1177 # py_func wrapper for calling from Python
1178 # overridable whether or not this is a cpdef function
1180 child_attrs = ["base_type", "declarator", "body", "py_func"]
1182 def unqualified_name(self):
1183 return self.entry.name
1185 def analyse_declarations(self, env):
1186 if 'locals' in env.directives:
1187 directive_locals = env.directives['locals']
1188 else:
1189 directive_locals = {}
1190 self.directive_locals = directive_locals
1191 base_type = self.base_type.analyse(env)
1192 # The 2 here is because we need both function and argument names.
1193 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1194 if not type.is_cfunction:
1195 error(self.pos,
1196 "Suite attached to non-function declaration")
1197 # Remember the actual type according to the function header
1198 # written here, because the type in the symbol table entry
1199 # may be different if we're overriding a C method inherited
1200 # from the base type of an extension type.
1201 self.type = type
1202 type.is_overridable = self.overridable
1203 declarator = self.declarator
1204 while not hasattr(declarator, 'args'):
1205 declarator = declarator.base
1206 self.args = declarator.args
1207 for formal_arg, type_arg in zip(self.args, type.args):
1208 formal_arg.type = type_arg.type
1209 formal_arg.cname = type_arg.cname
1210 name = name_declarator.name
1211 cname = name_declarator.cname
1212 self.entry = env.declare_cfunction(
1213 name, type, self.pos,
1214 cname = cname, visibility = self.visibility,
1215 defining = self.body is not None,
1216 api = self.api)
1217 self.return_type = type.return_type
1219 if self.overridable:
1220 import ExprNodes
1221 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1222 self.py_func = DefNode(pos = self.pos,
1223 name = self.entry.name,
1224 args = self.args,
1225 star_arg = None,
1226 starstar_arg = None,
1227 doc = self.doc,
1228 body = py_func_body,
1229 is_wrapper = 1)
1230 self.py_func.is_module_scope = env.is_module_scope
1231 self.py_func.analyse_declarations(env)
1232 self.entry.as_variable = self.py_func.entry
1233 # Reset scope entry the above cfunction
1234 env.entries[name] = self.entry
1235 self.py_func.interned_attr_cname = env.intern_identifier(
1236 self.py_func.entry.name)
1237 if not env.is_module_scope or Options.lookup_module_cpdef:
1238 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1239 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1241 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1242 import ExprNodes
1243 args = self.type.args
1244 if omit_optional_args:
1245 args = args[:len(args) - self.type.optional_arg_count]
1246 arg_names = [arg.name for arg in args]
1247 if is_module_scope:
1248 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1249 else:
1250 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1251 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1252 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1253 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)
1254 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1256 def declare_arguments(self, env):
1257 for arg in self.type.args:
1258 if not arg.name:
1259 error(arg.pos, "Missing argument name")
1260 self.declare_argument(env, arg)
1262 def need_gil_acquisition(self, lenv):
1263 type = self.type
1264 with_gil = self.type.with_gil
1265 if type.nogil and not with_gil:
1266 if type.return_type.is_pyobject:
1267 error(self.pos,
1268 "Function with Python return type cannot be declared nogil")
1269 for entry in lenv.var_entries + lenv.temp_entries:
1270 if entry.type.is_pyobject:
1271 error(self.pos, "Function declared nogil has Python locals or temporaries")
1272 return with_gil
1274 def analyse_expressions(self, env):
1275 self.analyse_default_values(env)
1276 if self.overridable:
1277 self.py_func.analyse_expressions(env)
1279 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1280 arg_decls = []
1281 type = self.type
1282 visibility = self.entry.visibility
1283 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1284 arg_decls.append(arg.declaration_code())
1285 if with_dispatch and self.overridable:
1286 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1287 if type.optional_arg_count and with_opt_args:
1288 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1289 if type.has_varargs:
1290 arg_decls.append("...")
1291 if not arg_decls:
1292 arg_decls = ["void"]
1293 if cname is None:
1294 cname = self.entry.func_cname
1295 entity = type.function_header_code(cname, string.join(arg_decls, ", "))
1296 if visibility == 'public':
1297 dll_linkage = "DL_EXPORT"
1298 else:
1299 dll_linkage = None
1300 header = self.return_type.declaration_code(entity,
1301 dll_linkage = dll_linkage)
1302 if visibility == 'extern':
1303 storage_class = "%s " % Naming.extern_c_macro
1304 elif visibility == 'public':
1305 storage_class = ""
1306 else:
1307 storage_class = "static "
1308 code.putln("%s%s %s {" % (
1309 storage_class,
1310 ' '.join(self.modifiers).upper(), # macro forms
1311 header))
1313 def generate_argument_declarations(self, env, code):
1314 for arg in self.args:
1315 if arg.default:
1316 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1318 def generate_keyword_list(self, code):
1319 pass
1321 def generate_argument_parsing_code(self, env, code):
1322 i = 0
1323 if self.type.optional_arg_count:
1324 code.putln('if (%s) {' % Naming.optional_args_cname)
1325 for arg in self.args:
1326 if arg.default:
1327 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1328 declarator = arg.declarator
1329 while not hasattr(declarator, 'name'):
1330 declarator = declarator.base
1331 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1332 i += 1
1333 for _ in range(self.type.optional_arg_count):
1334 code.putln('}')
1335 code.putln('}')
1337 def generate_argument_conversion_code(self, code):
1338 pass
1340 def generate_argument_type_tests(self, code):
1341 # Generate type tests for args whose type in a parent
1342 # class is a supertype of the declared type.
1343 for arg in self.type.args:
1344 if arg.needs_type_test:
1345 self.generate_arg_type_test(arg, code)
1347 def generate_arg_type_test(self, arg, code):
1348 # Generate type test for one argument.
1349 if arg.type.typeobj_is_available():
1350 typeptr_cname = arg.type.typeptr_cname
1351 arg_code = "((PyObject *)%s)" % arg.cname
1352 code.putln(
1353 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1354 arg_code,
1355 typeptr_cname,
1356 not arg.not_none,
1357 arg.name,
1358 type.is_builtin_type,
1359 code.error_goto(arg.pos)))
1360 else:
1361 error(arg.pos, "Cannot test type of extern C class "
1362 "without type object name specification")
1364 def error_value(self):
1365 if self.return_type.is_pyobject:
1366 return "0"
1367 else:
1368 #return None
1369 return self.entry.type.exception_value
1371 def caller_will_check_exceptions(self):
1372 return self.entry.type.exception_check
1374 def generate_wrapper_functions(self, code):
1375 # If the C signature of a function has changed, we need to generate
1376 # wrappers to put in the slots here.
1377 k = 0
1378 entry = self.entry
1379 func_type = entry.type
1380 while entry.prev_entry is not None:
1381 k += 1
1382 entry = entry.prev_entry
1383 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1384 code.putln()
1385 self.generate_function_header(code,
1386 0,
1387 with_dispatch = entry.type.is_overridable,
1388 with_opt_args = entry.type.optional_arg_count,
1389 cname = entry.func_cname)
1390 if not self.return_type.is_void:
1391 code.put('return ')
1392 args = self.type.args
1393 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1394 if entry.type.is_overridable:
1395 arglist.append(Naming.skip_dispatch_cname)
1396 elif func_type.is_overridable:
1397 arglist.append('0')
1398 if entry.type.optional_arg_count:
1399 arglist.append(Naming.optional_args_cname)
1400 elif func_type.optional_arg_count:
1401 arglist.append('NULL')
1402 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1403 code.putln('}')
1406 class PyArgDeclNode(Node):
1407 # Argument which must be a Python object (used
1408 # for * and ** arguments).
1410 # name string
1411 # entry Symtab.Entry
1412 child_attrs = []
1415 class DecoratorNode(Node):
1416 # A decorator
1418 # decorator NameNode or CallNode
1419 child_attrs = ['decorator']
1422 class DefNode(FuncDefNode):
1423 # A Python function definition.
1425 # name string the Python name of the function
1426 # decorators [DecoratorNode] list of decorators
1427 # args [CArgDeclNode] formal arguments
1428 # star_arg PyArgDeclNode or None * argument
1429 # starstar_arg PyArgDeclNode or None ** argument
1430 # doc EncodedString or None
1431 # body StatListNode
1433 # The following subnode is constructed internally
1434 # when the def statement is inside a Python class definition.
1436 # assmt AssignmentNode Function construction/assignment
1438 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1440 assmt = None
1441 num_kwonly_args = 0
1442 num_required_kw_args = 0
1443 reqd_kw_flags_cname = "0"
1444 is_wrapper = 0
1445 decorators = None
1446 entry = None
1449 def __init__(self, pos, **kwds):
1450 FuncDefNode.__init__(self, pos, **kwds)
1451 k = rk = r = 0
1452 for arg in self.args:
1453 if arg.kw_only:
1454 k += 1
1455 if not arg.default:
1456 rk += 1
1457 if not arg.default:
1458 r += 1
1459 self.num_kwonly_args = k
1460 self.num_required_kw_args = rk
1461 self.num_required_args = r
1463 def as_cfunction(self, cfunc):
1464 if self.star_arg:
1465 error(self.star_arg.pos, "cdef function cannot have star argument")
1466 if self.starstar_arg:
1467 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1468 if len(self.args) != len(cfunc.type.args) or cfunc.type.has_varargs:
1469 error(self.pos, "wrong number of arguments")
1470 error(declarator.pos, "previous declaration here")
1471 for formal_arg, type_arg in zip(self.args, cfunc.type.args):
1472 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1473 if type is PyrexTypes.py_object_type or formal_arg.is_self:
1474 formal_arg.type = type_arg.type
1475 formal_arg.name_declarator = name_declarator
1476 import ExprNodes
1477 if cfunc.type.exception_value is None:
1478 exception_value = None
1479 else:
1480 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc.type.exception_value, type=cfunc.type.return_type)
1481 declarator = CFuncDeclaratorNode(self.pos,
1482 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1483 args = self.args,
1484 has_varargs = False,
1485 exception_check = cfunc.type.exception_check,
1486 exception_value = exception_value,
1487 with_gil = cfunc.type.with_gil,
1488 nogil = cfunc.type.nogil)
1489 return CFuncDefNode(self.pos,
1490 modifiers = [],
1491 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc.type.return_type),
1492 declarator = declarator,
1493 body = self.body,
1494 doc = self.doc,
1495 overridable = cfunc.type.is_overridable,
1496 type = cfunc.type,
1497 with_gil = cfunc.type.with_gil,
1498 nogil = cfunc.type.nogil,
1499 visibility = 'private',
1500 api = False)
1502 def analyse_declarations(self, env):
1503 if 'locals' in env.directives:
1504 directive_locals = env.directives['locals']
1505 else:
1506 directive_locals = {}
1507 self.directive_locals = directive_locals
1508 for arg in self.args:
1509 base_type = arg.base_type.analyse(env)
1510 name_declarator, type = \
1511 arg.declarator.analyse(base_type, env)
1512 arg.name = name_declarator.name
1513 if arg.name in directive_locals:
1514 type_node = directive_locals[arg.name]
1515 other_type = type_node.analyse_as_type(env)
1516 if other_type is None:
1517 error(type_node.pos, "Not a type")
1518 elif (type is not PyrexTypes.py_object_type
1519 and not type.same_as(other_type)):
1520 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1521 error(type_node.pos, "Previous declaration here")
1522 else:
1523 type = other_type
1524 if name_declarator.cname:
1525 error(self.pos,
1526 "Python function argument cannot have C name specification")
1527 arg.type = type.as_argument_type()
1528 arg.hdr_type = None
1529 arg.needs_conversion = 0
1530 arg.needs_type_test = 0
1531 arg.is_generic = 1
1532 if arg.not_none and not arg.type.is_extension_type:
1533 error(self.pos,
1534 "Only extension type arguments can have 'not None'")
1535 self.declare_pyfunction(env)
1536 self.analyse_signature(env)
1537 self.return_type = self.entry.signature.return_type()
1539 def analyse_signature(self, env):
1540 any_type_tests_needed = 0
1541 # Use the simpler calling signature for zero- and one-argument functions.
1542 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1543 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1544 if len(self.args) == 0:
1545 self.entry.signature = TypeSlots.pyfunction_noargs
1546 elif len(self.args) == 1:
1547 if self.args[0].default is None and not self.args[0].kw_only:
1548 self.entry.signature = TypeSlots.pyfunction_onearg
1549 elif self.entry.signature is TypeSlots.pymethod_signature:
1550 if len(self.args) == 1:
1551 self.entry.signature = TypeSlots.unaryfunc
1552 elif len(self.args) == 2:
1553 if self.args[1].default is None and not self.args[1].kw_only:
1554 self.entry.signature = TypeSlots.ibinaryfunc
1555 elif self.entry.is_special:
1556 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1557 sig = self.entry.signature
1558 nfixed = sig.num_fixed_args()
1559 for i in range(nfixed):
1560 if i < len(self.args):
1561 arg = self.args[i]
1562 arg.is_generic = 0
1563 if sig.is_self_arg(i):
1564 arg.is_self_arg = 1
1565 arg.hdr_type = arg.type = env.parent_type
1566 arg.needs_conversion = 0
1567 else:
1568 arg.hdr_type = sig.fixed_arg_type(i)
1569 if not arg.type.same_as(arg.hdr_type):
1570 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1571 arg.needs_type_test = 1
1572 any_type_tests_needed = 1
1573 else:
1574 arg.needs_conversion = 1
1575 if arg.needs_conversion:
1576 arg.hdr_cname = Naming.arg_prefix + arg.name
1577 else:
1578 arg.hdr_cname = Naming.var_prefix + arg.name
1579 else:
1580 self.bad_signature()
1581 return
1582 if nfixed < len(self.args):
1583 if not sig.has_generic_args:
1584 self.bad_signature()
1585 for arg in self.args:
1586 if arg.is_generic and \
1587 (arg.type.is_extension_type or arg.type.is_builtin_type):
1588 arg.needs_type_test = 1
1589 any_type_tests_needed = 1
1590 elif arg.type is PyrexTypes.c_py_ssize_t_type:
1591 # Want to use __index__ rather than __int__ method
1592 # that PyArg_ParseTupleAndKeywords calls
1593 arg.needs_conversion = 1
1594 arg.hdr_type = PyrexTypes.py_object_type
1595 arg.hdr_cname = Naming.arg_prefix + arg.name
1596 if any_type_tests_needed:
1597 env.use_utility_code(arg_type_test_utility_code)
1599 def bad_signature(self):
1600 sig = self.entry.signature
1601 expected_str = "%d" % sig.num_fixed_args()
1602 if sig.has_generic_args:
1603 expected_str = expected_str + " or more"
1604 name = self.name
1605 if name.startswith("__") and name.endswith("__"):
1606 desc = "Special method"
1607 else:
1608 desc = "Method"
1609 error(self.pos,
1610 "%s %s has wrong number of arguments "
1611 "(%d declared, %s expected)" % (
1612 desc, self.name, len(self.args), expected_str))
1614 def signature_has_nongeneric_args(self):
1615 argcount = len(self.args)
1616 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1617 return 0
1618 return 1
1620 def signature_has_generic_args(self):
1621 return self.entry.signature.has_generic_args
1623 def declare_pyfunction(self, env):
1624 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1625 name = self.name
1626 entry = env.lookup_here(self.name)
1627 if entry and entry.type.is_cfunction and not self.is_wrapper:
1628 warning(self.pos, "Overriding cdef method with def method.", 5)
1629 entry = env.declare_pyfunction(self.name, self.pos)
1630 self.entry = entry
1631 prefix = env.scope_prefix
1632 entry.func_cname = \
1633 Naming.pyfunc_prefix + prefix + name
1634 entry.pymethdef_cname = \
1635 Naming.pymethdef_prefix + prefix + name
1636 if Options.docstrings:
1637 entry.doc = embed_position(self.pos, self.doc)
1638 entry.doc_cname = \
1639 Naming.funcdoc_prefix + prefix + name
1640 else:
1641 entry.doc = None
1643 def declare_arguments(self, env):
1644 for arg in self.args:
1645 if not arg.name:
1646 error(arg.pos, "Missing argument name")
1647 if arg.needs_conversion:
1648 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1649 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1650 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1651 if arg.type.is_pyobject:
1652 arg.entry.init = "0"
1653 arg.entry.init_to_none = 0
1654 else:
1655 arg.entry = self.declare_argument(env, arg)
1656 arg.entry.used = 1
1657 arg.entry.is_self_arg = arg.is_self_arg
1658 if not arg.is_self_arg:
1659 arg.name_entry = env.get_string_const(
1660 arg.name, identifier = True)
1661 env.add_py_string(arg.name_entry, identifier = True)
1662 if arg.hdr_type:
1663 if arg.is_self_arg or \
1664 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1665 arg.entry.is_declared_generic = 1
1666 self.declare_python_arg(env, self.star_arg)
1667 self.declare_python_arg(env, self.starstar_arg)
1669 def declare_python_arg(self, env, arg):
1670 if arg:
1671 entry = env.declare_var(arg.name,
1672 PyrexTypes.py_object_type, arg.pos)
1673 entry.used = 1
1674 entry.init = "0"
1675 entry.init_to_none = 0
1676 entry.xdecref_cleanup = 1
1677 arg.entry = entry
1678 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1680 def analyse_expressions(self, env):
1681 self.analyse_default_values(env)
1682 if env.is_py_class_scope:
1683 self.synthesize_assignment_node(env)
1685 def synthesize_assignment_node(self, env):
1686 import ExprNodes
1687 self.assmt = SingleAssignmentNode(self.pos,
1688 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1689 rhs = ExprNodes.UnboundMethodNode(self.pos,
1690 class_cname = env.class_obj_cname,
1691 function = ExprNodes.PyCFunctionNode(self.pos,
1692 pymethdef_cname = self.entry.pymethdef_cname)))
1693 self.assmt.analyse_declarations(env)
1694 self.assmt.analyse_expressions(env)
1696 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1697 arg_code_list = []
1698 sig = self.entry.signature
1699 if sig.has_dummy_arg:
1700 arg_code_list.append(
1701 "PyObject *%s" % Naming.self_cname)
1702 for arg in self.args:
1703 if not arg.is_generic:
1704 if arg.is_self_arg:
1705 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1706 else:
1707 arg_code_list.append(
1708 arg.hdr_type.declaration_code(arg.hdr_cname))
1709 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1710 arg_code_list.append("PyObject *unused")
1711 if sig.has_generic_args:
1712 arg_code_list.append(
1713 "PyObject *%s, PyObject *%s"
1714 % (Naming.args_cname, Naming.kwds_cname))
1715 arg_code = ", ".join(arg_code_list)
1716 dc = self.return_type.declaration_code(self.entry.func_cname)
1717 header = "static %s(%s)" % (dc, arg_code)
1718 code.putln("%s; /*proto*/" % header)
1719 if proto_only:
1720 return
1721 if self.entry.doc and Options.docstrings:
1722 docstr = self.entry.doc
1723 if not isinstance(docstr, str):
1724 docstr = docstr.utf8encode()
1725 code.putln(
1726 'static char %s[] = "%s";' % (
1727 self.entry.doc_cname,
1728 split_docstring(escape_byte_string(docstr))))
1729 if with_pymethdef:
1730 code.put(
1731 "static PyMethodDef %s = " %
1732 self.entry.pymethdef_cname)
1733 code.put_pymethoddef(self.entry, ";")
1734 code.putln("%s {" % header)
1736 def generate_argument_declarations(self, env, code):
1737 for arg in self.args:
1738 if arg.is_generic: # or arg.needs_conversion:
1739 if arg.needs_conversion:
1740 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1741 else:
1742 code.put_var_declaration(arg.entry)
1744 def generate_keyword_list(self, code):
1745 if self.signature_has_generic_args() and \
1746 self.signature_has_nongeneric_args():
1747 code.put(
1748 "static PyObject **%s[] = {" %
1749 Naming.pykwdlist_cname)
1750 for arg in self.args:
1751 if arg.is_generic:
1752 code.put('&%s,' % arg.name_entry.pystring_cname)
1753 code.putln("0};")
1755 def generate_argument_parsing_code(self, env, code):
1756 # Generate PyArg_ParseTuple call for generic
1757 # arguments, if any.
1758 if self.entry.signature.has_dummy_arg:
1759 # get rid of unused argument warning
1760 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1762 old_error_label = code.new_error_label()
1763 our_error_label = code.error_label
1764 end_label = code.new_label("argument_unpacking_done")
1766 has_kwonly_args = self.num_kwonly_args > 0
1767 has_star_or_kw_args = self.star_arg is not None \
1768 or self.starstar_arg is not None or has_kwonly_args
1770 if not self.signature_has_generic_args():
1771 if has_star_or_kw_args:
1772 error(self.pos, "This method cannot have * or keyword arguments")
1773 self.generate_argument_conversion_code(code)
1775 elif not self.signature_has_nongeneric_args():
1776 # func(*args) or func(**kw) or func(*args, **kw)
1777 self.generate_stararg_copy_code(code)
1779 else:
1780 positional_args = []
1781 kw_only_args = []
1782 default_seen = 0
1783 for arg in self.args:
1784 arg_entry = arg.entry
1785 if arg.is_generic:
1786 if arg.default:
1787 code.putln(
1788 "%s = %s;" % (
1789 arg_entry.cname,
1790 arg.default_result_code))
1791 default_seen = 1
1792 if not arg.is_self_arg:
1793 if arg.kw_only:
1794 kw_only_args.append(arg)
1795 else:
1796 positional_args.append(arg)
1797 elif arg.kw_only:
1798 kw_only_args.append(arg)
1799 default_seen = 1
1800 elif default_seen:
1801 error(arg.pos, "Non-default argument following default argument")
1802 elif not arg.is_self_arg:
1803 positional_args.append(arg)
1804 if arg.needs_conversion:
1805 format = arg.hdr_type.parsetuple_format
1806 else:
1807 format = arg_entry.type.parsetuple_format
1808 if not format:
1809 error(arg.pos,
1810 "Cannot convert Python object argument to type '%s' (when parsing input arguments)"
1811 % arg.type)
1813 self.generate_tuple_and_keyword_parsing_code(
1814 positional_args, kw_only_args, end_label, code)
1816 code.error_label = old_error_label
1817 if code.label_used(our_error_label):
1818 if not code.label_used(end_label):
1819 code.put_goto(end_label)
1820 code.put_label(our_error_label)
1821 if has_star_or_kw_args:
1822 self.generate_arg_decref(self.star_arg, code)
1823 if self.starstar_arg:
1824 if self.starstar_arg.entry.xdecref_cleanup:
1825 code.put_var_xdecref(self.starstar_arg.entry)
1826 else:
1827 code.put_var_decref(self.starstar_arg.entry)
1828 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1829 code.putln("return %s;" % self.error_value())
1830 if code.label_used(end_label):
1831 code.put_label(end_label)
1833 def generate_arg_assignment(self, arg, item, code):
1834 if arg.type.is_pyobject:
1835 if arg.is_generic:
1836 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1837 code.putln("%s = %s;" % (arg.entry.cname, item))
1838 else:
1839 func = arg.type.from_py_function
1840 if func:
1841 code.putln("%s = %s(%s); %s" % (
1842 arg.entry.cname,
1843 func,
1844 item,
1845 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1846 else:
1847 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1849 def generate_arg_xdecref(self, arg, code):
1850 if arg:
1851 code.put_var_xdecref(arg.entry)
1853 def generate_arg_decref(self, arg, code):
1854 if arg:
1855 code.put_var_decref(arg.entry)
1857 def generate_stararg_copy_code(self, code):
1858 if not self.star_arg:
1859 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1860 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1861 Naming.args_cname)
1862 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
1863 self.name.utf8encode(), Naming.args_cname, self.error_value()))
1864 code.putln("}")
1866 code.globalstate.use_utility_code(keyword_string_check_utility_code)
1868 if self.starstar_arg:
1869 if self.star_arg:
1870 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
1871 else:
1872 kwarg_check = "%s" % Naming.kwds_cname
1873 else:
1874 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
1875 Naming.kwds_cname, Naming.kwds_cname)
1876 code.putln(
1877 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
1878 kwarg_check, Naming.kwds_cname, self.name,
1879 bool(self.starstar_arg), self.error_value()))
1881 if self.starstar_arg:
1882 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
1883 self.starstar_arg.entry.cname,
1884 Naming.kwds_cname,
1885 Naming.kwds_cname))
1886 code.putln("if (unlikely(!%s)) return %s;" % (
1887 self.starstar_arg.entry.cname, self.error_value()))
1888 self.starstar_arg.entry.xdecref_cleanup = 0
1890 if self.star_arg:
1891 code.put_incref(Naming.args_cname, py_object_type)
1892 code.putln("%s = %s;" % (
1893 self.star_arg.entry.cname,
1894 Naming.args_cname))
1895 self.star_arg.entry.xdecref_cleanup = 0
1897 def generate_tuple_and_keyword_parsing_code(self, positional_args,
1898 kw_only_args, success_label, code):
1899 argtuple_error_label = code.new_label("argtuple_error")
1901 min_positional_args = self.num_required_args - self.num_required_kw_args
1902 if len(self.args) > 0 and self.args[0].is_self_arg:
1903 min_positional_args -= 1
1904 max_positional_args = len(positional_args)
1905 has_fixed_positional_count = not self.star_arg and \
1906 min_positional_args == max_positional_args
1908 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
1909 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1910 if self.num_required_kw_args:
1911 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
1913 if self.starstar_arg or self.star_arg:
1914 self.generate_stararg_init_code(max_positional_args, code)
1916 # --- optimised code when we receive keyword arguments
1917 if self.num_required_kw_args:
1918 likely_hint = "likely"
1919 else:
1920 likely_hint = "unlikely"
1921 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
1922 self.generate_keyword_unpacking_code(
1923 min_positional_args, max_positional_args,
1924 has_fixed_positional_count,
1925 positional_args, kw_only_args, argtuple_error_label, code)
1927 # --- optimised code when we do not receive any keyword arguments
1928 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
1929 # Python raises arg tuple related errors first, so we must
1930 # check the length here
1931 if min_positional_args == max_positional_args and not self.star_arg:
1932 compare = '!='
1933 else:
1934 compare = '<'
1935 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
1936 Naming.args_cname, compare, min_positional_args))
1937 code.put_goto(argtuple_error_label)
1939 if self.num_required_kw_args:
1940 # pure error case: keywords required but not passed
1941 if max_positional_args > min_positional_args and not self.star_arg:
1942 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
1943 Naming.args_cname, max_positional_args))
1944 code.put_goto(argtuple_error_label)
1945 code.putln('} else {')
1946 for i, arg in enumerate(kw_only_args):
1947 if not arg.default:
1948 # required keyword-only argument missing
1949 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
1950 self.name.utf8encode(),
1951 arg.name_entry.pystring_cname))
1952 code.putln(code.error_goto(self.pos))
1953 break
1955 elif min_positional_args == max_positional_args:
1956 # parse the exact number of positional arguments from the
1957 # args tuple
1958 code.putln('} else {')
1959 for i, arg in enumerate(positional_args):
1960 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
1961 self.generate_arg_assignment(arg, item, code)
1963 else:
1964 # parse the positional arguments from the variable length
1965 # args tuple
1966 code.putln('} else {')
1967 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
1968 if self.star_arg:
1969 code.putln('default:')
1970 reversed_args = list(enumerate(positional_args))[::-1]
1971 for i, arg in reversed_args:
1972 if i >= min_positional_args-1:
1973 if min_positional_args > 1:
1974 code.putln('case %2d:' % (i+1)) # pure code beautification
1975 else:
1976 code.put('case %2d: ' % (i+1))
1977 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
1978 self.generate_arg_assignment(arg, item, code)
1979 if min_positional_args == 0:
1980 code.put('case 0: ')
1981 code.putln('break;')
1982 if self.star_arg:
1983 if min_positional_args:
1984 for i in range(min_positional_args-1, -1, -1):
1985 code.putln('case %2d:' % i)
1986 code.put_goto(argtuple_error_label)
1987 else:
1988 code.put('default: ')
1989 code.put_goto(argtuple_error_label)
1990 code.putln('}')
1992 code.putln('}')
1994 if code.label_used(argtuple_error_label):
1995 code.put_goto(success_label)
1996 code.put_label(argtuple_error_label)
1997 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
1998 self.name.utf8encode(), has_fixed_positional_count,
1999 min_positional_args, max_positional_args,
2000 Naming.args_cname))
2001 code.putln(code.error_goto(self.pos))
2003 def generate_stararg_init_code(self, max_positional_args, code):
2004 if self.starstar_arg:
2005 self.starstar_arg.entry.xdecref_cleanup = 0
2006 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2007 self.starstar_arg.entry.cname,
2008 self.starstar_arg.entry.cname,
2009 self.error_value()))
2010 if self.star_arg:
2011 self.star_arg.entry.xdecref_cleanup = 0
2012 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2013 Naming.args_cname,
2014 max_positional_args))
2015 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2016 self.star_arg.entry.cname, Naming.args_cname,
2017 max_positional_args, Naming.args_cname))
2018 if self.starstar_arg:
2019 code.putln("")
2020 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2021 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2022 code.putln('return %s;' % self.error_value())
2023 code.putln('}')
2024 else:
2025 code.putln("if (unlikely(!%s)) return %s;" % (
2026 self.star_arg.entry.cname, self.error_value()))
2027 code.putln('} else {')
2028 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2029 code.put_incref(Naming.empty_tuple, py_object_type)
2030 code.putln('}')
2032 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2033 has_fixed_positional_count, positional_args,
2034 kw_only_args, argtuple_error_label, code):
2035 all_args = tuple(positional_args) + tuple(kw_only_args)
2036 max_args = len(all_args)
2038 code.putln("PyObject* values[%d] = {%s};" % (
2039 max_args, ('0,'*max_args)[:-1]))
2040 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2041 Naming.kwds_cname)
2043 # parse the tuple and check that it's not too long
2044 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2045 if self.star_arg:
2046 code.putln('default:')
2047 for i in range(max_positional_args-1, -1, -1):
2048 code.put('case %2d: ' % (i+1))
2049 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2050 i, Naming.args_cname, i))
2051 code.putln('case 0: break;')
2052 if not self.star_arg:
2053 code.put('default: ') # more arguments than allowed
2054 code.put_goto(argtuple_error_label)
2055 code.putln('}')
2057 # now fill up the required arguments with values from the kw dict
2058 last_required_arg = -1
2059 for i, arg in enumerate(all_args):
2060 if not arg.default:
2061 last_required_arg = i
2062 if last_required_arg >= 0:
2063 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2064 for i, arg in enumerate(all_args[:last_required_arg+1]):
2065 if i <= max_positional_args:
2066 if self.star_arg and i == max_positional_args:
2067 code.putln('default:')
2068 else:
2069 code.putln('case %2d:' % i)
2070 if arg.default:
2071 # handled in ParseOptionalKeywords() below
2072 continue
2073 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2074 i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2075 if i < min_positional_args:
2076 code.putln('if (likely(values[%d])) kw_args--;' % i);
2077 if i == 0:
2078 # special case: we know arg 0 is missing
2079 code.put('else ')
2080 code.put_goto(argtuple_error_label)
2081 else:
2082 # print the correct number of values (args or
2083 # kwargs) that were passed into positional
2084 # arguments up to this point
2085 code.putln('else {')
2086 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2087 self.name.utf8encode(), has_fixed_positional_count,
2088 min_positional_args, max_positional_args, i))
2089 code.putln(code.error_goto(self.pos))
2090 code.putln('}')
2091 else:
2092 code.putln('if (values[%d]) kw_args--;' % i);
2093 if arg.kw_only and not arg.default:
2094 code.putln('else {')
2095 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2096 self.name.utf8encode(), arg.name_entry.pystring_cname))
2097 code.putln(code.error_goto(self.pos))
2098 code.putln('}')
2099 code.putln('}')
2101 code.putln('if (unlikely(kw_args > 0)) {')
2102 # non-positional kw args left in dict: default args, **kwargs or error
2103 if self.star_arg:
2104 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2105 Naming.args_cname, max_positional_args,
2106 Naming.args_cname, max_positional_args))
2107 pos_arg_count = "used_pos_args"
2108 else:
2109 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2110 code.globalstate.use_utility_code(parse_keywords_utility_code)
2111 code.put(
2112 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2113 Naming.kwds_cname,
2114 Naming.pykwdlist_cname,
2115 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2116 pos_arg_count,
2117 self.name.utf8encode()))
2118 code.putln(code.error_goto(self.pos))
2119 code.putln('}')
2121 # convert arg values to their final type and assign them
2122 for i, arg in enumerate(all_args):
2123 if arg.default:
2124 code.putln("if (values[%d]) {" % i)
2125 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2126 if arg.default:
2127 code.putln('}')
2129 def generate_argument_conversion_code(self, code):
2130 # Generate code to convert arguments from
2131 # signature type to declared type, if needed.
2132 for arg in self.args:
2133 if arg.needs_conversion:
2134 self.generate_arg_conversion(arg, code)
2136 def generate_arg_conversion(self, arg, code):
2137 # Generate conversion code for one argument.
2138 old_type = arg.hdr_type
2139 new_type = arg.type
2140 if old_type.is_pyobject:
2141 if arg.default:
2142 code.putln("if (%s) {" % arg.hdr_cname)
2143 else:
2144 code.putln("assert(%s); {" % arg.hdr_cname)
2145 self.generate_arg_conversion_from_pyobject(arg, code)
2146 code.putln("}")
2147 elif new_type.is_pyobject:
2148 self.generate_arg_conversion_to_pyobject(arg, code)
2149 else:
2150 if new_type.assignable_from(old_type):
2151 code.putln(
2152 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2153 else:
2154 error(arg.pos,
2155 "Cannot convert 1 argument from '%s' to '%s'" %
2156 (old_type, new_type))
2158 def generate_arg_conversion_from_pyobject(self, arg, code):
2159 new_type = arg.type
2160 func = new_type.from_py_function
2161 # copied from CoerceFromPyTypeNode
2162 if func:
2163 code.putln("%s = %s(%s); %s" % (
2164 arg.entry.cname,
2165 func,
2166 arg.hdr_cname,
2167 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2168 else:
2169 error(arg.pos,
2170 "Cannot convert Python object argument to type '%s'"
2171 % new_type)
2173 def generate_arg_conversion_to_pyobject(self, arg, code):
2174 old_type = arg.hdr_type
2175 func = old_type.to_py_function
2176 if func:
2177 code.putln("%s = %s(%s); %s" % (
2178 arg.entry.cname,
2179 func,
2180 arg.hdr_cname,
2181 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2182 else:
2183 error(arg.pos,
2184 "Cannot convert argument of type '%s' to Python object"
2185 % old_type)
2187 def generate_argument_type_tests(self, code):
2188 # Generate type tests for args whose signature
2189 # type is PyObject * and whose declared type is
2190 # a subtype thereof.
2191 for arg in self.args:
2192 if arg.needs_type_test:
2193 self.generate_arg_type_test(arg, code)
2195 def generate_arg_type_test(self, arg, code):
2196 # Generate type test for one argument.
2197 if arg.type.typeobj_is_available():
2198 typeptr_cname = arg.type.typeptr_cname
2199 arg_code = "((PyObject *)%s)" % arg.entry.cname
2200 code.putln(
2201 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2202 arg_code,
2203 typeptr_cname,
2204 not arg.not_none,
2205 arg.name,
2206 arg.type.is_builtin_type,
2207 code.error_goto(arg.pos)))
2208 else:
2209 error(arg.pos, "Cannot test type of extern C class "
2210 "without type object name specification")
2212 def error_value(self):
2213 return self.entry.signature.error_value
2215 def caller_will_check_exceptions(self):
2216 return 1
2218 class OverrideCheckNode(StatNode):
2219 # A Node for dispatching to the def method if it
2220 # is overriden.
2222 # py_func
2224 # args
2225 # func_temp
2226 # body
2228 child_attrs = ['body']
2230 body = None
2232 def analyse_expressions(self, env):
2233 self.args = env.arg_entries
2234 if self.py_func.is_module_scope:
2235 first_arg = 0
2236 else:
2237 first_arg = 1
2238 import ExprNodes
2239 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2240 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2241 call_node = ExprNodes.SimpleCallNode(self.pos,
2242 function=self.func_node,
2243 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2244 self.body = ReturnStatNode(self.pos, value=call_node)
2245 self.body.analyse_expressions(env)
2247 def generate_execution_code(self, code):
2248 # Check to see if we are an extension type
2249 if self.py_func.is_module_scope:
2250 self_arg = "((PyObject *)%s)" % Naming.module_cname
2251 else:
2252 self_arg = "((PyObject *)%s)" % self.args[0].cname
2253 code.putln("/* Check if called by wrapper */")
2254 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2255 code.putln("/* Check if overriden in Python */")
2256 if self.py_func.is_module_scope:
2257 code.putln("else {")
2258 else:
2259 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2260 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2261 # need to get attribute manually--scope would return cdef method
2262 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2263 # It appears that this type is not anywhere exposed in the Python/C API
2264 is_builtin_function_or_method = '(strcmp(Py_TYPE(%s)->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result()
2265 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2266 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2267 self.body.generate_execution_code(code)
2268 code.putln('}')
2269 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2270 code.putln("}")
2272 class ClassDefNode(StatNode, BlockNode):
2273 pass
2275 class PyClassDefNode(ClassDefNode):
2276 # A Python class definition.
2278 # name EncodedString Name of the class
2279 # doc string or None
2280 # body StatNode Attribute definition code
2281 # entry Symtab.Entry
2282 # scope PyClassScope
2284 # The following subnodes are constructed internally:
2286 # dict DictNode Class dictionary
2287 # classobj ClassNode Class object
2288 # target NameNode Variable to assign class object to
2290 child_attrs = ["body", "dict", "classobj", "target"]
2292 def __init__(self, pos, name, bases, doc, body):
2293 StatNode.__init__(self, pos)
2294 self.name = name
2295 self.doc = doc
2296 self.body = body
2297 import ExprNodes
2298 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2299 if self.doc and Options.docstrings:
2300 doc = embed_position(self.pos, self.doc)
2301 doc_node = ExprNodes.StringNode(pos, value = doc)
2302 else:
2303 doc_node = None
2304 self.classobj = ExprNodes.ClassNode(pos, name = name,
2305 bases = bases, dict = self.dict, doc = doc_node)
2306 self.target = ExprNodes.NameNode(pos, name = name)
2308 def as_cclass(self):
2309 """
2310 Return this node as if it were declared as an extension class"
2311 """
2312 bases = self.classobj.bases.args
2313 if len(bases) == 0:
2314 base_class_name = None
2315 base_class_module = None
2316 elif len(bases) == 1:
2317 base = bases[0]
2318 path = []
2319 while isinstance(base, ExprNodes.AttributeNode):
2320 path.insert(0, base.attribute)
2321 base = base.obj
2322 if isinstance(base, ExprNodes.NameNode):
2323 path.insert(0, base.name)
2324 base_class_name = path[-1]
2325 if len(path) > 1:
2326 base_class_module = u'.'.join(path[:-1])
2327 else:
2328 base_class_module = None
2329 else:
2330 error(self.classobj.bases.args.pos, "Invalid base class")
2331 else:
2332 error(self.classobj.bases.args.pos, "C class may only have one base class")
2333 return None
2335 return CClassDefNode(self.pos,
2336 visibility = 'private',
2337 module_name = None,
2338 class_name = self.name,
2339 base_class_module = base_class_module,
2340 base_class_name = base_class_name,
2341 body = self.body,
2342 in_pxd = False,
2343 doc = self.doc)
2345 def create_scope(self, env):
2346 genv = env
2347 while env.is_py_class_scope or env.is_c_class_scope:
2348 env = env.outer_scope
2349 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2350 return cenv
2352 def analyse_declarations(self, env):
2353 self.target.analyse_target_declaration(env)
2354 cenv = self.create_scope(env)
2355 cenv.class_obj_cname = self.target.entry.cname
2356 self.body.analyse_declarations(cenv)
2358 def analyse_expressions(self, env):
2359 self.dict.analyse_expressions(env)
2360 self.classobj.analyse_expressions(env)
2361 genv = env.global_scope()
2362 cenv = self.scope
2363 cenv.class_dict_cname = self.dict.result()
2364 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2365 self.body.analyse_expressions(cenv)
2366 self.target.analyse_target_expression(env, self.classobj)
2367 self.dict.release_temp(env)
2368 #self.classobj.release_temp(env)
2369 #self.target.release_target_temp(env)
2371 def generate_function_definitions(self, env, code):
2372 self.generate_py_string_decls(self.scope, code)
2373 self.body.generate_function_definitions(self.scope, code)
2375 def generate_execution_code(self, code):
2376 self.dict.generate_evaluation_code(code)
2377 self.classobj.generate_evaluation_code(code)
2378 self.body.generate_execution_code(code)
2379 self.target.generate_assignment_code(self.classobj, code)
2380 self.dict.generate_disposal_code(code)
2383 class CClassDefNode(ClassDefNode):
2384 # An extension type definition.
2386 # visibility 'private' or 'public' or 'extern'
2387 # typedef_flag boolean
2388 # api boolean
2389 # module_name string or None For import of extern type objects
2390 # class_name string Unqualified name of class
2391 # as_name string or None Name to declare as in this scope
2392 # base_class_module string or None Module containing the base class
2393 # base_class_name string or None Name of the base class
2394 # objstruct_name string or None Specified C name of object struct
2395 # typeobj_name string or None Specified C name of type object
2396 # in_pxd boolean Is in a .pxd file
2397 # doc string or None
2398 # body StatNode or None
2399 # entry Symtab.Entry
2400 # base_type PyExtensionType or None
2401 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2402 # buffer_defaults_pos
2404 child_attrs = ["body"]
2405 buffer_defaults_node = None
2406 buffer_defaults_pos = None
2407 typedef_flag = False
2408 api = False
2409 objstruct_name = None
2410 typeobj_name = None
2412 def analyse_declarations(self, env):
2413 #print "CClassDefNode.analyse_declarations:", self.class_name
2414 #print "...visibility =", self.visibility
2415 #print "...module_name =", self.module_name
2417 import Buffer
2418 if self.buffer_defaults_node:
2419 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2420 env, [], self.buffer_defaults_node,
2421 need_complete=False)
2422 else:
2423 buffer_defaults = None
2425 if env.in_cinclude and not self.objstruct_name:
2426 error(self.pos, "Object struct name specification required for "
2427 "C class defined in 'extern from' block")
2428 self.base_type = None
2429 # Now that module imports are cached, we need to
2430 # import the modules for extern classes.
2431 if self.module_name:
2432 self.module = None
2433 for module in env.cimported_modules:
2434 if module.name == self.module_name:
2435 self.module = module
2436 if self.module is None:
2437 self.module = ModuleScope(self.module_name, None, env.context)
2438 self.module.has_extern_class = 1
2439 env.cimported_modules.append(self.module)
2441 if self.base_class_name:
2442 if self.base_class_module:
2443 base_class_scope = env.find_module(self.base_class_module, self.pos)
2444 else:
2445 base_class_scope = env
2446 if base_class_scope:
2447 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2448 if base_class_entry:
2449 if not base_class_entry.is_type:
2450 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2451 elif not base_class_entry.type.is_extension_type:
2452 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2453 elif not base_class_entry.type.is_complete():
2454 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2455 else:
2456 self.base_type = base_class_entry.type
2457 has_body = self.body is not None
2458 if self.module_name and self.visibility != 'extern':
2459 module_path = self.module_name.split(".")
2460 home_scope = env.find_imported_module(module_path, self.pos)
2461 if not home_scope:
2462 return
2463 else:
2464 home_scope = env
2465 self.entry = home_scope.declare_c_class(
2466 name = self.class_name,
2467 pos = self.pos,
2468 defining = has_body and self.in_pxd,
2469 implementing = has_body and not self.in_pxd,
2470 module_name = self.module_name,
2471 base_type = self.base_type,
2472 objstruct_cname = self.objstruct_name,
2473 typeobj_cname = self.typeobj_name,
2474 visibility = self.visibility,
2475 typedef_flag = self.typedef_flag,
2476 api = self.api,
2477 buffer_defaults = buffer_defaults)
2478 if home_scope is not env and self.visibility == 'extern':
2479 env.add_imported_entry(self.class_name, self.entry, pos)
2480 scope = self.entry.type.scope
2482 if self.doc and Options.docstrings:
2483 scope.doc = embed_position(self.pos, self.doc)
2485 if has_body:
2486 self.body.analyse_declarations(scope)
2487 if self.in_pxd:
2488 scope.defined = 1
2489 else:
2490 scope.implemented = 1
2491 env.allocate_vtable_names(self.entry)
2493 def analyse_expressions(self, env):
2494 if self.body:
2495 scope = self.entry.type.scope
2496 self.body.analyse_expressions(scope)
2498 def generate_function_definitions(self, env, code):
2499 self.generate_py_string_decls(self.entry.type.scope, code)
2500 if self.body:
2501 self.body.generate_function_definitions(
2502 self.entry.type.scope, code)
2504 def generate_execution_code(self, code):
2505 # This is needed to generate evaluation code for
2506 # default values of method arguments.
2507 if self.body:
2508 self.body.generate_execution_code(code)
2510 def annotate(self, code):
2511 if self.body:
2512 self.body.annotate(code)
2515 class PropertyNode(StatNode):
2516 # Definition of a property in an extension type.
2518 # name string
2519 # doc EncodedString or None Doc string
2520 # body StatListNode
2522 child_attrs = ["body"]
2524 def analyse_declarations(self, env):
2525 entry = env.declare_property(self.name, self.doc, self.pos)
2526 if entry:
2527 if self.doc and Options.docstrings:
2528 doc_entry = env.get_string_const(
2529 self.doc, identifier = False)
2530 entry.doc_cname = doc_entry.cname
2531 self.body.analyse_declarations(entry.scope)
2533 def analyse_expressions(self, env):
2534 self.body.analyse_expressions(env)
2536 def generate_function_definitions(self, env, code):
2537 self.body.generate_function_definitions(env, code)
2539 def generate_execution_code(self, code):
2540 pass
2542 def annotate(self, code):
2543 self.body.annotate(code)
2546 class GlobalNode(StatNode):
2547 # Global variable declaration.
2549 # names [string]
2551 child_attrs = []
2553 def analyse_declarations(self, env):
2554 for name in self.names:
2555 env.declare_global(name, self.pos)
2557 def analyse_expressions(self, env):
2558 pass
2560 def generate_execution_code(self, code):
2561 pass
2564 class ExprStatNode(StatNode):
2565 # Expression used as a statement.
2567 # expr ExprNode
2569 child_attrs = ["expr"]
2571 def analyse_declarations(self, env):
2572 import ExprNodes
2573 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2574 func = self.expr.function.as_cython_attribute()
2575 if func == u'declare':
2576 args, kwds = self.expr.explicit_args_kwds()
2577 if len(args):
2578 error(self.expr.pos, "Variable names must be specified.")
2579 for var, type_node in kwds.key_value_pairs:
2580 type = type_node.analyse_as_type(env)
2581 if type is None:
2582 error(type_node.pos, "Unknown type")
2583 else:
2584 env.declare_var(var.value, type, var.pos, is_cdef = True)
2585 self.__class__ = PassStatNode
2587 def analyse_expressions(self, env):
2588 self.expr.analyse_expressions(env)
2589 self.expr.release_temp(env)
2591 def generate_execution_code(self, code):
2592 self.expr.generate_evaluation_code(code)
2593 if not self.expr.is_temp and self.expr.result():
2594 code.putln("%s;" % self.expr.result())
2595 self.expr.generate_disposal_code(code)
2597 def annotate(self, code):
2598 self.expr.annotate(code)
2601 class AssignmentNode(StatNode):
2602 # Abstract base class for assignment nodes.
2604 # The analyse_expressions and generate_execution_code
2605 # phases of assignments are split into two sub-phases
2606 # each, to enable all the right hand sides of a
2607 # parallel assignment to be evaluated before assigning
2608 # to any of the left hand sides.
2610 def analyse_expressions(self, env):
2611 self.analyse_types(env)
2612 self.allocate_rhs_temps(env)
2613 self.allocate_lhs_temps(env)
2615 # def analyse_expressions(self, env):
2616 # self.analyse_expressions_1(env)
2617 # self.analyse_expressions_2(env)
2619 def generate_execution_code(self, code):
2620 self.generate_rhs_evaluation_code(code)
2621 self.generate_assignment_code(code)
2624 class SingleAssignmentNode(AssignmentNode):
2625 # The simplest case:
2627 # a = b
2629 # lhs ExprNode Left hand side
2630 # rhs ExprNode Right hand side
2631 # first bool Is this guaranteed the first assignment to lhs?
2633 child_attrs = ["lhs", "rhs"]
2634 first = False
2635 declaration_only = False
2637 def analyse_declarations(self, env):
2638 import ExprNodes
2640 # handle declarations of the form x = cython.foo()
2641 if isinstance(self.rhs, ExprNodes.CallNode):
2642 func_name = self.rhs.function.as_cython_attribute()
2643 if func_name:
2644 args, kwds = self.rhs.explicit_args_kwds()
2646 if func_name in ['declare', 'typedef']:
2647 if len(args) > 2 or kwds is not None:
2648 error(rhs.pos, "Can only declare one type at a time.")
2649 return
2650 type = args[0].analyse_as_type(env)
2651 if type is None:
2652 error(args[0].pos, "Unknown type")
2653 return
2654 lhs = self.lhs
2655 if func_name == 'declare':
2656 if isinstance(lhs, ExprNodes.NameNode):
2657 vars = [(lhs.name, lhs.pos)]
2658 elif isinstance(lhs, ExprNodes.TupleNode):
2659 vars = [(var.name, var.pos) for var in lhs.args]
2660 else:
2661 error(lhs.pos, "Invalid declaration")
2662 return
2663 for var, pos in vars:
2664 env.declare_var(var, type, pos, is_cdef = True)
2665 if len(args) == 2:
2666 # we have a value
2667 self.rhs = args[1]
2668 else:
2669 self.declaration_only = True
2670 else:
2671 self.declaration_only = True
2672 if not isinstance(lhs, ExprNodes.NameNode):
2673 error(lhs.pos, "Invalid declaration.")
2674 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2676 elif func_name in ['struct', 'union']:
2677 self.declaration_only = True
2678 if len(args) > 0 or kwds is None:
2679 error(rhs.pos, "Struct or union members must be given by name.")
2680 return
2681 members = []
2682 for member, type_node in kwds.key_value_pairs:
2683 type = type_node.analyse_as_type(env)
2684 if type is None:
2685 error(type_node.pos, "Unknown type")
2686 else:
2687 members.append((member.value, type, member.pos))
2688 if len(members) < len(kwds.key_value_pairs):
2689 return
2690 if not isinstance(self.lhs, ExprNodes.NameNode):
2691 error(self.lhs.pos, "Invalid declaration.")
2692 name = self.lhs.name
2693 scope = StructOrUnionScope(name)
2694 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2695 for member, type, pos in members:
2696 scope.declare_var(member, type, pos)
2698 if self.declaration_only:
2699 return
2700 else:
2701 self.lhs.analyse_target_declaration(env)
2703 def analyse_types(self, env, use_temp = 0):
2704 self.rhs.analyse_types(env)
2705 self.lhs.analyse_target_types(env)
2706 self.lhs.gil_assignment_check(env)
2707 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2708 if use_temp:
2709 self.rhs = self.rhs.coerce_to_temp(env)
2711 def allocate_rhs_temps(self, env):
2712 self.rhs.allocate_temps(env)
2714 def allocate_lhs_temps(self, env):
2715 self.lhs.allocate_target_temps(env, self.rhs)
2716 #self.lhs.release_target_temp(env)
2717 #self.rhs.release_temp(env)
2719 # def analyse_expressions_1(self, env, use_temp = 0):
2720 # self.rhs.analyse_types(env)
2721 # self.lhs.analyse_target_types(env)
2722 # self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2723 # if use_temp:
2724 # self.rhs = self.rhs.coerce_to_temp(env)
2725 # self.rhs.allocate_temps(env)
2727 # def analyse_expressions_2(self, env):
2728 # self.lhs.allocate_target_temps(env)
2729 # self.lhs.release_target_temp(env)
2730 # self.rhs.release_temp(env)
2732 def generate_rhs_evaluation_code(self, code):
2733 self.rhs.generate_evaluation_code(code)
2735 def generate_assignment_code(self, code):
2736 self.lhs.generate_assignment_code(self.rhs, code)
2738 def annotate(self, code):
2739 self.lhs.annotate(code)
2740 self.rhs.annotate(code)
2743 class CascadedAssignmentNode(AssignmentNode):
2744 # An assignment with multiple left hand sides:
2746 # a = b = c
2748 # lhs_list [ExprNode] Left hand sides
2749 # rhs ExprNode Right hand sides
2751 # Used internally:
2753 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2755 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2756 coerced_rhs_list = None
2758 def analyse_declarations(self, env):
2759 for lhs in self.lhs_list:
2760 lhs.analyse_target_declaration(env)
2762 def analyse_types(self, env, use_temp = 0):
2763 self.rhs.analyse_types(env)
2764 if use_temp:
2765 self.rhs = self.rhs.coerce_to_temp(env)
2766 else:
2767 self.rhs = self.rhs.coerce_to_simple(env)
2768 from ExprNodes import CloneNode
2769 self.coerced_rhs_list = []
2770 for lhs in self.lhs_list:
2771 lhs.analyse_target_types(env)
2772 lhs.gil_assignment_check(env)
2773 rhs = CloneNode(self.rhs)
2774 rhs = rhs.coerce_to(lhs.type, env)
2775 self.coerced_rhs_list.append(rhs)
2777 def allocate_rhs_temps(self, env):
2778 self.rhs.allocate_temps(env)
2780 def allocate_lhs_temps(self, env):
2781 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2782 rhs.allocate_temps(env)
2783 lhs.allocate_target_temps(env, rhs)
2784 #lhs.release_target_temp(env)
2785 #rhs.release_temp(env)
2786 self.rhs.release_temp(env)
2788 # def analyse_expressions_1(self, env, use_temp = 0):
2789 # self.rhs.analyse_types(env)
2790 # if use_temp:
2791 # self.rhs = self.rhs.coerce_to_temp(env)
2792 # else:
2793 # self.rhs = self.rhs.coerce_to_simple(env)
2794 # self.rhs.allocate_temps(env)
2796 # def analyse_expressions_2(self, env):
2797 # from ExprNodes import CloneNode
2798 # self.coerced_rhs_list = []
2799 # for lhs in self.lhs_list:
2800 # lhs.analyse_target_types(env)
2801 # rhs = CloneNode(self.rhs)
2802 # rhs = rhs.coerce_to(lhs.type, env)
2803 # self.coerced_rhs_list.append(rhs)
2804 # rhs.allocate_temps(env)
2805 # lhs.allocate_target_temps(env)
2806 # lhs.release_target_temp(env)
2807 # rhs.release_temp(env)
2808 # self.rhs.release_temp(env)
2810 def generate_rhs_evaluation_code(self, code):
2811 self.rhs.generate_evaluation_code(code)
2813 def generate_assignment_code(self, code):
2814 for i in range(len(self.lhs_list)):
2815 lhs = self.lhs_list[i]
2816 rhs = self.coerced_rhs_list[i]
2817 rhs.generate_evaluation_code(code)
2818 lhs.generate_assignment_code(rhs, code)
2819 # Assignment has disposed of the cloned RHS
2820 self.rhs.generate_disposal_code(code)
2822 def annotate(self, code):
2823 for i in range(len(self.lhs_list)):
2824 lhs = self.lhs_list[i].annotate(code)
2825 rhs = self.coerced_rhs_list[i].annotate(code)
2826 self.rhs.annotate(code)
2829 class ParallelAssignmentNode(AssignmentNode):
2830 # A combined packing/unpacking assignment:
2832 # a, b, c = d, e, f
2834 # This has been rearranged by the parser into
2836 # a = d ; b = e ; c = f
2838 # but we must evaluate all the right hand sides
2839 # before assigning to any of the left hand sides.
2841 # stats [AssignmentNode] The constituent assignments
2843 child_attrs = ["stats"]
2845 def analyse_declarations(self, env):
2846 for stat in self.stats:
2847 stat.analyse_declarations(env)
2849 def analyse_expressions(self, env):
2850 for stat in self.stats:
2851 stat.analyse_types(env, use_temp = 1)
2852 stat.allocate_rhs_temps(env)
2853 for stat in self.stats:
2854 stat.allocate_lhs_temps(env)
2856 # def analyse_expressions(self, env):
2857 # for stat in self.stats:
2858 # stat.analyse_expressions_1(env, use_temp = 1)
2859 # for stat in self.stats:
2860 # stat.analyse_expressions_2(env)
2862 def generate_execution_code(self, code):
2863 for stat in self.stats:
2864 stat.generate_rhs_evaluation_code(code)
2865 for stat in self.stats:
2866 stat.generate_assignment_code(code)
2868 def annotate(self, code):
2869 for stat in self.stats:
2870 stat.annotate(code)
2873 class InPlaceAssignmentNode(AssignmentNode):
2874 # An in place arithmatic operand:
2876 # a += b
2877 # a -= b
2878 # ...
2880 # lhs ExprNode Left hand side
2881 # rhs ExprNode Right hand side
2882 # op char one of "+-*/%^&|"
2883 # dup (ExprNode) copy of lhs used for operation (auto-generated)
2885 # This code is a bit tricky because in order to obey Python
2886 # semantics the sub-expressions (e.g. indices) of the lhs must
2887 # not be evaluated twice. So we must re-use the values calculated
2888 # in evaluation phase for the assignment phase as well.
2889 # Fortunately, the type of the lhs node is fairly constrained
2890 # (it must be a NameNode, AttributeNode, or IndexNode).
2892 child_attrs = ["lhs", "rhs"]
2893 dup = None
2895 def analyse_declarations(self, env):
2896 self.lhs.analyse_target_declaration(env)
2898 def analyse_types(self, env):
2899 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
2900 self.rhs.analyse_types(env)
2901 self.lhs.analyse_target_types(env)
2902 if Options.incref_local_binop and self.dup.type.is_pyobject:
2903 self.dup = self.dup.coerce_to_temp(env)
2905 def allocate_rhs_temps(self, env):
2906 import ExprNodes
2907 if self.lhs.type.is_pyobject:
2908 self.rhs = self.rhs.coerce_to_pyobject(env)
2909 elif self.rhs.type.is_pyobject:
2910 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2911 if self.lhs.type.is_pyobject:
2912 self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
2913 self.result_value.allocate_temps(env)
2914 # if use_temp:
2915 # self.rhs = self.rhs.coerce_to_temp(env)
2916 self.rhs.allocate_temps(env)
2917 self.dup.allocate_subexpr_temps(env)
2918 self.dup.allocate_temp(env)
2920 def allocate_lhs_temps(self, env):
2921 self.lhs.allocate_target_temps(env, self.rhs)
2922 # self.lhs.release_target_temp(env)
2923 self.dup.release_temp(env)
2924 if self.dup.is_temp:
2925 self.dup.release_subexpr_temps(env)
2926 # self.rhs.release_temp(env)
2927 if self.lhs.type.is_pyobject:
2928 self.result_value.release_temp(env)
2930 def generate_execution_code(self, code):
2931 self.rhs.generate_evaluation_code(code)
2932 self.dup.generate_subexpr_evaluation_code(code)
2933 # self.dup.generate_result_code is run only if it is not buffer access
2934 if self.operator == "**":
2935 extra = ", Py_None"
2936 else:
2937 extra = ""
2938 import ExprNodes
2939 if self.lhs.type.is_pyobject:
2940 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
2941 error(self.pos, "In-place operators not allowed on object buffers in this release.")
2942 self.dup.generate_result_code(code)
2943 code.putln(
2944 "%s = %s(%s, %s%s); %s" % (
2945 self.result_value.result(),
2946 self.py_operation_function(),
2947 self.dup.py_result(),
2948 self.rhs.py_result(),
2949 extra,
2950 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
2951 self.result_value.generate_evaluation_code(code) # May be a type check...
2952 self.rhs.generate_disposal_code(code)
2953 self.dup.generate_disposal_code(code)
2954 self.lhs.generate_assignment_code(self.result_value, code)
2955 else:
2956 c_op = self.operator
2957 if c_op == "//":
2958 c_op = "/"
2959 elif c_op == "**":
2960 if self.lhs.type.is_int and self.rhs.type.is_int:
2961 error(self.pos, "** with two C int types is ambiguous")
2962 else:
2963 error(self.pos, "No C inplace power operator")
2964 # have to do assignment directly to avoid side-effects
2965 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
2966 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
2967 else:
2968 self.dup.generate_result_code(code)
2969 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
2970 self.rhs.generate_disposal_code(code)
2971 if self.dup.is_temp:
2972 self.dup.generate_subexpr_disposal_code(code)
2974 def create_dup_node(self, env):
2975 import ExprNodes
2976 self.dup = self.lhs
2977 self.dup.analyse_types(env)
2978 if isinstance(self.lhs, ExprNodes.NameNode):
2979 target_lhs = ExprNodes.NameNode(self.dup.pos,
2980 name = self.dup.name,
2981 is_temp = self.dup.is_temp,
2982 entry = self.dup.entry)
2983 elif isinstance(self.lhs, ExprNodes.AttributeNode):
2984 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
2985 obj = ExprNodes.CloneNode(self.lhs.obj),
2986 attribute = self.dup.attribute,
2987 is_temp = self.dup.is_temp)
2988 elif isinstance(self.lhs, ExprNodes.IndexNode):
2989 if self.lhs.index:
2990 index = ExprNodes.CloneNode(self.lhs.index)
2991 else:
2992 index = None
2993 if self.lhs.indices:
2994 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
2995 else:
2996 indices = []
2997 target_lhs = ExprNodes.IndexNode(self.dup.pos,
2998 base = ExprNodes.CloneNode(self.dup.base),
2999 index = index,
3000 indices = indices,
3001 is_temp = self.dup.is_temp)
3002 self.lhs = target_lhs
3003 return self.dup
3005 def py_operation_function(self):
3006 return self.py_functions[self.operator]
3008 py_functions = {
3009 "|": "PyNumber_InPlaceOr",
3010 "^": "PyNumber_InPlaceXor",
3011 "&": "PyNumber_InPlaceAnd",
3012 "+": "PyNumber_InPlaceAdd",
3013 "-": "PyNumber_InPlaceSubtract",
3014 "*": "PyNumber_InPlaceMultiply",
3015 "/": "PyNumber_InPlaceDivide",
3016 "%": "PyNumber_InPlaceRemainder",
3017 "<<": "PyNumber_InPlaceLshift",
3018 ">>": "PyNumber_InPlaceRshift",
3019 "**": "PyNumber_InPlacePower",
3020 "//": "PyNumber_InPlaceFloorDivide",
3023 def annotate(self, code):
3024 self.lhs.annotate(code)
3025 self.rhs.annotate(code)
3026 self.dup.annotate(code)
3029 class PrintStatNode(StatNode):
3030 # print statement
3032 # arg_tuple TupleNode
3033 # append_newline boolean
3035 child_attrs = ["arg_tuple"]
3037 def analyse_expressions(self, env):
3038 self.arg_tuple.analyse_expressions(env)
3039 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3040 self.arg_tuple.release_temp(env)
3041 env.use_utility_code(printing_utility_code)
3042 self.gil_check(env)
3044 gil_message = "Python print statement"
3046 def generate_execution_code(self, code):
3047 self.arg_tuple.generate_evaluation_code(code)
3048 code.putln(
3049 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3050 self.arg_tuple.py_result(),
3051 self.append_newline,
3052 code.error_goto(self.pos)))
3053 self.arg_tuple.generate_disposal_code(code)
3055 def annotate(self, code):
3056 self.arg_tuple.annotate(code)
3059 class DelStatNode(StatNode):
3060 # del statement
3062 # args [ExprNode]
3064 child_attrs = ["args"]
3066 def analyse_declarations(self, env):
3067 for arg in self.args:
3068 arg.analyse_target_declaration(env)
3070 def analyse_expressions(self, env):
3071 for arg in self.args:
3072 arg.analyse_target_expression(env, None)
3073 if arg.type.is_pyobject:
3074 self.gil_check(env)
3075 else:
3076 error(arg.pos, "Deletion of non-Python object")
3077 #arg.release_target_temp(env)
3079 gil_message = "Deleting Python object"
3081 def generate_execution_code(self, code):
3082 for arg in self.args:
3083 if arg.type.is_pyobject:
3084 arg.generate_deletion_code(code)
3085 # else error reported earlier
3087 def annotate(self, code):
3088 for arg in self.args:
3089 arg.annotate(code)
3092 class PassStatNode(StatNode):
3093 # pass statement
3095 child_attrs = []
3097 def analyse_expressions(self, env):
3098 pass
3100 def generate_execution_code(self, code):
3101 pass
3104 class BreakStatNode(StatNode):
3106 child_attrs = []
3108 def analyse_expressions(self, env):
3109 pass
3111 def generate_execution_code(self, code):
3112 if not code.break_label:
3113 error(self.pos, "break statement not inside loop")
3114 else:
3115 #code.putln(
3116 # "goto %s;" %
3117 # code.break_label)
3118 code.put_goto(code.break_label)
3121 class ContinueStatNode(StatNode):
3123 child_attrs = []
3125 def analyse_expressions(self, env):
3126 pass
3128 def generate_execution_code(self, code):
3129 if code.funcstate.in_try_finally:
3130 error(self.pos, "continue statement inside try of try...finally")
3131 elif not code.continue_label:
3132 error(self.pos, "continue statement not inside loop")
3133 else:
3134 code.put_goto(code.continue_label)
3137 class ReturnStatNode(StatNode):
3138 # return statement
3140 # value ExprNode or None
3141 # return_type PyrexType
3142 # temps_in_use [Entry] Temps in use at time of return
3144 child_attrs = ["value"]
3146 def analyse_expressions(self, env):
3147 return_type = env.return_type
3148 self.return_type = return_type
3149 self.temps_in_use = env.temps_in_use()
3150 if not return_type:
3151 error(self.pos, "Return not inside a function body")
3152 return
3153 if self.value:
3154 self.value.analyse_types(env)
3155 if return_type.is_void or return_type.is_returncode:
3156 error(self.value.pos,
3157 "Return with value in void function")
3158 else:
3159 self.value = self.value.coerce_to(env.return_type, env)
3160 self.value.allocate_temps(env)
3161 self.value.release_temp(env)
3162 else:
3163 if (not return_type.is_void
3164 and not return_type.is_pyobject
3165 and not return_type.is_returncode):
3166 error(self.pos, "Return value required")
3167 if return_type.is_pyobject:
3168 self.gil_check(env)
3170 gil_message = "Returning Python object"
3172 def generate_execution_code(self, code):
3173 code.mark_pos(self.pos)
3174 if not self.return_type:
3175 # error reported earlier
3176 return
3177 if self.value:
3178 self.value.generate_evaluation_code(code)
3179 self.value.make_owned_reference(code)
3180 code.putln(
3181 "%s = %s;" % (
3182 Naming.retval_cname,
3183 self.value.result_as(self.return_type)))
3184 self.value.generate_post_assignment_code(code)
3185 else:
3186 if self.return_type.is_pyobject:
3187 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3188 elif self.return_type.is_returncode:
3189 code.putln(
3190 "%s = %s;" % (
3191 Naming.retval_cname,
3192 self.return_type.default_value))
3193 for entry in self.temps_in_use:
3194 code.put_var_decref_clear(entry)
3195 #code.putln(
3196 # "goto %s;" %
3197 # code.return_label)
3198 code.put_goto(code.return_label)
3200 def annotate(self, code):
3201 if self.value:
3202 self.value.annotate(code)
3205 class RaiseStatNode(StatNode):
3206 # raise statement
3208 # exc_type ExprNode or None
3209 # exc_value ExprNode or None
3210 # exc_tb ExprNode or None
3212 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3214 def analyse_expressions(self, env):
3215 if self.exc_type:
3216 self.exc_type.analyse_types(env)
3217 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3218 self.exc_type.allocate_temps(env)
3219 if self.exc_value:
3220 self.exc_value.analyse_types(env)
3221 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3222 self.exc_value.allocate_temps(env)
3223 if self.exc_tb:
3224 self.exc_tb.analyse_types(env)
3225 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3226 self.exc_tb.allocate_temps(env)
3227 if self.exc_type:
3228 self.exc_type.release_temp(env)
3229 if self.exc_value:
3230 self.exc_value.release_temp(env)
3231 if self.exc_tb:
3232 self.exc_tb.release_temp(env)
3233 env.use_utility_code(raise_utility_code)
3234 env.use_utility_code(restore_exception_utility_code)
3235 self.gil_check(env)
3237 gil_message = "Raising exception"
3239 def generate_execution_code(self, code):
3240 if self.exc_type:
3241 self.exc_type.generate_evaluation_code(code)
3242 type_code = self.exc_type.py_result()
3243 else:
3244 type_code = 0
3245 if self.exc_value:
3246 self.exc_value.generate_evaluation_code(code)
3247 value_code = self.exc_value.py_result()
3248 else:
3249 value_code = "0"
3250 if self.exc_tb:
3251 self.exc_tb.generate_evaluation_code(code)
3252 tb_code = self.exc_tb.py_result()
3253 else:
3254 tb_code = "0"
3255 if self.exc_type or self.exc_value or self.exc_tb:
3256 code.putln(
3257 "__Pyx_Raise(%s, %s, %s);" % (
3258 type_code,
3259 value_code,
3260 tb_code))
3261 else:
3262 code.putln(
3263 "__Pyx_ReRaise();")
3264 if self.exc_type:
3265 self.exc_type.generate_disposal_code(code)
3266 if self.exc_value:
3267 self.exc_value.generate_disposal_code(code)
3268 if self.exc_tb:
3269 self.exc_tb.generate_disposal_code(code)
3270 code.putln(
3271 code.error_goto(self.pos))
3273 def annotate(self, code):
3274 if self.exc_type:
3275 self.exc_type.annotate(code)
3276 if self.exc_value:
3277 self.exc_value.annotate(code)
3278 if self.exc_tb:
3279 self.exc_tb.annotate(code)
3282 class ReraiseStatNode(StatNode):
3284 child_attrs = []
3286 def analyse_expressions(self, env):
3287 self.gil_check(env)
3288 env.use_utility_code(raise_utility_code)
3289 env.use_utility_code(restore_exception_utility_code)
3291 gil_message = "Raising exception"
3293 def generate_execution_code(self, code):
3294 vars = code.funcstate.exc_vars
3295 if vars:
3296 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3297 code.putln(code.error_goto(self.pos))
3298 else:
3299 error(self.pos, "Reraise not inside except clause")
3302 class AssertStatNode(StatNode):
3303 # assert statement
3305 # cond ExprNode
3306 # value ExprNode or None
3308 child_attrs = ["cond", "value"]
3310 def analyse_expressions(self, env):
3311 self.cond = self.cond.analyse_boolean_expression(env)
3312 if self.value:
3313 self.value.analyse_types(env)
3314 self.value = self.value.coerce_to_pyobject(env)
3315 self.value.allocate_temps(env)
3316 self.cond.release_temp(env)
3317 if self.value:
3318 self.value.release_temp(env)
3319 self.gil_check(env)
3320 #env.recycle_pending_temps() # TEMPORARY
3322 gil_message = "Raising exception"
3324 def generate_execution_code(self, code):
3325 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3326 self.cond.generate_evaluation_code(code)
3327 code.putln(
3328 "if (unlikely(!%s)) {" %
3329 self.cond.result())
3330 if self.value:
3331 self.value.generate_evaluation_code(code)
3332 code.putln(
3333 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3334 self.value.py_result())
3335 self.value.generate_disposal_code(code)
3336 else:
3337 code.putln(
3338 "PyErr_SetNone(PyExc_AssertionError);")
3339 code.putln(
3340 code.error_goto(self.pos))
3341 code.putln(
3342 "}")
3343 self.cond.generate_disposal_code(code)
3344 code.putln("#endif")
3346 def annotate(self, code):
3347 self.cond.annotate(code)
3348 if self.value:
3349 self.value.annotate(code)
3352 class IfStatNode(StatNode):
3353 # if statement
3355 # if_clauses [IfClauseNode]
3356 # else_clause StatNode or None
3358 child_attrs = ["if_clauses", "else_clause"]
3360 def analyse_control_flow(self, env):
3361 env.start_branching(self.pos)
3362 for if_clause in self.if_clauses:
3363 if_clause.analyse_control_flow(env)
3364 env.next_branch(if_clause.end_pos())
3365 if self.else_clause:
3366 self.else_clause.analyse_control_flow(env)
3367 env.finish_branching(self.end_pos())
3369 def analyse_declarations(self, env):
3370 for if_clause in self.if_clauses:
3371 if_clause.analyse_declarations(env)
3372 if self.else_clause:
3373 self.else_clause.analyse_declarations(env)
3375 def analyse_expressions(self, env):
3376 for if_clause in self.if_clauses:
3377 if_clause.analyse_expressions(env)
3378 if self.else_clause:
3379 self.else_clause.analyse_expressions(env)
3381 def generate_execution_code(self, code):
3382 code.mark_pos(self.pos)
3383 end_label = code.new_label()
3384 for if_clause in self.if_clauses:
3385 if_clause.generate_execution_code(code, end_label)
3386 if self.else_clause:
3387 code.putln("/*else*/ {")
3388 self.else_clause.generate_execution_code(code)
3389 code.putln("}")
3390 code.put_label(end_label)
3392 def annotate(self, code):
3393 for if_clause in self.if_clauses:
3394 if_clause.annotate(code)
3395 if self.else_clause:
3396 self.else_clause.annotate(code)
3399 class IfClauseNode(Node):
3400 # if or elif clause in an if statement
3402 # condition ExprNode
3403 # body StatNode
3405 child_attrs = ["condition", "body"]
3407 def analyse_control_flow(self, env):
3408 self.body.analyse_control_flow(env)
3410 def analyse_declarations(self, env):
3411 self.condition.analyse_declarations(env)
3412 self.body.analyse_declarations(env)
3414 def analyse_expressions(self, env):
3415 self.condition = \
3416 self.condition.analyse_temp_boolean_expression(env)
3417 self.condition.release_temp(env)
3418 self.body.analyse_expressions(env)
3420 def generate_execution_code(self, code, end_label):
3421 self.condition.generate_evaluation_code(code)
3422 code.putln(
3423 "if (%s) {" %
3424 self.condition.result())
3425 self.body.generate_execution_code(code)
3426 #code.putln(
3427 # "goto %s;" %
3428 # end_label)
3429 code.put_goto(end_label)
3430 code.putln("}")
3432 def annotate(self, code):
3433 self.condition.annotate(code)
3434 self.body.annotate(code)
3437 class SwitchCaseNode(StatNode):
3438 # Generated in the optimization of an if-elif-else node
3440 # conditions [ExprNode]
3441 # body StatNode
3443 child_attrs = ['conditions', 'body']
3445 def generate_execution_code(self, code):
3446 for cond in self.conditions:
3447 code.putln("case %s:" % cond.calculate_result_code())
3448 self.body.generate_execution_code(code)
3449 code.putln("break;")
3451 def annotate(self, code):
3452 for cond in self.conditions:
3453 cond.annotate(code)
3454 self.body.annotate(code)
3456 class SwitchStatNode(StatNode):
3457 # Generated in the optimization of an if-elif-else node
3459 # test ExprNode
3460 # cases [SwitchCaseNode]
3461 # else_clause StatNode or None
3463 child_attrs = ['test', 'cases', 'else_clause']
3465 def generate_execution_code(self, code):
3466 code.putln("switch (%s) {" % self.test.calculate_result_code())
3467 for case in self.cases:
3468 case.generate_execution_code(code)
3469 if self.else_clause is not None:
3470 code.putln("default:")
3471 self.else_clause.generate_execution_code(code)
3472 code.putln("break;")
3473 code.putln("}")
3475 def annotate(self, code):
3476 self.test.annotate(code)
3477 for case in self.cases:
3478 case.annotate(code)
3479 if self.else_clause is not None:
3480 self.else_clause.annotate(code)
3482 class LoopNode:
3484 def analyse_control_flow(self, env):
3485 env.start_branching(self.pos)
3486 self.body.analyse_control_flow(env)
3487 env.next_branch(self.body.end_pos())
3488 if self.else_clause:
3489 self.else_clause.analyse_control_flow(env)
3490 env.finish_branching(self.end_pos())
3493 class WhileStatNode(LoopNode, StatNode):
3494 # while statement
3496 # condition ExprNode
3497 # body StatNode
3498 # else_clause StatNode
3500 child_attrs = ["condition", "body", "else_clause"]
3502 def analyse_declarations(self, env):
3503 self.body.analyse_declarations(env)
3504 if self.else_clause:
3505 self.else_clause.analyse_declarations(env)
3507 def analyse_expressions(self, env):
3508 self.condition = \
3509 self.condition.analyse_temp_boolean_expression(env)
3510 self.condition.release_temp(env)
3511 #env.recycle_pending_temps() # TEMPORARY
3512 self.body.analyse_expressions(env)
3513 if self.else_clause:
3514 self.else_clause.analyse_expressions(env)
3516 def generate_execution_code(self, code):
3517 old_loop_labels = code.new_loop_labels()
3518 code.putln(
3519 "while (1) {")
3520 self.condition.generate_evaluation_code(code)
3521 code.putln(
3522 "if (!%s) break;" %
3523 self.condition.result())
3524 self.body.generate_execution_code(code)
3525 code.put_label(code.continue_label)
3526 code.putln("}")
3527 break_label = code.break_label
3528 code.set_loop_labels(old_loop_labels)
3529 if self.else_clause:
3530 code.putln("/*else*/ {")
3531 self.else_clause.generate_execution_code(code)
3532 code.putln("}")
3533 code.put_label(break_label)
3535 def annotate(self, code):
3536 self.condition.annotate(code)
3537 self.body.annotate(code)
3538 if self.else_clause:
3539 self.else_clause.annotate(code)
3542 def ForStatNode(pos, **kw):
3543 if kw.has_key('iterator'):
3544 return ForInStatNode(pos, **kw)
3545 else:
3546 return ForFromStatNode(pos, **kw)
3548 class ForInStatNode(LoopNode, StatNode):
3549 # for statement
3551 # target ExprNode
3552 # iterator IteratorNode
3553 # body StatNode
3554 # else_clause StatNode
3555 # item NextNode used internally
3557 child_attrs = ["target", "iterator", "body", "else_clause"]
3558 item = None
3560 def analyse_declarations(self, env):
3561 self.target.analyse_target_declaration(env)
3562 self.body.analyse_declarations(env)
3563 if self.else_clause:
3564 self.else_clause.analyse_declarations(env)
3566 def analyse_range_step(self, args):
3567 import ExprNodes
3568 # The direction must be determined at compile time to set relations.
3569 # Otherwise, return False.
3570 if len(args) < 3:
3571 self.step = ExprNodes.IntNode(pos = args[0].pos, value='1')
3572 self.relation1 = '<='
3573 self.relation2 = '<'
3574 return True
3575 else:
3576 step = args[2]
3577 if isinstance(step, ExprNodes.UnaryMinusNode) and isinstance(step.operand, ExprNodes.IntNode):
3578 step = ExprNodes.IntNode(pos = step.pos, value=str(-int(step.operand.value, 0)))
3579 if isinstance(step, ExprNodes.IntNode):
3580 step_value = int(step.value, 0)
3581 if step_value > 0:
3582 self.step = step
3583 self.relation1 = '<='
3584 self.relation2 = '<'
3585 return True
3586 elif step_value < 0:
3587 self.step = ExprNodes.IntNode(pos = step.pos, value=str(-step_value))
3588 self.relation1 = '>='
3589 self.relation2 = '>'
3590 return True
3591 return False
3594 def analyse_expressions(self, env):
3595 import ExprNodes
3596 self.target.analyse_target_types(env)
3597 if Options.convert_range and self.target.type.is_int:
3598 sequence = self.iterator.sequence
3599 if isinstance(sequence, ExprNodes.SimpleCallNode) \
3600 and sequence.self is None \
3601 and isinstance(sequence.function, ExprNodes.NameNode) \
3602 and (sequence.function.name == 'range' or sequence.function.name == 'xrange'):
3603 args = sequence.args
3604 # Make sure we can determine direction from step
3605 if self.analyse_range_step(args):
3606 # Mutate to ForFrom loop type
3607 self.__class__ = ForFromStatNode
3608 if len(args) == 1:
3609 self.bound1 = ExprNodes.IntNode(pos = sequence.pos, value='0')
3610 self.bound2 = args[0]
3611 else:
3612 self.bound1 = args[0]
3613 self.bound2 = args[1]
3614 ForFromStatNode.analyse_expressions(self, env)
3615 return
3617 self.iterator.analyse_expressions(env)
3618 self.item = ExprNodes.NextNode(self.iterator, env)
3619 self.item = self.item.coerce_to(self.target.type, env)
3620 self.item.allocate_temps(env)
3621 self.target.allocate_target_temps(env, self.item)
3622 #self.item.release_temp(env)
3623 #self.target.release_target_temp(env)
3624 self.body.analyse_expressions(env)
3625 if self.else_clause:
3626 self.else_clause.analyse_expressions(env)
3627 self.iterator.release_temp(env)
3629 def generate_execution_code(self, code):
3630 old_loop_labels = code.new_loop_labels()
3631 self.iterator.generate_evaluation_code(code)
3632 code.putln(
3633 "for (;;) {")
3634 self.item.generate_evaluation_code(code)
3635 self.target.generate_assignment_code(self.item, code)
3636 self.body.generate_execution_code(code)
3637 code.put_label(code.continue_label)
3638 code.putln(
3639 "}")
3640 break_label = code.break_label
3641 code.set_loop_labels(old_loop_labels)
3642 if self.else_clause:
3643 code.putln("/*else*/ {")
3644 self.else_clause.generate_execution_code(code)
3645 code.putln("}")
3646 code.put_label(break_label)
3647 self.iterator.generate_disposal_code(code)
3649 def annotate(self, code):
3650 self.target.annotate(code)
3651 self.iterator.annotate(code)
3652 self.body.annotate(code)
3653 if self.else_clause:
3654 self.else_clause.annotate(code)
3655 self.item.annotate(code)
3658 class ForFromStatNode(LoopNode, StatNode):
3659 # for name from expr rel name rel expr
3661 # target NameNode
3662 # bound1 ExprNode
3663 # relation1 string
3664 # relation2 string
3665 # bound2 ExprNode
3666 # step ExprNode or None
3667 # body StatNode
3668 # else_clause StatNode or None
3670 # Used internally:
3672 # is_py_target bool
3673 # loopvar_name string
3674 # py_loopvar_node PyTempNode or None
3675 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3677 def analyse_declarations(self, env):
3678 self.target.analyse_target_declaration(env)
3679 self.body.analyse_declarations(env)
3680 if self.else_clause:
3681 self.else_clause.analyse_declarations(env)
3683 def analyse_expressions(self, env):
3684 import ExprNodes
3685 self.target.analyse_target_types(env)
3686 self.bound1.analyse_types(env)
3687 self.bound2.analyse_types(env)
3688 if self.target.type.is_numeric:
3689 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3690 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3691 else:
3692 self.bound1 = self.bound1.coerce_to_integer(env)
3693 self.bound2 = self.bound2.coerce_to_integer(env)
3694 if self.step is not None:
3695 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3696 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3697 self.step.analyse_types(env)
3698 self.step = self.step.coerce_to_integer(env)
3699 if not (self.bound2.is_name or self.bound2.is_literal):
3700 self.bound2 = self.bound2.coerce_to_temp(env)
3701 target_type = self.target.type
3702 if not (target_type.is_pyobject or target_type.is_numeric):
3703 error(self.target.pos,
3704 "Integer for-loop variable must be of type int or Python object")
3705 #if not (target_type.is_pyobject
3706 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3707 # error(self.target.pos,
3708 # "Cannot assign integer to variable of type '%s'" % target_type)
3709 if target_type.is_numeric:
3710 self.is_py_target = 0
3711 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3712 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3713 self.loopvar_name = self.target.entry.cname
3714 self.py_loopvar_node = None
3715 else:
3716 self.is_py_target = 1
3717 c_loopvar_node = ExprNodes.TempNode(self.pos,
3718 PyrexTypes.c_long_type, env)
3719 c_loopvar_node.allocate_temps(env)
3720 self.loopvar_name = c_loopvar_node.result()
3721 self.py_loopvar_node = \
3722 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3723 self.bound1.allocate_temps(env)
3724 self.bound2.allocate_temps(env)
3725 if self.step is not None:
3726 self.step.allocate_temps(env)
3727 if self.is_py_target:
3728 self.py_loopvar_node.allocate_temps(env)
3729 self.target.allocate_target_temps(env, self.py_loopvar_node)
3730 #self.target.release_target_temp(env)
3731 #self.py_loopvar_node.release_temp(env)
3732 self.body.analyse_expressions(env)
3733 if self.is_py_target:
3734 c_loopvar_node.release_temp(env)
3735 if self.else_clause:
3736 self.else_clause.analyse_expressions(env)
3737 self.bound1.release_temp(env)
3738 self.bound2.release_temp(env)
3739 if self.step is not None:
3740 self.step.release_temp(env)
3742 def generate_execution_code(self, code):
3743 old_loop_labels = code.new_loop_labels()
3744 self.bound1.generate_evaluation_code(code)
3745 self.bound2.generate_evaluation_code(code)
3746 offset, incop = self.relation_table[self.relation1]
3747 if self.step is not None:
3748 self.step.generate_evaluation_code(code)
3749 incop = "%s=%s" % (incop[0], self.step.result())
3750 code.putln(
3751 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3752 self.loopvar_name,
3753 self.bound1.result(), offset,
3754 self.loopvar_name, self.relation2, self.bound2.result(),
3755 self.loopvar_name, incop))
3756 if self.py_loopvar_node:
3757 self.py_loopvar_node.generate_evaluation_code(code)
3758 self.target.generate_assignment_code(self.py_loopvar_node, code)
3759 self.body.generate_execution_code(code)
3760 code.put_label(code.continue_label)
3761 code.putln("}")
3762 break_label = code.break_label
3763 code.set_loop_labels(old_loop_labels)
3764 if self.else_clause:
3765 code.putln("/*else*/ {")
3766 self.else_clause.generate_execution_code(code)
3767 code.putln("}")
3768 code.put_label(break_label)
3769 self.bound1.generate_disposal_code(code)
3770 self.bound2.generate_disposal_code(code)
3771 if self.step is not None:
3772 self.step.generate_disposal_code(code)
3774 relation_table = {
3775 # {relop : (initial offset, increment op)}
3776 '<=': ("", "++"),
3777 '<' : ("+1", "++"),
3778 '>=': ("", "--"),
3779 '>' : ("-1", "--")
3782 def annotate(self, code):
3783 self.target.annotate(code)
3784 self.bound1.annotate(code)
3785 self.bound2.annotate(code)
3786 if self.step:
3787 self.bound2.annotate(code)
3788 self.body.annotate(code)
3789 if self.else_clause:
3790 self.else_clause.annotate(code)
3793 class WithStatNode(StatNode):
3794 """
3795 Represents a Python with statement.
3797 This is only used at parse tree level; and is not present in
3798 analysis or generation phases.
3799 """
3800 # manager The with statement manager object
3801 # target Node (lhs expression)
3802 # body StatNode
3803 child_attrs = ["manager", "target", "body"]
3805 class TryExceptStatNode(StatNode):
3806 # try .. except statement
3808 # body StatNode
3809 # except_clauses [ExceptClauseNode]
3810 # else_clause StatNode or None
3811 # cleanup_list [Entry] temps to clean up on error
3813 child_attrs = ["body", "except_clauses", "else_clause"]
3815 def analyse_control_flow(self, env):
3816 env.start_branching(self.pos)
3817 self.body.analyse_control_flow(env)
3818 successful_try = env.control_flow # grab this for later
3819 env.next_branch(self.body.end_pos())
3820 env.finish_branching(self.body.end_pos())
3822 env.start_branching(self.except_clauses[0].pos)
3823 for except_clause in self.except_clauses:
3824 except_clause.analyse_control_flow(env)
3825 env.next_branch(except_clause.end_pos())
3827 # the else cause it executed only when the try clause finishes
3828 env.control_flow.incoming = successful_try
3829 if self.else_clause:
3830 self.else_clause.analyse_control_flow(env)
3831 env.finish_branching(self.end_pos())
3833 def analyse_declarations(self, env):
3834 self.body.analyse_declarations(env)
3835 for except_clause in self.except_clauses:
3836 except_clause.analyse_declarations(env)
3837 if self.else_clause:
3838 self.else_clause.analyse_declarations(env)
3839 self.gil_check(env)
3840 env.use_utility_code(reset_exception_utility_code)
3842 def analyse_expressions(self, env):
3843 self.body.analyse_expressions(env)
3844 self.cleanup_list = env.free_temp_entries[:]
3845 default_clause_seen = 0
3846 for except_clause in self.except_clauses:
3847 except_clause.analyse_expressions(env)
3848 if default_clause_seen:
3849 error(except_clause.pos, "default 'except:' must be last")
3850 if not except_clause.pattern:
3851 default_clause_seen = 1
3852 self.has_default_clause = default_clause_seen
3853 if self.else_clause:
3854 self.else_clause.analyse_expressions(env)
3855 self.gil_check(env)
3857 gil_message = "Try-except statement"
3859 def generate_execution_code(self, code):
3860 old_return_label = code.return_label
3861 old_error_label = code.new_error_label()
3862 our_error_label = code.error_label
3863 except_end_label = code.new_label('exception_handled')
3864 except_error_label = code.new_label('except_error')
3865 except_return_label = code.new_label('except_return')
3866 try_end_label = code.new_label('try')
3868 code.putln("{")
3869 code.putln("PyObject %s;" %
3870 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
3871 code.putln("__Pyx_ExceptionSave(%s);" %
3872 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
3873 code.putln(
3874 "/*try:*/ {")
3875 self.body.generate_execution_code(code)
3876 code.putln(
3877 "}")
3878 code.error_label = except_error_label
3879 code.return_label = except_return_label
3880 if self.else_clause:
3881 code.putln(
3882 "/*else:*/ {")
3883 self.else_clause.generate_execution_code(code)
3884 code.putln(
3885 "}")
3886 for var in Naming.exc_save_vars:
3887 code.put_xdecref_clear(var, py_object_type)
3888 code.put_goto(try_end_label)
3889 code.put_label(our_error_label)
3890 code.put_var_xdecrefs_clear(self.cleanup_list)
3891 for except_clause in self.except_clauses:
3892 except_clause.generate_handling_code(code, except_end_label)
3894 error_label_used = code.label_used(except_error_label)
3895 if error_label_used or not self.has_default_clause:
3896 if error_label_used:
3897 code.put_label(except_error_label)
3898 for var in Naming.exc_save_vars:
3899 code.put_xdecref(var, py_object_type)
3900 code.put_goto(old_error_label)
3902 if code.label_used(except_return_label):
3903 code.put_label(except_return_label)
3904 code.putln("__Pyx_ExceptionReset(%s);" %
3905 ', '.join(Naming.exc_save_vars))
3906 code.put_goto(old_return_label)
3908 if code.label_used(except_end_label):
3909 code.put_label(except_end_label)
3910 code.putln("__Pyx_ExceptionReset(%s);" %
3911 ', '.join(Naming.exc_save_vars))
3912 code.put_label(try_end_label)
3913 code.putln("}")
3915 code.return_label = old_return_label
3916 code.error_label = old_error_label
3918 def annotate(self, code):
3919 self.body.annotate(code)
3920 for except_node in self.except_clauses:
3921 except_node.annotate(code)
3922 if self.else_clause:
3923 self.else_clause.annotate(code)
3926 class ExceptClauseNode(Node):
3927 # Part of try ... except statement.
3929 # pattern ExprNode
3930 # target ExprNode or None
3931 # body StatNode
3932 # excinfo_target NameNode or None optional target for exception info
3933 # match_flag string result of exception match
3934 # exc_value ExcValueNode used internally
3935 # function_name string qualified name of enclosing function
3936 # exc_vars (string * 3) local exception variables
3938 # excinfo_target is never set by the parser, but can be set by a transform
3939 # in order to extract more extensive information about the exception as a
3940 # sys.exc_info()-style tuple into a target variable
3942 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
3944 exc_value = None
3945 excinfo_target = None
3947 def analyse_declarations(self, env):
3948 if self.target:
3949 self.target.analyse_target_declaration(env)
3950 if self.excinfo_target is not None:
3951 self.excinfo_target.analyse_target_declaration(env)
3952 self.body.analyse_declarations(env)
3954 def analyse_expressions(self, env):
3955 import ExprNodes
3956 genv = env.global_scope()
3957 self.function_name = env.qualified_name
3958 if self.pattern:
3959 self.pattern.analyse_expressions(env)
3960 self.pattern = self.pattern.coerce_to_pyobject(env)
3961 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
3962 self.pattern.release_temp(env)
3963 env.release_temp(self.match_flag)
3964 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
3965 if self.target:
3966 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
3967 self.exc_value.allocate_temps(env)
3968 self.target.analyse_target_expression(env, self.exc_value)
3969 if self.excinfo_target is not None:
3970 import ExprNodes
3971 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
3972 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
3973 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
3974 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
3975 ])
3976 self.excinfo_tuple.analyse_expressions(env)
3977 self.excinfo_tuple.allocate_temps(env)
3978 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
3980 self.body.analyse_expressions(env)
3981 for var in self.exc_vars:
3982 env.release_temp(var)
3983 env.use_utility_code(get_exception_utility_code)
3984 env.use_utility_code(restore_exception_utility_code)
3986 def generate_handling_code(self, code, end_label):
3987 code.mark_pos(self.pos)
3988 if self.pattern:
3989 self.pattern.generate_evaluation_code(code)
3990 code.putln(
3991 "%s = PyErr_ExceptionMatches(%s);" % (
3992 self.match_flag,
3993 self.pattern.py_result()))
3994 self.pattern.generate_disposal_code(code)
3995 code.putln(
3996 "if (%s) {" %
3997 self.match_flag)
3998 else:
3999 code.putln("/*except:*/ {")
4000 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4001 # We always have to fetch the exception value even if
4002 # there is no target, because this also normalises the
4003 # exception and stores it in the thread state.
4004 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
4005 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4006 code.error_goto(self.pos)))
4007 if self.target:
4008 self.exc_value.generate_evaluation_code(code)
4009 self.target.generate_assignment_code(self.exc_value, code)
4010 if self.excinfo_target is not None:
4011 self.excinfo_tuple.generate_evaluation_code(code)
4012 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4014 old_exc_vars = code.funcstate.exc_vars
4015 code.funcstate.exc_vars = self.exc_vars
4016 self.body.generate_execution_code(code)
4017 code.funcstate.exc_vars = old_exc_vars
4018 for var in self.exc_vars:
4019 code.putln("Py_DECREF(%s); %s = 0;" % (var, var))
4020 code.put_goto(end_label)
4021 code.putln(
4022 "}")
4024 def annotate(self, code):
4025 if self.pattern:
4026 self.pattern.annotate(code)
4027 if self.target:
4028 self.target.annotate(code)
4029 self.body.annotate(code)
4032 class TryFinallyStatNode(StatNode):
4033 # try ... finally statement
4035 # body StatNode
4036 # finally_clause StatNode
4038 # cleanup_list [Entry] temps to clean up on error
4040 # The plan is that we funnel all continue, break
4041 # return and error gotos into the beginning of the
4042 # finally block, setting a variable to remember which
4043 # one we're doing. At the end of the finally block, we
4044 # switch on the variable to figure out where to go.
4045 # In addition, if we're doing an error, we save the
4046 # exception on entry to the finally block and restore
4047 # it on exit.
4049 child_attrs = ["body", "finally_clause"]
4051 preserve_exception = 1
4053 disallow_continue_in_try_finally = 0
4054 # There doesn't seem to be any point in disallowing
4055 # continue in the try block, since we have no problem
4056 # handling it.
4058 def create_analysed(pos, env, body, finally_clause):
4059 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4060 node.cleanup_list = []
4061 return node
4062 create_analysed = staticmethod(create_analysed)
4064 def analyse_control_flow(self, env):
4065 env.start_branching(self.pos)
4066 self.body.analyse_control_flow(env)
4067 env.next_branch(self.body.end_pos())
4068 env.finish_branching(self.body.end_pos())
4069 self.finally_clause.analyse_control_flow(env)
4071 def analyse_declarations(self, env):
4072 self.body.analyse_declarations(env)
4073 self.finally_clause.analyse_declarations(env)
4075 def analyse_expressions(self, env):
4076 self.body.analyse_expressions(env)
4077 self.cleanup_list = env.free_temp_entries[:]
4078 self.finally_clause.analyse_expressions(env)
4079 self.gil_check(env)
4081 gil_message = "Try-finally statement"
4083 def generate_execution_code(self, code):
4084 old_error_label = code.error_label
4085 old_labels = code.all_new_labels()
4086 new_labels = code.get_all_labels()
4087 new_error_label = code.error_label
4088 catch_label = code.new_label()
4089 code.putln(
4090 "/*try:*/ {")
4091 if self.disallow_continue_in_try_finally:
4092 was_in_try_finally = code.funcstate.in_try_finally
4093 code.funcstate.in_try_finally = 1
4094 self.body.generate_execution_code(code)
4095 if self.disallow_continue_in_try_finally:
4096 code.funcstate.in_try_finally = was_in_try_finally
4097 code.putln(
4098 "}")
4099 code.putln(
4100 "/*finally:*/ {")
4101 cases_used = []
4102 error_label_used = 0
4103 for i, new_label in enumerate(new_labels):
4104 if new_label in code.labels_used:
4105 cases_used.append(i)
4106 if new_label == new_error_label:
4107 error_label_used = 1
4108 error_label_case = i
4109 if cases_used:
4110 code.putln(
4111 "int __pyx_why;")
4112 if error_label_used and self.preserve_exception:
4113 code.putln(
4114 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4115 code.putln(
4116 "int %s;" % Naming.exc_lineno_name)
4117 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4118 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4119 code.putln(exc_var_init_zero)
4120 else:
4121 exc_var_init_zero = None
4122 code.use_label(catch_label)
4123 code.putln(
4124 "__pyx_why = 0; goto %s;" % catch_label)
4125 for i in cases_used:
4126 new_label = new_labels[i]
4127 #if new_label and new_label != "<try>":
4128 if new_label == new_error_label and self.preserve_exception:
4129 self.put_error_catcher(code,
4130 new_error_label, i+1, catch_label)
4131 else:
4132 code.put('%s: ' % new_label)
4133 if exc_var_init_zero:
4134 code.putln(exc_var_init_zero)
4135 code.putln("__pyx_why = %s; goto %s;" % (
4136 i+1,
4137 catch_label))
4138 code.put_label(catch_label)
4139 code.set_all_labels(old_labels)
4140 if error_label_used:
4141 code.new_error_label()
4142 finally_error_label = code.error_label
4143 self.finally_clause.generate_execution_code(code)
4144 if error_label_used:
4145 if finally_error_label in code.labels_used and self.preserve_exception:
4146 over_label = code.new_label()
4147 code.put_goto(over_label);
4148 code.put_label(finally_error_label)
4149 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4150 for var in Naming.exc_vars:
4151 code.putln("Py_XDECREF(%s);" % var)
4152 code.putln("}")
4153 code.put_goto(old_error_label)
4154 code.put_label(over_label)
4155 code.error_label = old_error_label
4156 if cases_used:
4157 code.putln(
4158 "switch (__pyx_why) {")
4159 for i in cases_used:
4160 old_label = old_labels[i]
4161 if old_label == old_error_label and self.preserve_exception:
4162 self.put_error_uncatcher(code, i+1, old_error_label)
4163 else:
4164 code.use_label(old_label)
4165 code.putln(
4166 "case %s: goto %s;" % (
4167 i+1,
4168 old_label))
4169 code.putln(
4170 "}")
4171 code.putln(
4172 "}")
4174 def put_error_catcher(self, code, error_label, i, catch_label):
4175 code.globalstate.use_utility_code(restore_exception_utility_code)
4176 code.putln(
4177 "%s: {" %
4178 error_label)
4179 code.putln(
4180 "__pyx_why = %s;" %
4181 i)
4182 code.put_var_xdecrefs_clear(self.cleanup_list)
4183 code.putln(
4184 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4185 Naming.exc_vars)
4186 code.putln(
4187 "%s = %s;" % (
4188 Naming.exc_lineno_name, Naming.lineno_cname))
4189 #code.putln(
4190 # "goto %s;" %
4191 # catch_label)
4192 code.put_goto(catch_label)
4193 code.putln(
4194 "}")
4196 def put_error_uncatcher(self, code, i, error_label):
4197 code.globalstate.use_utility_code(restore_exception_utility_code)
4198 code.putln(
4199 "case %s: {" %
4200 i)
4201 code.putln(
4202 "__Pyx_ErrRestore(%s, %s, %s);" %
4203 Naming.exc_vars)
4204 code.putln(
4205 "%s = %s;" % (
4206 Naming.lineno_cname, Naming.exc_lineno_name))
4207 for var in Naming.exc_vars:
4208 code.putln(
4209 "%s = 0;" %
4210 var)
4211 code.put_goto(error_label)
4212 code.putln(
4213 "}")
4215 def annotate(self, code):
4216 self.body.annotate(code)
4217 self.finally_clause.annotate(code)
4220 class GILStatNode(TryFinallyStatNode):
4221 # 'with gil' or 'with nogil' statement
4223 # state string 'gil' or 'nogil'
4225 child_attrs = []
4227 preserve_exception = 0
4229 def __init__(self, pos, state, body):
4230 self.state = state
4231 TryFinallyStatNode.__init__(self, pos,
4232 body = body,
4233 finally_clause = GILExitNode(pos, state = state))
4235 def analyse_expressions(self, env):
4236 was_nogil = env.nogil
4237 env.nogil = 1
4238 TryFinallyStatNode.analyse_expressions(self, env)
4239 env.nogil = was_nogil
4241 def gil_check(self, env):
4242 pass
4244 def generate_execution_code(self, code):
4245 code.putln("/*with %s:*/ {" % self.state)
4246 if self.state == 'gil':
4247 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
4248 else:
4249 code.putln("PyThreadState *_save;")
4250 code.putln("Py_UNBLOCK_THREADS")
4251 TryFinallyStatNode.generate_execution_code(self, code)
4252 code.putln("}")
4255 class GILExitNode(StatNode):
4256 # Used as the 'finally' block in a GILStatNode
4258 # state string 'gil' or 'nogil'
4260 child_attrs = []
4262 def analyse_expressions(self, env):
4263 pass
4265 def generate_execution_code(self, code):
4266 if self.state == 'gil':
4267 code.putln("PyGILState_Release();")
4268 else:
4269 code.putln("Py_BLOCK_THREADS")
4272 class CImportStatNode(StatNode):
4273 # cimport statement
4275 # module_name string Qualified name of module being imported
4276 # as_name string or None Name specified in "as" clause, if any
4278 child_attrs = []
4280 def analyse_declarations(self, env):
4281 if not env.is_module_scope:
4282 error(self.pos, "cimport only allowed at module level")
4283 return
4284 module_scope = env.find_module(self.module_name, self.pos)
4285 if "." in self.module_name:
4286 names = [EncodedString(name) for name in self.module_name.split(".")]
4287 top_name = names[0]
4288 top_module_scope = env.context.find_submodule(top_name)
4289 module_scope = top_module_scope
4290 for name in names[1:]:
4291 submodule_scope = module_scope.find_submodule(name)
4292 module_scope.declare_module(name, submodule_scope, self.pos)
4293 module_scope = submodule_scope
4294 if self.as_name:
4295 env.declare_module(self.as_name, module_scope, self.pos)
4296 else:
4297 env.declare_module(top_name, top_module_scope, self.pos)
4298 else:
4299 name = self.as_name or self.module_name
4300 env.declare_module(name, module_scope, self.pos)
4302 def analyse_expressions(self, env):
4303 pass
4305 def generate_execution_code(self, code):
4306 pass
4309 class FromCImportStatNode(StatNode):
4310 # from ... cimport statement
4312 # module_name string Qualified name of module
4313 # imported_names [(pos, name, as_name, kind)] Names to be imported
4315 child_attrs = []
4317 def analyse_declarations(self, env):
4318 if not env.is_module_scope:
4319 error(self.pos, "cimport only allowed at module level")
4320 return
4321 module_scope = env.find_module(self.module_name, self.pos)
4322 env.add_imported_module(module_scope)
4323 for pos, name, as_name, kind in self.imported_names:
4324 if name == "*":
4325 for local_name, entry in module_scope.entries.items():
4326 env.add_imported_entry(local_name, entry, pos)
4327 else:
4328 entry = module_scope.lookup(name)
4329 if entry:
4330 if kind and not self.declaration_matches(entry, kind):
4331 entry.redeclared(pos)
4332 else:
4333 if kind == 'struct' or kind == 'union':
4334 entry = module_scope.declare_struct_or_union(name,
4335 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4336 elif kind == 'class':
4337 entry = module_scope.declare_c_class(name, pos = pos,
4338 module_name = self.module_name)
4339 else:
4340 error(pos, "Name '%s' not declared in module '%s'"
4341 % (name, self.module_name))
4343 if entry:
4344 local_name = as_name or name
4345 env.add_imported_entry(local_name, entry, pos)
4347 def declaration_matches(self, entry, kind):
4348 if not entry.is_type:
4349 return 0
4350 type = entry.type
4351 if kind == 'class':
4352 if not type.is_extension_type:
4353 return 0
4354 else:
4355 if not type.is_struct_or_union:
4356 return 0
4357 if kind <> type.kind:
4358 return 0
4359 return 1
4361 def analyse_expressions(self, env):
4362 pass
4364 def generate_execution_code(self, code):
4365 pass
4368 class FromImportStatNode(StatNode):
4369 # from ... import statement
4371 # module ImportNode
4372 # items [(string, NameNode)]
4373 # interned_items [(string, NameNode)]
4374 # item PyTempNode used internally
4375 # import_star boolean used internally
4377 child_attrs = ["module"]
4378 import_star = 0
4380 def analyse_declarations(self, env):
4381 for name, target in self.items:
4382 if name == "*":
4383 if not env.is_module_scope:
4384 error(self.pos, "import * only allowed at module level")
4385 return
4386 env.has_import_star = 1
4387 self.import_star = 1
4388 else:
4389 target.analyse_target_declaration(env)
4391 def analyse_expressions(self, env):
4392 import ExprNodes
4393 self.module.analyse_expressions(env)
4394 self.item = ExprNodes.PyTempNode(self.pos, env)
4395 self.item.allocate_temp(env)
4396 self.interned_items = []
4397 for name, target in self.items:
4398 if name == '*':
4399 for _, entry in env.entries.items():
4400 if not entry.is_type and entry.type.is_extension_type:
4401 env.use_utility_code(ExprNodes.type_test_utility_code)
4402 break
4403 else:
4404 self.interned_items.append(
4405 (env.intern_identifier(name), target))
4406 target.analyse_target_expression(env, None)
4407 #target.release_target_temp(env) # was release_temp ?!?
4408 self.module.release_temp(env)
4409 self.item.release_temp(env)
4411 def generate_execution_code(self, code):
4412 self.module.generate_evaluation_code(code)
4413 if self.import_star:
4414 code.putln(
4415 'if (%s(%s) < 0) %s;' % (
4416 Naming.import_star,
4417 self.module.py_result(),
4418 code.error_goto(self.pos)))
4419 for cname, target in self.interned_items:
4420 code.putln(
4421 '%s = PyObject_GetAttr(%s, %s); %s' % (
4422 self.item.result(),
4423 self.module.py_result(),
4424 cname,
4425 code.error_goto_if_null(self.item.result(), self.pos)))
4426 target.generate_assignment_code(self.item, code)
4427 self.module.generate_disposal_code(code)
4431 #------------------------------------------------------------------------------------
4433 # Runtime support code
4435 #------------------------------------------------------------------------------------
4437 utility_function_predeclarations = \
4438 """
4439 #ifdef __GNUC__
4440 #define INLINE __inline__
4441 #elif _WIN32
4442 #define INLINE __inline
4443 #else
4444 #define INLINE
4445 #endif
4447 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4449 """ + """
4451 static int %(skip_dispatch_cname)s = 0;
4453 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4455 if Options.gcc_branch_hints:
4456 branch_prediction_macros = \
4457 """
4458 #ifdef __GNUC__
4459 /* Test for GCC > 2.95 */
4460 #if __GNUC__ > 2 || \
4461 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4462 #define likely(x) __builtin_expect(!!(x), 1)
4463 #define unlikely(x) __builtin_expect(!!(x), 0)
4464 #else /* __GNUC__ > 2 ... */
4465 #define likely(x) (x)
4466 #define unlikely(x) (x)
4467 #endif /* __GNUC__ > 2 ... */
4468 #else /* __GNUC__ */
4469 #define likely(x) (x)
4470 #define unlikely(x) (x)
4471 #endif /* __GNUC__ */
4472 """
4473 else:
4474 branch_prediction_macros = \
4475 """
4476 #define likely(x) (x)
4477 #define unlikely(x) (x)
4478 """
4480 #get_name_predeclaration = \
4481 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4483 #get_name_interned_predeclaration = \
4484 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4486 #------------------------------------------------------------------------------------
4488 printing_utility_code = UtilityCode(
4489 proto = """
4490 static int __Pyx_Print(PyObject *, int); /*proto*/
4491 #if PY_MAJOR_VERSION >= 3
4492 static PyObject* %s = 0;
4493 static PyObject* %s = 0;
4494 #endif
4495 """ % (Naming.print_function, Naming.print_function_kwargs),
4496 impl = r"""
4497 #if PY_MAJOR_VERSION < 3
4498 static PyObject *__Pyx_GetStdout(void) {
4499 PyObject *f = PySys_GetObject("stdout");
4500 if (!f) {
4501 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4503 return f;
4506 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4507 PyObject *f;
4508 PyObject* v;
4509 int i;
4511 if (!(f = __Pyx_GetStdout()))
4512 return -1;
4513 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4514 if (PyFile_SoftSpace(f, 1)) {
4515 if (PyFile_WriteString(" ", f) < 0)
4516 return -1;
4518 v = PyTuple_GET_ITEM(arg_tuple, i);
4519 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4520 return -1;
4521 if (PyString_Check(v)) {
4522 char *s = PyString_AsString(v);
4523 Py_ssize_t len = PyString_Size(v);
4524 if (len > 0 &&
4525 isspace(Py_CHARMASK(s[len-1])) &&
4526 s[len-1] != ' ')
4527 PyFile_SoftSpace(f, 0);
4530 if (newline) {
4531 if (PyFile_WriteString("\n", f) < 0)
4532 return -1;
4533 PyFile_SoftSpace(f, 0);
4535 return 0;
4538 #else /* Python 3 has a print function */
4539 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4540 PyObject* kwargs = 0;
4541 PyObject* result = 0;
4542 PyObject* end_string;
4543 if (!%(PRINT_FUNCTION)s) {
4544 %(PRINT_FUNCTION)s = PyObject_GetAttrString(%(BUILTINS)s, "print");
4545 if (!%(PRINT_FUNCTION)s)
4546 return -1;
4548 if (!newline) {
4549 if (!%(PRINT_KWARGS)s) {
4550 %(PRINT_KWARGS)s = PyDict_New();
4551 if (!%(PRINT_KWARGS)s)
4552 return -1;
4553 end_string = PyUnicode_FromStringAndSize(" ", 1);
4554 if (!end_string)
4555 return -1;
4556 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4557 Py_DECREF(end_string);
4558 return -1;
4560 Py_DECREF(end_string);
4562 kwargs = %(PRINT_KWARGS)s;
4564 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4565 if (!result)
4566 return -1;
4567 Py_DECREF(result);
4568 return 0;
4570 #endif
4571 """ % {'BUILTINS' : Naming.builtins_cname,
4572 'PRINT_FUNCTION' : Naming.print_function,
4573 'PRINT_KWARGS' : Naming.print_function_kwargs}
4576 #------------------------------------------------------------------------------------
4578 # The following function is based on do_raise() from ceval.c.
4580 raise_utility_code = UtilityCode(
4581 proto = """
4582 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4583 """,
4584 impl = """
4585 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4586 Py_XINCREF(type);
4587 Py_XINCREF(value);
4588 Py_XINCREF(tb);
4589 /* First, check the traceback argument, replacing None with NULL. */
4590 if (tb == Py_None) {
4591 Py_DECREF(tb);
4592 tb = 0;
4594 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4595 PyErr_SetString(PyExc_TypeError,
4596 "raise: arg 3 must be a traceback or None");
4597 goto raise_error;
4599 /* Next, replace a missing value with None */
4600 if (value == NULL) {
4601 value = Py_None;
4602 Py_INCREF(value);
4604 #if PY_VERSION_HEX < 0x02050000
4605 if (!PyClass_Check(type))
4606 #else
4607 if (!PyType_Check(type))
4608 #endif
4610 /* Raising an instance. The value should be a dummy. */
4611 if (value != Py_None) {
4612 PyErr_SetString(PyExc_TypeError,
4613 "instance exception may not have a separate value");
4614 goto raise_error;
4616 /* Normalize to raise <class>, <instance> */
4617 Py_DECREF(value);
4618 value = type;
4619 #if PY_VERSION_HEX < 0x02050000
4620 if (PyInstance_Check(type)) {
4621 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4622 Py_INCREF(type);
4624 else {
4625 type = 0;
4626 PyErr_SetString(PyExc_TypeError,
4627 "raise: exception must be an old-style class or instance");
4628 goto raise_error;
4630 #else
4631 type = (PyObject*) Py_TYPE(type);
4632 Py_INCREF(type);
4633 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4634 PyErr_SetString(PyExc_TypeError,
4635 "raise: exception class must be a subclass of BaseException");
4636 goto raise_error;
4638 #endif
4640 __Pyx_ErrRestore(type, value, tb);
4641 return;
4642 raise_error:
4643 Py_XDECREF(value);
4644 Py_XDECREF(type);
4645 Py_XDECREF(tb);
4646 return;
4648 """)
4650 #------------------------------------------------------------------------------------
4652 reraise_utility_code = UtilityCode(
4653 proto = """
4654 static void __Pyx_ReRaise(void); /*proto*/
4655 """,
4656 impl = """
4657 static void __Pyx_ReRaise(void) {
4658 PyThreadState *tstate = PyThreadState_Get();
4659 PyObject *type = tstate->exc_type;
4660 PyObject *value = tstate->exc_value;
4661 PyObject *tb = tstate->exc_traceback;
4662 Py_XINCREF(type);
4663 Py_XINCREF(value);
4664 Py_XINCREF(tb);
4665 __Pyx_ErrRestore(type, value, tb);
4667 """)
4669 #------------------------------------------------------------------------------------
4671 arg_type_test_utility_code = UtilityCode(
4672 proto = """
4673 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4674 const char *name, int exact); /*proto*/
4675 """,
4676 impl = """
4677 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4678 const char *name, int exact)
4680 if (!type) {
4681 PyErr_Format(PyExc_SystemError, "Missing type object");
4682 return 0;
4684 if (none_allowed && obj == Py_None) return 1;
4685 else if (exact) {
4686 if (Py_TYPE(obj) == type) return 1;
4688 else {
4689 if (PyObject_TypeCheck(obj, type)) return 1;
4691 PyErr_Format(PyExc_TypeError,
4692 "Argument '%s' has incorrect type (expected %s, got %s)",
4693 name, type->tp_name, Py_TYPE(obj)->tp_name);
4694 return 0;
4696 """)
4698 #------------------------------------------------------------------------------------
4700 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
4701 # many or too few positional arguments were found. This handles
4702 # Py_ssize_t formatting correctly.
4704 raise_argtuple_invalid_utility_code = UtilityCode(
4705 proto = """
4706 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
4707 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
4708 """,
4709 impl = """
4710 static void __Pyx_RaiseArgtupleInvalid(
4711 const char* func_name,
4712 int exact,
4713 Py_ssize_t num_min,
4714 Py_ssize_t num_max,
4715 Py_ssize_t num_found)
4717 Py_ssize_t num_expected;
4718 const char *number, *more_or_less;
4720 if (num_found < num_min) {
4721 num_expected = num_min;
4722 more_or_less = "at least";
4723 } else {
4724 num_expected = num_max;
4725 more_or_less = "at most";
4727 if (exact) {
4728 more_or_less = "exactly";
4730 number = (num_expected == 1) ? "" : "s";
4731 PyErr_Format(PyExc_TypeError,
4732 #if PY_VERSION_HEX < 0x02050000
4733 "%s() takes %s %d positional argument%s (%d given)",
4734 #else
4735 "%s() takes %s %zd positional argument%s (%zd given)",
4736 #endif
4737 func_name, more_or_less, num_expected, number, num_found);
4739 """)
4741 raise_keyword_required_utility_code = UtilityCode(
4742 proto = """
4743 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
4744 """,
4745 impl = """
4746 static INLINE void __Pyx_RaiseKeywordRequired(
4747 const char* func_name,
4748 PyObject* kw_name)
4750 PyErr_Format(PyExc_TypeError,
4751 #if PY_MAJOR_VERSION >= 3
4752 "%s() needs keyword-only argument %U", func_name, kw_name);
4753 #else
4754 "%s() needs keyword-only argument %s", func_name,
4755 PyString_AS_STRING(kw_name));
4756 #endif
4758 """)
4760 raise_double_keywords_utility_code = UtilityCode(
4761 proto = """
4762 static void __Pyx_RaiseDoubleKeywordsError(
4763 const char* func_name, PyObject* kw_name); /*proto*/
4764 """,
4765 impl = """
4766 static void __Pyx_RaiseDoubleKeywordsError(
4767 const char* func_name,
4768 PyObject* kw_name)
4770 PyErr_Format(PyExc_TypeError,
4771 #if PY_MAJOR_VERSION >= 3
4772 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
4773 #else
4774 "%s() got multiple values for keyword argument '%s'", func_name,
4775 PyString_AS_STRING(kw_name));
4776 #endif
4778 """)
4780 #------------------------------------------------------------------------------------
4782 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
4783 # were passed to a function, or if any keywords were passed to a
4784 # function that does not accept them.
4786 keyword_string_check_utility_code = UtilityCode(
4787 proto = """
4788 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
4789 const char* function_name, int kw_allowed); /*proto*/
4790 """,
4791 impl = """
4792 static INLINE int __Pyx_CheckKeywordStrings(
4793 PyObject *kwdict,
4794 const char* function_name,
4795 int kw_allowed)
4797 PyObject* key = 0;
4798 Py_ssize_t pos = 0;
4799 while (PyDict_Next(kwdict, &pos, &key, 0)) {
4800 #if PY_MAJOR_VERSION < 3
4801 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
4802 #else
4803 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
4804 #endif
4805 goto invalid_keyword_type;
4807 if ((!kw_allowed) && unlikely(key))
4808 goto invalid_keyword;
4809 return 1;
4810 invalid_keyword_type:
4811 PyErr_Format(PyExc_TypeError,
4812 "%s() keywords must be strings", function_name);
4813 return 0;
4814 invalid_keyword:
4815 PyErr_Format(PyExc_TypeError,
4816 #if PY_MAJOR_VERSION < 3
4817 "%s() got an unexpected keyword argument '%s'",
4818 function_name, PyString_AsString(key));
4819 #else
4820 "%s() got an unexpected keyword argument '%U'",
4821 function_name, key);
4822 #endif
4823 return 0;
4825 """)
4827 #------------------------------------------------------------------------------------
4829 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
4830 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
4831 # keywords will raise an invalid keyword error.
4833 # Three kinds of errors are checked: 1) non-string keywords, 2)
4834 # unexpected keywords and 3) overlap with positional arguments.
4836 # If num_posargs is greater 0, it denotes the number of positional
4837 # arguments that were passed and that must therefore not appear
4838 # amongst the keywords as well.
4840 # This method does not check for required keyword arguments.
4843 parse_keywords_utility_code = UtilityCode(
4844 proto = """
4845 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
4846 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
4847 const char* function_name); /*proto*/
4848 """,
4849 impl = """
4850 static int __Pyx_ParseOptionalKeywords(
4851 PyObject *kwds,
4852 PyObject **argnames[],
4853 PyObject *kwds2,
4854 PyObject *values[],
4855 Py_ssize_t num_pos_args,
4856 const char* function_name)
4858 PyObject *key = 0, *value = 0;
4859 Py_ssize_t pos = 0;
4860 PyObject*** name;
4861 PyObject*** first_kw_arg = argnames + num_pos_args;
4863 while (PyDict_Next(kwds, &pos, &key, &value)) {
4864 #if PY_MAJOR_VERSION < 3
4865 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
4866 #else
4867 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
4868 #endif
4869 goto invalid_keyword_type;
4870 } else {
4871 name = argnames;
4872 while (*name && (**name != key)) name++;
4873 if (*name) {
4874 if (name < first_kw_arg) goto arg_passed_twice;
4875 values[name-argnames] = value;
4876 } else {
4877 for (name = first_kw_arg; *name; name++) {
4878 #if PY_MAJOR_VERSION >= 3
4879 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
4880 PyUnicode_Compare(**name, key) == 0) break;
4881 #else
4882 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
4883 strcmp(PyString_AS_STRING(**name),
4884 PyString_AS_STRING(key)) == 0) break;
4885 #endif
4887 if (*name) {
4888 values[name-argnames] = value;
4889 } else {
4890 /* unexpected keyword found */
4891 for (name=argnames; name != first_kw_arg; name++) {
4892 if (**name == key) goto arg_passed_twice;
4893 #if PY_MAJOR_VERSION >= 3
4894 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
4895 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
4896 #else
4897 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
4898 strcmp(PyString_AS_STRING(**name),
4899 PyString_AS_STRING(key)) == 0) goto arg_passed_twice;
4900 #endif
4902 if (kwds2) {
4903 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
4904 } else {
4905 goto invalid_keyword;
4911 return 0;
4912 arg_passed_twice:
4913 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
4914 goto bad;
4915 invalid_keyword_type:
4916 PyErr_Format(PyExc_TypeError,
4917 "%s() keywords must be strings", function_name);
4918 goto bad;
4919 invalid_keyword:
4920 PyErr_Format(PyExc_TypeError,
4921 #if PY_MAJOR_VERSION < 3
4922 "%s() got an unexpected keyword argument '%s'",
4923 function_name, PyString_AsString(key));
4924 #else
4925 "%s() got an unexpected keyword argument '%U'",
4926 function_name, key);
4927 #endif
4928 bad:
4929 return -1;
4931 """)
4933 #------------------------------------------------------------------------------------
4935 unraisable_exception_utility_code = UtilityCode(
4936 proto = """
4937 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
4938 """,
4939 impl = """
4940 static void __Pyx_WriteUnraisable(const char *name) {
4941 PyObject *old_exc, *old_val, *old_tb;
4942 PyObject *ctx;
4943 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
4944 #if PY_MAJOR_VERSION < 3
4945 ctx = PyString_FromString(name);
4946 #else
4947 ctx = PyUnicode_FromString(name);
4948 #endif
4949 __Pyx_ErrRestore(old_exc, old_val, old_tb);
4950 if (!ctx) {
4951 PyErr_WriteUnraisable(Py_None);
4952 } else {
4953 PyErr_WriteUnraisable(ctx);
4954 Py_DECREF(ctx);
4957 """)
4959 #------------------------------------------------------------------------------------
4961 traceback_utility_code = UtilityCode(
4962 proto = """
4963 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
4964 """,
4965 impl = """
4966 #include "compile.h"
4967 #include "frameobject.h"
4968 #include "traceback.h"
4970 static void __Pyx_AddTraceback(const char *funcname) {
4971 PyObject *py_srcfile = 0;
4972 PyObject *py_funcname = 0;
4973 PyObject *py_globals = 0;
4974 PyObject *empty_string = 0;
4975 PyCodeObject *py_code = 0;
4976 PyFrameObject *py_frame = 0;
4978 #if PY_MAJOR_VERSION < 3
4979 py_srcfile = PyString_FromString(%(FILENAME)s);
4980 #else
4981 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
4982 #endif
4983 if (!py_srcfile) goto bad;
4984 if (%(CLINENO)s) {
4985 #if PY_MAJOR_VERSION < 3
4986 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
4987 #else
4988 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
4989 #endif
4991 else {
4992 #if PY_MAJOR_VERSION < 3
4993 py_funcname = PyString_FromString(funcname);
4994 #else
4995 py_funcname = PyUnicode_FromString(funcname);
4996 #endif
4998 if (!py_funcname) goto bad;
4999 py_globals = PyModule_GetDict(%(GLOBALS)s);
5000 if (!py_globals) goto bad;
5001 #if PY_MAJOR_VERSION < 3
5002 empty_string = PyString_FromStringAndSize("", 0);
5003 #else
5004 empty_string = PyBytes_FromStringAndSize("", 0);
5005 #endif
5006 if (!empty_string) goto bad;
5007 py_code = PyCode_New(
5008 0, /*int argcount,*/
5009 #if PY_MAJOR_VERSION >= 3
5010 0, /*int kwonlyargcount,*/
5011 #endif
5012 0, /*int nlocals,*/
5013 0, /*int stacksize,*/
5014 0, /*int flags,*/
5015 empty_string, /*PyObject *code,*/
5016 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5017 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5018 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5019 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5020 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5021 py_srcfile, /*PyObject *filename,*/
5022 py_funcname, /*PyObject *name,*/
5023 %(LINENO)s, /*int firstlineno,*/
5024 empty_string /*PyObject *lnotab*/
5025 );
5026 if (!py_code) goto bad;
5027 py_frame = PyFrame_New(
5028 PyThreadState_GET(), /*PyThreadState *tstate,*/
5029 py_code, /*PyCodeObject *code,*/
5030 py_globals, /*PyObject *globals,*/
5031 0 /*PyObject *locals*/
5032 );
5033 if (!py_frame) goto bad;
5034 py_frame->f_lineno = %(LINENO)s;
5035 PyTraceBack_Here(py_frame);
5036 bad:
5037 Py_XDECREF(py_srcfile);
5038 Py_XDECREF(py_funcname);
5039 Py_XDECREF(empty_string);
5040 Py_XDECREF(py_code);
5041 Py_XDECREF(py_frame);
5043 """ % {
5044 'FILENAME': Naming.filename_cname,
5045 'LINENO': Naming.lineno_cname,
5046 'CFILENAME': Naming.cfilenm_cname,
5047 'CLINENO': Naming.clineno_cname,
5048 'GLOBALS': Naming.module_cname,
5049 'EMPTY_TUPLE' : Naming.empty_tuple,
5050 })
5052 restore_exception_utility_code = UtilityCode(
5053 proto = """
5054 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5055 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5056 """,
5057 impl = """
5058 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5059 PyObject *tmp_type, *tmp_value, *tmp_tb;
5060 PyThreadState *tstate = PyThreadState_GET();
5062 tmp_type = tstate->curexc_type;
5063 tmp_value = tstate->curexc_value;
5064 tmp_tb = tstate->curexc_traceback;
5065 tstate->curexc_type = type;
5066 tstate->curexc_value = value;
5067 tstate->curexc_traceback = tb;
5068 Py_XDECREF(tmp_type);
5069 Py_XDECREF(tmp_value);
5070 Py_XDECREF(tmp_tb);
5073 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5074 PyThreadState *tstate = PyThreadState_GET();
5075 *type = tstate->curexc_type;
5076 *value = tstate->curexc_value;
5077 *tb = tstate->curexc_traceback;
5079 tstate->curexc_type = 0;
5080 tstate->curexc_value = 0;
5081 tstate->curexc_traceback = 0;
5084 """)
5086 #------------------------------------------------------------------------------------
5088 set_vtable_utility_code = UtilityCode(
5089 proto = """
5090 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5091 """,
5092 impl = """
5093 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5094 PyObject *pycobj = 0;
5095 int result;
5097 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5098 if (!pycobj)
5099 goto bad;
5100 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5101 goto bad;
5102 result = 0;
5103 goto done;
5105 bad:
5106 result = -1;
5107 done:
5108 Py_XDECREF(pycobj);
5109 return result;
5111 """)
5113 #------------------------------------------------------------------------------------
5115 get_vtable_utility_code = UtilityCode(
5116 proto = """
5117 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5118 """,
5119 impl = r"""
5120 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5121 int result;
5122 PyObject *pycobj;
5124 pycobj = PyMapping_GetItemString(dict, "__pyx_vtable__");
5125 if (!pycobj)
5126 goto bad;
5127 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5128 if (!*(void **)vtabptr)
5129 goto bad;
5130 result = 0;
5131 goto done;
5133 bad:
5134 result = -1;
5135 done:
5136 Py_XDECREF(pycobj);
5137 return result;
5139 """)
5141 #------------------------------------------------------------------------------------
5143 init_string_tab_utility_code = UtilityCode(
5144 proto = """
5145 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5146 """,
5147 impl = """
5148 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5149 while (t->p) {
5150 #if PY_MAJOR_VERSION < 3
5151 if (t->is_unicode && (!t->is_identifier)) {
5152 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5153 } else if (t->intern) {
5154 *t->p = PyString_InternFromString(t->s);
5155 } else {
5156 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5158 #else /* Python 3+ has unicode identifiers */
5159 if (t->is_identifier || (t->is_unicode && t->intern)) {
5160 *t->p = PyUnicode_InternFromString(t->s);
5161 } else if (t->is_unicode) {
5162 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5163 } else {
5164 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5166 #endif
5167 if (!*t->p)
5168 return -1;
5169 ++t;
5171 return 0;
5173 """)
5175 #------------------------------------------------------------------------------------
5177 get_exception_utility_code = UtilityCode(
5178 proto = """
5179 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5180 """,
5181 impl = """
5182 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5183 PyObject *tmp_type, *tmp_value, *tmp_tb;
5184 PyThreadState *tstate = PyThreadState_GET();
5185 __Pyx_ErrFetch(type, value, tb);
5186 PyErr_NormalizeException(type, value, tb);
5187 if (PyErr_Occurred())
5188 goto bad;
5189 Py_INCREF(*type);
5190 Py_INCREF(*value);
5191 Py_INCREF(*tb);
5192 tmp_type = tstate->exc_type;
5193 tmp_value = tstate->exc_value;
5194 tmp_tb = tstate->exc_traceback;
5195 tstate->exc_type = *type;
5196 tstate->exc_value = *value;
5197 tstate->exc_traceback = *tb;
5198 /* Make sure tstate is in a consistent state when we XDECREF
5199 these objects (XDECREF may run arbitrary code). */
5200 Py_XDECREF(tmp_type);
5201 Py_XDECREF(tmp_value);
5202 Py_XDECREF(tmp_tb);
5203 return 0;
5204 bad:
5205 Py_XDECREF(*type);
5206 Py_XDECREF(*value);
5207 Py_XDECREF(*tb);
5208 return -1;
5211 """)
5213 #------------------------------------------------------------------------------------
5215 reset_exception_utility_code = UtilityCode(
5216 proto = """
5217 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5218 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5219 """,
5220 impl = """
5221 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5222 PyThreadState *tstate = PyThreadState_GET();
5223 *type = tstate->exc_type;
5224 *value = tstate->exc_value;
5225 *tb = tstate->exc_traceback;
5226 Py_XINCREF(*type);
5227 Py_XINCREF(*value);
5228 Py_XINCREF(*tb);
5231 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5232 PyObject *tmp_type, *tmp_value, *tmp_tb;
5233 PyThreadState *tstate = PyThreadState_GET();
5234 tmp_type = tstate->exc_type;
5235 tmp_value = tstate->exc_value;
5236 tmp_tb = tstate->exc_traceback;
5237 tstate->exc_type = type;
5238 tstate->exc_value = value;
5239 tstate->exc_traceback = tb;
5240 Py_XDECREF(tmp_type);
5241 Py_XDECREF(tmp_value);
5242 Py_XDECREF(tmp_tb);
5244 """)
5246 #------------------------------------------------------------------------------------