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