Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 902:19282c553659

public attribute fix
author Robert Bradshaw <robertwb@math.washington.edu>
date Sat Aug 02 17:16:52 2008 -0700 (3 years ago)
parents 193fe7e34b57
children 8b22ff3db9f7
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, EncodedString
16 import Options
17 import ControlFlow
19 from DebugFlags import debug_disposal_code
21 absolute_path_length = 0
23 def relative_position(pos):
24 """
25 We embed the relative filename in the generated C file, since we
26 don't want to have to regnerate and compile all the source code
27 whenever the Python install directory moves (which could happen,
28 e.g,. when distributing binaries.)
30 INPUT:
31 a position tuple -- (absolute filename, line number column position)
33 OUTPUT:
34 relative filename
35 line number
37 AUTHOR: William Stein
38 """
39 global absolute_path_length
40 if absolute_path_length==0:
41 absolute_path_length = len(os.path.abspath(os.getcwd()))
42 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
44 def embed_position(pos, docstring):
45 if not Options.embed_pos_in_docstring:
46 return docstring
47 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
48 if docstring is None:
49 # unicode string
50 return EncodedString(pos_line)
52 # make sure we can encode the filename in the docstring encoding
53 # otherwise make the docstring a unicode string
54 encoding = docstring.encoding
55 if encoding is not None:
56 try:
57 encoded_bytes = pos_line.encode(encoding)
58 except UnicodeEncodeError:
59 encoding = None
61 if not docstring:
62 # reuse the string encoding of the original docstring
63 doc = EncodedString(pos_line)
64 else:
65 doc = EncodedString(pos_line + u'\\n' + docstring)
66 doc.encoding = encoding
67 return doc
69 class Node(object):
70 # pos (string, int, int) Source file position
71 # is_name boolean Is a NameNode
72 # is_literal boolean Is a ConstNode
74 is_name = 0
75 is_literal = 0
76 temps = None
78 # All descandants should set child_attrs to a list of the attributes
79 # containing nodes considered "children" in the tree. Each such attribute
80 # can either contain a single node or a list of nodes. See Visitor.py.
81 child_attrs = None
83 def __init__(self, pos, **kw):
84 self.pos = pos
85 self.__dict__.update(kw)
87 gil_message = "Operation"
89 def gil_check(self, env):
90 if env.nogil:
91 self.gil_error()
93 def gil_error(self):
94 error(self.pos, "%s not allowed without gil" % self.gil_message)
96 def clone_node(self):
97 """Clone the node. This is defined as a shallow copy, except for member lists
98 amongst the child attributes (from get_child_accessors) which are also
99 copied. Lists containing child nodes are thus seen as a way for the node
100 to hold multiple children directly; the list is not treated as a seperate
101 level in the tree."""
102 result = copy.copy(self)
103 for attrname in result.child_attrs:
104 value = getattr(result, attrname)
105 if isinstance(value, list):
106 setattr(result, attrname, [x for x in value])
107 return result
110 #
111 # There are 4 phases of parse tree processing, applied in order to
112 # all the statements in a given scope-block:
113 #
114 # (0) analyse_control_flow
115 # Create the control flow tree into which state can be asserted and
116 # queried.
117 #
118 # (1) analyse_declarations
119 # Make symbol table entries for all declarations at the current
120 # level, both explicit (def, cdef, etc.) and implicit (assignment
121 # to an otherwise undeclared name).
122 #
123 # (2) analyse_expressions
124 # Determine the result types of expressions and fill in the
125 # 'type' attribute of each ExprNode. Insert coercion nodes into the
126 # tree where needed to convert to and from Python objects.
127 # Allocate temporary locals for intermediate results. Fill
128 # in the 'result_code' attribute of each ExprNode with a C code
129 # fragment.
130 #
131 # (3) generate_code
132 # Emit C code for all declarations, statements and expressions.
133 # Recursively applies the 3 processing phases to the bodies of
134 # functions.
135 #
137 def analyse_control_flow(self, env):
138 pass
140 def analyse_declarations(self, env):
141 pass
143 def analyse_expressions(self, env):
144 raise InternalError("analyse_expressions not implemented for %s" % \
145 self.__class__.__name__)
147 def generate_code(self, code):
148 raise InternalError("generate_code not implemented for %s" % \
149 self.__class__.__name__)
151 def annotate(self, code):
152 # mro does the wrong thing
153 if isinstance(self, BlockNode):
154 self.body.annotate(code)
156 def end_pos(self):
157 if not self.child_attrs:
158 return self.pos
159 try:
160 return self._end_pos
161 except AttributeError:
162 pos = self.pos
163 for attr in self.child_attrs:
164 child = getattr(self, attr)
165 # Sometimes lists, sometimes nodes
166 if child is None:
167 pass
168 elif isinstance(child, list):
169 for c in child:
170 pos = max(pos, c.end_pos())
171 else:
172 pos = max(pos, child.end_pos())
173 self._end_pos = pos
174 return pos
176 def dump(self, level=0, filter_out=("pos",)):
177 def dump_child(x, level):
178 if isinstance(x, Node):
179 return x.dump(level)
180 elif isinstance(x, list):
181 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
182 else:
183 return repr(x)
186 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
187 if len(attrs) == 0:
188 return "<%s (%d)>" % (self.__class__.__name__, id(self))
189 else:
190 indent = " " * level
191 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
192 for key, value in attrs:
193 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
194 res += "%s>" % indent
195 return res
197 class BlockNode:
198 # Mixin class for nodes representing a declaration block.
200 def generate_const_definitions(self, env, code):
201 if env.const_entries:
202 code.putln("")
203 for entry in env.const_entries:
204 if not entry.is_interned:
205 code.put_var_declaration(entry, static = 1)
207 def generate_interned_string_decls(self, env, code):
208 entries = env.global_scope().new_interned_string_entries
209 if entries:
210 code.putln("")
211 for entry in entries:
212 code.put_var_declaration(entry, static = 1)
213 code.putln("")
214 for entry in entries:
215 code.putln(
216 "static PyObject *%s;" % entry.pystring_cname)
217 del entries[:]
219 def generate_py_string_decls(self, env, code):
220 if env is None:
221 return # earlier error
222 entries = env.pystring_entries
223 if entries:
224 code.putln("")
225 for entry in entries:
226 if not entry.is_interned:
227 code.putln(
228 "static PyObject *%s;" % entry.pystring_cname)
230 def generate_interned_num_decls(self, env, code):
231 # Flush accumulated interned nums from the global scope
232 # and generate declarations for them.
233 genv = env.global_scope()
234 entries = genv.interned_nums
235 if entries:
236 code.putln("")
237 for entry in entries:
238 code.putln(
239 "static PyObject *%s;" % entry.cname)
240 del entries[:]
242 def generate_cached_builtins_decls(self, env, code):
243 entries = env.global_scope().undeclared_cached_builtins
244 if len(entries) > 0:
245 code.putln("")
246 for entry in entries:
247 code.putln("static PyObject *%s;" % entry.cname)
248 del entries[:]
251 class StatListNode(Node):
252 # stats a list of StatNode
254 child_attrs = ["stats"]
256 def create_analysed(pos, env, *args, **kw):
257 node = StatListNode(pos, *args, **kw)
258 return node # No node-specific analysis necesarry
259 create_analysed = staticmethod(create_analysed)
261 def analyse_control_flow(self, env):
262 for stat in self.stats:
263 stat.analyse_control_flow(env)
265 def analyse_declarations(self, env):
266 #print "StatListNode.analyse_declarations" ###
267 for stat in self.stats:
268 stat.analyse_declarations(env)
270 def analyse_expressions(self, env):
271 #print "StatListNode.analyse_expressions" ###
272 for stat in self.stats:
273 stat.analyse_expressions(env)
275 def generate_function_definitions(self, env, code, transforms):
276 #print "StatListNode.generate_function_definitions" ###
277 for stat in self.stats:
278 stat.generate_function_definitions(env, code, transforms)
280 def generate_execution_code(self, code):
281 #print "StatListNode.generate_execution_code" ###
282 for stat in self.stats:
283 code.mark_pos(stat.pos)
284 stat.generate_execution_code(code)
286 def annotate(self, code):
287 for stat in self.stats:
288 stat.annotate(code)
291 class StatNode(Node):
292 #
293 # Code generation for statements is split into the following subphases:
294 #
295 # (1) generate_function_definitions
296 # Emit C code for the definitions of any structs,
297 # unions, enums and functions defined in the current
298 # scope-block.
299 #
300 # (2) generate_execution_code
301 # Emit C code for executable statements.
302 #
304 def generate_function_definitions(self, env, code, transforms):
305 pass
307 def generate_execution_code(self, code):
308 raise InternalError("generate_execution_code not implemented for %s" % \
309 self.__class__.__name__)
312 class CDefExternNode(StatNode):
313 # include_file string or None
314 # body StatNode
316 child_attrs = ["body"]
318 def analyse_declarations(self, env):
319 if self.include_file:
320 env.add_include_file(self.include_file)
321 old_cinclude_flag = env.in_cinclude
322 env.in_cinclude = 1
323 self.body.analyse_declarations(env)
324 env.in_cinclude = old_cinclude_flag
326 def analyse_expressions(self, env):
327 pass
329 def generate_execution_code(self, code):
330 pass
332 def annotate(self, code):
333 self.body.annotate(code)
336 class CDeclaratorNode(Node):
337 # Part of a C declaration.
338 #
339 # Processing during analyse_declarations phase:
340 #
341 # analyse
342 # Returns (name, type) pair where name is the
343 # CNameDeclaratorNode of the name being declared
344 # and type is the type it is being declared as.
345 #
346 # calling_convention string Calling convention of CFuncDeclaratorNode
347 # for which this is a base
349 child_attrs = []
351 calling_convention = ""
354 class CNameDeclaratorNode(CDeclaratorNode):
355 # name string The Pyrex name being declared
356 # cname string or None C name, if specified
357 # default ExprNode or None the value assigned on declaration
359 child_attrs = ['default']
361 default = None
363 def analyse(self, base_type, env, nonempty = 0):
364 if nonempty and self.name == '':
365 # Must have mistaken the name for the type.
366 self.name = base_type.name
367 base_type = py_object_type
368 self.type = base_type
369 return self, base_type
371 class CPtrDeclaratorNode(CDeclaratorNode):
372 # base CDeclaratorNode
374 child_attrs = ["base"]
376 def analyse(self, base_type, env, nonempty = 0):
377 if base_type.is_pyobject:
378 error(self.pos,
379 "Pointer base type cannot be a Python object")
380 ptr_type = PyrexTypes.c_ptr_type(base_type)
381 return self.base.analyse(ptr_type, env, nonempty = nonempty)
383 class CArrayDeclaratorNode(CDeclaratorNode):
384 # base CDeclaratorNode
385 # dimension ExprNode
387 child_attrs = ["base", "dimension"]
389 def analyse(self, base_type, env, nonempty = 0):
390 if self.dimension:
391 self.dimension.analyse_const_expression(env)
392 if not self.dimension.type.is_int:
393 error(self.dimension.pos, "Array dimension not integer")
394 size = self.dimension.result_code
395 else:
396 size = None
397 if not base_type.is_complete():
398 error(self.pos,
399 "Array element type '%s' is incomplete" % base_type)
400 if base_type.is_pyobject:
401 error(self.pos,
402 "Array element cannot be a Python object")
403 if base_type.is_cfunction:
404 error(self.pos,
405 "Array element cannot be a function")
406 array_type = PyrexTypes.c_array_type(base_type, size)
407 return self.base.analyse(array_type, env, nonempty = nonempty)
410 class CFuncDeclaratorNode(CDeclaratorNode):
411 # base CDeclaratorNode
412 # args [CArgDeclNode]
413 # has_varargs boolean
414 # exception_value ConstNode
415 # exception_check boolean True if PyErr_Occurred check needed
416 # nogil boolean Can be called without gil
417 # with_gil boolean Acquire gil around function body
419 child_attrs = ["base", "args", "exception_value"]
421 overridable = 0
422 optional_arg_count = 0
424 def analyse(self, return_type, env, nonempty = 0):
425 func_type_args = []
426 for arg_node in self.args:
427 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
428 name = name_declarator.name
429 if name_declarator.cname:
430 error(self.pos,
431 "Function argument cannot have C name specification")
432 # Turn *[] argument into **
433 if type.is_array:
434 type = PyrexTypes.c_ptr_type(type.base_type)
435 # Catch attempted C-style func(void) decl
436 if type.is_void:
437 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
438 # if type.is_pyobject and self.nogil:
439 # error(self.pos,
440 # "Function with Python argument cannot be declared nogil")
441 func_type_args.append(
442 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
443 if arg_node.default:
444 self.optional_arg_count += 1
445 elif self.optional_arg_count:
446 error(self.pos, "Non-default argument follows default argument")
448 if self.optional_arg_count:
449 scope = StructOrUnionScope()
450 scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
451 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
452 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
453 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
454 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
455 kind = 'struct',
456 scope = scope,
457 typedef_flag = 0,
458 pos = self.pos,
459 cname = struct_cname)
460 self.op_args_struct.defined_in_pxd = 1
461 self.op_args_struct.used = 1
463 exc_val = None
464 exc_check = 0
465 if return_type.is_pyobject \
466 and (self.exception_value or self.exception_check) \
467 and self.exception_check != '+':
468 error(self.pos,
469 "Exception clause not allowed for function returning Python object")
470 else:
471 if self.exception_value:
472 self.exception_value.analyse_const_expression(env)
473 if self.exception_check == '+':
474 exc_val_type = self.exception_value.type
475 if not exc_val_type.is_error and \
476 not exc_val_type.is_pyobject and \
477 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
478 error(self.exception_value.pos,
479 "Exception value must be a Python exception or cdef function with no arguments.")
480 exc_val = self.exception_value
481 else:
482 exc_val = self.exception_value.result_code
483 if not return_type.assignable_from(self.exception_value.type):
484 error(self.exception_value.pos,
485 "Exception value incompatible with function return type")
486 exc_check = self.exception_check
487 if return_type.is_array:
488 error(self.pos,
489 "Function cannot return an array")
490 if return_type.is_cfunction:
491 error(self.pos,
492 "Function cannot return a function")
493 func_type = PyrexTypes.CFuncType(
494 return_type, func_type_args, self.has_varargs,
495 optional_arg_count = self.optional_arg_count,
496 exception_value = exc_val, exception_check = exc_check,
497 calling_convention = self.base.calling_convention,
498 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
499 if self.optional_arg_count:
500 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
501 return self.base.analyse(func_type, env)
504 class CArgDeclNode(Node):
505 # Item in a function declaration argument list.
506 #
507 # base_type CBaseTypeNode
508 # declarator CDeclaratorNode
509 # not_none boolean Tagged with 'not None'
510 # default ExprNode or None
511 # default_entry Symtab.Entry Entry for the variable holding the default value
512 # default_result_code string cname or code fragment for default value
513 # is_self_arg boolean Is the "self" arg of an extension type method
514 # is_kw_only boolean Is a keyword-only argument
516 child_attrs = ["base_type", "declarator", "default"]
518 is_self_arg = 0
519 is_generic = 1
521 def analyse(self, env, nonempty = 0):
522 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
523 base_type = self.base_type.analyse(env)
524 return self.declarator.analyse(base_type, env, nonempty = nonempty)
526 def annotate(self, code):
527 if self.default:
528 self.default.annotate(code)
531 class CBaseTypeNode(Node):
532 # Abstract base class for C base type nodes.
533 #
534 # Processing during analyse_declarations phase:
535 #
536 # analyse
537 # Returns the type.
539 pass
541 class CSimpleBaseTypeNode(CBaseTypeNode):
542 # name string
543 # module_path [string] Qualifying name components
544 # is_basic_c_type boolean
545 # signed boolean
546 # longness integer
547 # is_self_arg boolean Is self argument of C method
549 child_attrs = []
551 def analyse(self, env):
552 # Return type descriptor.
553 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
554 type = None
555 if self.is_basic_c_type:
556 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
557 if not type:
558 error(self.pos, "Unrecognised type modifier combination")
559 elif self.name == "object" and not self.module_path:
560 type = py_object_type
561 elif self.name is None:
562 if self.is_self_arg and env.is_c_class_scope:
563 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
564 type = env.parent_type
565 else:
566 type = py_object_type
567 else:
568 scope = env.find_imported_module(self.module_path, self.pos)
569 if scope:
570 if scope.is_c_class_scope:
571 scope = scope.global_scope()
572 entry = scope.find(self.name, self.pos)
573 if entry and entry.is_type:
574 type = entry.type
575 else:
576 error(self.pos, "'%s' is not a type identifier" % self.name)
577 if type:
578 return type
579 else:
580 return PyrexTypes.error_type
582 class CBufferAccessTypeNode(Node):
583 # After parsing:
584 # positional_args [ExprNode] List of positional arguments
585 # keyword_args DictNode Keyword arguments
586 # base_type_node CBaseTypeNode
588 # After PostParse:
589 # dtype_node CBaseTypeNode
590 # ndim int
592 # After analysis:
593 # type PyrexType.PyrexType
595 child_attrs = ["base_type_node", "positional_args", "keyword_args",
596 "dtype_node"]
598 dtype_node = None
600 def analyse(self, env):
601 base_type = self.base_type_node.analyse(env)
602 dtype = self.dtype_node.analyse(env)
603 self.type = PyrexTypes.BufferType(base_type, dtype=dtype, ndim=self.ndim,
604 mode=self.mode)
605 return self.type
607 class CComplexBaseTypeNode(CBaseTypeNode):
608 # base_type CBaseTypeNode
609 # declarator CDeclaratorNode
611 child_attrs = ["base_type", "declarator"]
613 def analyse(self, env):
614 base = self.base_type.analyse(env)
615 _, type = self.declarator.analyse(base, env)
616 return type
619 class CVarDefNode(StatNode):
620 # C variable definition or forward/extern function declaration.
621 #
622 # visibility 'private' or 'public' or 'extern'
623 # base_type CBaseTypeNode
624 # declarators [CDeclaratorNode]
625 # in_pxd boolean
626 # api boolean
627 # need_properties [entry]
629 child_attrs = ["base_type", "declarators"]
630 need_properties = ()
632 def analyse_declarations(self, env, dest_scope = None):
633 if not dest_scope:
634 dest_scope = env
635 self.dest_scope = dest_scope
636 base_type = self.base_type.analyse(env)
638 if (dest_scope.is_c_class_scope
639 and self.visibility == 'public'
640 and base_type.is_pyobject
641 and (base_type.is_builtin_type or base_type.is_extension_type)):
642 self.need_properties = []
643 need_property = True
644 visibility = 'private'
645 else:
646 need_property = False
647 visibility = self.visibility
649 for declarator in self.declarators:
650 name_declarator, type = declarator.analyse(base_type, env)
651 if not type.is_complete():
652 if not (self.visibility == 'extern' and type.is_array):
653 error(declarator.pos,
654 "Variable type '%s' is incomplete" % type)
655 if self.visibility == 'extern' and type.is_pyobject:
656 error(declarator.pos,
657 "Python object cannot be declared extern")
658 name = name_declarator.name
659 cname = name_declarator.cname
660 if name == '':
661 error(declarator.pos, "Missing name in declaration.")
662 return
663 if type.is_cfunction:
664 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
665 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
666 api = self.api)
667 else:
668 if self.in_pxd and self.visibility != 'extern':
669 error(self.pos,
670 "Only 'extern' C variable declaration allowed in .pxd file")
671 entry = dest_scope.declare_var(name, type, declarator.pos,
672 cname = cname, visibility = visibility, is_cdef = 1)
673 if need_property:
674 self.need_properties.append(entry)
677 class CStructOrUnionDefNode(StatNode):
678 # name string
679 # cname string or None
680 # kind "struct" or "union"
681 # typedef_flag boolean
682 # visibility "public" or "private"
683 # in_pxd boolean
684 # attributes [CVarDefNode] or None
685 # entry Entry
687 child_attrs = ["attributes"]
689 def analyse_declarations(self, env):
690 scope = None
691 if self.attributes is not None:
692 scope = StructOrUnionScope(self.name)
693 self.entry = env.declare_struct_or_union(
694 self.name, self.kind, scope, self.typedef_flag, self.pos,
695 self.cname, visibility = self.visibility)
696 if self.attributes is not None:
697 if self.in_pxd and not env.in_cinclude:
698 self.entry.defined_in_pxd = 1
699 for attr in self.attributes:
700 attr.analyse_declarations(env, scope)
702 def analyse_expressions(self, env):
703 pass
705 def generate_execution_code(self, code):
706 pass
709 class CEnumDefNode(StatNode):
710 # name string or None
711 # cname string or None
712 # items [CEnumDefItemNode]
713 # typedef_flag boolean
714 # visibility "public" or "private"
715 # in_pxd boolean
716 # entry Entry
718 child_attrs = ["items"]
720 def analyse_declarations(self, env):
721 self.entry = env.declare_enum(self.name, self.pos,
722 cname = self.cname, typedef_flag = self.typedef_flag,
723 visibility = self.visibility)
724 if self.items is not None:
725 if self.in_pxd and not env.in_cinclude:
726 self.entry.defined_in_pxd = 1
727 for item in self.items:
728 item.analyse_declarations(env, self.entry)
730 def analyse_expressions(self, env):
731 if self.visibility == 'public':
732 self.temp = env.allocate_temp_pyobject()
733 env.release_temp(self.temp)
735 def generate_execution_code(self, code):
736 if self.visibility == 'public':
737 for item in self.entry.enum_values:
738 code.putln("%s = PyInt_FromLong(%s); %s" % (
739 self.temp,
740 item.cname,
741 code.error_goto_if_null(self.temp, item.pos)))
742 code.putln('if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
743 Naming.module_cname,
744 item.name,
745 self.temp,
746 code.error_goto(item.pos)))
747 code.putln("%s = 0;" % self.temp)
750 class CEnumDefItemNode(StatNode):
751 # name string
752 # cname string or None
753 # value ExprNode or None
755 child_attrs = ["value"]
757 def analyse_declarations(self, env, enum_entry):
758 if self.value:
759 self.value.analyse_const_expression(env)
760 if not self.value.type.is_int:
761 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
762 self.value.analyse_const_expression(env)
763 value = self.value.result_code
764 else:
765 value = self.name
766 entry = env.declare_const(self.name, enum_entry.type,
767 value, self.pos, cname = self.cname)
768 enum_entry.enum_values.append(entry)
771 class CTypeDefNode(StatNode):
772 # base_type CBaseTypeNode
773 # declarator CDeclaratorNode
774 # visibility "public" or "private"
775 # in_pxd boolean
777 child_attrs = ["base_type", "declarator"]
779 def analyse_declarations(self, env):
780 base = self.base_type.analyse(env)
781 name_declarator, type = self.declarator.analyse(base, env)
782 name = name_declarator.name
783 cname = name_declarator.cname
784 entry = env.declare_typedef(name, type, self.pos,
785 cname = cname, visibility = self.visibility)
786 if self.in_pxd and not env.in_cinclude:
787 entry.defined_in_pxd = 1
789 def analyse_expressions(self, env):
790 pass
791 def generate_execution_code(self, code):
792 pass
795 class FuncDefNode(StatNode, BlockNode):
796 # Base class for function definition nodes.
797 #
798 # return_type PyrexType
799 # #filename string C name of filename string const
800 # entry Symtab.Entry
801 # needs_closure boolean Whether or not this function has inner functions/classes/yield
803 py_func = None
804 assmt = None
805 needs_closure = False
807 def analyse_default_values(self, env):
808 genv = env.global_scope()
809 for arg in self.args:
810 if arg.default:
811 if arg.is_generic:
812 if not hasattr(arg, 'default_entry'):
813 arg.default.analyse_types(env)
814 arg.default = arg.default.coerce_to(arg.type, genv)
815 if arg.default.is_literal:
816 arg.default_entry = arg.default
817 arg.default_result_code = arg.default.calculate_result_code()
818 if arg.default.type != arg.type and not arg.type.is_int:
819 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
820 else:
821 arg.default.allocate_temps(genv)
822 arg.default_entry = genv.add_default_value(arg.type)
823 arg.default_entry.used = 1
824 arg.default_result_code = arg.default_entry.cname
825 else:
826 error(arg.pos,
827 "This argument cannot have a default value")
828 arg.default = None
830 def need_gil_acquisition(self, lenv):
831 return 0
833 def create_local_scope(self, env):
834 genv = env
835 while env.is_py_class_scope or env.is_c_class_scope:
836 env = env.outer_scope
837 if self.needs_closure:
838 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
839 else:
840 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
841 lenv.return_type = self.return_type
842 type = self.entry.type
843 if type.is_cfunction:
844 lenv.nogil = type.nogil and not type.with_gil
845 self.local_scope = lenv
846 return lenv
848 def generate_function_definitions(self, env, code, transforms):
849 import Buffer
851 lenv = self.local_scope
853 # Generate C code for header and body of function
854 code.enter_cfunc_scope()
855 code.return_from_error_cleanup_label = code.new_label()
857 # ----- Top-level constants used by this function
858 code.mark_pos(self.pos)
859 self.generate_interned_num_decls(lenv, code)
860 self.generate_interned_string_decls(lenv, code)
861 self.generate_py_string_decls(lenv, code)
862 self.generate_cached_builtins_decls(lenv, code)
863 #code.putln("")
864 #code.put_var_declarations(lenv.const_entries, static = 1)
865 self.generate_const_definitions(lenv, code)
866 # ----- Function header
867 code.putln("")
868 if self.py_func:
869 self.py_func.generate_function_header(code,
870 with_pymethdef = env.is_py_class_scope,
871 proto_only=True)
872 self.generate_function_header(code,
873 with_pymethdef = env.is_py_class_scope)
874 # ----- Local variable declarations
875 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
876 self.generate_argument_declarations(lenv, code)
877 if self.needs_closure:
878 code.putln("/* TODO: declare and create scope object */")
879 code.put_var_declarations(lenv.var_entries)
880 init = ""
881 if not self.return_type.is_void:
882 code.putln(
883 "%s%s;" %
884 (self.return_type.declaration_code(
885 Naming.retval_cname),
886 init))
887 tempvardecl_code = code.insertion_point()
888 self.generate_keyword_list(code)
889 # ----- Extern library function declarations
890 lenv.generate_library_function_declarations(code)
891 # ----- GIL acquisition
892 acquire_gil = self.need_gil_acquisition(lenv)
893 if acquire_gil:
894 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
895 # ----- Fetch arguments
896 self.generate_argument_parsing_code(env, code)
897 # If an argument is assigned to in the body, we must
898 # incref it to properly keep track of refcounts.
899 for entry in lenv.arg_entries:
900 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
901 code.put_var_incref(entry)
902 if entry.type.is_buffer:
903 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
904 # ----- Initialise local variables
905 for entry in lenv.var_entries:
906 if entry.type.is_pyobject and entry.init_to_none and entry.used:
907 code.put_init_var_to_py_none(entry)
908 # ----- Check and convert arguments
909 self.generate_argument_type_tests(code)
910 # ----- Function body
911 self.body.generate_execution_code(code)
912 # ----- Default return value
913 code.putln("")
914 if self.return_type.is_pyobject:
915 #if self.return_type.is_extension_type:
916 # lhs = "(PyObject *)%s" % Naming.retval_cname
917 #else:
918 lhs = Naming.retval_cname
919 code.put_init_to_py_none(lhs, self.return_type)
920 else:
921 val = self.return_type.default_value
922 if val:
923 code.putln("%s = %s;" % (Naming.retval_cname, val))
924 # ----- Error cleanup
925 if code.error_label in code.labels_used:
926 code.put_goto(code.return_label)
927 code.put_label(code.error_label)
928 code.put_var_xdecrefs(lenv.temp_entries)
930 # Clean up buffers -- this calls a Python function
931 # so need to save and restore error state
932 buffers_present = len(lenv.buffer_entries) > 0
933 if buffers_present:
934 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
935 code.putln("PyErr_Fetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
936 for entry in lenv.buffer_entries:
937 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
938 #code.putln("%s = 0;" % entry.cname)
939 code.putln("PyErr_Restore(__pyx_type, __pyx_value, __pyx_tb);}")
941 err_val = self.error_value()
942 exc_check = self.caller_will_check_exceptions()
943 if err_val is not None or exc_check:
944 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
945 else:
946 code.putln(
947 '__Pyx_WriteUnraisable("%s");' %
948 self.entry.qualified_name)
949 env.use_utility_code(unraisable_exception_utility_code)
950 default_retval = self.return_type.default_value
951 if err_val is None and default_retval:
952 err_val = default_retval
953 if err_val is not None:
954 code.putln(
955 "%s = %s;" % (
956 Naming.retval_cname,
957 err_val))
958 if buffers_present:
959 # Else, non-error return will be an empty clause
960 code.put_goto(code.return_from_error_cleanup_label)
962 # ----- Non-error return cleanup
963 # PS! If adding something here, modify the conditions for the
964 # goto statement in error cleanup above
965 code.put_label(code.return_label)
966 for entry in lenv.buffer_entries:
967 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
968 # ----- Return cleanup for both error and no-error return
969 code.put_label(code.return_from_error_cleanup_label)
970 if not Options.init_local_none:
971 for entry in lenv.var_entries:
972 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
973 entry.xdecref_cleanup = 1
974 code.put_var_decrefs(lenv.var_entries, used_only = 1)
975 # Decref any increfed args
976 for entry in lenv.arg_entries:
977 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
978 code.put_var_decref(entry)
979 self.put_stararg_decrefs(code)
980 if acquire_gil:
981 code.putln("PyGILState_Release(_save);")
982 code.putln("/* TODO: decref scope object */")
983 # ----- Return
984 if not self.return_type.is_void:
985 code.putln("return %s;" % Naming.retval_cname)
986 code.putln("}")
987 # ----- Go back and insert temp variable declarations
988 tempvardecl_code.put_var_declarations(lenv.temp_entries)
989 tempvardecl_code.put_temp_declarations(code.func)
990 # ----- Python version
991 code.exit_cfunc_scope()
992 if self.py_func:
993 self.py_func.generate_function_definitions(env, code, transforms)
994 self.generate_optarg_wrapper_function(env, code)
996 def put_stararg_decrefs(self, code):
997 pass
999 def declare_argument(self, env, arg):
1000 if arg.type.is_void:
1001 error(arg.pos, "Invalid use of 'void'")
1002 elif not arg.type.is_complete() and not arg.type.is_array:
1003 error(arg.pos,
1004 "Argument type '%s' is incomplete" % arg.type)
1005 return env.declare_arg(arg.name, arg.type, arg.pos)
1006 def generate_optarg_wrapper_function(self, env, code):
1007 pass
1009 def generate_execution_code(self, code):
1010 # Evaluate and store argument default values
1011 for arg in self.args:
1012 default = arg.default
1013 if default:
1014 if not default.is_literal:
1015 default.generate_evaluation_code(code)
1016 default.make_owned_reference(code)
1017 code.putln(
1018 "%s = %s;" % (
1019 arg.default_entry.cname,
1020 default.result_as(arg.default_entry.type)))
1021 if default.is_temp and default.type.is_pyobject:
1022 code.putln(
1023 "%s = 0;" %
1024 default.result_code)
1025 # For Python class methods, create and store function object
1026 if self.assmt:
1027 self.assmt.generate_execution_code(code)
1031 class CFuncDefNode(FuncDefNode):
1032 # C function definition.
1034 # modifiers ['inline']
1035 # visibility 'private' or 'public' or 'extern'
1036 # base_type CBaseTypeNode
1037 # declarator CDeclaratorNode
1038 # body StatListNode
1039 # api boolean
1041 # with_gil boolean Acquire GIL around body
1042 # type CFuncType
1043 # py_func wrapper for calling from Python
1045 child_attrs = ["base_type", "declarator", "body", "py_func"]
1047 def unqualified_name(self):
1048 return self.entry.name
1050 def analyse_declarations(self, env):
1051 base_type = self.base_type.analyse(env)
1052 name_declarator, type = self.declarator.analyse(base_type, env, self.body is not None)
1053 if not type.is_cfunction:
1054 error(self.pos,
1055 "Suite attached to non-function declaration")
1056 # Remember the actual type according to the function header
1057 # written here, because the type in the symbol table entry
1058 # may be different if we're overriding a C method inherited
1059 # from the base type of an extension type.
1060 self.type = type
1061 type.is_overridable = self.overridable
1062 declarator = self.declarator
1063 while not hasattr(declarator, 'args'):
1064 declarator = declarator.base
1065 self.args = declarator.args
1066 for formal_arg, type_arg in zip(self.args, type.args):
1067 formal_arg.type = type_arg.type
1068 formal_arg.cname = type_arg.cname
1069 name = name_declarator.name
1070 cname = name_declarator.cname
1071 self.entry = env.declare_cfunction(
1072 name, type, self.pos,
1073 cname = cname, visibility = self.visibility,
1074 defining = self.body is not None,
1075 api = self.api)
1076 self.return_type = type.return_type
1078 if self.overridable:
1079 import ExprNodes
1080 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1081 self.py_func = DefNode(pos = self.pos,
1082 name = self.entry.name,
1083 args = self.args,
1084 star_arg = None,
1085 starstar_arg = None,
1086 doc = self.doc,
1087 body = py_func_body,
1088 is_wrapper = 1)
1089 self.py_func.is_module_scope = env.is_module_scope
1090 self.py_func.analyse_declarations(env)
1091 self.entry.as_variable = self.py_func.entry
1092 # Reset scope entry the above cfunction
1093 env.entries[name] = self.entry
1094 self.py_func.interned_attr_cname = env.intern_identifier(
1095 self.py_func.entry.name)
1096 if not env.is_module_scope or Options.lookup_module_cpdef:
1097 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1098 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1100 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1101 import ExprNodes
1102 args = self.type.args
1103 if omit_optional_args:
1104 args = args[:len(args) - self.type.optional_arg_count]
1105 arg_names = [arg.name for arg in args]
1106 if is_module_scope:
1107 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1108 else:
1109 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1110 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1111 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1112 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)
1113 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1115 def declare_arguments(self, env):
1116 for arg in self.type.args:
1117 if not arg.name:
1118 error(arg.pos, "Missing argument name")
1119 self.declare_argument(env, arg)
1121 def need_gil_acquisition(self, lenv):
1122 type = self.type
1123 with_gil = self.type.with_gil
1124 if type.nogil and not with_gil:
1125 if type.return_type.is_pyobject:
1126 error(self.pos,
1127 "Function with Python return type cannot be declared nogil")
1128 for entry in lenv.var_entries + lenv.temp_entries:
1129 if entry.type.is_pyobject:
1130 error(self.pos, "Function declared nogil has Python locals or temporaries")
1131 return with_gil
1133 def analyse_expressions(self, env):
1134 self.analyse_default_values(env)
1135 if self.overridable:
1136 self.py_func.analyse_expressions(env)
1138 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1):
1139 arg_decls = []
1140 type = self.type
1141 visibility = self.entry.visibility
1142 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1143 arg_decls.append(arg.declaration_code())
1144 if type.optional_arg_count and with_opt_args:
1145 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1146 if type.has_varargs:
1147 arg_decls.append("...")
1148 if not arg_decls:
1149 arg_decls = ["void"]
1150 cname = self.entry.func_cname
1151 if not with_opt_args:
1152 cname += Naming.no_opt_args
1153 entity = type.function_header_code(cname, string.join(arg_decls, ", "))
1154 if visibility == 'public':
1155 dll_linkage = "DL_EXPORT"
1156 else:
1157 dll_linkage = None
1158 header = self.return_type.declaration_code(entity,
1159 dll_linkage = dll_linkage)
1160 if visibility != 'private':
1161 storage_class = "%s " % Naming.extern_c_macro
1162 else:
1163 storage_class = "static "
1164 code.putln("%s%s %s {" % (
1165 storage_class,
1166 ' '.join(self.modifiers).upper(), # macro forms
1167 header))
1169 def generate_argument_declarations(self, env, code):
1170 for arg in self.args:
1171 if arg.default:
1172 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1174 def generate_keyword_list(self, code):
1175 pass
1177 def generate_argument_parsing_code(self, env, code):
1178 i = 0
1179 if self.type.optional_arg_count:
1180 code.putln('if (%s) {' % Naming.optional_args_cname)
1181 for arg in self.args:
1182 if arg.default:
1183 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1184 declarator = arg.declarator
1185 while not hasattr(declarator, 'name'):
1186 declarator = declarator.base
1187 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1188 i += 1
1189 for _ in range(self.type.optional_arg_count):
1190 code.putln('}')
1191 code.putln('}')
1193 def generate_argument_conversion_code(self, code):
1194 pass
1196 def generate_argument_type_tests(self, code):
1197 # Generate type tests for args whose type in a parent
1198 # class is a supertype of the declared type.
1199 for arg in self.type.args:
1200 if arg.needs_type_test:
1201 self.generate_arg_type_test(arg, code)
1203 def generate_arg_type_test(self, arg, code):
1204 # Generate type test for one argument.
1205 if arg.type.typeobj_is_available():
1206 typeptr_cname = arg.type.typeptr_cname
1207 arg_code = "((PyObject *)%s)" % arg.cname
1208 code.putln(
1209 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1210 arg_code,
1211 typeptr_cname,
1212 not arg.not_none,
1213 arg.name,
1214 type.is_builtin_type,
1215 code.error_goto(arg.pos)))
1216 else:
1217 error(arg.pos, "Cannot test type of extern C class "
1218 "without type object name specification")
1220 def error_value(self):
1221 if self.return_type.is_pyobject:
1222 return "0"
1223 else:
1224 #return None
1225 return self.entry.type.exception_value
1227 def caller_will_check_exceptions(self):
1228 return self.entry.type.exception_check
1230 def generate_optarg_wrapper_function(self, env, code):
1231 if self.type.optional_arg_count and \
1232 self.type.original_sig and not self.type.original_sig.optional_arg_count:
1233 code.putln()
1234 self.generate_function_header(code, 0, with_opt_args = 0)
1235 if not self.return_type.is_void:
1236 code.put('return ')
1237 args = self.type.args
1238 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1239 arglist.append('NULL')
1240 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1241 code.putln('}')
1244 class PyArgDeclNode(Node):
1245 # Argument which must be a Python object (used
1246 # for * and ** arguments).
1248 # name string
1249 # entry Symtab.Entry
1250 child_attrs = []
1253 class DecoratorNode(Node):
1254 # A decorator
1256 # decorator NameNode or CallNode
1257 child_attrs = ['decorator']
1260 class DefNode(FuncDefNode):
1261 # A Python function definition.
1263 # name string the Python name of the function
1264 # decorators [DecoratorNode] list of decorators
1265 # args [CArgDeclNode] formal arguments
1266 # star_arg PyArgDeclNode or None * argument
1267 # starstar_arg PyArgDeclNode or None ** argument
1268 # doc EncodedString or None
1269 # body StatListNode
1271 # The following subnode is constructed internally
1272 # when the def statement is inside a Python class definition.
1274 # assmt AssignmentNode Function construction/assignment
1276 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1278 assmt = None
1279 num_kwonly_args = 0
1280 num_required_kw_args = 0
1281 reqd_kw_flags_cname = "0"
1282 is_wrapper = 0
1283 decorators = None
1285 def __init__(self, pos, **kwds):
1286 FuncDefNode.__init__(self, pos, **kwds)
1287 k = rk = r = 0
1288 for arg in self.args:
1289 if arg.kw_only:
1290 k += 1
1291 if not arg.default:
1292 rk += 1
1293 if not arg.default:
1294 r += 1
1295 self.num_kwonly_args = k
1296 self.num_required_kw_args = rk
1297 self.num_required_args = r
1299 entry = None
1301 def analyse_declarations(self, env):
1302 for arg in self.args:
1303 base_type = arg.base_type.analyse(env)
1304 name_declarator, type = \
1305 arg.declarator.analyse(base_type, env)
1306 arg.name = name_declarator.name
1307 if name_declarator.cname:
1308 error(self.pos,
1309 "Python function argument cannot have C name specification")
1310 arg.type = type.as_argument_type()
1311 arg.hdr_type = None
1312 arg.needs_conversion = 0
1313 arg.needs_type_test = 0
1314 arg.is_generic = 1
1315 if arg.not_none and not arg.type.is_extension_type:
1316 error(self.pos,
1317 "Only extension type arguments can have 'not None'")
1318 self.declare_pyfunction(env)
1319 self.analyse_signature(env)
1320 self.return_type = self.entry.signature.return_type()
1321 if self.signature_has_generic_args():
1322 if self.star_arg:
1323 env.use_utility_code(get_stararg_utility_code)
1324 elif self.signature_has_generic_args():
1325 env.use_utility_code(raise_argtuple_too_long_utility_code)
1326 if not self.signature_has_nongeneric_args():
1327 env.use_utility_code(get_keyword_string_check_utility_code)
1328 elif self.starstar_arg:
1329 env.use_utility_code(get_splitkeywords_utility_code)
1330 if self.num_required_kw_args:
1331 env.use_utility_code(get_checkkeywords_utility_code)
1333 def analyse_signature(self, env):
1334 any_type_tests_needed = 0
1335 # Use the simpler calling signature for zero- and one-argument functions.
1336 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1337 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1338 if len(self.args) == 0:
1339 self.entry.signature = TypeSlots.pyfunction_noargs
1340 elif len(self.args) == 1:
1341 if self.args[0].default is None and not self.args[0].kw_only:
1342 self.entry.signature = TypeSlots.pyfunction_onearg
1343 elif self.entry.signature is TypeSlots.pymethod_signature:
1344 if len(self.args) == 1:
1345 self.entry.signature = TypeSlots.unaryfunc
1346 elif len(self.args) == 2:
1347 if self.args[1].default is None and not self.args[1].kw_only:
1348 self.entry.signature = TypeSlots.ibinaryfunc
1349 elif self.entry.is_special:
1350 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1351 sig = self.entry.signature
1352 nfixed = sig.num_fixed_args()
1353 for i in range(nfixed):
1354 if i < len(self.args):
1355 arg = self.args[i]
1356 arg.is_generic = 0
1357 if sig.is_self_arg(i):
1358 arg.is_self_arg = 1
1359 arg.hdr_type = arg.type = env.parent_type
1360 arg.needs_conversion = 0
1361 else:
1362 arg.hdr_type = sig.fixed_arg_type(i)
1363 if not arg.type.same_as(arg.hdr_type):
1364 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1365 arg.needs_type_test = 1
1366 any_type_tests_needed = 1
1367 else:
1368 arg.needs_conversion = 1
1369 if arg.needs_conversion:
1370 arg.hdr_cname = Naming.arg_prefix + arg.name
1371 else:
1372 arg.hdr_cname = Naming.var_prefix + arg.name
1373 else:
1374 self.bad_signature()
1375 return
1376 if nfixed < len(self.args):
1377 if not sig.has_generic_args:
1378 self.bad_signature()
1379 for arg in self.args:
1380 if arg.is_generic and \
1381 (arg.type.is_extension_type or arg.type.is_builtin_type):
1382 arg.needs_type_test = 1
1383 any_type_tests_needed = 1
1384 elif arg.type is PyrexTypes.c_py_ssize_t_type:
1385 # Want to use __index__ rather than __int__ method
1386 # that PyArg_ParseTupleAndKeywords calls
1387 arg.needs_conversion = 1
1388 arg.hdr_type = PyrexTypes.py_object_type
1389 arg.hdr_cname = Naming.arg_prefix + arg.name
1390 if any_type_tests_needed:
1391 env.use_utility_code(arg_type_test_utility_code)
1393 def bad_signature(self):
1394 sig = self.entry.signature
1395 expected_str = "%d" % sig.num_fixed_args()
1396 if sig.has_generic_args:
1397 expected_str = expected_str + " or more"
1398 name = self.name
1399 if name.startswith("__") and name.endswith("__"):
1400 desc = "Special method"
1401 else:
1402 desc = "Method"
1403 error(self.pos,
1404 "%s %s has wrong number of arguments "
1405 "(%d declared, %s expected)" % (
1406 desc, self.name, len(self.args), expected_str))
1408 def signature_has_nongeneric_args(self):
1409 argcount = len(self.args)
1410 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1411 return 0
1412 return 1
1414 def signature_has_generic_args(self):
1415 return self.entry.signature.has_generic_args
1417 def declare_pyfunction(self, env):
1418 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1419 name = self.name
1420 entry = env.lookup_here(self.name)
1421 if entry and entry.type.is_cfunction and not self.is_wrapper:
1422 warning(self.pos, "Overriding cdef method with def method.", 5)
1423 entry = env.declare_pyfunction(self.name, self.pos)
1424 self.entry = entry
1425 prefix = env.scope_prefix
1426 entry.func_cname = \
1427 Naming.pyfunc_prefix + prefix + name
1428 entry.pymethdef_cname = \
1429 Naming.pymethdef_prefix + prefix + name
1430 if Options.docstrings:
1431 entry.doc = embed_position(self.pos, self.doc)
1432 entry.doc_cname = \
1433 Naming.funcdoc_prefix + prefix + name
1434 else:
1435 entry.doc = None
1437 def declare_arguments(self, env):
1438 for arg in self.args:
1439 if not arg.name:
1440 error(arg.pos, "Missing argument name")
1441 if arg.needs_conversion:
1442 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1443 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1444 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1445 if arg.type.is_pyobject:
1446 arg.entry.init = "0"
1447 arg.entry.init_to_none = 0
1448 else:
1449 arg.entry = self.declare_argument(env, arg)
1450 arg.entry.used = 1
1451 arg.entry.is_self_arg = arg.is_self_arg
1452 if arg.hdr_type:
1453 if arg.is_self_arg or \
1454 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1455 arg.entry.is_declared_generic = 1
1456 self.declare_python_arg(env, self.star_arg)
1457 self.declare_python_arg(env, self.starstar_arg)
1459 def declare_python_arg(self, env, arg):
1460 if arg:
1461 entry = env.declare_var(arg.name,
1462 PyrexTypes.py_object_type, arg.pos)
1463 entry.used = 1
1464 entry.init = "0"
1465 entry.init_to_none = 0
1466 entry.xdecref_cleanup = 1
1467 arg.entry = entry
1468 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1470 def analyse_expressions(self, env):
1471 self.analyse_default_values(env)
1472 if env.is_py_class_scope:
1473 self.synthesize_assignment_node(env)
1475 def synthesize_assignment_node(self, env):
1476 import ExprNodes
1477 self.assmt = SingleAssignmentNode(self.pos,
1478 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1479 rhs = ExprNodes.UnboundMethodNode(self.pos,
1480 class_cname = env.class_obj_cname,
1481 function = ExprNodes.PyCFunctionNode(self.pos,
1482 pymethdef_cname = self.entry.pymethdef_cname)))
1483 self.assmt.analyse_declarations(env)
1484 self.assmt.analyse_expressions(env)
1486 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1487 arg_code_list = []
1488 sig = self.entry.signature
1489 if sig.has_dummy_arg:
1490 arg_code_list.append(
1491 "PyObject *%s" % Naming.self_cname)
1492 for arg in self.args:
1493 if not arg.is_generic:
1494 if arg.is_self_arg:
1495 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1496 else:
1497 arg_code_list.append(
1498 arg.hdr_type.declaration_code(arg.hdr_cname))
1499 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1500 arg_code_list.append("PyObject *unused")
1501 if sig.has_generic_args:
1502 arg_code_list.append(
1503 "PyObject *%s, PyObject *%s"
1504 % (Naming.args_cname, Naming.kwds_cname))
1505 arg_code = ", ".join(arg_code_list)
1506 dc = self.return_type.declaration_code(self.entry.func_cname)
1507 header = "static %s(%s)" % (dc, arg_code)
1508 code.putln("%s; /*proto*/" % header)
1509 if proto_only:
1510 return
1511 if self.entry.doc and Options.docstrings:
1512 code.putln(
1513 'static char %s[] = "%s";' % (
1514 self.entry.doc_cname,
1515 self.entry.doc))
1516 if with_pymethdef:
1517 code.put(
1518 "static PyMethodDef %s = " %
1519 self.entry.pymethdef_cname)
1520 code.put_pymethoddef(self.entry, ";")
1521 code.putln("%s {" % header)
1523 def generate_argument_declarations(self, env, code):
1524 for arg in self.args:
1525 if arg.is_generic: # or arg.needs_conversion:
1526 if arg.needs_conversion:
1527 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1528 else:
1529 code.put_var_declaration(arg.entry)
1531 def generate_keyword_list(self, code):
1532 if self.signature_has_generic_args() and \
1533 self.signature_has_nongeneric_args():
1534 reqd_kw_flags = []
1535 has_reqd_kwds = False
1536 code.put(
1537 "static char *%s[] = {" %
1538 Naming.kwdlist_cname)
1539 for arg in self.args:
1540 if arg.is_generic:
1541 code.put(
1542 '"%s",' %
1543 arg.name)
1544 if arg.kw_only and not arg.default:
1545 has_reqd_kwds = 1
1546 flag = "1"
1547 else:
1548 flag = "0"
1549 reqd_kw_flags.append(flag)
1550 code.putln(
1551 "0};")
1552 if has_reqd_kwds:
1553 flags_name = Naming.reqd_kwds_cname
1554 self.reqd_kw_flags_cname = flags_name
1555 code.putln(
1556 "static char %s[] = {%s};" % (
1557 flags_name,
1558 ",".join(reqd_kw_flags)))
1560 def generate_argument_parsing_code(self, env, code):
1561 # Generate PyArg_ParseTuple call for generic
1562 # arguments, if any.
1563 if self.entry.signature.has_dummy_arg:
1564 # get rid of unused argument warning
1565 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1567 old_error_label = code.new_error_label()
1568 our_error_label = code.error_label
1569 end_label = code.new_label()
1571 has_kwonly_args = self.num_kwonly_args > 0
1572 has_star_or_kw_args = self.star_arg is not None \
1573 or self.starstar_arg is not None or has_kwonly_args
1575 if not self.signature_has_generic_args():
1576 if has_star_or_kw_args:
1577 error(self.pos, "This method cannot have * or keyword arguments")
1578 self.generate_argument_conversion_code(code)
1580 elif not self.signature_has_nongeneric_args():
1581 # func(*args) or func(**kw) or func(*args, **kw)
1582 self.generate_stararg_copy_code(code)
1584 else:
1585 arg_addrs = []
1586 arg_formats = []
1587 positional_args = []
1588 default_seen = 0
1589 for arg in self.args:
1590 arg_entry = arg.entry
1591 if arg.is_generic:
1592 if arg.default:
1593 code.putln(
1594 "%s = %s;" % (
1595 arg_entry.cname,
1596 arg.default_result_code))
1597 if not default_seen:
1598 arg_formats.append("|")
1599 default_seen = 1
1600 if not arg.is_self_arg and not arg.kw_only:
1601 positional_args.append(arg)
1602 elif arg.kw_only:
1603 if not default_seen:
1604 arg_formats.append("|")
1605 default_seen = 1
1606 elif default_seen:
1607 error(arg.pos, "Non-default argument following default argument")
1608 elif not arg.is_self_arg:
1609 positional_args.append(arg)
1610 if arg.needs_conversion:
1611 arg_addrs.append("&" + arg.hdr_cname)
1612 format = arg.hdr_type.parsetuple_format
1613 else:
1614 arg_addrs.append("&" + arg_entry.cname)
1615 format = arg_entry.type.parsetuple_format
1616 if format:
1617 arg_formats.append(format)
1618 else:
1619 error(arg.pos,
1620 "Cannot convert Python object argument to type '%s' (when parsing input arguments)"
1621 % arg.type)
1623 if has_star_or_kw_args:
1624 self.generate_stararg_getting_code(code)
1626 self.generate_argument_tuple_parsing_code(
1627 positional_args, arg_formats, arg_addrs, code)
1629 code.error_label = old_error_label
1630 if code.label_used(our_error_label):
1631 code.put_goto(end_label)
1632 code.put_label(our_error_label)
1633 if has_star_or_kw_args:
1634 self.put_stararg_decrefs(code)
1635 self.generate_arg_decref(self.star_arg, code)
1636 if self.starstar_arg:
1637 if self.starstar_arg.entry.xdecref_cleanup:
1638 code.put_var_xdecref(self.starstar_arg.entry)
1639 else:
1640 code.put_var_decref(self.starstar_arg.entry)
1641 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1642 code.putln("return %s;" % self.error_value())
1643 code.put_label(end_label)
1645 def generate_argument_tuple_parsing_code(self, positional_args,
1646 arg_formats, arg_addrs, code):
1647 # Unpack inplace if it's simple
1648 if not self.num_required_kw_args:
1649 min_positional_args = self.num_required_args - self.num_required_kw_args
1650 max_positional_args = len(positional_args)
1651 if len(self.args) > 0 and self.args[0].is_self_arg:
1652 min_positional_args -= 1
1653 if max_positional_args == min_positional_args:
1654 count_cond = "likely(PyTuple_GET_SIZE(%s) == %s)" % (
1655 Naming.args_cname, max_positional_args)
1656 else:
1657 count_cond = "likely(%s <= PyTuple_GET_SIZE(%s)) && likely(PyTuple_GET_SIZE(%s) <= %s)" % (
1658 min_positional_args,
1659 Naming.args_cname,
1660 Naming.args_cname,
1661 max_positional_args)
1662 code.putln(
1663 'if (likely(!%s) && %s) {' % (Naming.kwds_cname, count_cond))
1664 i = 0
1665 closing = 0
1666 for arg in positional_args:
1667 if arg.default:
1668 code.putln('if (PyTuple_GET_SIZE(%s) > %s) {' % (Naming.args_cname, i))
1669 closing += 1
1670 item = "PyTuple_GET_ITEM(%s, %s)" % (Naming.args_cname, i)
1671 if arg.type.is_pyobject:
1672 if arg.is_generic:
1673 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1674 code.putln("%s = %s;" % (arg.entry.cname, item))
1675 else:
1676 func = arg.type.from_py_function
1677 if func:
1678 code.putln("%s = %s(%s); %s" % (
1679 arg.entry.cname,
1680 func,
1681 item,
1682 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1683 else:
1684 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1685 i += 1
1686 for _ in range(closing):
1687 code.putln('}')
1688 code.putln(
1689 '}')
1690 code.putln('else {')
1692 argformat = '"%s"' % string.join(arg_formats, "")
1693 pt_arglist = [Naming.args_cname, Naming.kwds_cname, argformat, Naming.kwdlist_cname] + arg_addrs
1694 pt_argstring = string.join(pt_arglist, ", ")
1695 code.putln(
1696 'if (unlikely(!PyArg_ParseTupleAndKeywords(%s))) %s' % (
1697 pt_argstring,
1698 code.error_goto(self.pos)))
1699 self.generate_argument_conversion_code(code)
1701 if not self.num_required_kw_args:
1702 code.putln('}')
1704 def put_stararg_decrefs(self, code):
1705 if self.star_arg:
1706 code.put_decref(Naming.args_cname, py_object_type)
1707 if self.starstar_arg:
1708 code.put_xdecref(Naming.kwds_cname, py_object_type)
1710 def generate_arg_xdecref(self, arg, code):
1711 if arg:
1712 code.put_var_xdecref(arg.entry)
1714 def generate_arg_decref(self, arg, code):
1715 if arg:
1716 code.put_var_decref(arg.entry)
1718 def arg_address(self, arg):
1719 if arg:
1720 return "&%s" % arg.entry.cname
1721 else:
1722 return 0
1724 def generate_stararg_copy_code(self, code):
1725 if not self.star_arg:
1726 self.generate_positional_args_check(code, 0)
1727 self.generate_keyword_args_check(code)
1729 if self.starstar_arg:
1730 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
1731 self.starstar_arg.entry.cname,
1732 Naming.kwds_cname,
1733 Naming.kwds_cname))
1734 code.putln("if (unlikely(!%s)) return %s;" % (
1735 self.starstar_arg.entry.cname, self.error_value()))
1736 self.starstar_arg.entry.xdecref_cleanup = 0
1737 self.starstar_arg = None
1739 if self.star_arg:
1740 code.put_incref(Naming.args_cname, py_object_type)
1741 code.putln("%s = %s;" % (
1742 self.star_arg.entry.cname,
1743 Naming.args_cname))
1744 self.star_arg.entry.xdecref_cleanup = 0
1745 self.star_arg = None
1747 def generate_stararg_getting_code(self, code):
1748 num_kwonly = self.num_kwonly_args
1749 fixed_args = self.entry.signature.num_fixed_args()
1750 nargs = len(self.args) - num_kwonly - fixed_args
1751 error_return = "return %s;" % self.error_value()
1753 if self.star_arg:
1754 star_arg_cname = self.star_arg.entry.cname
1755 code.putln("if (likely(PyTuple_GET_SIZE(%s) <= %d)) {" % (
1756 Naming.args_cname, nargs))
1757 code.put_incref(Naming.args_cname, py_object_type)
1758 code.put("%s = %s; " % (star_arg_cname, Naming.empty_tuple))
1759 code.put_incref(Naming.empty_tuple, py_object_type)
1760 code.putln("}")
1761 code.putln("else {")
1762 code.putln(
1763 "if (unlikely(__Pyx_SplitStarArg(&%s, %d, &%s) < 0)) return %s;" % (
1764 Naming.args_cname,
1765 nargs,
1766 star_arg_cname,
1767 self.error_value()))
1768 code.putln("}")
1769 self.star_arg.entry.xdecref_cleanup = 0
1770 elif self.signature_has_generic_args():
1771 # make sure supernumerous positional arguments do not run
1772 # into keyword-only arguments and provide a more helpful
1773 # message than PyArg_ParseTupelAndKeywords()
1774 self.generate_positional_args_check(code, nargs)
1776 handle_error = 0
1777 if self.starstar_arg:
1778 handle_error = 1
1779 code.put(
1780 "if (unlikely(__Pyx_SplitKeywords(&%s, %s, &%s, %s) < 0)) " % (
1781 Naming.kwds_cname,
1782 Naming.kwdlist_cname,
1783 self.starstar_arg.entry.cname,
1784 self.reqd_kw_flags_cname))
1785 self.starstar_arg.entry.xdecref_cleanup = 0
1786 elif self.num_required_kw_args:
1787 handle_error = 1
1788 code.put("if (unlikely(__Pyx_CheckRequiredKeywords(%s, %s, %s) < 0)) " % (
1789 Naming.kwds_cname,
1790 Naming.kwdlist_cname,
1791 self.reqd_kw_flags_cname))
1793 if handle_error:
1794 if self.star_arg:
1795 code.putln("{")
1796 code.put_decref(Naming.args_cname, py_object_type)
1797 code.put_decref(self.star_arg.entry.cname, py_object_type)
1798 code.putln(error_return)
1799 code.putln("}")
1800 else:
1801 code.putln(error_return)
1803 def generate_positional_args_check(self, code, nargs):
1804 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > %d)) {" % (
1805 Naming.args_cname, nargs))
1806 code.putln("__Pyx_RaiseArgtupleTooLong(%d, PyTuple_GET_SIZE(%s));" % (
1807 nargs, Naming.args_cname))
1808 code.putln("return %s;" % self.error_value())
1809 code.putln("}")
1811 def generate_keyword_args_check(self, code):
1812 code.putln("if (unlikely(%s)) {" % Naming.kwds_cname)
1813 code.putln("if (unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
1814 Naming.kwds_cname, self.name,
1815 bool(self.starstar_arg), self.error_value()))
1816 code.putln("}")
1818 def generate_argument_conversion_code(self, code):
1819 # Generate code to convert arguments from
1820 # signature type to declared type, if needed.
1821 for arg in self.args:
1822 if arg.needs_conversion:
1823 self.generate_arg_conversion(arg, code)
1825 def generate_arg_conversion(self, arg, code):
1826 # Generate conversion code for one argument.
1827 old_type = arg.hdr_type
1828 new_type = arg.type
1829 if old_type.is_pyobject:
1830 if arg.default:
1831 code.putln("if (%s) {" % arg.hdr_cname)
1832 else:
1833 code.putln("assert(%s); {" % arg.hdr_cname)
1834 self.generate_arg_conversion_from_pyobject(arg, code)
1835 code.putln("}")
1836 elif new_type.is_pyobject:
1837 self.generate_arg_conversion_to_pyobject(arg, code)
1838 else:
1839 if new_type.assignable_from(old_type):
1840 code.putln(
1841 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
1842 else:
1843 error(arg.pos,
1844 "Cannot convert 1 argument from '%s' to '%s'" %
1845 (old_type, new_type))
1847 def generate_arg_conversion_from_pyobject(self, arg, code):
1848 new_type = arg.type
1849 func = new_type.from_py_function
1850 # copied from CoerceFromPyTypeNode
1851 if func:
1852 code.putln("%s = %s(%s); %s" % (
1853 arg.entry.cname,
1854 func,
1855 arg.hdr_cname,
1856 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
1857 else:
1858 error(arg.pos,
1859 "Cannot convert Python object argument to type '%s'"
1860 % new_type)
1862 def generate_arg_conversion_to_pyobject(self, arg, code):
1863 old_type = arg.hdr_type
1864 func = old_type.to_py_function
1865 if func:
1866 code.putln("%s = %s(%s); %s" % (
1867 arg.entry.cname,
1868 func,
1869 arg.hdr_cname,
1870 code.error_goto_if_null(arg.entry.cname, arg.pos)))
1871 else:
1872 error(arg.pos,
1873 "Cannot convert argument of type '%s' to Python object"
1874 % old_type)
1876 def generate_argument_type_tests(self, code):
1877 # Generate type tests for args whose signature
1878 # type is PyObject * and whose declared type is
1879 # a subtype thereof.
1880 for arg in self.args:
1881 if arg.needs_type_test:
1882 self.generate_arg_type_test(arg, code)
1884 def generate_arg_type_test(self, arg, code):
1885 # Generate type test for one argument.
1886 if arg.type.typeobj_is_available():
1887 typeptr_cname = arg.type.typeptr_cname
1888 arg_code = "((PyObject *)%s)" % arg.entry.cname
1889 code.putln(
1890 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1891 arg_code,
1892 typeptr_cname,
1893 not arg.not_none,
1894 arg.name,
1895 arg.type.is_builtin_type,
1896 code.error_goto(arg.pos)))
1897 else:
1898 error(arg.pos, "Cannot test type of extern C class "
1899 "without type object name specification")
1901 def error_value(self):
1902 return self.entry.signature.error_value
1904 def caller_will_check_exceptions(self):
1905 return 1
1907 class OverrideCheckNode(StatNode):
1908 # A Node for dispatching to the def method if it
1909 # is overriden.
1911 # py_func
1913 # args
1914 # func_temp
1915 # body
1917 child_attrs = ['body']
1919 body = None
1921 def analyse_expressions(self, env):
1922 self.args = env.arg_entries
1923 if self.py_func.is_module_scope:
1924 first_arg = 0
1925 else:
1926 first_arg = 1
1927 import ExprNodes
1928 self.func_node = ExprNodes.PyTempNode(self.pos, env)
1929 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
1930 call_node = ExprNodes.SimpleCallNode(self.pos,
1931 function=self.func_node,
1932 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
1933 self.body = ReturnStatNode(self.pos, value=call_node)
1934 self.body.analyse_expressions(env)
1936 def generate_execution_code(self, code):
1937 # Check to see if we are an extension type
1938 if self.py_func.is_module_scope:
1939 self_arg = "((PyObject *)%s)" % Naming.module_cname
1940 else:
1941 self_arg = "((PyObject *)%s)" % self.args[0].cname
1942 code.putln("/* Check if called by wrapper */")
1943 code.putln("if (unlikely(%s)) %s = 0;" % (Naming.skip_dispatch_cname, Naming.skip_dispatch_cname))
1944 code.putln("/* Check if overriden in Python */")
1945 if self.py_func.is_module_scope:
1946 code.putln("else {")
1947 else:
1948 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
1949 err = code.error_goto_if_null(self.func_node.result_code, self.pos)
1950 # need to get attribute manually--scope would return cdef method
1951 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result_code, self_arg, self.py_func.interned_attr_cname, err))
1952 # It appears that this type is not anywhere exposed in the Python/C API
1953 is_builtin_function_or_method = '(strcmp(Py_TYPE(%s)->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result_code
1954 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result_code, self.py_func.entry.func_cname)
1955 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
1956 self.body.generate_execution_code(code)
1957 code.putln('}')
1958 code.put_decref_clear(self.func_node.result_code, PyrexTypes.py_object_type)
1959 code.putln("}")
1961 class ClassDefNode(StatNode, BlockNode):
1962 pass
1964 class PyClassDefNode(ClassDefNode):
1965 # A Python class definition.
1967 # name EncodedString Name of the class
1968 # doc string or None
1969 # body StatNode Attribute definition code
1970 # entry Symtab.Entry
1971 # scope PyClassScope
1973 # The following subnodes are constructed internally:
1975 # dict DictNode Class dictionary
1976 # classobj ClassNode Class object
1977 # target NameNode Variable to assign class object to
1979 child_attrs = ["body", "dict", "classobj", "target"]
1981 def __init__(self, pos, name, bases, doc, body):
1982 StatNode.__init__(self, pos)
1983 self.name = name
1984 self.doc = doc
1985 self.body = body
1986 import ExprNodes
1987 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
1988 if self.doc and Options.docstrings:
1989 doc = embed_position(self.pos, self.doc)
1990 doc_node = ExprNodes.StringNode(pos, value = doc)
1991 else:
1992 doc_node = None
1993 self.classobj = ExprNodes.ClassNode(pos, name = name,
1994 bases = bases, dict = self.dict, doc = doc_node)
1995 self.target = ExprNodes.NameNode(pos, name = name)
1997 def create_scope(self, env):
1998 genv = env
1999 while env.is_py_class_scope or env.is_c_class_scope:
2000 env = env.outer_scope
2001 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2002 return cenv
2004 def analyse_declarations(self, env):
2005 self.target.analyse_target_declaration(env)
2006 cenv = self.create_scope(env)
2007 cenv.class_obj_cname = self.target.entry.cname
2008 self.body.analyse_declarations(cenv)
2010 def analyse_expressions(self, env):
2011 self.dict.analyse_expressions(env)
2012 self.classobj.analyse_expressions(env)
2013 genv = env.global_scope()
2014 cenv = self.scope
2015 cenv.class_dict_cname = self.dict.result_code
2016 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result_code
2017 self.body.analyse_expressions(cenv)
2018 self.target.analyse_target_expression(env, self.classobj)
2019 self.dict.release_temp(env)
2020 #self.classobj.release_temp(env)
2021 #self.target.release_target_temp(env)
2023 def generate_function_definitions(self, env, code, transforms):
2024 self.generate_py_string_decls(self.scope, code)
2025 self.body.generate_function_definitions(
2026 self.scope, code, transforms)
2028 def generate_execution_code(self, code):
2029 self.dict.generate_evaluation_code(code)
2030 self.classobj.generate_evaluation_code(code)
2031 self.body.generate_execution_code(code)
2032 self.target.generate_assignment_code(self.classobj, code)
2033 self.dict.generate_disposal_code(code)
2036 class CClassDefNode(ClassDefNode):
2037 # An extension type definition.
2039 # visibility 'private' or 'public' or 'extern'
2040 # typedef_flag boolean
2041 # api boolean
2042 # module_name string or None For import of extern type objects
2043 # class_name string Unqualified name of class
2044 # as_name string or None Name to declare as in this scope
2045 # base_class_module string or None Module containing the base class
2046 # base_class_name string or None Name of the base class
2047 # objstruct_name string or None Specified C name of object struct
2048 # typeobj_name string or None Specified C name of type object
2049 # in_pxd boolean Is in a .pxd file
2050 # doc string or None
2051 # body StatNode or None
2052 # entry Symtab.Entry
2053 # base_type PyExtensionType or None
2055 child_attrs = ["body"]
2057 def analyse_declarations(self, env):
2058 #print "CClassDefNode.analyse_declarations:", self.class_name
2059 #print "...visibility =", self.visibility
2060 #print "...module_name =", self.module_name
2061 if env.in_cinclude and not self.objstruct_name:
2062 error(self.pos, "Object struct name specification required for "
2063 "C class defined in 'extern from' block")
2064 self.base_type = None
2065 # Now that module imports are cached, we need to
2066 # import the modules for extern classes.
2067 if self.module_name:
2068 self.module = None
2069 for module in env.cimported_modules:
2070 if module.name == self.module_name:
2071 self.module = module
2072 if self.module is None:
2073 self.module = ModuleScope(self.module_name, None, env.context)
2074 self.module.has_extern_class = 1
2075 env.cimported_modules.append(self.module)
2077 if self.base_class_name:
2078 if self.base_class_module:
2079 base_class_scope = env.find_module(self.base_class_module, self.pos)
2080 else:
2081 base_class_scope = env
2082 if base_class_scope:
2083 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2084 if base_class_entry:
2085 if not base_class_entry.is_type:
2086 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2087 elif not base_class_entry.type.is_extension_type:
2088 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2089 elif not base_class_entry.type.is_complete():
2090 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2091 else:
2092 self.base_type = base_class_entry.type
2093 has_body = self.body is not None
2094 if self.module_name and self.visibility != 'extern':
2095 module_path = self.module_name.split(".")
2096 home_scope = env.find_imported_module(module_path, self.pos)
2097 if not home_scope:
2098 return
2099 else:
2100 home_scope = env
2101 self.entry = home_scope.declare_c_class(
2102 name = self.class_name,
2103 pos = self.pos,
2104 defining = has_body and self.in_pxd,
2105 implementing = has_body and not self.in_pxd,
2106 module_name = self.module_name,
2107 base_type = self.base_type,
2108 objstruct_cname = self.objstruct_name,
2109 typeobj_cname = self.typeobj_name,
2110 visibility = self.visibility,
2111 typedef_flag = self.typedef_flag,
2112 api = self.api)
2113 if home_scope is not env and self.visibility == 'extern':
2114 env.add_imported_entry(self.class_name, self.entry, pos)
2115 scope = self.entry.type.scope
2117 if self.doc and Options.docstrings:
2118 scope.doc = embed_position(self.pos, self.doc)
2120 if has_body:
2121 self.body.analyse_declarations(scope)
2122 if self.in_pxd:
2123 scope.defined = 1
2124 else:
2125 scope.implemented = 1
2126 env.allocate_vtable_names(self.entry)
2128 def analyse_expressions(self, env):
2129 if self.body:
2130 scope = self.entry.type.scope
2131 self.body.analyse_expressions(scope)
2133 def generate_function_definitions(self, env, code, transforms):
2134 self.generate_py_string_decls(self.entry.type.scope, code)
2135 if self.body:
2136 self.body.generate_function_definitions(
2137 self.entry.type.scope, code, transforms)
2139 def generate_execution_code(self, code):
2140 # This is needed to generate evaluation code for
2141 # default values of method arguments.
2142 if self.body:
2143 self.body.generate_execution_code(code)
2145 def annotate(self, code):
2146 if self.body:
2147 self.body.annotate(code)
2150 class PropertyNode(StatNode):
2151 # Definition of a property in an extension type.
2153 # name string
2154 # doc EncodedString or None Doc string
2155 # body StatListNode
2157 child_attrs = ["body"]
2159 def analyse_declarations(self, env):
2160 entry = env.declare_property(self.name, self.doc, self.pos)
2161 if entry:
2162 if self.doc and Options.docstrings:
2163 doc_entry = env.get_string_const(
2164 self.doc, identifier = False)
2165 entry.doc_cname = doc_entry.cname
2166 self.body.analyse_declarations(entry.scope)
2168 def analyse_expressions(self, env):
2169 self.body.analyse_expressions(env)
2171 def generate_function_definitions(self, env, code, transforms):
2172 self.body.generate_function_definitions(env, code, transforms)
2174 def generate_execution_code(self, code):
2175 pass
2177 def annotate(self, code):
2178 self.body.annotate(code)
2181 class GlobalNode(StatNode):
2182 # Global variable declaration.
2184 # names [string]
2186 child_attrs = []
2188 def analyse_declarations(self, env):
2189 for name in self.names:
2190 env.declare_global(name, self.pos)
2192 def analyse_expressions(self, env):
2193 pass
2195 def generate_execution_code(self, code):
2196 pass
2199 class ExprStatNode(StatNode):
2200 # Expression used as a statement.
2202 # expr ExprNode
2204 child_attrs = ["expr"]
2206 def analyse_expressions(self, env):
2207 self.expr.analyse_expressions(env)
2208 self.expr.release_temp(env)
2210 def generate_execution_code(self, code):
2211 self.expr.generate_evaluation_code(code)
2212 if not self.expr.is_temp and self.expr.result_code:
2213 code.putln("%s;" % self.expr.result_code)
2214 self.expr.generate_disposal_code(code)
2216 def annotate(self, code):
2217 self.expr.annotate(code)
2220 class AssignmentNode(StatNode):
2221 # Abstract base class for assignment nodes.
2223 # The analyse_expressions and generate_execution_code
2224 # phases of assignments are split into two sub-phases
2225 # each, to enable all the right hand sides of a
2226 # parallel assignment to be evaluated before assigning
2227 # to any of the left hand sides.
2229 def analyse_expressions(self, env):
2230 self.analyse_types(env)
2231 self.allocate_rhs_temps(env)
2232 self.allocate_lhs_temps(env)
2234 # def analyse_expressions(self, env):
2235 # self.analyse_expressions_1(env)
2236 # self.analyse_expressions_2(env)
2238 def generate_execution_code(self, code):
2239 self.generate_rhs_evaluation_code(code)
2240 self.generate_assignment_code(code)
2243 class SingleAssignmentNode(AssignmentNode):
2244 # The simplest case:
2246 # a = b
2248 # lhs ExprNode Left hand side
2249 # rhs ExprNode Right hand side
2250 # first bool Is this guaranteed the first assignment to lhs?
2252 child_attrs = ["lhs", "rhs"]
2253 first = False
2255 def analyse_declarations(self, env):
2256 self.lhs.analyse_target_declaration(env)
2258 def analyse_types(self, env, use_temp = 0):
2259 self.rhs.analyse_types(env)
2260 self.lhs.analyse_target_types(env)
2261 self.lhs.gil_assignment_check(env)
2262 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2263 if use_temp:
2264 self.rhs = self.rhs.coerce_to_temp(env)
2266 def allocate_rhs_temps(self, env):
2267 self.rhs.allocate_temps(env)
2269 def allocate_lhs_temps(self, env):
2270 self.lhs.allocate_target_temps(env, self.rhs)
2271 #self.lhs.release_target_temp(env)
2272 #self.rhs.release_temp(env)
2274 # def analyse_expressions_1(self, env, use_temp = 0):
2275 # self.rhs.analyse_types(env)
2276 # self.lhs.analyse_target_types(env)
2277 # self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2278 # if use_temp:
2279 # self.rhs = self.rhs.coerce_to_temp(env)
2280 # self.rhs.allocate_temps(env)
2282 # def analyse_expressions_2(self, env):
2283 # self.lhs.allocate_target_temps(env)
2284 # self.lhs.release_target_temp(env)
2285 # self.rhs.release_temp(env)
2287 def generate_rhs_evaluation_code(self, code):
2288 self.rhs.generate_evaluation_code(code)
2290 def generate_assignment_code(self, code):
2291 self.lhs.generate_assignment_code(self.rhs, code)
2293 def annotate(self, code):
2294 self.lhs.annotate(code)
2295 self.rhs.annotate(code)
2298 class CascadedAssignmentNode(AssignmentNode):
2299 # An assignment with multiple left hand sides:
2301 # a = b = c
2303 # lhs_list [ExprNode] Left hand sides
2304 # rhs ExprNode Right hand sides
2306 # Used internally:
2308 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2310 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2311 coerced_rhs_list = None
2313 def analyse_declarations(self, env):
2314 for lhs in self.lhs_list:
2315 lhs.analyse_target_declaration(env)
2317 def analyse_types(self, env, use_temp = 0):
2318 self.rhs.analyse_types(env)
2319 if use_temp:
2320 self.rhs = self.rhs.coerce_to_temp(env)
2321 else:
2322 self.rhs = self.rhs.coerce_to_simple(env)
2323 from ExprNodes import CloneNode
2324 self.coerced_rhs_list = []
2325 for lhs in self.lhs_list:
2326 lhs.analyse_target_types(env)
2327 lhs.gil_assignment_check(env)
2328 rhs = CloneNode(self.rhs)
2329 rhs = rhs.coerce_to(lhs.type, env)
2330 self.coerced_rhs_list.append(rhs)
2332 def allocate_rhs_temps(self, env):
2333 self.rhs.allocate_temps(env)
2335 def allocate_lhs_temps(self, env):
2336 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2337 rhs.allocate_temps(env)
2338 lhs.allocate_target_temps(env, rhs)
2339 #lhs.release_target_temp(env)
2340 #rhs.release_temp(env)
2341 self.rhs.release_temp(env)
2343 # def analyse_expressions_1(self, env, use_temp = 0):
2344 # self.rhs.analyse_types(env)
2345 # if use_temp:
2346 # self.rhs = self.rhs.coerce_to_temp(env)
2347 # else:
2348 # self.rhs = self.rhs.coerce_to_simple(env)
2349 # self.rhs.allocate_temps(env)
2351 # def analyse_expressions_2(self, env):
2352 # from ExprNodes import CloneNode
2353 # self.coerced_rhs_list = []
2354 # for lhs in self.lhs_list:
2355 # lhs.analyse_target_types(env)
2356 # rhs = CloneNode(self.rhs)
2357 # rhs = rhs.coerce_to(lhs.type, env)
2358 # self.coerced_rhs_list.append(rhs)
2359 # rhs.allocate_temps(env)
2360 # lhs.allocate_target_temps(env)
2361 # lhs.release_target_temp(env)
2362 # rhs.release_temp(env)
2363 # self.rhs.release_temp(env)
2365 def generate_rhs_evaluation_code(self, code):
2366 self.rhs.generate_evaluation_code(code)
2368 def generate_assignment_code(self, code):
2369 for i in range(len(self.lhs_list)):
2370 lhs = self.lhs_list[i]
2371 rhs = self.coerced_rhs_list[i]
2372 rhs.generate_evaluation_code(code)
2373 lhs.generate_assignment_code(rhs, code)
2374 # Assignment has disposed of the cloned RHS
2375 self.rhs.generate_disposal_code(code)
2377 def annotate(self, code):
2378 for i in range(len(self.lhs_list)):
2379 lhs = self.lhs_list[i].annotate(code)
2380 rhs = self.coerced_rhs_list[i].annotate(code)
2381 self.rhs.annotate(code)
2384 class ParallelAssignmentNode(AssignmentNode):
2385 # A combined packing/unpacking assignment:
2387 # a, b, c = d, e, f
2389 # This has been rearranged by the parser into
2391 # a = d ; b = e ; c = f
2393 # but we must evaluate all the right hand sides
2394 # before assigning to any of the left hand sides.
2396 # stats [AssignmentNode] The constituent assignments
2398 child_attrs = ["stats"]
2400 def analyse_declarations(self, env):
2401 for stat in self.stats:
2402 stat.analyse_declarations(env)
2404 def analyse_expressions(self, env):
2405 for stat in self.stats:
2406 stat.analyse_types(env, use_temp = 1)
2407 stat.allocate_rhs_temps(env)
2408 for stat in self.stats:
2409 stat.allocate_lhs_temps(env)
2411 # def analyse_expressions(self, env):
2412 # for stat in self.stats:
2413 # stat.analyse_expressions_1(env, use_temp = 1)
2414 # for stat in self.stats:
2415 # stat.analyse_expressions_2(env)
2417 def generate_execution_code(self, code):
2418 for stat in self.stats:
2419 stat.generate_rhs_evaluation_code(code)
2420 for stat in self.stats:
2421 stat.generate_assignment_code(code)
2423 def annotate(self, code):
2424 for stat in self.stats:
2425 stat.annotate(code)
2428 class InPlaceAssignmentNode(AssignmentNode):
2429 # An in place arithmatic operand:
2431 # a += b
2432 # a -= b
2433 # ...
2435 # lhs ExprNode Left hand side
2436 # rhs ExprNode Right hand side
2437 # op char one of "+-*/%^&|"
2438 # dup (ExprNode) copy of lhs used for operation (auto-generated)
2440 # This code is a bit tricky because in order to obey Python
2441 # semantics the sub-expressions (e.g. indices) of the lhs must
2442 # not be evaluated twice. So we must re-use the values calculated
2443 # in evaluation phase for the assignment phase as well.
2444 # Fortunately, the type of the lhs node is fairly constrained
2445 # (it must be a NameNode, AttributeNode, or IndexNode).
2447 child_attrs = ["lhs", "rhs"]
2448 dup = None
2450 def analyse_declarations(self, env):
2451 self.lhs.analyse_target_declaration(env)
2453 def analyse_types(self, env):
2454 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
2455 self.rhs.analyse_types(env)
2456 self.lhs.analyse_target_types(env)
2457 if Options.incref_local_binop and self.dup.type.is_pyobject:
2458 self.dup = self.dup.coerce_to_temp(env)
2460 def allocate_rhs_temps(self, env):
2461 import ExprNodes
2462 if self.lhs.type.is_pyobject:
2463 self.rhs = self.rhs.coerce_to_pyobject(env)
2464 elif self.rhs.type.is_pyobject:
2465 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2466 if self.lhs.type.is_pyobject:
2467 self.result = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
2468 self.result.allocate_temps(env)
2469 # if use_temp:
2470 # self.rhs = self.rhs.coerce_to_temp(env)
2471 self.rhs.allocate_temps(env)
2472 self.dup.allocate_subexpr_temps(env)
2473 self.dup.allocate_temp(env)
2475 def allocate_lhs_temps(self, env):
2476 self.lhs.allocate_target_temps(env, self.rhs)
2477 # self.lhs.release_target_temp(env)
2478 self.dup.release_temp(env)
2479 if self.dup.is_temp:
2480 self.dup.release_subexpr_temps(env)
2481 # self.rhs.release_temp(env)
2482 if self.lhs.type.is_pyobject:
2483 self.result.release_temp(env)
2485 def generate_execution_code(self, code):
2486 self.rhs.generate_evaluation_code(code)
2487 self.dup.generate_subexpr_evaluation_code(code)
2488 self.dup.generate_result_code(code)
2489 if self.operator == "**":
2490 extra = ", Py_None"
2491 else:
2492 extra = ""
2493 if self.lhs.type.is_pyobject:
2494 code.putln(
2495 "%s = %s(%s, %s%s); %s" % (
2496 self.result.result_code,
2497 self.py_operation_function(),
2498 self.dup.py_result(),
2499 self.rhs.py_result(),
2500 extra,
2501 code.error_goto_if_null(self.result.py_result(), self.pos)))
2502 self.result.generate_evaluation_code(code) # May be a type check...
2503 self.rhs.generate_disposal_code(code)
2504 self.dup.generate_disposal_code(code)
2505 self.lhs.generate_assignment_code(self.result, code)
2506 else:
2507 c_op = self.operator
2508 if c_op == "//":
2509 c_op = "/"
2510 elif c_op == "**":
2511 if self.lhs.type.is_int and self.rhs.type.is_int:
2512 error(self.pos, "** with two C int types is ambiguous")
2513 else:
2514 error(self.pos, "No C inplace power operator")
2515 # have to do assignment directly to avoid side-effects
2516 code.putln("%s %s= %s;" % (self.lhs.result_code, c_op, self.rhs.result_code) )
2517 self.rhs.generate_disposal_code(code)
2518 if self.dup.is_temp:
2519 self.dup.generate_subexpr_disposal_code(code)
2521 def create_dup_node(self, env):
2522 import ExprNodes
2523 self.dup = self.lhs
2524 self.dup.analyse_types(env)
2525 if isinstance(self.lhs, ExprNodes.NameNode):
2526 target_lhs = ExprNodes.NameNode(self.dup.pos, name = self.dup.name, is_temp = self.dup.is_temp, entry = self.dup.entry)
2527 elif isinstance(self.lhs, ExprNodes.AttributeNode):
2528 target_lhs = ExprNodes.AttributeNode(self.dup.pos, obj = ExprNodes.CloneNode(self.lhs.obj), attribute = self.dup.attribute, is_temp = self.dup.is_temp)
2529 elif isinstance(self.lhs, ExprNodes.IndexNode):
2530 target_lhs = ExprNodes.IndexNode(self.dup.pos, base = ExprNodes.CloneNode(self.dup.base), index = ExprNodes.CloneNode(self.lhs.index), is_temp = self.dup.is_temp)
2531 self.lhs = target_lhs
2532 return self.dup
2534 def py_operation_function(self):
2535 return self.py_functions[self.operator]
2537 py_functions = {
2538 "|": "PyNumber_InPlaceOr",
2539 "^": "PyNumber_InPlaceXor",
2540 "&": "PyNumber_InPlaceAnd",
2541 "+": "PyNumber_InPlaceAdd",
2542 "-": "PyNumber_InPlaceSubtract",
2543 "*": "PyNumber_InPlaceMultiply",
2544 "/": "PyNumber_InPlaceDivide",
2545 "%": "PyNumber_InPlaceRemainder",
2546 "<<": "PyNumber_InPlaceLshift",
2547 ">>": "PyNumber_InPlaceRshift",
2548 "**": "PyNumber_InPlacePower",
2549 "//": "PyNumber_InPlaceFloorDivide",
2552 def annotate(self, code):
2553 self.lhs.annotate(code)
2554 self.rhs.annotate(code)
2555 self.dup.annotate(code)
2558 class PrintStatNode(StatNode):
2559 # print statement
2561 # arg_tuple TupleNode
2562 # append_newline boolean
2564 child_attrs = ["arg_tuple"]
2566 def analyse_expressions(self, env):
2567 self.arg_tuple.analyse_expressions(env)
2568 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
2569 self.arg_tuple.release_temp(env)
2570 env.use_utility_code(printing_utility_code)
2571 self.gil_check(env)
2573 gil_message = "Python print statement"
2575 def generate_execution_code(self, code):
2576 self.arg_tuple.generate_evaluation_code(code)
2577 code.putln(
2578 "if (__Pyx_Print(%s, %d) < 0) %s" % (
2579 self.arg_tuple.py_result(),
2580 self.append_newline,
2581 code.error_goto(self.pos)))
2582 self.arg_tuple.generate_disposal_code(code)
2584 def annotate(self, code):
2585 self.arg_tuple.annotate(code)
2588 class DelStatNode(StatNode):
2589 # del statement
2591 # args [ExprNode]
2593 child_attrs = ["args"]
2595 def analyse_declarations(self, env):
2596 for arg in self.args:
2597 arg.analyse_target_declaration(env)
2599 def analyse_expressions(self, env):
2600 for arg in self.args:
2601 arg.analyse_target_expression(env, None)
2602 if arg.type.is_pyobject:
2603 self.gil_check(env)
2604 else:
2605 error(arg.pos, "Deletion of non-Python object")
2606 #arg.release_target_temp(env)
2608 gil_message = "Deleting Python object"
2610 def generate_execution_code(self, code):
2611 for arg in self.args:
2612 if arg.type.is_pyobject:
2613 arg.generate_deletion_code(code)
2614 # else error reported earlier
2616 def annotate(self, code):
2617 for arg in self.args:
2618 arg.annotate(code)
2621 class PassStatNode(StatNode):
2622 # pass statement
2624 child_attrs = []
2626 def analyse_expressions(self, env):
2627 pass
2629 def generate_execution_code(self, code):
2630 pass
2633 class BreakStatNode(StatNode):
2635 child_attrs = []
2637 def analyse_expressions(self, env):
2638 pass
2640 def generate_execution_code(self, code):
2641 if not code.break_label:
2642 error(self.pos, "break statement not inside loop")
2643 else:
2644 #code.putln(
2645 # "goto %s;" %
2646 # code.break_label)
2647 code.put_goto(code.break_label)
2650 class ContinueStatNode(StatNode):
2652 child_attrs = []
2654 def analyse_expressions(self, env):
2655 pass
2657 def generate_execution_code(self, code):
2658 if code.in_try_finally:
2659 error(self.pos, "continue statement inside try of try...finally")
2660 elif not code.continue_label:
2661 error(self.pos, "continue statement not inside loop")
2662 else:
2663 code.put_goto(code.continue_label)
2666 class ReturnStatNode(StatNode):
2667 # return statement
2669 # value ExprNode or None
2670 # return_type PyrexType
2671 # temps_in_use [Entry] Temps in use at time of return
2673 child_attrs = ["value"]
2675 def analyse_expressions(self, env):
2676 return_type = env.return_type
2677 self.return_type = return_type
2678 self.temps_in_use = env.temps_in_use()
2679 if not return_type:
2680 error(self.pos, "Return not inside a function body")
2681 return
2682 if self.value:
2683 self.value.analyse_types(env)
2684 if return_type.is_void or return_type.is_returncode:
2685 error(self.value.pos,
2686 "Return with value in void function")
2687 else:
2688 self.value = self.value.coerce_to(env.return_type, env)
2689 self.value.allocate_temps(env)
2690 self.value.release_temp(env)
2691 else:
2692 if (not return_type.is_void
2693 and not return_type.is_pyobject
2694 and not return_type.is_returncode):
2695 error(self.pos, "Return value required")
2696 if return_type.is_pyobject:
2697 self.gil_check(env)
2699 gil_message = "Returning Python object"
2701 def generate_execution_code(self, code):
2702 code.mark_pos(self.pos)
2703 if not self.return_type:
2704 # error reported earlier
2705 return
2706 if self.value:
2707 self.value.generate_evaluation_code(code)
2708 self.value.make_owned_reference(code)
2709 code.putln(
2710 "%s = %s;" % (
2711 Naming.retval_cname,
2712 self.value.result_as(self.return_type)))
2713 self.value.generate_post_assignment_code(code)
2714 else:
2715 if self.return_type.is_pyobject:
2716 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
2717 elif self.return_type.is_returncode:
2718 code.putln(
2719 "%s = %s;" % (
2720 Naming.retval_cname,
2721 self.return_type.default_value))
2722 for entry in self.temps_in_use:
2723 code.put_var_decref_clear(entry)
2724 #code.putln(
2725 # "goto %s;" %
2726 # code.return_label)
2727 code.put_goto(code.return_label)
2729 def annotate(self, code):
2730 if self.value:
2731 self.value.annotate(code)
2734 class RaiseStatNode(StatNode):
2735 # raise statement
2737 # exc_type ExprNode or None
2738 # exc_value ExprNode or None
2739 # exc_tb ExprNode or None
2741 child_attrs = ["exc_type", "exc_value", "exc_tb"]
2743 def analyse_expressions(self, env):
2744 if self.exc_type:
2745 self.exc_type.analyse_types(env)
2746 self.exc_type = self.exc_type.coerce_to_pyobject(env)
2747 self.exc_type.allocate_temps(env)
2748 if self.exc_value:
2749 self.exc_value.analyse_types(env)
2750 self.exc_value = self.exc_value.coerce_to_pyobject(env)
2751 self.exc_value.allocate_temps(env)
2752 if self.exc_tb:
2753 self.exc_tb.analyse_types(env)
2754 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
2755 self.exc_tb.allocate_temps(env)
2756 if self.exc_type:
2757 self.exc_type.release_temp(env)
2758 if self.exc_value:
2759 self.exc_value.release_temp(env)
2760 if self.exc_tb:
2761 self.exc_tb.release_temp(env)
2762 env.use_utility_code(raise_utility_code)
2763 self.gil_check(env)
2765 gil_message = "Raising exception"
2767 def generate_execution_code(self, code):
2768 if self.exc_type:
2769 self.exc_type.generate_evaluation_code(code)
2770 type_code = self.exc_type.py_result()
2771 else:
2772 type_code = 0
2773 if self.exc_value:
2774 self.exc_value.generate_evaluation_code(code)
2775 value_code = self.exc_value.py_result()
2776 else:
2777 value_code = "0"
2778 if self.exc_tb:
2779 self.exc_tb.generate_evaluation_code(code)
2780 tb_code = self.exc_tb.py_result()
2781 else:
2782 tb_code = "0"
2783 if self.exc_type or self.exc_value or self.exc_tb:
2784 code.putln(
2785 "__Pyx_Raise(%s, %s, %s);" % (
2786 type_code,
2787 value_code,
2788 tb_code))
2789 else:
2790 code.putln(
2791 "__Pyx_ReRaise();")
2792 if self.exc_type:
2793 self.exc_type.generate_disposal_code(code)
2794 if self.exc_value:
2795 self.exc_value.generate_disposal_code(code)
2796 if self.exc_tb:
2797 self.exc_tb.generate_disposal_code(code)
2798 code.putln(
2799 code.error_goto(self.pos))
2801 def annotate(self, code):
2802 if self.exc_type:
2803 self.exc_type.annotate(code)
2804 if self.exc_value:
2805 self.exc_value.annotate(code)
2806 if self.exc_tb:
2807 self.exc_tb.annotate(code)
2810 class ReraiseStatNode(StatNode):
2812 child_attrs = []
2814 def analyse_expressions(self, env):
2815 self.gil_check(env)
2816 env.use_utility_code(raise_utility_code)
2818 gil_message = "Raising exception"
2820 def generate_execution_code(self, code):
2821 vars = code.exc_vars
2822 if vars:
2823 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
2824 code.putln(code.error_goto(self.pos))
2825 else:
2826 error(self.pos, "Reraise not inside except clause")
2829 class AssertStatNode(StatNode):
2830 # assert statement
2832 # cond ExprNode
2833 # value ExprNode or None
2835 child_attrs = ["cond", "value"]
2837 def analyse_expressions(self, env):
2838 self.cond = self.cond.analyse_boolean_expression(env)
2839 if self.value:
2840 self.value.analyse_types(env)
2841 self.value = self.value.coerce_to_pyobject(env)
2842 self.value.allocate_temps(env)
2843 self.cond.release_temp(env)
2844 if self.value:
2845 self.value.release_temp(env)
2846 self.gil_check(env)
2847 #env.recycle_pending_temps() # TEMPORARY
2849 gil_message = "Raising exception"
2851 def generate_execution_code(self, code):
2852 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
2853 self.cond.generate_evaluation_code(code)
2854 code.putln(
2855 "if (unlikely(!%s)) {" %
2856 self.cond.result_code)
2857 if self.value:
2858 self.value.generate_evaluation_code(code)
2859 code.putln(
2860 "PyErr_SetObject(PyExc_AssertionError, %s);" %
2861 self.value.py_result())
2862 self.value.generate_disposal_code(code)
2863 else:
2864 code.putln(
2865 "PyErr_SetNone(PyExc_AssertionError);")
2866 code.putln(
2867 code.error_goto(self.pos))
2868 code.putln(
2869 "}")
2870 self.cond.generate_disposal_code(code)
2871 code.putln("#endif")
2873 def annotate(self, code):
2874 self.cond.annotate(code)
2875 if self.value:
2876 self.value.annotate(code)
2879 class IfStatNode(StatNode):
2880 # if statement
2882 # if_clauses [IfClauseNode]
2883 # else_clause StatNode or None
2885 child_attrs = ["if_clauses", "else_clause"]
2887 def analyse_control_flow(self, env):
2888 env.start_branching(self.pos)
2889 for if_clause in self.if_clauses:
2890 if_clause.analyse_control_flow(env)
2891 env.next_branch(if_clause.end_pos())
2892 if self.else_clause:
2893 self.else_clause.analyse_control_flow(env)
2894 env.finish_branching(self.end_pos())
2896 def analyse_declarations(self, env):
2897 for if_clause in self.if_clauses:
2898 if_clause.analyse_declarations(env)
2899 if self.else_clause:
2900 self.else_clause.analyse_declarations(env)
2902 def analyse_expressions(self, env):
2903 for if_clause in self.if_clauses:
2904 if_clause.analyse_expressions(env)
2905 if self.else_clause:
2906 self.else_clause.analyse_expressions(env)
2908 def generate_execution_code(self, code):
2909 code.mark_pos(self.pos)
2910 end_label = code.new_label()
2911 for if_clause in self.if_clauses:
2912 if_clause.generate_execution_code(code, end_label)
2913 if self.else_clause:
2914 code.putln("/*else*/ {")
2915 self.else_clause.generate_execution_code(code)
2916 code.putln("}")
2917 code.put_label(end_label)
2919 def annotate(self, code):
2920 for if_clause in self.if_clauses:
2921 if_clause.annotate(code)
2922 if self.else_clause:
2923 self.else_clause.annotate(code)
2926 class IfClauseNode(Node):
2927 # if or elif clause in an if statement
2929 # condition ExprNode
2930 # body StatNode
2932 child_attrs = ["condition", "body"]
2934 def analyse_control_flow(self, env):
2935 self.body.analyse_control_flow(env)
2937 def analyse_declarations(self, env):
2938 self.condition.analyse_declarations(env)
2939 self.body.analyse_declarations(env)
2941 def analyse_expressions(self, env):
2942 self.condition = \
2943 self.condition.analyse_temp_boolean_expression(env)
2944 self.condition.release_temp(env)
2945 self.body.analyse_expressions(env)
2947 def generate_execution_code(self, code, end_label):
2948 self.condition.generate_evaluation_code(code)
2949 code.putln(
2950 "if (%s) {" %
2951 self.condition.result_code)
2952 self.body.generate_execution_code(code)
2953 #code.putln(
2954 # "goto %s;" %
2955 # end_label)
2956 code.put_goto(end_label)
2957 code.putln("}")
2959 def annotate(self, code):
2960 self.condition.annotate(code)
2961 self.body.annotate(code)
2964 class SwitchCaseNode(StatNode):
2965 # Generated in the optimization of an if-elif-else node
2967 # conditions [ExprNode]
2968 # body StatNode
2970 child_attrs = ['conditions', 'body']
2972 def generate_execution_code(self, code):
2973 for cond in self.conditions:
2974 code.putln("case %s:" % cond.calculate_result_code())
2975 self.body.generate_execution_code(code)
2976 code.putln("break;")
2978 def annotate(self, code):
2979 for cond in self.conditions:
2980 cond.annotate(code)
2981 body.annotate(code)
2983 class SwitchStatNode(StatNode):
2984 # Generated in the optimization of an if-elif-else node
2986 # test ExprNode
2987 # cases [SwitchCaseNode]
2988 # else_clause StatNode or None
2990 child_attrs = ['test', 'cases', 'else_clause']
2992 def generate_execution_code(self, code):
2993 code.putln("switch (%s) {" % self.test.calculate_result_code())
2994 for case in self.cases:
2995 case.generate_execution_code(code)
2996 if self.else_clause is not None:
2997 code.putln("default:")
2998 self.else_clause.generate_execution_code(code)
2999 code.putln("}")
3001 def annotate(self, code):
3002 self.test.annotate(code)
3003 for case in self.cases:
3004 case.annotate(code)
3005 self.else_clause.annotate(code)
3007 class LoopNode:
3009 def analyse_control_flow(self, env):
3010 env.start_branching(self.pos)
3011 self.body.analyse_control_flow(env)
3012 env.next_branch(self.body.end_pos())
3013 if self.else_clause:
3014 self.else_clause.analyse_control_flow(env)
3015 env.finish_branching(self.end_pos())
3018 class WhileStatNode(LoopNode, StatNode):
3019 # while statement
3021 # condition ExprNode
3022 # body StatNode
3023 # else_clause StatNode
3025 child_attrs = ["condition", "body", "else_clause"]
3027 def analyse_declarations(self, env):
3028 self.body.analyse_declarations(env)
3029 if self.else_clause:
3030 self.else_clause.analyse_declarations(env)
3032 def analyse_expressions(self, env):
3033 self.condition = \
3034 self.condition.analyse_temp_boolean_expression(env)
3035 self.condition.release_temp(env)
3036 #env.recycle_pending_temps() # TEMPORARY
3037 self.body.analyse_expressions(env)
3038 if self.else_clause:
3039 self.else_clause.analyse_expressions(env)
3041 def generate_execution_code(self, code):
3042 old_loop_labels = code.new_loop_labels()
3043 code.putln(
3044 "while (1) {")
3045 self.condition.generate_evaluation_code(code)
3046 code.putln(
3047 "if (!%s) break;" %
3048 self.condition.result_code)
3049 self.body.generate_execution_code(code)
3050 code.put_label(code.continue_label)
3051 code.putln("}")
3052 break_label = code.break_label
3053 code.set_loop_labels(old_loop_labels)
3054 if self.else_clause:
3055 code.putln("/*else*/ {")
3056 self.else_clause.generate_execution_code(code)
3057 code.putln("}")
3058 code.put_label(break_label)
3060 def annotate(self, code):
3061 self.condition.annotate(code)
3062 self.body.annotate(code)
3063 if self.else_clause:
3064 self.else_clause.annotate(code)
3067 def ForStatNode(pos, **kw):
3068 if kw.has_key('iterator'):
3069 return ForInStatNode(pos, **kw)
3070 else:
3071 return ForFromStatNode(pos, **kw)
3073 class ForInStatNode(LoopNode, StatNode):
3074 # for statement
3076 # target ExprNode
3077 # iterator IteratorNode
3078 # body StatNode
3079 # else_clause StatNode
3080 # item NextNode used internally
3082 child_attrs = ["target", "iterator", "body", "else_clause"]
3083 item = None
3085 def analyse_declarations(self, env):
3086 self.target.analyse_target_declaration(env)
3087 self.body.analyse_declarations(env)
3088 if self.else_clause:
3089 self.else_clause.analyse_declarations(env)
3091 def analyse_range_step(self, args):
3092 import ExprNodes
3093 # The direction must be determined at compile time to set relations.
3094 # Otherwise, return False.
3095 if len(args) < 3:
3096 self.step = ExprNodes.IntNode(pos = args[0].pos, value='1')
3097 self.relation1 = '<='
3098 self.relation2 = '<'
3099 return True
3100 else:
3101 step = args[2]
3102 if isinstance(step, ExprNodes.UnaryMinusNode) and isinstance(step.operand, ExprNodes.IntNode):
3103 step = ExprNodes.IntNode(pos = step.pos, value=str(-int(step.operand.value, 0)))
3104 if isinstance(step, ExprNodes.IntNode):
3105 step_value = int(step.value, 0)
3106 if step_value > 0:
3107 self.step = step
3108 self.relation1 = '<='
3109 self.relation2 = '<'
3110 return True
3111 elif step_value < 0:
3112 self.step = ExprNodes.IntNode(pos = step.pos, value=str(-step_value))
3113 self.relation1 = '>='
3114 self.relation2 = '>'
3115 return True
3116 return False
3119 def analyse_expressions(self, env):
3120 import ExprNodes
3121 self.target.analyse_target_types(env)
3122 if Options.convert_range and self.target.type.is_int:
3123 sequence = self.iterator.sequence
3124 if isinstance(sequence, ExprNodes.SimpleCallNode) \
3125 and sequence.self is None \
3126 and isinstance(sequence.function, ExprNodes.NameNode) \
3127 and (sequence.function.name == 'range' or sequence.function.name == 'xrange'):
3128 args = sequence.args
3129 # Make sure we can determine direction from step
3130 if self.analyse_range_step(args):
3131 # Mutate to ForFrom loop type
3132 self.__class__ = ForFromStatNode
3133 if len(args) == 1:
3134 self.bound1 = ExprNodes.IntNode(pos = sequence.pos, value='0')
3135 self.bound2 = args[0]
3136 else:
3137 self.bound1 = args[0]
3138 self.bound2 = args[1]
3139 ForFromStatNode.analyse_expressions(self, env)
3140 return
3142 self.iterator.analyse_expressions(env)
3143 self.item = ExprNodes.NextNode(self.iterator, env)
3144 self.item = self.item.coerce_to(self.target.type, env)
3145 self.item.allocate_temps(env)
3146 self.target.allocate_target_temps(env, self.item)
3147 #self.item.release_temp(env)
3148 #self.target.release_target_temp(env)
3149 self.body.analyse_expressions(env)
3150 if self.else_clause:
3151 self.else_clause.analyse_expressions(env)
3152 self.iterator.release_temp(env)
3154 def generate_execution_code(self, code):
3155 old_loop_labels = code.new_loop_labels()
3156 self.iterator.generate_evaluation_code(code)
3157 code.putln(
3158 "for (;;) {")
3159 self.item.generate_evaluation_code(code)
3160 self.target.generate_assignment_code(self.item, code)
3161 self.body.generate_execution_code(code)
3162 code.put_label(code.continue_label)
3163 code.putln(
3164 "}")
3165 break_label = code.break_label
3166 code.set_loop_labels(old_loop_labels)
3167 if self.else_clause:
3168 code.putln("/*else*/ {")
3169 self.else_clause.generate_execution_code(code)
3170 code.putln("}")
3171 code.put_label(break_label)
3172 self.iterator.generate_disposal_code(code)
3174 def annotate(self, code):
3175 self.target.annotate(code)
3176 self.iterator.annotate(code)
3177 self.body.annotate(code)
3178 if self.else_clause:
3179 self.else_clause.annotate(code)
3180 self.item.annotate(code)
3183 class ForFromStatNode(LoopNode, StatNode):
3184 # for name from expr rel name rel expr
3186 # target NameNode
3187 # bound1 ExprNode
3188 # relation1 string
3189 # relation2 string
3190 # bound2 ExprNode
3191 # step ExprNode or None
3192 # body StatNode
3193 # else_clause StatNode or None
3195 # Used internally:
3197 # is_py_target bool
3198 # loopvar_name string
3199 # py_loopvar_node PyTempNode or None
3200 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3202 def analyse_declarations(self, env):
3203 self.target.analyse_target_declaration(env)
3204 self.body.analyse_declarations(env)
3205 if self.else_clause:
3206 self.else_clause.analyse_declarations(env)
3208 def analyse_expressions(self, env):
3209 import ExprNodes
3210 self.target.analyse_target_types(env)
3211 self.bound1.analyse_types(env)
3212 self.bound2.analyse_types(env)
3213 if self.target.type.is_numeric:
3214 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3215 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3216 else:
3217 self.bound1 = self.bound1.coerce_to_integer(env)
3218 self.bound2 = self.bound2.coerce_to_integer(env)
3219 if self.step is not None:
3220 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3221 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3222 self.step.analyse_types(env)
3223 self.step = self.step.coerce_to_integer(env)
3224 if not (self.bound2.is_name or self.bound2.is_literal):
3225 self.bound2 = self.bound2.coerce_to_temp(env)
3226 target_type = self.target.type
3227 if not (target_type.is_pyobject or target_type.is_numeric):
3228 error(self.target.pos,
3229 "Integer for-loop variable must be of type int or Python object")
3230 #if not (target_type.is_pyobject
3231 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3232 # error(self.target.pos,
3233 # "Cannot assign integer to variable of type '%s'" % target_type)
3234 if target_type.is_numeric:
3235 self.is_py_target = 0
3236 self.loopvar_name = self.target.entry.cname
3237 self.py_loopvar_node = None
3238 else:
3239 self.is_py_target = 1
3240 c_loopvar_node = ExprNodes.TempNode(self.pos,
3241 PyrexTypes.c_long_type, env)
3242 c_loopvar_node.allocate_temps(env)
3243 self.loopvar_name = c_loopvar_node.result_code
3244 self.py_loopvar_node = \
3245 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3246 self.bound1.allocate_temps(env)
3247 self.bound2.allocate_temps(env)
3248 if self.step is not None:
3249 self.step.allocate_temps(env)
3250 if self.is_py_target:
3251 self.py_loopvar_node.allocate_temps(env)
3252 self.target.allocate_target_temps(env, self.py_loopvar_node)
3253 #self.target.release_target_temp(env)
3254 #self.py_loopvar_node.release_temp(env)
3255 self.body.analyse_expressions(env)
3256 if self.is_py_target:
3257 c_loopvar_node.release_temp(env)
3258 if self.else_clause:
3259 self.else_clause.analyse_expressions(env)
3260 self.bound1.release_temp(env)
3261 self.bound2.release_temp(env)
3262 if self.step is not None:
3263 self.step.release_temp(env)
3265 def generate_execution_code(self, code):
3266 old_loop_labels = code.new_loop_labels()
3267 self.bound1.generate_evaluation_code(code)
3268 self.bound2.generate_evaluation_code(code)
3269 offset, incop = self.relation_table[self.relation1]
3270 if self.step is not None:
3271 self.step.generate_evaluation_code(code)
3272 incop = "%s=%s" % (incop[0], self.step.result_code)
3273 code.putln(
3274 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3275 self.loopvar_name,
3276 self.bound1.result_code, offset,
3277 self.loopvar_name, self.relation2, self.bound2.result_code,
3278 self.loopvar_name, incop))
3279 if self.py_loopvar_node:
3280 self.py_loopvar_node.generate_evaluation_code(code)
3281 self.target.generate_assignment_code(self.py_loopvar_node, code)
3282 self.body.generate_execution_code(code)
3283 code.put_label(code.continue_label)
3284 code.putln("}")
3285 break_label = code.break_label
3286 code.set_loop_labels(old_loop_labels)
3287 if self.else_clause:
3288 code.putln("/*else*/ {")
3289 self.else_clause.generate_execution_code(code)
3290 code.putln("}")
3291 code.put_label(break_label)
3292 self.bound1.generate_disposal_code(code)
3293 self.bound2.generate_disposal_code(code)
3294 if self.step is not None:
3295 self.step.generate_disposal_code(code)
3297 relation_table = {
3298 # {relop : (initial offset, increment op)}
3299 '<=': ("", "++"),
3300 '<' : ("+1", "++"),
3301 '>=': ("", "--"),
3302 '>' : ("-1", "--")
3305 def annotate(self, code):
3306 self.target.annotate(code)
3307 self.bound1.annotate(code)
3308 self.bound2.annotate(code)
3309 if self.step:
3310 self.bound2.annotate(code)
3311 self.body.annotate(code)
3312 if self.else_clause:
3313 self.else_clause.annotate(code)
3316 class WithStatNode(StatNode):
3317 """
3318 Represents a Python with statement.
3320 This is only used at parse tree level; and is not present in
3321 analysis or generation phases.
3322 """
3323 # manager The with statement manager object
3324 # target Node (lhs expression)
3325 # body StatNode
3326 child_attrs = ["manager", "target", "body"]
3328 class TryExceptStatNode(StatNode):
3329 # try .. except statement
3331 # body StatNode
3332 # except_clauses [ExceptClauseNode]
3333 # else_clause StatNode or None
3334 # cleanup_list [Entry] temps to clean up on error
3336 child_attrs = ["body", "except_clauses", "else_clause"]
3338 def analyse_control_flow(self, env):
3339 env.start_branching(self.pos)
3340 self.body.analyse_control_flow(env)
3341 successful_try = env.control_flow # grab this for later
3342 env.next_branch(self.body.end_pos())
3343 env.finish_branching(self.body.end_pos())
3345 env.start_branching(self.except_clauses[0].pos)
3346 for except_clause in self.except_clauses:
3347 except_clause.analyse_control_flow(env)
3348 env.next_branch(except_clause.end_pos())
3350 # the else cause it executed only when the try clause finishes
3351 env.control_flow.incoming = successful_try
3352 if self.else_clause:
3353 self.else_clause.analyse_control_flow(env)
3354 env.finish_branching(self.end_pos())
3356 def analyse_declarations(self, env):
3357 self.body.analyse_declarations(env)
3358 for except_clause in self.except_clauses:
3359 except_clause.analyse_declarations(env)
3360 if self.else_clause:
3361 self.else_clause.analyse_declarations(env)
3362 self.gil_check(env)
3364 def analyse_expressions(self, env):
3366 self.body.analyse_expressions(env)
3367 self.cleanup_list = env.free_temp_entries[:]
3368 for except_clause in self.except_clauses:
3369 except_clause.analyse_expressions(env)
3370 if self.else_clause:
3371 self.else_clause.analyse_expressions(env)
3372 self.gil_check(env)
3374 gil_message = "Try-except statement"
3376 def generate_execution_code(self, code):
3377 old_error_label = code.new_error_label()
3378 our_error_label = code.error_label
3379 end_label = code.new_label()
3380 code.putln(
3381 "/*try:*/ {")
3382 self.body.generate_execution_code(code)
3383 code.putln(
3384 "}")
3385 code.error_label = old_error_label
3386 if self.else_clause:
3387 code.putln(
3388 "/*else:*/ {")
3389 self.else_clause.generate_execution_code(code)
3390 code.putln(
3391 "}")
3392 code.put_goto(end_label)
3393 code.put_label(our_error_label)
3394 code.put_var_xdecrefs_clear(self.cleanup_list)
3395 default_clause_seen = 0
3396 for except_clause in self.except_clauses:
3397 if not except_clause.pattern:
3398 default_clause_seen = 1
3399 else:
3400 if default_clause_seen:
3401 error(except_clause.pos, "Default except clause not last")
3402 except_clause.generate_handling_code(code, end_label)
3403 if not default_clause_seen:
3404 code.put_goto(code.error_label)
3405 code.put_label(end_label)
3407 def annotate(self, code):
3408 self.body.annotate(code)
3409 for except_node in self.except_clauses:
3410 except_node.annotate(code)
3411 if self.else_clause:
3412 self.else_clause.annotate(code)
3415 class ExceptClauseNode(Node):
3416 # Part of try ... except statement.
3418 # pattern ExprNode
3419 # target ExprNode or None
3420 # body StatNode
3421 # excinfo_target NameNode or None optional target for exception info
3422 # match_flag string result of exception match
3423 # exc_value ExcValueNode used internally
3424 # function_name string qualified name of enclosing function
3425 # exc_vars (string * 3) local exception variables
3427 # excinfo_target is never set by the parser, but can be set by a transform
3428 # in order to extract more extensive information about the exception as a
3429 # sys.exc_info()-style tuple into a target variable
3431 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
3433 exc_value = None
3434 excinfo_target = None
3436 def analyse_declarations(self, env):
3437 if self.target:
3438 self.target.analyse_target_declaration(env)
3439 if self.excinfo_target is not None:
3440 self.excinfo_target.analyse_target_declaration(env)
3441 self.body.analyse_declarations(env)
3443 def analyse_expressions(self, env):
3444 import ExprNodes
3445 genv = env.global_scope()
3446 self.function_name = env.qualified_name
3447 if self.pattern:
3448 self.pattern.analyse_expressions(env)
3449 self.pattern = self.pattern.coerce_to_pyobject(env)
3450 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
3451 self.pattern.release_temp(env)
3452 env.release_temp(self.match_flag)
3453 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
3454 if self.target:
3455 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
3456 self.exc_value.allocate_temps(env)
3457 self.target.analyse_target_expression(env, self.exc_value)
3458 if self.excinfo_target is not None:
3459 import ExprNodes
3460 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
3461 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
3462 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
3463 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
3464 ])
3465 self.excinfo_tuple.analyse_expressions(env)
3466 self.excinfo_tuple.allocate_temps(env)
3467 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
3469 self.body.analyse_expressions(env)
3470 for var in self.exc_vars:
3471 env.release_temp(var)
3472 env.use_utility_code(get_exception_utility_code)
3474 def generate_handling_code(self, code, end_label):
3475 code.mark_pos(self.pos)
3476 if self.pattern:
3477 self.pattern.generate_evaluation_code(code)
3478 code.putln(
3479 "%s = PyErr_ExceptionMatches(%s);" % (
3480 self.match_flag,
3481 self.pattern.py_result()))
3482 self.pattern.generate_disposal_code(code)
3483 code.putln(
3484 "if (%s) {" %
3485 self.match_flag)
3486 else:
3487 code.putln("/*except:*/ {")
3488 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
3489 # We always have to fetch the exception value even if
3490 # there is no target, because this also normalises the
3491 # exception and stores it in the thread state.
3492 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
3493 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
3494 code.error_goto(self.pos)))
3495 if self.target:
3496 self.exc_value.generate_evaluation_code(code)
3497 self.target.generate_assignment_code(self.exc_value, code)
3498 if self.excinfo_target is not None:
3499 self.excinfo_tuple.generate_evaluation_code(code)
3500 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
3502 old_exc_vars = code.exc_vars
3503 code.exc_vars = self.exc_vars
3504 self.body.generate_execution_code(code)
3505 code.exc_vars = old_exc_vars
3506 for var in self.exc_vars:
3507 code.putln("Py_DECREF(%s); %s = 0;" % (var, var))
3508 code.put_goto(end_label)
3509 code.putln(
3510 "}")
3512 def annotate(self, code):
3513 if self.pattern:
3514 self.pattern.annotate(code)
3515 if self.target:
3516 self.target.annotate(code)
3517 self.body.annotate(code)
3520 class TryFinallyStatNode(StatNode):
3521 # try ... finally statement
3523 # body StatNode
3524 # finally_clause StatNode
3526 # cleanup_list [Entry] temps to clean up on error
3528 # The plan is that we funnel all continue, break
3529 # return and error gotos into the beginning of the
3530 # finally block, setting a variable to remember which
3531 # one we're doing. At the end of the finally block, we
3532 # switch on the variable to figure out where to go.
3533 # In addition, if we're doing an error, we save the
3534 # exception on entry to the finally block and restore
3535 # it on exit.
3537 child_attrs = ["body", "finally_clause"]
3539 preserve_exception = 1
3541 disallow_continue_in_try_finally = 0
3542 # There doesn't seem to be any point in disallowing
3543 # continue in the try block, since we have no problem
3544 # handling it.
3546 def create_analysed(pos, env, body, finally_clause):
3547 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
3548 node.cleanup_list = []
3549 return node
3550 create_analysed = staticmethod(create_analysed)
3552 def analyse_control_flow(self, env):
3553 env.start_branching(self.pos)
3554 self.body.analyse_control_flow(env)
3555 env.next_branch(self.body.end_pos())
3556 env.finish_branching(self.body.end_pos())
3557 self.finally_clause.analyse_control_flow(env)
3559 def analyse_declarations(self, env):
3560 self.body.analyse_declarations(env)
3561 self.finally_clause.analyse_declarations(env)
3563 def analyse_expressions(self, env):
3564 self.body.analyse_expressions(env)
3565 self.cleanup_list = env.free_temp_entries[:]
3566 self.finally_clause.analyse_expressions(env)
3567 self.gil_check(env)
3569 gil_message = "Try-finally statement"
3571 def generate_execution_code(self, code):
3572 old_error_label = code.error_label
3573 old_labels = code.all_new_labels()
3574 new_labels = code.get_all_labels()
3575 new_error_label = code.error_label
3576 catch_label = code.new_label()
3577 code.putln(
3578 "/*try:*/ {")
3579 if self.disallow_continue_in_try_finally:
3580 was_in_try_finally = code.in_try_finally
3581 code.in_try_finally = 1
3582 self.body.generate_execution_code(code)
3583 if self.disallow_continue_in_try_finally:
3584 code.in_try_finally = was_in_try_finally
3585 code.putln(
3586 "}")
3587 code.putln(
3588 "/*finally:*/ {")
3589 cases_used = []
3590 error_label_used = 0
3591 for i, new_label in enumerate(new_labels):
3592 if new_label in code.labels_used:
3593 cases_used.append(i)
3594 if new_label == new_error_label:
3595 error_label_used = 1
3596 error_label_case = i
3597 if cases_used:
3598 code.putln(
3599 "int __pyx_why;")
3600 if error_label_used and self.preserve_exception:
3601 code.putln(
3602 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
3603 code.putln(
3604 "int %s;" % Naming.exc_lineno_name)
3605 code.use_label(catch_label)
3606 code.putln(
3607 "__pyx_why = 0; goto %s;" % catch_label)
3608 for i in cases_used:
3609 new_label = new_labels[i]
3610 #if new_label and new_label != "<try>":
3611 if new_label == new_error_label and self.preserve_exception:
3612 self.put_error_catcher(code,
3613 new_error_label, i+1, catch_label)
3614 else:
3615 code.putln(
3616 "%s: __pyx_why = %s; goto %s;" % (
3617 new_label,
3618 i+1,
3619 catch_label))
3620 code.put_label(catch_label)
3621 code.set_all_labels(old_labels)
3622 if error_label_used:
3623 code.new_error_label()
3624 finally_error_label = code.error_label
3625 self.finally_clause.generate_execution_code(code)
3626 if error_label_used:
3627 if finally_error_label in code.labels_used and self.preserve_exception:
3628 over_label = code.new_label()
3629 code.put_goto(over_label);
3630 code.put_label(finally_error_label)
3631 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
3632 for var in Naming.exc_vars:
3633 code.putln("Py_XDECREF(%s);" % var)
3634 code.putln("}")
3635 code.put_goto(old_error_label)
3636 code.put_label(over_label)
3637 code.error_label = old_error_label
3638 if cases_used:
3639 code.putln(
3640 "switch (__pyx_why) {")
3641 for i in cases_used:
3642 old_label = old_labels[i]
3643 if old_label == old_error_label and self.preserve_exception:
3644 self.put_error_uncatcher(code, i+1, old_error_label)
3645 else:
3646 code.use_label(old_label)
3647 code.putln(
3648 "case %s: goto %s;" % (
3649 i+1,
3650 old_label))
3651 code.putln(
3652 "}")
3653 code.putln(
3654 "}")
3656 def put_error_catcher(self, code, error_label, i, catch_label):
3657 code.putln(
3658 "%s: {" %
3659 error_label)
3660 code.putln(
3661 "__pyx_why = %s;" %
3662 i)
3663 code.put_var_xdecrefs_clear(self.cleanup_list)
3664 code.putln(
3665 "PyErr_Fetch(&%s, &%s, &%s);" %
3666 Naming.exc_vars)
3667 code.putln(
3668 "%s = %s;" % (
3669 Naming.exc_lineno_name, Naming.lineno_cname))
3670 #code.putln(
3671 # "goto %s;" %
3672 # catch_label)
3673 code.put_goto(catch_label)
3674 code.putln(
3675 "}")
3677 def put_error_uncatcher(self, code, i, error_label):
3678 code.putln(
3679 "case %s: {" %
3680 i)
3681 code.putln(
3682 "PyErr_Restore(%s, %s, %s);" %
3683 Naming.exc_vars)
3684 code.putln(
3685 "%s = %s;" % (
3686 Naming.lineno_cname, Naming.exc_lineno_name))
3687 for var in Naming.exc_vars:
3688 code.putln(
3689 "%s = 0;" %
3690 var)
3691 code.put_goto(error_label)
3692 code.putln(
3693 "}")
3695 def annotate(self, code):
3696 self.body.annotate(code)
3697 self.finally_clause.annotate(code)
3700 class GILStatNode(TryFinallyStatNode):
3701 # 'with gil' or 'with nogil' statement
3703 # state string 'gil' or 'nogil'
3705 child_attrs = []
3707 preserve_exception = 0
3709 def __init__(self, pos, state, body):
3710 self.state = state
3711 TryFinallyStatNode.__init__(self, pos,
3712 body = body,
3713 finally_clause = GILExitNode(pos, state = state))
3715 def analyse_expressions(self, env):
3716 was_nogil = env.nogil
3717 env.nogil = 1
3718 TryFinallyStatNode.analyse_expressions(self, env)
3719 env.nogil = was_nogil
3721 def gil_check(self, env):
3722 pass
3724 def generate_execution_code(self, code):
3725 code.putln("/*with %s:*/ {" % self.state)
3726 if self.state == 'gil':
3727 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
3728 else:
3729 code.putln("PyThreadState *_save;")
3730 code.putln("Py_UNBLOCK_THREADS")
3731 TryFinallyStatNode.generate_execution_code(self, code)
3732 code.putln("}")
3735 class GILExitNode(StatNode):
3736 # Used as the 'finally' block in a GILStatNode
3738 # state string 'gil' or 'nogil'
3740 child_attrs = []
3742 def analyse_expressions(self, env):
3743 pass
3745 def generate_execution_code(self, code):
3746 if self.state == 'gil':
3747 code.putln("PyGILState_Release();")
3748 else:
3749 code.putln("Py_BLOCK_THREADS")
3752 class CImportStatNode(StatNode):
3753 # cimport statement
3755 # module_name string Qualified name of module being imported
3756 # as_name string or None Name specified in "as" clause, if any
3758 child_attrs = []
3760 def analyse_declarations(self, env):
3761 if not env.is_module_scope:
3762 error(self.pos, "cimport only allowed at module level")
3763 return
3764 module_scope = env.find_module(self.module_name, self.pos)
3765 if "." in self.module_name:
3766 names = [EncodedString(name) for name in self.module_name.split(".")]
3767 top_name = names[0]
3768 top_module_scope = env.context.find_submodule(top_name)
3769 module_scope = top_module_scope
3770 for name in names[1:]:
3771 submodule_scope = module_scope.find_submodule(name)
3772 module_scope.declare_module(name, submodule_scope, self.pos)
3773 module_scope = submodule_scope
3774 if self.as_name:
3775 env.declare_module(self.as_name, module_scope, self.pos)
3776 else:
3777 env.declare_module(top_name, top_module_scope, self.pos)
3778 else:
3779 name = self.as_name or self.module_name
3780 env.declare_module(name, module_scope, self.pos)
3782 def analyse_expressions(self, env):
3783 pass
3785 def generate_execution_code(self, code):
3786 pass
3789 class FromCImportStatNode(StatNode):
3790 # from ... cimport statement
3792 # module_name string Qualified name of module
3793 # imported_names [(pos, name, as_name, kind)] Names to be imported
3795 child_attrs = []
3797 def analyse_declarations(self, env):
3798 if not env.is_module_scope:
3799 error(self.pos, "cimport only allowed at module level")
3800 return
3801 module_scope = env.find_module(self.module_name, self.pos)
3802 env.add_imported_module(module_scope)
3803 for pos, name, as_name, kind in self.imported_names:
3804 if name == "*":
3805 for local_name, entry in module_scope.entries.items():
3806 env.add_imported_entry(local_name, entry, pos)
3807 else:
3808 entry = module_scope.lookup(name)
3809 if entry:
3810 if kind and not self.declaration_matches(entry, kind):
3811 entry.redeclared(pos)
3812 else:
3813 if kind == 'struct' or kind == 'union':
3814 entry = module_scope.declare_struct_or_union(name,
3815 kind = kind, scope = None, typedef_flag = 0, pos = pos)
3816 elif kind == 'class':
3817 entry = module_scope.declare_c_class(name, pos = pos,
3818 module_name = self.module_name)
3819 else:
3820 error(pos, "Name '%s' not declared in module '%s'"
3821 % (name, self.module_name))
3823 if entry:
3824 local_name = as_name or name
3825 env.add_imported_entry(local_name, entry, pos)
3827 def declaration_matches(self, entry, kind):
3828 if not entry.is_type:
3829 return 0
3830 type = entry.type
3831 if kind == 'class':
3832 if not type.is_extension_type:
3833 return 0
3834 else:
3835 if not type.is_struct_or_union:
3836 return 0
3837 if kind <> type.kind:
3838 return 0
3839 return 1
3841 def analyse_expressions(self, env):
3842 pass
3844 def generate_execution_code(self, code):
3845 pass
3848 class FromImportStatNode(StatNode):
3849 # from ... import statement
3851 # module ImportNode
3852 # items [(string, NameNode)]
3853 # interned_items [(string, NameNode)]
3854 # item PyTempNode used internally
3855 # import_star boolean used internally
3857 child_attrs = ["module"]
3858 import_star = 0
3860 def analyse_declarations(self, env):
3861 for name, target in self.items:
3862 if name == "*":
3863 if not env.is_module_scope:
3864 error(self.pos, "import * only allowed at module level")
3865 return
3866 env.has_import_star = 1
3867 self.import_star = 1
3868 else:
3869 target.analyse_target_declaration(env)
3871 def analyse_expressions(self, env):
3872 import ExprNodes
3873 self.module.analyse_expressions(env)
3874 self.item = ExprNodes.PyTempNode(self.pos, env)
3875 self.item.allocate_temp(env)
3876 self.interned_items = []
3877 for name, target in self.items:
3878 if name == '*':
3879 for _, entry in env.entries.items():
3880 if not entry.is_type and entry.type.is_extension_type:
3881 env.use_utility_code(ExprNodes.type_test_utility_code)
3882 break
3883 else:
3884 self.interned_items.append(
3885 (env.intern_identifier(name), target))
3886 target.analyse_target_expression(env, None)
3887 #target.release_target_temp(env) # was release_temp ?!?
3888 self.module.release_temp(env)
3889 self.item.release_temp(env)
3891 def generate_execution_code(self, code):
3892 self.module.generate_evaluation_code(code)
3893 if self.import_star:
3894 code.putln(
3895 'if (%s(%s) < 0) %s;' % (
3896 Naming.import_star,
3897 self.module.py_result(),
3898 code.error_goto(self.pos)))
3899 for cname, target in self.interned_items:
3900 code.putln(
3901 '%s = PyObject_GetAttr(%s, %s); %s' % (
3902 self.item.result_code,
3903 self.module.py_result(),
3904 cname,
3905 code.error_goto_if_null(self.item.result_code, self.pos)))
3906 target.generate_assignment_code(self.item, code)
3907 self.module.generate_disposal_code(code)
3909 #------------------------------------------------------------------------------------
3911 # Runtime support code
3913 #------------------------------------------------------------------------------------
3915 utility_function_predeclarations = \
3916 """
3917 #ifdef __GNUC__
3918 #define INLINE __inline__
3919 #elif _WIN32
3920 #define INLINE __inline
3921 #else
3922 #define INLINE
3923 #endif
3925 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
3927 """ + """
3929 static int %(skip_dispatch_cname)s = 0;
3931 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
3933 if Options.gcc_branch_hints:
3934 branch_prediction_macros = \
3935 """
3936 #ifdef __GNUC__
3937 /* Test for GCC > 2.95 */
3938 #if __GNUC__ > 2 || \
3939 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
3940 #define likely(x) __builtin_expect(!!(x), 1)
3941 #define unlikely(x) __builtin_expect(!!(x), 0)
3942 #else /* __GNUC__ > 2 ... */
3943 #define likely(x) (x)
3944 #define unlikely(x) (x)
3945 #endif /* __GNUC__ > 2 ... */
3946 #else /* __GNUC__ */
3947 #define likely(x) (x)
3948 #define unlikely(x) (x)
3949 #endif /* __GNUC__ */
3950 """
3951 else:
3952 branch_prediction_macros = \
3953 """
3954 #define likely(x) (x)
3955 #define unlikely(x) (x)
3956 """
3958 #get_name_predeclaration = \
3959 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
3961 #get_name_interned_predeclaration = \
3962 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
3964 #------------------------------------------------------------------------------------
3966 printing_utility_code = [
3967 """
3968 static int __Pyx_Print(PyObject *, int); /*proto*/
3969 #if PY_MAJOR_VERSION >= 3
3970 static PyObject* %s = 0;
3971 static PyObject* %s = 0;
3972 #endif
3973 """ % (Naming.print_function, Naming.print_function_kwargs), r"""
3974 #if PY_MAJOR_VERSION < 3
3975 static PyObject *__Pyx_GetStdout(void) {
3976 PyObject *f = PySys_GetObject("stdout");
3977 if (!f) {
3978 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
3980 return f;
3983 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
3984 PyObject *f;
3985 PyObject* v;
3986 int i;
3988 if (!(f = __Pyx_GetStdout()))
3989 return -1;
3990 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
3991 if (PyFile_SoftSpace(f, 1)) {
3992 if (PyFile_WriteString(" ", f) < 0)
3993 return -1;
3995 v = PyTuple_GET_ITEM(arg_tuple, i);
3996 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
3997 return -1;
3998 if (PyString_Check(v)) {
3999 char *s = PyString_AsString(v);
4000 Py_ssize_t len = PyString_Size(v);
4001 if (len > 0 &&
4002 isspace(Py_CHARMASK(s[len-1])) &&
4003 s[len-1] != ' ')
4004 PyFile_SoftSpace(f, 0);
4007 if (newline) {
4008 if (PyFile_WriteString("\n", f) < 0)
4009 return -1;
4010 PyFile_SoftSpace(f, 0);
4012 return 0;
4015 #else /* Python 3 has a print function */
4016 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4017 PyObject* kwargs = 0;
4018 PyObject* result = 0;
4019 PyObject* end_string;
4020 if (!%(PRINT_FUNCTION)s) {
4021 %(PRINT_FUNCTION)s = PyObject_GetAttrString(%(BUILTINS)s, "print");
4022 if (!%(PRINT_FUNCTION)s)
4023 return -1;
4025 if (!newline) {
4026 if (!%(PRINT_KWARGS)s) {
4027 %(PRINT_KWARGS)s = PyDict_New();
4028 if (!%(PRINT_KWARGS)s)
4029 return -1;
4030 end_string = PyUnicode_FromStringAndSize(" ", 1);
4031 if (!end_string)
4032 return -1;
4033 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4034 Py_DECREF(end_string);
4035 return -1;
4037 Py_DECREF(end_string);
4039 kwargs = %(PRINT_KWARGS)s;
4041 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4042 if (!result)
4043 return -1;
4044 Py_DECREF(result);
4045 return 0;
4047 #endif
4048 """ % {'BUILTINS' : Naming.builtins_cname,
4049 'PRINT_FUNCTION' : Naming.print_function,
4050 'PRINT_KWARGS' : Naming.print_function_kwargs}
4053 #------------------------------------------------------------------------------------
4055 # The following function is based on do_raise() from ceval.c.
4057 raise_utility_code = [
4058 """
4059 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4060 ""","""
4061 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4062 Py_XINCREF(type);
4063 Py_XINCREF(value);
4064 Py_XINCREF(tb);
4065 /* First, check the traceback argument, replacing None with NULL. */
4066 if (tb == Py_None) {
4067 Py_DECREF(tb);
4068 tb = 0;
4070 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4071 PyErr_SetString(PyExc_TypeError,
4072 "raise: arg 3 must be a traceback or None");
4073 goto raise_error;
4075 /* Next, replace a missing value with None */
4076 if (value == NULL) {
4077 value = Py_None;
4078 Py_INCREF(value);
4080 #if PY_VERSION_HEX < 0x02050000
4081 if (!PyClass_Check(type))
4082 #else
4083 if (!PyType_Check(type))
4084 #endif
4086 /* Raising an instance. The value should be a dummy. */
4087 if (value != Py_None) {
4088 PyErr_SetString(PyExc_TypeError,
4089 "instance exception may not have a separate value");
4090 goto raise_error;
4092 /* Normalize to raise <class>, <instance> */
4093 Py_DECREF(value);
4094 value = type;
4095 #if PY_VERSION_HEX < 0x02050000
4096 if (PyInstance_Check(type)) {
4097 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4098 Py_INCREF(type);
4100 else {
4101 type = 0;
4102 PyErr_SetString(PyExc_TypeError,
4103 "raise: exception must be an old-style class or instance");
4104 goto raise_error;
4106 #else
4107 type = (PyObject*) Py_TYPE(type);
4108 Py_INCREF(type);
4109 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4110 PyErr_SetString(PyExc_TypeError,
4111 "raise: exception class must be a subclass of BaseException");
4112 goto raise_error;
4114 #endif
4116 PyErr_Restore(type, value, tb);
4117 return;
4118 raise_error:
4119 Py_XDECREF(value);
4120 Py_XDECREF(type);
4121 Py_XDECREF(tb);
4122 return;
4124 """]
4126 #------------------------------------------------------------------------------------
4128 reraise_utility_code = [
4129 """
4130 static void __Pyx_ReRaise(void); /*proto*/
4131 ""","""
4132 static void __Pyx_ReRaise(void) {
4133 PyThreadState *tstate = PyThreadState_Get();
4134 PyObject *type = tstate->exc_type;
4135 PyObject *value = tstate->exc_value;
4136 PyObject *tb = tstate->exc_traceback;
4137 Py_XINCREF(type);
4138 Py_XINCREF(value);
4139 Py_XINCREF(tb);
4140 PyErr_Restore(type, value, tb);
4142 """]
4144 #------------------------------------------------------------------------------------
4146 arg_type_test_utility_code = [
4147 """
4148 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name, int exact); /*proto*/
4149 ""","""
4150 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name, int exact) {
4151 if (!type) {
4152 PyErr_Format(PyExc_SystemError, "Missing type object");
4153 return 0;
4155 if (none_allowed && obj == Py_None) return 1;
4156 else if (exact) {
4157 if (Py_TYPE(obj) == type) return 1;
4159 else {
4160 if (PyObject_TypeCheck(obj, type)) return 1;
4162 PyErr_Format(PyExc_TypeError,
4163 "Argument '%s' has incorrect type (expected %s, got %s)",
4164 name, type->tp_name, Py_TYPE(obj)->tp_name);
4165 return 0;
4167 """]
4169 #------------------------------------------------------------------------------------
4171 # __Pyx_SplitStarArg splits the args tuple into two parts, one part
4172 # suitable for passing to PyArg_ParseTupleAndKeywords, and the other
4173 # containing any extra arguments. On success, replaces the borrowed
4174 # reference *args with references to a new tuple, and passes back a
4175 # new reference in *args2. Does not touch any of its arguments on
4176 # failure.
4178 get_stararg_utility_code = [
4179 """
4180 static INLINE int __Pyx_SplitStarArg(PyObject **args, Py_ssize_t nargs, PyObject **args2); /*proto*/
4181 ""","""
4182 static INLINE int __Pyx_SplitStarArg(
4183 PyObject **args,
4184 Py_ssize_t nargs,
4185 PyObject **args2)
4187 PyObject *args1 = 0;
4188 args1 = PyTuple_GetSlice(*args, 0, nargs);
4189 if (!args1) {
4190 *args2 = 0;
4191 return -1;
4193 *args2 = PyTuple_GetSlice(*args, nargs, PyTuple_GET_SIZE(*args));
4194 if (!*args2) {
4195 Py_DECREF(args1);
4196 return -1;
4198 *args = args1;
4199 return 0;
4201 """]
4203 #------------------------------------------------------------------------------------
4205 # __Pyx_RaiseArgtupleTooLong raises the correct exception when too
4206 # many positional arguments were found. This handles Py_ssize_t
4207 # formatting correctly.
4209 raise_argtuple_too_long_utility_code = [
4210 """
4211 static INLINE void __Pyx_RaiseArgtupleTooLong(Py_ssize_t num_expected, Py_ssize_t num_found); /*proto*/
4212 ""","""
4213 static INLINE void __Pyx_RaiseArgtupleTooLong(
4214 Py_ssize_t num_expected,
4215 Py_ssize_t num_found)
4217 const char* error_message =
4218 #if PY_VERSION_HEX < 0x02050000
4219 "function takes at most %d positional arguments (%d given)";
4220 #else
4221 "function takes at most %zd positional arguments (%zd given)";
4222 #endif
4223 PyErr_Format(PyExc_TypeError, error_message, num_expected, num_found);
4225 """]
4227 #------------------------------------------------------------------------------------
4229 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
4230 # were passed to a function, or if any keywords were passed to a
4231 # function that does not accept them.
4233 get_keyword_string_check_utility_code = [
4234 """
4235 static int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed); /*proto*/
4236 ""","""
4237 static int __Pyx_CheckKeywordStrings(
4238 PyObject *kwdict,
4239 const char* function_name,
4240 int kw_allowed)
4242 PyObject* key = 0;
4243 Py_ssize_t pos = 0;
4244 while (PyDict_Next(kwdict, &pos, &key, 0)) {
4245 #if PY_MAJOR_VERSION < 3
4246 if (unlikely(!PyString_Check(key))) {
4247 #else
4248 if (unlikely(!PyUnicode_Check(key))) {
4249 #endif
4250 PyErr_Format(PyExc_TypeError,
4251 "%s() keywords must be strings", function_name);
4252 return 0;
4255 if (unlikely(!kw_allowed) && unlikely(key)) {
4256 PyErr_Format(PyExc_TypeError,
4257 "'%s' is an invalid keyword argument for this function",
4258 #if PY_MAJOR_VERSION < 3
4259 PyString_AsString(key));
4260 #else
4261 PyUnicode_AsString(key));
4262 #endif
4263 return 0;
4265 return 1;
4267 """]
4269 #------------------------------------------------------------------------------------
4271 # __Pyx_SplitKeywords splits the kwds dict into two parts one part
4272 # suitable for passing to PyArg_ParseTupleAndKeywords, and the other
4273 # containing any extra arguments. On success, replaces the borrowed
4274 # reference *kwds with references to a new dict, and passes back a
4275 # new reference in *kwds2. Does not touch any of its arguments on
4276 # failure.
4278 # Any of *kwds and kwds2 may be 0 (but not kwds). If *kwds == 0, it
4279 # is not changed. If kwds2 == 0 and *kwds != 0, a new reference to
4280 # the same dictionary is passed back in *kwds.
4282 # If rqd_kwds is not 0, it is an array of booleans corresponding to
4283 # the names in kwd_list, indicating required keyword arguments. If
4284 # any of these are not present in kwds, an exception is raised.
4287 get_splitkeywords_utility_code = [
4288 """
4289 static int __Pyx_SplitKeywords(PyObject **kwds, char *kwd_list[], \
4290 PyObject **kwds2, char rqd_kwds[]); /*proto*/
4291 ""","""
4292 static int __Pyx_SplitKeywords(
4293 PyObject **kwds,
4294 char *kwd_list[],
4295 PyObject **kwds2,
4296 char rqd_kwds[])
4298 PyObject *s = 0, *x = 0, *kwds1 = 0;
4299 int i;
4300 char **p;
4302 if (*kwds) {
4303 kwds1 = PyDict_New();
4304 if (!kwds1)
4305 goto bad;
4306 *kwds2 = PyDict_Copy(*kwds);
4307 if (!*kwds2)
4308 goto bad;
4309 for (i = 0, p = kwd_list; *p; i++, p++) {
4310 #if PY_MAJOR_VERSION < 3
4311 s = PyString_FromString(*p);
4312 #else
4313 s = PyUnicode_FromString(*p);
4314 #endif
4315 x = PyDict_GetItem(*kwds, s);
4316 if (x) {
4317 if (PyDict_SetItem(kwds1, s, x) < 0)
4318 goto bad;
4319 if (PyDict_DelItem(*kwds2, s) < 0)
4320 goto bad;
4322 else if (rqd_kwds && rqd_kwds[i])
4323 goto missing_kwarg;
4324 Py_DECREF(s);
4326 s = 0;
4328 else {
4329 if (rqd_kwds) {
4330 for (i = 0, p = kwd_list; *p; i++, p++)
4331 if (rqd_kwds[i])
4332 goto missing_kwarg;
4334 *kwds2 = PyDict_New();
4335 if (!*kwds2)
4336 goto bad;
4339 *kwds = kwds1;
4340 return 0;
4341 missing_kwarg:
4342 PyErr_Format(PyExc_TypeError,
4343 "required keyword argument '%s' is missing", *p);
4344 bad:
4345 Py_XDECREF(s);
4346 Py_XDECREF(kwds1);
4347 Py_XDECREF(*kwds2);
4348 return -1;
4350 """]
4352 get_checkkeywords_utility_code = [
4353 """
4354 static INLINE int __Pyx_CheckRequiredKeywords(PyObject *kwds, char *kwd_list[],
4355 char rqd_kwds[]); /*proto*/
4356 ""","""
4357 static INLINE int __Pyx_CheckRequiredKeywords(
4358 PyObject *kwds,
4359 char *kwd_list[],
4360 char rqd_kwds[])
4362 int i;
4363 char **p;
4365 if (kwds) {
4366 for (i = 0, p = kwd_list; *p; i++, p++)
4367 if (rqd_kwds[i] && !PyDict_GetItemString(kwds, *p))
4368 goto missing_kwarg;
4370 else {
4371 for (i = 0, p = kwd_list; *p; i++, p++)
4372 if (rqd_kwds[i])
4373 goto missing_kwarg;
4376 return 0;
4377 missing_kwarg:
4378 PyErr_Format(PyExc_TypeError,
4379 "required keyword argument '%s' is missing", *p);
4380 return -1;
4382 """]
4384 #------------------------------------------------------------------------------------
4386 unraisable_exception_utility_code = [
4387 """
4388 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
4389 ""","""
4390 static void __Pyx_WriteUnraisable(const char *name) {
4391 PyObject *old_exc, *old_val, *old_tb;
4392 PyObject *ctx;
4393 PyErr_Fetch(&old_exc, &old_val, &old_tb);
4394 #if PY_MAJOR_VERSION < 3
4395 ctx = PyString_FromString(name);
4396 #else
4397 ctx = PyUnicode_FromString(name);
4398 #endif
4399 PyErr_Restore(old_exc, old_val, old_tb);
4400 if (!ctx)
4401 ctx = Py_None;
4402 PyErr_WriteUnraisable(ctx);
4404 """]
4406 #------------------------------------------------------------------------------------
4408 traceback_utility_code = [
4409 """
4410 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
4411 ""","""
4412 #include "compile.h"
4413 #include "frameobject.h"
4414 #include "traceback.h"
4416 static void __Pyx_AddTraceback(const char *funcname) {
4417 PyObject *py_srcfile = 0;
4418 PyObject *py_funcname = 0;
4419 PyObject *py_globals = 0;
4420 PyObject *empty_string = 0;
4421 PyCodeObject *py_code = 0;
4422 PyFrameObject *py_frame = 0;
4424 #if PY_MAJOR_VERSION < 3
4425 py_srcfile = PyString_FromString(%(FILENAME)s);
4426 #else
4427 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
4428 #endif
4429 if (!py_srcfile) goto bad;
4430 if (%(CLINENO)s) {
4431 #if PY_MAJOR_VERSION < 3
4432 py_funcname = PyString_FromFormat( "%%s (%%s:%%u)", funcname, %(CFILENAME)s, %(CLINENO)s);
4433 #else
4434 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%u)", funcname, %(CFILENAME)s, %(CLINENO)s);
4435 #endif
4437 else {
4438 #if PY_MAJOR_VERSION < 3
4439 py_funcname = PyString_FromString(funcname);
4440 #else
4441 py_funcname = PyUnicode_FromString(funcname);
4442 #endif
4444 if (!py_funcname) goto bad;
4445 py_globals = PyModule_GetDict(%(GLOBALS)s);
4446 if (!py_globals) goto bad;
4447 #if PY_MAJOR_VERSION < 3
4448 empty_string = PyString_FromStringAndSize("", 0);
4449 #else
4450 empty_string = PyBytes_FromStringAndSize("", 0);
4451 #endif
4452 if (!empty_string) goto bad;
4453 py_code = PyCode_New(
4454 0, /*int argcount,*/
4455 #if PY_MAJOR_VERSION >= 3
4456 0, /*int kwonlyargcount,*/
4457 #endif
4458 0, /*int nlocals,*/
4459 0, /*int stacksize,*/
4460 0, /*int flags,*/
4461 empty_string, /*PyObject *code,*/
4462 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
4463 %(EMPTY_TUPLE)s, /*PyObject *names,*/
4464 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
4465 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
4466 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
4467 py_srcfile, /*PyObject *filename,*/
4468 py_funcname, /*PyObject *name,*/
4469 %(LINENO)s, /*int firstlineno,*/
4470 empty_string /*PyObject *lnotab*/
4471 );
4472 if (!py_code) goto bad;
4473 py_frame = PyFrame_New(
4474 PyThreadState_Get(), /*PyThreadState *tstate,*/
4475 py_code, /*PyCodeObject *code,*/
4476 py_globals, /*PyObject *globals,*/
4477 0 /*PyObject *locals*/
4478 );
4479 if (!py_frame) goto bad;
4480 py_frame->f_lineno = %(LINENO)s;
4481 PyTraceBack_Here(py_frame);
4482 bad:
4483 Py_XDECREF(py_srcfile);
4484 Py_XDECREF(py_funcname);
4485 Py_XDECREF(empty_string);
4486 Py_XDECREF(py_code);
4487 Py_XDECREF(py_frame);
4489 """ % {
4490 'FILENAME': Naming.filename_cname,
4491 'LINENO': Naming.lineno_cname,
4492 'CFILENAME': Naming.cfilenm_cname,
4493 'CLINENO': Naming.clineno_cname,
4494 'GLOBALS': Naming.module_cname,
4495 'EMPTY_TUPLE' : Naming.empty_tuple,
4496 }]
4498 #------------------------------------------------------------------------------------
4500 set_vtable_utility_code = [
4501 """
4502 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
4503 ""","""
4504 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
4505 PyObject *pycobj = 0;
4506 int result;
4508 pycobj = PyCObject_FromVoidPtr(vtable, 0);
4509 if (!pycobj)
4510 goto bad;
4511 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
4512 goto bad;
4513 result = 0;
4514 goto done;
4516 bad:
4517 result = -1;
4518 done:
4519 Py_XDECREF(pycobj);
4520 return result;
4522 """]
4524 #------------------------------------------------------------------------------------
4526 get_vtable_utility_code = [
4527 """
4528 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
4529 """,r"""
4530 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
4531 int result;
4532 PyObject *pycobj;
4534 pycobj = PyMapping_GetItemString(dict, "__pyx_vtable__");
4535 if (!pycobj)
4536 goto bad;
4537 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
4538 if (!*(void **)vtabptr)
4539 goto bad;
4540 result = 0;
4541 goto done;
4543 bad:
4544 result = -1;
4545 done:
4546 Py_XDECREF(pycobj);
4547 return result;
4549 """]
4551 #------------------------------------------------------------------------------------
4553 init_string_tab_utility_code = [
4554 """
4555 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
4556 ""","""
4557 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
4558 while (t->p) {
4559 #if PY_MAJOR_VERSION < 3
4560 if (t->is_unicode && (!t->is_identifier)) {
4561 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
4562 } else if (t->intern) {
4563 *t->p = PyString_InternFromString(t->s);
4564 } else {
4565 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
4567 #else /* Python 3+ has unicode identifiers */
4568 if (t->is_identifier || (t->is_unicode && t->intern)) {
4569 *t->p = PyUnicode_InternFromString(t->s);
4570 } else if (t->is_unicode) {
4571 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
4572 } else {
4573 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
4575 #endif
4576 if (!*t->p)
4577 return -1;
4578 ++t;
4580 return 0;
4582 """]
4584 #------------------------------------------------------------------------------------
4586 get_exception_utility_code = [
4587 """
4588 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
4589 ""","""
4590 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
4591 PyObject *tmp_type, *tmp_value, *tmp_tb;
4592 PyThreadState *tstate = PyThreadState_Get();
4593 PyErr_Fetch(type, value, tb);
4594 PyErr_NormalizeException(type, value, tb);
4595 if (PyErr_Occurred())
4596 goto bad;
4597 Py_INCREF(*type);
4598 Py_INCREF(*value);
4599 Py_INCREF(*tb);
4600 tmp_type = tstate->exc_type;
4601 tmp_value = tstate->exc_value;
4602 tmp_tb = tstate->exc_traceback;
4603 tstate->exc_type = *type;
4604 tstate->exc_value = *value;
4605 tstate->exc_traceback = *tb;
4606 /* Make sure tstate is in a consistent state when we XDECREF
4607 these objects (XDECREF may run arbitrary code). */
4608 Py_XDECREF(tmp_type);
4609 Py_XDECREF(tmp_value);
4610 Py_XDECREF(tmp_tb);
4611 return 0;
4612 bad:
4613 Py_XDECREF(*type);
4614 Py_XDECREF(*value);
4615 Py_XDECREF(*tb);
4616 return -1;
4619 """]
4621 #------------------------------------------------------------------------------------