Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 908:7a1defb8455d

Function pointers as arguments, better errors for unnamed arguments.
author Robert Bradshaw <robertwb@math.washington.edu>
date Sat Aug 02 23:35:16 2008 -0700 (3 years ago)
parents 8b22ff3db9f7
children 0f6d684807e3 5c0621a6c0ae
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 raise RuntimeError
366 # May have mistaken the name for the type.
367 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
368 error(self.pos, "Missing argument name.")
369 elif base_type.is_void:
370 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
371 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
372 base_type = py_object_type
373 self.type = base_type
374 return self, base_type
376 class CPtrDeclaratorNode(CDeclaratorNode):
377 # base CDeclaratorNode
379 child_attrs = ["base"]
381 def analyse(self, base_type, env, nonempty = 0):
382 if base_type.is_pyobject:
383 error(self.pos,
384 "Pointer base type cannot be a Python object")
385 ptr_type = PyrexTypes.c_ptr_type(base_type)
386 return self.base.analyse(ptr_type, env, nonempty = nonempty)
388 class CArrayDeclaratorNode(CDeclaratorNode):
389 # base CDeclaratorNode
390 # dimension ExprNode
392 child_attrs = ["base", "dimension"]
394 def analyse(self, base_type, env, nonempty = 0):
395 if self.dimension:
396 self.dimension.analyse_const_expression(env)
397 if not self.dimension.type.is_int:
398 error(self.dimension.pos, "Array dimension not integer")
399 size = self.dimension.result_code
400 else:
401 size = None
402 if not base_type.is_complete():
403 error(self.pos,
404 "Array element type '%s' is incomplete" % base_type)
405 if base_type.is_pyobject:
406 error(self.pos,
407 "Array element cannot be a Python object")
408 if base_type.is_cfunction:
409 error(self.pos,
410 "Array element cannot be a function")
411 array_type = PyrexTypes.c_array_type(base_type, size)
412 return self.base.analyse(array_type, env, nonempty = nonempty)
415 class CFuncDeclaratorNode(CDeclaratorNode):
416 # base CDeclaratorNode
417 # args [CArgDeclNode]
418 # has_varargs boolean
419 # exception_value ConstNode
420 # exception_check boolean True if PyErr_Occurred check needed
421 # nogil boolean Can be called without gil
422 # with_gil boolean Acquire gil around function body
424 child_attrs = ["base", "args", "exception_value"]
426 overridable = 0
427 optional_arg_count = 0
429 def analyse(self, return_type, env, nonempty = 0):
430 func_type_args = []
431 for arg_node in self.args:
432 name_declarator, type = arg_node.analyse(env)
433 name = name_declarator.name
434 if name_declarator.cname:
435 error(self.pos,
436 "Function argument cannot have C name specification")
437 # Turn *[] argument into **
438 if type.is_array:
439 type = PyrexTypes.c_ptr_type(type.base_type)
440 # Catch attempted C-style func(void) decl
441 if type.is_void:
442 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
443 # if type.is_pyobject and self.nogil:
444 # error(self.pos,
445 # "Function with Python argument cannot be declared nogil")
446 func_type_args.append(
447 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
448 if arg_node.default:
449 self.optional_arg_count += 1
450 elif self.optional_arg_count:
451 error(self.pos, "Non-default argument follows default argument")
453 if self.optional_arg_count:
454 scope = StructOrUnionScope()
455 scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
456 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
457 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
458 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
459 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
460 kind = 'struct',
461 scope = scope,
462 typedef_flag = 0,
463 pos = self.pos,
464 cname = struct_cname)
465 self.op_args_struct.defined_in_pxd = 1
466 self.op_args_struct.used = 1
468 exc_val = None
469 exc_check = 0
470 if return_type.is_pyobject \
471 and (self.exception_value or self.exception_check) \
472 and self.exception_check != '+':
473 error(self.pos,
474 "Exception clause not allowed for function returning Python object")
475 else:
476 if self.exception_value:
477 self.exception_value.analyse_const_expression(env)
478 if self.exception_check == '+':
479 exc_val_type = self.exception_value.type
480 if not exc_val_type.is_error and \
481 not exc_val_type.is_pyobject and \
482 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
483 error(self.exception_value.pos,
484 "Exception value must be a Python exception or cdef function with no arguments.")
485 exc_val = self.exception_value
486 else:
487 exc_val = self.exception_value.result_code
488 if not return_type.assignable_from(self.exception_value.type):
489 error(self.exception_value.pos,
490 "Exception value incompatible with function return type")
491 exc_check = self.exception_check
492 if return_type.is_array:
493 error(self.pos,
494 "Function cannot return an array")
495 if return_type.is_cfunction:
496 error(self.pos,
497 "Function cannot return a function")
498 func_type = PyrexTypes.CFuncType(
499 return_type, func_type_args, self.has_varargs,
500 optional_arg_count = self.optional_arg_count,
501 exception_value = exc_val, exception_check = exc_check,
502 calling_convention = self.base.calling_convention,
503 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
504 if self.optional_arg_count:
505 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
506 return self.base.analyse(func_type, env)
509 class CArgDeclNode(Node):
510 # Item in a function declaration argument list.
511 #
512 # base_type CBaseTypeNode
513 # declarator CDeclaratorNode
514 # not_none boolean Tagged with 'not None'
515 # default ExprNode or None
516 # default_entry Symtab.Entry Entry for the variable holding the default value
517 # default_result_code string cname or code fragment for default value
518 # is_self_arg boolean Is the "self" arg of an extension type method
519 # is_kw_only boolean Is a keyword-only argument
521 child_attrs = ["base_type", "declarator", "default"]
523 is_self_arg = 0
524 is_generic = 1
526 def analyse(self, env, nonempty = 0):
527 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
528 base_type = self.base_type.analyse(env)
529 return self.declarator.analyse(base_type, env, nonempty = nonempty)
531 def annotate(self, code):
532 if self.default:
533 self.default.annotate(code)
536 class CBaseTypeNode(Node):
537 # Abstract base class for C base type nodes.
538 #
539 # Processing during analyse_declarations phase:
540 #
541 # analyse
542 # Returns the type.
544 pass
546 class CSimpleBaseTypeNode(CBaseTypeNode):
547 # name string
548 # module_path [string] Qualifying name components
549 # is_basic_c_type boolean
550 # signed boolean
551 # longness integer
552 # is_self_arg boolean Is self argument of C method
554 child_attrs = []
556 def analyse(self, env):
557 # Return type descriptor.
558 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
559 type = None
560 if self.is_basic_c_type:
561 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
562 if not type:
563 error(self.pos, "Unrecognised type modifier combination")
564 elif self.name == "object" and not self.module_path:
565 type = py_object_type
566 elif self.name is None:
567 if self.is_self_arg and env.is_c_class_scope:
568 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
569 type = env.parent_type
570 else:
571 type = py_object_type
572 else:
573 scope = env.find_imported_module(self.module_path, self.pos)
574 if scope:
575 if scope.is_c_class_scope:
576 scope = scope.global_scope()
577 entry = scope.find(self.name, self.pos)
578 if entry and entry.is_type:
579 type = entry.type
580 else:
581 error(self.pos, "'%s' is not a type identifier" % self.name)
582 if type:
583 return type
584 else:
585 return PyrexTypes.error_type
587 class CBufferAccessTypeNode(Node):
588 # After parsing:
589 # positional_args [ExprNode] List of positional arguments
590 # keyword_args DictNode Keyword arguments
591 # base_type_node CBaseTypeNode
593 # After PostParse:
594 # dtype_node CBaseTypeNode
595 # ndim int
597 # After analysis:
598 # type PyrexType.PyrexType
600 child_attrs = ["base_type_node", "positional_args", "keyword_args",
601 "dtype_node"]
603 dtype_node = None
605 def analyse(self, env):
606 base_type = self.base_type_node.analyse(env)
607 dtype = self.dtype_node.analyse(env)
608 self.type = PyrexTypes.BufferType(base_type, dtype=dtype, ndim=self.ndim,
609 mode=self.mode)
610 return self.type
612 class CComplexBaseTypeNode(CBaseTypeNode):
613 # base_type CBaseTypeNode
614 # declarator CDeclaratorNode
616 child_attrs = ["base_type", "declarator"]
618 def analyse(self, env):
619 base = self.base_type.analyse(env)
620 _, type = self.declarator.analyse(base, env)
621 return type
624 class CVarDefNode(StatNode):
625 # C variable definition or forward/extern function declaration.
626 #
627 # visibility 'private' or 'public' or 'extern'
628 # base_type CBaseTypeNode
629 # declarators [CDeclaratorNode]
630 # in_pxd boolean
631 # api boolean
632 # need_properties [entry]
634 child_attrs = ["base_type", "declarators"]
635 need_properties = ()
637 def analyse_declarations(self, env, dest_scope = None):
638 if not dest_scope:
639 dest_scope = env
640 self.dest_scope = dest_scope
641 base_type = self.base_type.analyse(env)
643 if (dest_scope.is_c_class_scope
644 and self.visibility == 'public'
645 and base_type.is_pyobject
646 and (base_type.is_builtin_type or base_type.is_extension_type)):
647 self.need_properties = []
648 need_property = True
649 visibility = 'private'
650 else:
651 need_property = False
652 visibility = self.visibility
654 for declarator in self.declarators:
655 name_declarator, type = declarator.analyse(base_type, env)
656 if not type.is_complete():
657 if not (self.visibility == 'extern' and type.is_array):
658 error(declarator.pos,
659 "Variable type '%s' is incomplete" % type)
660 if self.visibility == 'extern' and type.is_pyobject:
661 error(declarator.pos,
662 "Python object cannot be declared extern")
663 name = name_declarator.name
664 cname = name_declarator.cname
665 if name == '':
666 error(declarator.pos, "Missing name in declaration.")
667 return
668 if type.is_cfunction:
669 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
670 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
671 api = self.api)
672 else:
673 if self.in_pxd and self.visibility != 'extern':
674 error(self.pos,
675 "Only 'extern' C variable declaration allowed in .pxd file")
676 entry = dest_scope.declare_var(name, type, declarator.pos,
677 cname = cname, visibility = visibility, is_cdef = 1)
678 if need_property:
679 self.need_properties.append(entry)
680 entry.needs_property = 1
683 class CStructOrUnionDefNode(StatNode):
684 # name string
685 # cname string or None
686 # kind "struct" or "union"
687 # typedef_flag boolean
688 # visibility "public" or "private"
689 # in_pxd boolean
690 # attributes [CVarDefNode] or None
691 # entry Entry
693 child_attrs = ["attributes"]
695 def analyse_declarations(self, env):
696 scope = None
697 if self.attributes is not None:
698 scope = StructOrUnionScope(self.name)
699 self.entry = env.declare_struct_or_union(
700 self.name, self.kind, scope, self.typedef_flag, self.pos,
701 self.cname, visibility = self.visibility)
702 if self.attributes is not None:
703 if self.in_pxd and not env.in_cinclude:
704 self.entry.defined_in_pxd = 1
705 for attr in self.attributes:
706 attr.analyse_declarations(env, scope)
708 def analyse_expressions(self, env):
709 pass
711 def generate_execution_code(self, code):
712 pass
715 class CEnumDefNode(StatNode):
716 # name string or None
717 # cname string or None
718 # items [CEnumDefItemNode]
719 # typedef_flag boolean
720 # visibility "public" or "private"
721 # in_pxd boolean
722 # entry Entry
724 child_attrs = ["items"]
726 def analyse_declarations(self, env):
727 self.entry = env.declare_enum(self.name, self.pos,
728 cname = self.cname, typedef_flag = self.typedef_flag,
729 visibility = self.visibility)
730 if self.items is not None:
731 if self.in_pxd and not env.in_cinclude:
732 self.entry.defined_in_pxd = 1
733 for item in self.items:
734 item.analyse_declarations(env, self.entry)
736 def analyse_expressions(self, env):
737 if self.visibility == 'public':
738 self.temp = env.allocate_temp_pyobject()
739 env.release_temp(self.temp)
741 def generate_execution_code(self, code):
742 if self.visibility == 'public':
743 for item in self.entry.enum_values:
744 code.putln("%s = PyInt_FromLong(%s); %s" % (
745 self.temp,
746 item.cname,
747 code.error_goto_if_null(self.temp, item.pos)))
748 code.putln('if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
749 Naming.module_cname,
750 item.name,
751 self.temp,
752 code.error_goto(item.pos)))
753 code.putln("%s = 0;" % self.temp)
756 class CEnumDefItemNode(StatNode):
757 # name string
758 # cname string or None
759 # value ExprNode or None
761 child_attrs = ["value"]
763 def analyse_declarations(self, env, enum_entry):
764 if self.value:
765 self.value.analyse_const_expression(env)
766 if not self.value.type.is_int:
767 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
768 self.value.analyse_const_expression(env)
769 value = self.value.result_code
770 else:
771 value = self.name
772 entry = env.declare_const(self.name, enum_entry.type,
773 value, self.pos, cname = self.cname)
774 enum_entry.enum_values.append(entry)
777 class CTypeDefNode(StatNode):
778 # base_type CBaseTypeNode
779 # declarator CDeclaratorNode
780 # visibility "public" or "private"
781 # in_pxd boolean
783 child_attrs = ["base_type", "declarator"]
785 def analyse_declarations(self, env):
786 base = self.base_type.analyse(env)
787 name_declarator, type = self.declarator.analyse(base, env)
788 name = name_declarator.name
789 cname = name_declarator.cname
790 entry = env.declare_typedef(name, type, self.pos,
791 cname = cname, visibility = self.visibility)
792 if self.in_pxd and not env.in_cinclude:
793 entry.defined_in_pxd = 1
795 def analyse_expressions(self, env):
796 pass
797 def generate_execution_code(self, code):
798 pass
801 class FuncDefNode(StatNode, BlockNode):
802 # Base class for function definition nodes.
803 #
804 # return_type PyrexType
805 # #filename string C name of filename string const
806 # entry Symtab.Entry
807 # needs_closure boolean Whether or not this function has inner functions/classes/yield
809 py_func = None
810 assmt = None
811 needs_closure = False
813 def analyse_default_values(self, env):
814 genv = env.global_scope()
815 for arg in self.args:
816 if arg.default:
817 if arg.is_generic:
818 if not hasattr(arg, 'default_entry'):
819 arg.default.analyse_types(env)
820 arg.default = arg.default.coerce_to(arg.type, genv)
821 if arg.default.is_literal:
822 arg.default_entry = arg.default
823 arg.default_result_code = arg.default.calculate_result_code()
824 if arg.default.type != arg.type and not arg.type.is_int:
825 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
826 else:
827 arg.default.allocate_temps(genv)
828 arg.default_entry = genv.add_default_value(arg.type)
829 arg.default_entry.used = 1
830 arg.default_result_code = arg.default_entry.cname
831 else:
832 error(arg.pos,
833 "This argument cannot have a default value")
834 arg.default = None
836 def need_gil_acquisition(self, lenv):
837 return 0
839 def create_local_scope(self, env):
840 genv = env
841 while env.is_py_class_scope or env.is_c_class_scope:
842 env = env.outer_scope
843 if self.needs_closure:
844 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
845 else:
846 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
847 lenv.return_type = self.return_type
848 type = self.entry.type
849 if type.is_cfunction:
850 lenv.nogil = type.nogil and not type.with_gil
851 self.local_scope = lenv
852 return lenv
854 def generate_function_definitions(self, env, code, transforms):
855 import Buffer
857 lenv = self.local_scope
859 # Generate C code for header and body of function
860 code.enter_cfunc_scope()
861 code.return_from_error_cleanup_label = code.new_label()
863 # ----- Top-level constants used by this function
864 code.mark_pos(self.pos)
865 self.generate_interned_num_decls(lenv, code)
866 self.generate_interned_string_decls(lenv, code)
867 self.generate_py_string_decls(lenv, code)
868 self.generate_cached_builtins_decls(lenv, code)
869 #code.putln("")
870 #code.put_var_declarations(lenv.const_entries, static = 1)
871 self.generate_const_definitions(lenv, code)
872 # ----- Function header
873 code.putln("")
874 if self.py_func:
875 self.py_func.generate_function_header(code,
876 with_pymethdef = env.is_py_class_scope,
877 proto_only=True)
878 self.generate_function_header(code,
879 with_pymethdef = env.is_py_class_scope)
880 # ----- Local variable declarations
881 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
882 self.generate_argument_declarations(lenv, code)
883 if self.needs_closure:
884 code.putln("/* TODO: declare and create scope object */")
885 code.put_var_declarations(lenv.var_entries)
886 init = ""
887 if not self.return_type.is_void:
888 code.putln(
889 "%s%s;" %
890 (self.return_type.declaration_code(
891 Naming.retval_cname),
892 init))
893 tempvardecl_code = code.insertion_point()
894 self.generate_keyword_list(code)
895 # ----- Extern library function declarations
896 lenv.generate_library_function_declarations(code)
897 # ----- GIL acquisition
898 acquire_gil = self.need_gil_acquisition(lenv)
899 if acquire_gil:
900 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
901 # ----- Fetch arguments
902 self.generate_argument_parsing_code(env, code)
903 # If an argument is assigned to in the body, we must
904 # incref it to properly keep track of refcounts.
905 for entry in lenv.arg_entries:
906 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
907 code.put_var_incref(entry)
908 if entry.type.is_buffer:
909 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
910 # ----- Initialise local variables
911 for entry in lenv.var_entries:
912 if entry.type.is_pyobject and entry.init_to_none and entry.used:
913 code.put_init_var_to_py_none(entry)
914 # ----- Check and convert arguments
915 self.generate_argument_type_tests(code)
916 # ----- Function body
917 self.body.generate_execution_code(code)
918 # ----- Default return value
919 code.putln("")
920 if self.return_type.is_pyobject:
921 #if self.return_type.is_extension_type:
922 # lhs = "(PyObject *)%s" % Naming.retval_cname
923 #else:
924 lhs = Naming.retval_cname
925 code.put_init_to_py_none(lhs, self.return_type)
926 else:
927 val = self.return_type.default_value
928 if val:
929 code.putln("%s = %s;" % (Naming.retval_cname, val))
930 # ----- Error cleanup
931 if code.error_label in code.labels_used:
932 code.put_goto(code.return_label)
933 code.put_label(code.error_label)
934 code.put_var_xdecrefs(lenv.temp_entries)
936 # Clean up buffers -- this calls a Python function
937 # so need to save and restore error state
938 buffers_present = len(lenv.buffer_entries) > 0
939 if buffers_present:
940 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
941 code.putln("PyErr_Fetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
942 for entry in lenv.buffer_entries:
943 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
944 #code.putln("%s = 0;" % entry.cname)
945 code.putln("PyErr_Restore(__pyx_type, __pyx_value, __pyx_tb);}")
947 err_val = self.error_value()
948 exc_check = self.caller_will_check_exceptions()
949 if err_val is not None or exc_check:
950 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
951 else:
952 code.putln(
953 '__Pyx_WriteUnraisable("%s");' %
954 self.entry.qualified_name)
955 env.use_utility_code(unraisable_exception_utility_code)
956 default_retval = self.return_type.default_value
957 if err_val is None and default_retval:
958 err_val = default_retval
959 if err_val is not None:
960 code.putln(
961 "%s = %s;" % (
962 Naming.retval_cname,
963 err_val))
964 if buffers_present:
965 # Else, non-error return will be an empty clause
966 code.put_goto(code.return_from_error_cleanup_label)
968 # ----- Non-error return cleanup
969 # PS! If adding something here, modify the conditions for the
970 # goto statement in error cleanup above
971 code.put_label(code.return_label)
972 for entry in lenv.buffer_entries:
973 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
974 # ----- Return cleanup for both error and no-error return
975 code.put_label(code.return_from_error_cleanup_label)
976 if not Options.init_local_none:
977 for entry in lenv.var_entries:
978 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
979 entry.xdecref_cleanup = 1
980 code.put_var_decrefs(lenv.var_entries, used_only = 1)
981 # Decref any increfed args
982 for entry in lenv.arg_entries:
983 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
984 code.put_var_decref(entry)
985 self.put_stararg_decrefs(code)
986 if acquire_gil:
987 code.putln("PyGILState_Release(_save);")
988 # code.putln("/* TODO: decref scope object */")
989 # ----- Return
990 if not self.return_type.is_void:
991 code.putln("return %s;" % Naming.retval_cname)
992 code.putln("}")
993 # ----- Go back and insert temp variable declarations
994 tempvardecl_code.put_var_declarations(lenv.temp_entries)
995 tempvardecl_code.put_temp_declarations(code.func)
996 # ----- Python version
997 code.exit_cfunc_scope()
998 if self.py_func:
999 self.py_func.generate_function_definitions(env, code, transforms)
1000 self.generate_optarg_wrapper_function(env, code)
1002 def put_stararg_decrefs(self, code):
1003 pass
1005 def declare_argument(self, env, arg):
1006 if arg.type.is_void:
1007 error(arg.pos, "Invalid use of 'void'")
1008 elif not arg.type.is_complete() and not arg.type.is_array:
1009 error(arg.pos,
1010 "Argument type '%s' is incomplete" % arg.type)
1011 return env.declare_arg(arg.name, arg.type, arg.pos)
1012 def generate_optarg_wrapper_function(self, env, code):
1013 pass
1015 def generate_execution_code(self, code):
1016 # Evaluate and store argument default values
1017 for arg in self.args:
1018 default = arg.default
1019 if default:
1020 if not default.is_literal:
1021 default.generate_evaluation_code(code)
1022 default.make_owned_reference(code)
1023 code.putln(
1024 "%s = %s;" % (
1025 arg.default_entry.cname,
1026 default.result_as(arg.default_entry.type)))
1027 if default.is_temp and default.type.is_pyobject:
1028 code.putln(
1029 "%s = 0;" %
1030 default.result_code)
1031 # For Python class methods, create and store function object
1032 if self.assmt:
1033 self.assmt.generate_execution_code(code)
1037 class CFuncDefNode(FuncDefNode):
1038 # C function definition.
1040 # modifiers ['inline']
1041 # visibility 'private' or 'public' or 'extern'
1042 # base_type CBaseTypeNode
1043 # declarator CDeclaratorNode
1044 # body StatListNode
1045 # api boolean
1047 # with_gil boolean Acquire GIL around body
1048 # type CFuncType
1049 # py_func wrapper for calling from Python
1051 child_attrs = ["base_type", "declarator", "body", "py_func"]
1053 def unqualified_name(self):
1054 return self.entry.name
1056 def analyse_declarations(self, env):
1057 base_type = self.base_type.analyse(env)
1058 name_declarator, type = self.declarator.analyse(base_type, env, self.body is not None)
1059 if not type.is_cfunction:
1060 error(self.pos,
1061 "Suite attached to non-function declaration")
1062 # Remember the actual type according to the function header
1063 # written here, because the type in the symbol table entry
1064 # may be different if we're overriding a C method inherited
1065 # from the base type of an extension type.
1066 self.type = type
1067 type.is_overridable = self.overridable
1068 declarator = self.declarator
1069 while not hasattr(declarator, 'args'):
1070 declarator = declarator.base
1071 self.args = declarator.args
1072 for formal_arg, type_arg in zip(self.args, type.args):
1073 formal_arg.type = type_arg.type
1074 formal_arg.cname = type_arg.cname
1075 name = name_declarator.name
1076 cname = name_declarator.cname
1077 self.entry = env.declare_cfunction(
1078 name, type, self.pos,
1079 cname = cname, visibility = self.visibility,
1080 defining = self.body is not None,
1081 api = self.api)
1082 self.return_type = type.return_type
1084 if self.overridable:
1085 import ExprNodes
1086 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1087 self.py_func = DefNode(pos = self.pos,
1088 name = self.entry.name,
1089 args = self.args,
1090 star_arg = None,
1091 starstar_arg = None,
1092 doc = self.doc,
1093 body = py_func_body,
1094 is_wrapper = 1)
1095 self.py_func.is_module_scope = env.is_module_scope
1096 self.py_func.analyse_declarations(env)
1097 self.entry.as_variable = self.py_func.entry
1098 # Reset scope entry the above cfunction
1099 env.entries[name] = self.entry
1100 self.py_func.interned_attr_cname = env.intern_identifier(
1101 self.py_func.entry.name)
1102 if not env.is_module_scope or Options.lookup_module_cpdef:
1103 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1104 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1106 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1107 import ExprNodes
1108 args = self.type.args
1109 if omit_optional_args:
1110 args = args[:len(args) - self.type.optional_arg_count]
1111 arg_names = [arg.name for arg in args]
1112 if is_module_scope:
1113 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1114 else:
1115 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1116 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1117 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1118 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)
1119 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1121 def declare_arguments(self, env):
1122 for arg in self.type.args:
1123 if not arg.name:
1124 error(arg.pos, "Missing argument name")
1125 self.declare_argument(env, arg)
1127 def need_gil_acquisition(self, lenv):
1128 type = self.type
1129 with_gil = self.type.with_gil
1130 if type.nogil and not with_gil:
1131 if type.return_type.is_pyobject:
1132 error(self.pos,
1133 "Function with Python return type cannot be declared nogil")
1134 for entry in lenv.var_entries + lenv.temp_entries:
1135 if entry.type.is_pyobject:
1136 error(self.pos, "Function declared nogil has Python locals or temporaries")
1137 return with_gil
1139 def analyse_expressions(self, env):
1140 self.analyse_default_values(env)
1141 if self.overridable:
1142 self.py_func.analyse_expressions(env)
1144 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1):
1145 arg_decls = []
1146 type = self.type
1147 visibility = self.entry.visibility
1148 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1149 arg_decls.append(arg.declaration_code())
1150 if type.optional_arg_count and with_opt_args:
1151 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1152 if type.has_varargs:
1153 arg_decls.append("...")
1154 if not arg_decls:
1155 arg_decls = ["void"]
1156 cname = self.entry.func_cname
1157 if not with_opt_args:
1158 cname += Naming.no_opt_args
1159 entity = type.function_header_code(cname, string.join(arg_decls, ", "))
1160 if visibility == 'public':
1161 dll_linkage = "DL_EXPORT"
1162 else:
1163 dll_linkage = None
1164 header = self.return_type.declaration_code(entity,
1165 dll_linkage = dll_linkage)
1166 if visibility != 'private':
1167 storage_class = "%s " % Naming.extern_c_macro
1168 else:
1169 storage_class = "static "
1170 code.putln("%s%s %s {" % (
1171 storage_class,
1172 ' '.join(self.modifiers).upper(), # macro forms
1173 header))
1175 def generate_argument_declarations(self, env, code):
1176 for arg in self.args:
1177 if arg.default:
1178 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1180 def generate_keyword_list(self, code):
1181 pass
1183 def generate_argument_parsing_code(self, env, code):
1184 i = 0
1185 if self.type.optional_arg_count:
1186 code.putln('if (%s) {' % Naming.optional_args_cname)
1187 for arg in self.args:
1188 if arg.default:
1189 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1190 declarator = arg.declarator
1191 while not hasattr(declarator, 'name'):
1192 declarator = declarator.base
1193 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1194 i += 1
1195 for _ in range(self.type.optional_arg_count):
1196 code.putln('}')
1197 code.putln('}')
1199 def generate_argument_conversion_code(self, code):
1200 pass
1202 def generate_argument_type_tests(self, code):
1203 # Generate type tests for args whose type in a parent
1204 # class is a supertype of the declared type.
1205 for arg in self.type.args:
1206 if arg.needs_type_test:
1207 self.generate_arg_type_test(arg, code)
1209 def generate_arg_type_test(self, arg, code):
1210 # Generate type test for one argument.
1211 if arg.type.typeobj_is_available():
1212 typeptr_cname = arg.type.typeptr_cname
1213 arg_code = "((PyObject *)%s)" % arg.cname
1214 code.putln(
1215 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1216 arg_code,
1217 typeptr_cname,
1218 not arg.not_none,
1219 arg.name,
1220 type.is_builtin_type,
1221 code.error_goto(arg.pos)))
1222 else:
1223 error(arg.pos, "Cannot test type of extern C class "
1224 "without type object name specification")
1226 def error_value(self):
1227 if self.return_type.is_pyobject:
1228 return "0"
1229 else:
1230 #return None
1231 return self.entry.type.exception_value
1233 def caller_will_check_exceptions(self):
1234 return self.entry.type.exception_check
1236 def generate_optarg_wrapper_function(self, env, code):
1237 if self.type.optional_arg_count and \
1238 self.type.original_sig and not self.type.original_sig.optional_arg_count:
1239 code.putln()
1240 self.generate_function_header(code, 0, with_opt_args = 0)
1241 if not self.return_type.is_void:
1242 code.put('return ')
1243 args = self.type.args
1244 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1245 arglist.append('NULL')
1246 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1247 code.putln('}')
1250 class PyArgDeclNode(Node):
1251 # Argument which must be a Python object (used
1252 # for * and ** arguments).
1254 # name string
1255 # entry Symtab.Entry
1256 child_attrs = []
1259 class DecoratorNode(Node):
1260 # A decorator
1262 # decorator NameNode or CallNode
1263 child_attrs = ['decorator']
1266 class DefNode(FuncDefNode):
1267 # A Python function definition.
1269 # name string the Python name of the function
1270 # decorators [DecoratorNode] list of decorators
1271 # args [CArgDeclNode] formal arguments
1272 # star_arg PyArgDeclNode or None * argument
1273 # starstar_arg PyArgDeclNode or None ** argument
1274 # doc EncodedString or None
1275 # body StatListNode
1277 # The following subnode is constructed internally
1278 # when the def statement is inside a Python class definition.
1280 # assmt AssignmentNode Function construction/assignment
1282 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1284 assmt = None
1285 num_kwonly_args = 0
1286 num_required_kw_args = 0
1287 reqd_kw_flags_cname = "0"
1288 is_wrapper = 0
1289 decorators = None
1291 def __init__(self, pos, **kwds):
1292 FuncDefNode.__init__(self, pos, **kwds)
1293 k = rk = r = 0
1294 for arg in self.args:
1295 if arg.kw_only:
1296 k += 1
1297 if not arg.default:
1298 rk += 1
1299 if not arg.default:
1300 r += 1
1301 self.num_kwonly_args = k
1302 self.num_required_kw_args = rk
1303 self.num_required_args = r
1305 entry = None
1307 def analyse_declarations(self, env):
1308 for arg in self.args:
1309 base_type = arg.base_type.analyse(env)
1310 name_declarator, type = \
1311 arg.declarator.analyse(base_type, env)
1312 arg.name = name_declarator.name
1313 if name_declarator.cname:
1314 error(self.pos,
1315 "Python function argument cannot have C name specification")
1316 arg.type = type.as_argument_type()
1317 arg.hdr_type = None
1318 arg.needs_conversion = 0
1319 arg.needs_type_test = 0
1320 arg.is_generic = 1
1321 if arg.not_none and not arg.type.is_extension_type:
1322 error(self.pos,
1323 "Only extension type arguments can have 'not None'")
1324 self.declare_pyfunction(env)
1325 self.analyse_signature(env)
1326 self.return_type = self.entry.signature.return_type()
1327 if self.signature_has_generic_args():
1328 if self.star_arg:
1329 env.use_utility_code(get_stararg_utility_code)
1330 elif self.signature_has_generic_args():
1331 env.use_utility_code(raise_argtuple_too_long_utility_code)
1332 if not self.signature_has_nongeneric_args():
1333 env.use_utility_code(get_keyword_string_check_utility_code)
1334 elif self.starstar_arg:
1335 env.use_utility_code(get_splitkeywords_utility_code)
1336 if self.num_required_kw_args:
1337 env.use_utility_code(get_checkkeywords_utility_code)
1339 def analyse_signature(self, env):
1340 any_type_tests_needed = 0
1341 # Use the simpler calling signature for zero- and one-argument functions.
1342 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1343 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1344 if len(self.args) == 0:
1345 self.entry.signature = TypeSlots.pyfunction_noargs
1346 elif len(self.args) == 1:
1347 if self.args[0].default is None and not self.args[0].kw_only:
1348 self.entry.signature = TypeSlots.pyfunction_onearg
1349 elif self.entry.signature is TypeSlots.pymethod_signature:
1350 if len(self.args) == 1:
1351 self.entry.signature = TypeSlots.unaryfunc
1352 elif len(self.args) == 2:
1353 if self.args[1].default is None and not self.args[1].kw_only:
1354 self.entry.signature = TypeSlots.ibinaryfunc
1355 elif self.entry.is_special:
1356 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1357 sig = self.entry.signature
1358 nfixed = sig.num_fixed_args()
1359 for i in range(nfixed):
1360 if i < len(self.args):
1361 arg = self.args[i]
1362 arg.is_generic = 0
1363 if sig.is_self_arg(i):
1364 arg.is_self_arg = 1
1365 arg.hdr_type = arg.type = env.parent_type
1366 arg.needs_conversion = 0
1367 else:
1368 arg.hdr_type = sig.fixed_arg_type(i)
1369 if not arg.type.same_as(arg.hdr_type):
1370 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1371 arg.needs_type_test = 1
1372 any_type_tests_needed = 1
1373 else:
1374 arg.needs_conversion = 1
1375 if arg.needs_conversion:
1376 arg.hdr_cname = Naming.arg_prefix + arg.name
1377 else:
1378 arg.hdr_cname = Naming.var_prefix + arg.name
1379 else:
1380 self.bad_signature()
1381 return
1382 if nfixed < len(self.args):
1383 if not sig.has_generic_args:
1384 self.bad_signature()
1385 for arg in self.args:
1386 if arg.is_generic and \
1387 (arg.type.is_extension_type or arg.type.is_builtin_type):
1388 arg.needs_type_test = 1
1389 any_type_tests_needed = 1
1390 elif arg.type is PyrexTypes.c_py_ssize_t_type:
1391 # Want to use __index__ rather than __int__ method
1392 # that PyArg_ParseTupleAndKeywords calls
1393 arg.needs_conversion = 1
1394 arg.hdr_type = PyrexTypes.py_object_type
1395 arg.hdr_cname = Naming.arg_prefix + arg.name
1396 if any_type_tests_needed:
1397 env.use_utility_code(arg_type_test_utility_code)
1399 def bad_signature(self):
1400 sig = self.entry.signature
1401 expected_str = "%d" % sig.num_fixed_args()
1402 if sig.has_generic_args:
1403 expected_str = expected_str + " or more"
1404 name = self.name
1405 if name.startswith("__") and name.endswith("__"):
1406 desc = "Special method"
1407 else:
1408 desc = "Method"
1409 error(self.pos,
1410 "%s %s has wrong number of arguments "
1411 "(%d declared, %s expected)" % (
1412 desc, self.name, len(self.args), expected_str))
1414 def signature_has_nongeneric_args(self):
1415 argcount = len(self.args)
1416 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1417 return 0
1418 return 1
1420 def signature_has_generic_args(self):
1421 return self.entry.signature.has_generic_args
1423 def declare_pyfunction(self, env):
1424 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1425 name = self.name
1426 entry = env.lookup_here(self.name)
1427 if entry and entry.type.is_cfunction and not self.is_wrapper:
1428 warning(self.pos, "Overriding cdef method with def method.", 5)
1429 entry = env.declare_pyfunction(self.name, self.pos)
1430 self.entry = entry
1431 prefix = env.scope_prefix
1432 entry.func_cname = \
1433 Naming.pyfunc_prefix + prefix + name
1434 entry.pymethdef_cname = \
1435 Naming.pymethdef_prefix + prefix + name
1436 if Options.docstrings:
1437 entry.doc = embed_position(self.pos, self.doc)
1438 entry.doc_cname = \
1439 Naming.funcdoc_prefix + prefix + name
1440 else:
1441 entry.doc = None
1443 def declare_arguments(self, env):
1444 for arg in self.args:
1445 if not arg.name:
1446 error(arg.pos, "Missing argument name")
1447 if arg.needs_conversion:
1448 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1449 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1450 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1451 if arg.type.is_pyobject:
1452 arg.entry.init = "0"
1453 arg.entry.init_to_none = 0
1454 else:
1455 arg.entry = self.declare_argument(env, arg)
1456 arg.entry.used = 1
1457 arg.entry.is_self_arg = arg.is_self_arg
1458 if arg.hdr_type:
1459 if arg.is_self_arg or \
1460 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1461 arg.entry.is_declared_generic = 1
1462 self.declare_python_arg(env, self.star_arg)
1463 self.declare_python_arg(env, self.starstar_arg)
1465 def declare_python_arg(self, env, arg):
1466 if arg:
1467 entry = env.declare_var(arg.name,
1468 PyrexTypes.py_object_type, arg.pos)
1469 entry.used = 1
1470 entry.init = "0"
1471 entry.init_to_none = 0
1472 entry.xdecref_cleanup = 1
1473 arg.entry = entry
1474 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1476 def analyse_expressions(self, env):
1477 self.analyse_default_values(env)
1478 if env.is_py_class_scope:
1479 self.synthesize_assignment_node(env)
1481 def synthesize_assignment_node(self, env):
1482 import ExprNodes
1483 self.assmt = SingleAssignmentNode(self.pos,
1484 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1485 rhs = ExprNodes.UnboundMethodNode(self.pos,
1486 class_cname = env.class_obj_cname,
1487 function = ExprNodes.PyCFunctionNode(self.pos,
1488 pymethdef_cname = self.entry.pymethdef_cname)))
1489 self.assmt.analyse_declarations(env)
1490 self.assmt.analyse_expressions(env)
1492 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1493 arg_code_list = []
1494 sig = self.entry.signature
1495 if sig.has_dummy_arg:
1496 arg_code_list.append(
1497 "PyObject *%s" % Naming.self_cname)
1498 for arg in self.args:
1499 if not arg.is_generic:
1500 if arg.is_self_arg:
1501 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1502 else:
1503 arg_code_list.append(
1504 arg.hdr_type.declaration_code(arg.hdr_cname))
1505 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1506 arg_code_list.append("PyObject *unused")
1507 if sig.has_generic_args:
1508 arg_code_list.append(
1509 "PyObject *%s, PyObject *%s"
1510 % (Naming.args_cname, Naming.kwds_cname))
1511 arg_code = ", ".join(arg_code_list)
1512 dc = self.return_type.declaration_code(self.entry.func_cname)
1513 header = "static %s(%s)" % (dc, arg_code)
1514 code.putln("%s; /*proto*/" % header)
1515 if proto_only:
1516 return
1517 if self.entry.doc and Options.docstrings:
1518 code.putln(
1519 'static char %s[] = "%s";' % (
1520 self.entry.doc_cname,
1521 self.entry.doc))
1522 if with_pymethdef:
1523 code.put(
1524 "static PyMethodDef %s = " %
1525 self.entry.pymethdef_cname)
1526 code.put_pymethoddef(self.entry, ";")
1527 code.putln("%s {" % header)
1529 def generate_argument_declarations(self, env, code):
1530 for arg in self.args:
1531 if arg.is_generic: # or arg.needs_conversion:
1532 if arg.needs_conversion:
1533 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1534 else:
1535 code.put_var_declaration(arg.entry)
1537 def generate_keyword_list(self, code):
1538 if self.signature_has_generic_args() and \
1539 self.signature_has_nongeneric_args():
1540 reqd_kw_flags = []
1541 has_reqd_kwds = False
1542 code.put(
1543 "static char *%s[] = {" %
1544 Naming.kwdlist_cname)
1545 for arg in self.args:
1546 if arg.is_generic:
1547 code.put(
1548 '"%s",' %
1549 arg.name)
1550 if arg.kw_only and not arg.default:
1551 has_reqd_kwds = 1
1552 flag = "1"
1553 else:
1554 flag = "0"
1555 reqd_kw_flags.append(flag)
1556 code.putln(
1557 "0};")
1558 if has_reqd_kwds:
1559 flags_name = Naming.reqd_kwds_cname
1560 self.reqd_kw_flags_cname = flags_name
1561 code.putln(
1562 "static char %s[] = {%s};" % (
1563 flags_name,
1564 ",".join(reqd_kw_flags)))
1566 def generate_argument_parsing_code(self, env, code):
1567 # Generate PyArg_ParseTuple call for generic
1568 # arguments, if any.
1569 if self.entry.signature.has_dummy_arg:
1570 # get rid of unused argument warning
1571 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1573 old_error_label = code.new_error_label()
1574 our_error_label = code.error_label
1575 end_label = code.new_label()
1577 has_kwonly_args = self.num_kwonly_args > 0
1578 has_star_or_kw_args = self.star_arg is not None \
1579 or self.starstar_arg is not None or has_kwonly_args
1581 if not self.signature_has_generic_args():
1582 if has_star_or_kw_args:
1583 error(self.pos, "This method cannot have * or keyword arguments")
1584 self.generate_argument_conversion_code(code)
1586 elif not self.signature_has_nongeneric_args():
1587 # func(*args) or func(**kw) or func(*args, **kw)
1588 self.generate_stararg_copy_code(code)
1590 else:
1591 arg_addrs = []
1592 arg_formats = []
1593 positional_args = []
1594 default_seen = 0
1595 for arg in self.args:
1596 arg_entry = arg.entry
1597 if arg.is_generic:
1598 if arg.default:
1599 code.putln(
1600 "%s = %s;" % (
1601 arg_entry.cname,
1602 arg.default_result_code))
1603 if not default_seen:
1604 arg_formats.append("|")
1605 default_seen = 1
1606 if not arg.is_self_arg and not arg.kw_only:
1607 positional_args.append(arg)
1608 elif arg.kw_only:
1609 if not default_seen:
1610 arg_formats.append("|")
1611 default_seen = 1
1612 elif default_seen:
1613 error(arg.pos, "Non-default argument following default argument")
1614 elif not arg.is_self_arg:
1615 positional_args.append(arg)
1616 if arg.needs_conversion:
1617 arg_addrs.append("&" + arg.hdr_cname)
1618 format = arg.hdr_type.parsetuple_format
1619 else:
1620 arg_addrs.append("&" + arg_entry.cname)
1621 format = arg_entry.type.parsetuple_format
1622 if format:
1623 arg_formats.append(format)
1624 else:
1625 error(arg.pos,
1626 "Cannot convert Python object argument to type '%s' (when parsing input arguments)"
1627 % arg.type)
1629 if has_star_or_kw_args:
1630 self.generate_stararg_getting_code(code)
1632 self.generate_argument_tuple_parsing_code(
1633 positional_args, arg_formats, arg_addrs, code)
1635 code.error_label = old_error_label
1636 if code.label_used(our_error_label):
1637 code.put_goto(end_label)
1638 code.put_label(our_error_label)
1639 if has_star_or_kw_args:
1640 self.put_stararg_decrefs(code)
1641 self.generate_arg_decref(self.star_arg, code)
1642 if self.starstar_arg:
1643 if self.starstar_arg.entry.xdecref_cleanup:
1644 code.put_var_xdecref(self.starstar_arg.entry)
1645 else:
1646 code.put_var_decref(self.starstar_arg.entry)
1647 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1648 code.putln("return %s;" % self.error_value())
1649 code.put_label(end_label)
1651 def generate_argument_tuple_parsing_code(self, positional_args,
1652 arg_formats, arg_addrs, code):
1653 # Unpack inplace if it's simple
1654 if not self.num_required_kw_args:
1655 min_positional_args = self.num_required_args - self.num_required_kw_args
1656 max_positional_args = len(positional_args)
1657 if len(self.args) > 0 and self.args[0].is_self_arg:
1658 min_positional_args -= 1
1659 if max_positional_args == min_positional_args:
1660 count_cond = "likely(PyTuple_GET_SIZE(%s) == %s)" % (
1661 Naming.args_cname, max_positional_args)
1662 else:
1663 count_cond = "likely(%s <= PyTuple_GET_SIZE(%s)) && likely(PyTuple_GET_SIZE(%s) <= %s)" % (
1664 min_positional_args,
1665 Naming.args_cname,
1666 Naming.args_cname,
1667 max_positional_args)
1668 code.putln(
1669 'if (likely(!%s) && %s) {' % (Naming.kwds_cname, count_cond))
1670 i = 0
1671 closing = 0
1672 for arg in positional_args:
1673 if arg.default:
1674 code.putln('if (PyTuple_GET_SIZE(%s) > %s) {' % (Naming.args_cname, i))
1675 closing += 1
1676 item = "PyTuple_GET_ITEM(%s, %s)" % (Naming.args_cname, i)
1677 if arg.type.is_pyobject:
1678 if arg.is_generic:
1679 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1680 code.putln("%s = %s;" % (arg.entry.cname, item))
1681 else:
1682 func = arg.type.from_py_function
1683 if func:
1684 code.putln("%s = %s(%s); %s" % (
1685 arg.entry.cname,
1686 func,
1687 item,
1688 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1689 else:
1690 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1691 i += 1
1692 for _ in range(closing):
1693 code.putln('}')
1694 code.putln(
1695 '}')
1696 code.putln('else {')
1698 argformat = '"%s"' % string.join(arg_formats, "")
1699 pt_arglist = [Naming.args_cname, Naming.kwds_cname, argformat, Naming.kwdlist_cname] + arg_addrs
1700 pt_argstring = string.join(pt_arglist, ", ")
1701 code.putln(
1702 'if (unlikely(!PyArg_ParseTupleAndKeywords(%s))) %s' % (
1703 pt_argstring,
1704 code.error_goto(self.pos)))
1705 self.generate_argument_conversion_code(code)
1707 if not self.num_required_kw_args:
1708 code.putln('}')
1710 def put_stararg_decrefs(self, code):
1711 if self.star_arg:
1712 code.put_decref(Naming.args_cname, py_object_type)
1713 if self.starstar_arg:
1714 code.put_xdecref(Naming.kwds_cname, py_object_type)
1716 def generate_arg_xdecref(self, arg, code):
1717 if arg:
1718 code.put_var_xdecref(arg.entry)
1720 def generate_arg_decref(self, arg, code):
1721 if arg:
1722 code.put_var_decref(arg.entry)
1724 def arg_address(self, arg):
1725 if arg:
1726 return "&%s" % arg.entry.cname
1727 else:
1728 return 0
1730 def generate_stararg_copy_code(self, code):
1731 if not self.star_arg:
1732 self.generate_positional_args_check(code, 0)
1733 self.generate_keyword_args_check(code)
1735 if self.starstar_arg:
1736 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
1737 self.starstar_arg.entry.cname,
1738 Naming.kwds_cname,
1739 Naming.kwds_cname))
1740 code.putln("if (unlikely(!%s)) return %s;" % (
1741 self.starstar_arg.entry.cname, self.error_value()))
1742 self.starstar_arg.entry.xdecref_cleanup = 0
1743 self.starstar_arg = None
1745 if self.star_arg:
1746 code.put_incref(Naming.args_cname, py_object_type)
1747 code.putln("%s = %s;" % (
1748 self.star_arg.entry.cname,
1749 Naming.args_cname))
1750 self.star_arg.entry.xdecref_cleanup = 0
1751 self.star_arg = None
1753 def generate_stararg_getting_code(self, code):
1754 num_kwonly = self.num_kwonly_args
1755 fixed_args = self.entry.signature.num_fixed_args()
1756 nargs = len(self.args) - num_kwonly - fixed_args
1757 error_return = "return %s;" % self.error_value()
1759 if self.star_arg:
1760 star_arg_cname = self.star_arg.entry.cname
1761 code.putln("if (likely(PyTuple_GET_SIZE(%s) <= %d)) {" % (
1762 Naming.args_cname, nargs))
1763 code.put_incref(Naming.args_cname, py_object_type)
1764 code.put("%s = %s; " % (star_arg_cname, Naming.empty_tuple))
1765 code.put_incref(Naming.empty_tuple, py_object_type)
1766 code.putln("}")
1767 code.putln("else {")
1768 code.putln(
1769 "if (unlikely(__Pyx_SplitStarArg(&%s, %d, &%s) < 0)) return %s;" % (
1770 Naming.args_cname,
1771 nargs,
1772 star_arg_cname,
1773 self.error_value()))
1774 code.putln("}")
1775 self.star_arg.entry.xdecref_cleanup = 0
1776 elif self.signature_has_generic_args():
1777 # make sure supernumerous positional arguments do not run
1778 # into keyword-only arguments and provide a more helpful
1779 # message than PyArg_ParseTupelAndKeywords()
1780 self.generate_positional_args_check(code, nargs)
1782 handle_error = 0
1783 if self.starstar_arg:
1784 handle_error = 1
1785 code.put(
1786 "if (unlikely(__Pyx_SplitKeywords(&%s, %s, &%s, %s) < 0)) " % (
1787 Naming.kwds_cname,
1788 Naming.kwdlist_cname,
1789 self.starstar_arg.entry.cname,
1790 self.reqd_kw_flags_cname))
1791 self.starstar_arg.entry.xdecref_cleanup = 0
1792 elif self.num_required_kw_args:
1793 handle_error = 1
1794 code.put("if (unlikely(__Pyx_CheckRequiredKeywords(%s, %s, %s) < 0)) " % (
1795 Naming.kwds_cname,
1796 Naming.kwdlist_cname,
1797 self.reqd_kw_flags_cname))
1799 if handle_error:
1800 if self.star_arg:
1801 code.putln("{")
1802 code.put_decref(Naming.args_cname, py_object_type)
1803 code.put_decref(self.star_arg.entry.cname, py_object_type)
1804 code.putln(error_return)
1805 code.putln("}")
1806 else:
1807 code.putln(error_return)
1809 def generate_positional_args_check(self, code, nargs):
1810 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > %d)) {" % (
1811 Naming.args_cname, nargs))
1812 code.putln("__Pyx_RaiseArgtupleTooLong(%d, PyTuple_GET_SIZE(%s));" % (
1813 nargs, Naming.args_cname))
1814 code.putln("return %s;" % self.error_value())
1815 code.putln("}")
1817 def generate_keyword_args_check(self, code):
1818 code.putln("if (unlikely(%s)) {" % Naming.kwds_cname)
1819 code.putln("if (unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
1820 Naming.kwds_cname, self.name,
1821 bool(self.starstar_arg), self.error_value()))
1822 code.putln("}")
1824 def generate_argument_conversion_code(self, code):
1825 # Generate code to convert arguments from
1826 # signature type to declared type, if needed.
1827 for arg in self.args:
1828 if arg.needs_conversion:
1829 self.generate_arg_conversion(arg, code)
1831 def generate_arg_conversion(self, arg, code):
1832 # Generate conversion code for one argument.
1833 old_type = arg.hdr_type
1834 new_type = arg.type
1835 if old_type.is_pyobject:
1836 if arg.default:
1837 code.putln("if (%s) {" % arg.hdr_cname)
1838 else:
1839 code.putln("assert(%s); {" % arg.hdr_cname)
1840 self.generate_arg_conversion_from_pyobject(arg, code)
1841 code.putln("}")
1842 elif new_type.is_pyobject:
1843 self.generate_arg_conversion_to_pyobject(arg, code)
1844 else:
1845 if new_type.assignable_from(old_type):
1846 code.putln(
1847 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
1848 else:
1849 error(arg.pos,
1850 "Cannot convert 1 argument from '%s' to '%s'" %
1851 (old_type, new_type))
1853 def generate_arg_conversion_from_pyobject(self, arg, code):
1854 new_type = arg.type
1855 func = new_type.from_py_function
1856 # copied from CoerceFromPyTypeNode
1857 if func:
1858 code.putln("%s = %s(%s); %s" % (
1859 arg.entry.cname,
1860 func,
1861 arg.hdr_cname,
1862 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
1863 else:
1864 error(arg.pos,
1865 "Cannot convert Python object argument to type '%s'"
1866 % new_type)
1868 def generate_arg_conversion_to_pyobject(self, arg, code):
1869 old_type = arg.hdr_type
1870 func = old_type.to_py_function
1871 if func:
1872 code.putln("%s = %s(%s); %s" % (
1873 arg.entry.cname,
1874 func,
1875 arg.hdr_cname,
1876 code.error_goto_if_null(arg.entry.cname, arg.pos)))
1877 else:
1878 error(arg.pos,
1879 "Cannot convert argument of type '%s' to Python object"
1880 % old_type)
1882 def generate_argument_type_tests(self, code):
1883 # Generate type tests for args whose signature
1884 # type is PyObject * and whose declared type is
1885 # a subtype thereof.
1886 for arg in self.args:
1887 if arg.needs_type_test:
1888 self.generate_arg_type_test(arg, code)
1890 def generate_arg_type_test(self, arg, code):
1891 # Generate type test for one argument.
1892 if arg.type.typeobj_is_available():
1893 typeptr_cname = arg.type.typeptr_cname
1894 arg_code = "((PyObject *)%s)" % arg.entry.cname
1895 code.putln(
1896 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1897 arg_code,
1898 typeptr_cname,
1899 not arg.not_none,
1900 arg.name,
1901 arg.type.is_builtin_type,
1902 code.error_goto(arg.pos)))
1903 else:
1904 error(arg.pos, "Cannot test type of extern C class "
1905 "without type object name specification")
1907 def error_value(self):
1908 return self.entry.signature.error_value
1910 def caller_will_check_exceptions(self):
1911 return 1
1913 class OverrideCheckNode(StatNode):
1914 # A Node for dispatching to the def method if it
1915 # is overriden.
1917 # py_func
1919 # args
1920 # func_temp
1921 # body
1923 child_attrs = ['body']
1925 body = None
1927 def analyse_expressions(self, env):
1928 self.args = env.arg_entries
1929 if self.py_func.is_module_scope:
1930 first_arg = 0
1931 else:
1932 first_arg = 1
1933 import ExprNodes
1934 self.func_node = ExprNodes.PyTempNode(self.pos, env)
1935 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
1936 call_node = ExprNodes.SimpleCallNode(self.pos,
1937 function=self.func_node,
1938 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
1939 self.body = ReturnStatNode(self.pos, value=call_node)
1940 self.body.analyse_expressions(env)
1942 def generate_execution_code(self, code):
1943 # Check to see if we are an extension type
1944 if self.py_func.is_module_scope:
1945 self_arg = "((PyObject *)%s)" % Naming.module_cname
1946 else:
1947 self_arg = "((PyObject *)%s)" % self.args[0].cname
1948 code.putln("/* Check if called by wrapper */")
1949 code.putln("if (unlikely(%s)) %s = 0;" % (Naming.skip_dispatch_cname, Naming.skip_dispatch_cname))
1950 code.putln("/* Check if overriden in Python */")
1951 if self.py_func.is_module_scope:
1952 code.putln("else {")
1953 else:
1954 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
1955 err = code.error_goto_if_null(self.func_node.result_code, self.pos)
1956 # need to get attribute manually--scope would return cdef method
1957 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result_code, self_arg, self.py_func.interned_attr_cname, err))
1958 # It appears that this type is not anywhere exposed in the Python/C API
1959 is_builtin_function_or_method = '(strcmp(Py_TYPE(%s)->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result_code
1960 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result_code, self.py_func.entry.func_cname)
1961 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
1962 self.body.generate_execution_code(code)
1963 code.putln('}')
1964 code.put_decref_clear(self.func_node.result_code, PyrexTypes.py_object_type)
1965 code.putln("}")
1967 class ClassDefNode(StatNode, BlockNode):
1968 pass
1970 class PyClassDefNode(ClassDefNode):
1971 # A Python class definition.
1973 # name EncodedString Name of the class
1974 # doc string or None
1975 # body StatNode Attribute definition code
1976 # entry Symtab.Entry
1977 # scope PyClassScope
1979 # The following subnodes are constructed internally:
1981 # dict DictNode Class dictionary
1982 # classobj ClassNode Class object
1983 # target NameNode Variable to assign class object to
1985 child_attrs = ["body", "dict", "classobj", "target"]
1987 def __init__(self, pos, name, bases, doc, body):
1988 StatNode.__init__(self, pos)
1989 self.name = name
1990 self.doc = doc
1991 self.body = body
1992 import ExprNodes
1993 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
1994 if self.doc and Options.docstrings:
1995 doc = embed_position(self.pos, self.doc)
1996 doc_node = ExprNodes.StringNode(pos, value = doc)
1997 else:
1998 doc_node = None
1999 self.classobj = ExprNodes.ClassNode(pos, name = name,
2000 bases = bases, dict = self.dict, doc = doc_node)
2001 self.target = ExprNodes.NameNode(pos, name = name)
2003 def create_scope(self, env):
2004 genv = env
2005 while env.is_py_class_scope or env.is_c_class_scope:
2006 env = env.outer_scope
2007 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2008 return cenv
2010 def analyse_declarations(self, env):
2011 self.target.analyse_target_declaration(env)
2012 cenv = self.create_scope(env)
2013 cenv.class_obj_cname = self.target.entry.cname
2014 self.body.analyse_declarations(cenv)
2016 def analyse_expressions(self, env):
2017 self.dict.analyse_expressions(env)
2018 self.classobj.analyse_expressions(env)
2019 genv = env.global_scope()
2020 cenv = self.scope
2021 cenv.class_dict_cname = self.dict.result_code
2022 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result_code
2023 self.body.analyse_expressions(cenv)
2024 self.target.analyse_target_expression(env, self.classobj)
2025 self.dict.release_temp(env)
2026 #self.classobj.release_temp(env)
2027 #self.target.release_target_temp(env)
2029 def generate_function_definitions(self, env, code, transforms):
2030 self.generate_py_string_decls(self.scope, code)
2031 self.body.generate_function_definitions(
2032 self.scope, code, transforms)
2034 def generate_execution_code(self, code):
2035 self.dict.generate_evaluation_code(code)
2036 self.classobj.generate_evaluation_code(code)
2037 self.body.generate_execution_code(code)
2038 self.target.generate_assignment_code(self.classobj, code)
2039 self.dict.generate_disposal_code(code)
2042 class CClassDefNode(ClassDefNode):
2043 # An extension type definition.
2045 # visibility 'private' or 'public' or 'extern'
2046 # typedef_flag boolean
2047 # api boolean
2048 # module_name string or None For import of extern type objects
2049 # class_name string Unqualified name of class
2050 # as_name string or None Name to declare as in this scope
2051 # base_class_module string or None Module containing the base class
2052 # base_class_name string or None Name of the base class
2053 # objstruct_name string or None Specified C name of object struct
2054 # typeobj_name string or None Specified C name of type object
2055 # in_pxd boolean Is in a .pxd file
2056 # doc string or None
2057 # body StatNode or None
2058 # entry Symtab.Entry
2059 # base_type PyExtensionType or None
2061 child_attrs = ["body"]
2063 def analyse_declarations(self, env):
2064 #print "CClassDefNode.analyse_declarations:", self.class_name
2065 #print "...visibility =", self.visibility
2066 #print "...module_name =", self.module_name
2067 if env.in_cinclude and not self.objstruct_name:
2068 error(self.pos, "Object struct name specification required for "
2069 "C class defined in 'extern from' block")
2070 self.base_type = None
2071 # Now that module imports are cached, we need to
2072 # import the modules for extern classes.
2073 if self.module_name:
2074 self.module = None
2075 for module in env.cimported_modules:
2076 if module.name == self.module_name:
2077 self.module = module
2078 if self.module is None:
2079 self.module = ModuleScope(self.module_name, None, env.context)
2080 self.module.has_extern_class = 1
2081 env.cimported_modules.append(self.module)
2083 if self.base_class_name:
2084 if self.base_class_module:
2085 base_class_scope = env.find_module(self.base_class_module, self.pos)
2086 else:
2087 base_class_scope = env
2088 if base_class_scope:
2089 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2090 if base_class_entry:
2091 if not base_class_entry.is_type:
2092 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2093 elif not base_class_entry.type.is_extension_type:
2094 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2095 elif not base_class_entry.type.is_complete():
2096 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2097 else:
2098 self.base_type = base_class_entry.type
2099 has_body = self.body is not None
2100 if self.module_name and self.visibility != 'extern':
2101 module_path = self.module_name.split(".")
2102 home_scope = env.find_imported_module(module_path, self.pos)
2103 if not home_scope:
2104 return
2105 else:
2106 home_scope = env
2107 self.entry = home_scope.declare_c_class(
2108 name = self.class_name,
2109 pos = self.pos,
2110 defining = has_body and self.in_pxd,
2111 implementing = has_body and not self.in_pxd,
2112 module_name = self.module_name,
2113 base_type = self.base_type,
2114 objstruct_cname = self.objstruct_name,
2115 typeobj_cname = self.typeobj_name,
2116 visibility = self.visibility,
2117 typedef_flag = self.typedef_flag,
2118 api = self.api)
2119 if home_scope is not env and self.visibility == 'extern':
2120 env.add_imported_entry(self.class_name, self.entry, pos)
2121 scope = self.entry.type.scope
2123 if self.doc and Options.docstrings:
2124 scope.doc = embed_position(self.pos, self.doc)
2126 if has_body and not self.in_pxd:
2127 # transforms not yet run on pxd files
2128 from ParseTreeTransforms import AnalyseDeclarationsTransform
2129 transform = AnalyseDeclarationsTransform(None)
2130 for entry in scope.var_entries:
2131 if hasattr(entry, 'needs_property'):
2132 property = transform.create_Property(entry)
2133 self.body.stats.append(property)
2135 if has_body:
2136 self.body.analyse_declarations(scope)
2137 if self.in_pxd:
2138 scope.defined = 1
2139 else:
2140 scope.implemented = 1
2141 env.allocate_vtable_names(self.entry)
2143 def analyse_expressions(self, env):
2144 if self.body:
2145 scope = self.entry.type.scope
2146 self.body.analyse_expressions(scope)
2148 def generate_function_definitions(self, env, code, transforms):
2149 self.generate_py_string_decls(self.entry.type.scope, code)
2150 if self.body:
2151 self.body.generate_function_definitions(
2152 self.entry.type.scope, code, transforms)
2154 def generate_execution_code(self, code):
2155 # This is needed to generate evaluation code for
2156 # default values of method arguments.
2157 if self.body:
2158 self.body.generate_execution_code(code)
2160 def annotate(self, code):
2161 if self.body:
2162 self.body.annotate(code)
2165 class PropertyNode(StatNode):
2166 # Definition of a property in an extension type.
2168 # name string
2169 # doc EncodedString or None Doc string
2170 # body StatListNode
2172 child_attrs = ["body"]
2174 def analyse_declarations(self, env):
2175 entry = env.declare_property(self.name, self.doc, self.pos)
2176 if entry:
2177 if self.doc and Options.docstrings:
2178 doc_entry = env.get_string_const(
2179 self.doc, identifier = False)
2180 entry.doc_cname = doc_entry.cname
2181 self.body.analyse_declarations(entry.scope)
2183 def analyse_expressions(self, env):
2184 self.body.analyse_expressions(env)
2186 def generate_function_definitions(self, env, code, transforms):
2187 self.body.generate_function_definitions(env, code, transforms)
2189 def generate_execution_code(self, code):
2190 pass
2192 def annotate(self, code):
2193 self.body.annotate(code)
2196 class GlobalNode(StatNode):
2197 # Global variable declaration.
2199 # names [string]
2201 child_attrs = []
2203 def analyse_declarations(self, env):
2204 for name in self.names:
2205 env.declare_global(name, self.pos)
2207 def analyse_expressions(self, env):
2208 pass
2210 def generate_execution_code(self, code):
2211 pass
2214 class ExprStatNode(StatNode):
2215 # Expression used as a statement.
2217 # expr ExprNode
2219 child_attrs = ["expr"]
2221 def analyse_expressions(self, env):
2222 self.expr.analyse_expressions(env)
2223 self.expr.release_temp(env)
2225 def generate_execution_code(self, code):
2226 self.expr.generate_evaluation_code(code)
2227 if not self.expr.is_temp and self.expr.result_code:
2228 code.putln("%s;" % self.expr.result_code)
2229 self.expr.generate_disposal_code(code)
2231 def annotate(self, code):
2232 self.expr.annotate(code)
2235 class AssignmentNode(StatNode):
2236 # Abstract base class for assignment nodes.
2238 # The analyse_expressions and generate_execution_code
2239 # phases of assignments are split into two sub-phases
2240 # each, to enable all the right hand sides of a
2241 # parallel assignment to be evaluated before assigning
2242 # to any of the left hand sides.
2244 def analyse_expressions(self, env):
2245 self.analyse_types(env)
2246 self.allocate_rhs_temps(env)
2247 self.allocate_lhs_temps(env)
2249 # def analyse_expressions(self, env):
2250 # self.analyse_expressions_1(env)
2251 # self.analyse_expressions_2(env)
2253 def generate_execution_code(self, code):
2254 self.generate_rhs_evaluation_code(code)
2255 self.generate_assignment_code(code)
2258 class SingleAssignmentNode(AssignmentNode):
2259 # The simplest case:
2261 # a = b
2263 # lhs ExprNode Left hand side
2264 # rhs ExprNode Right hand side
2265 # first bool Is this guaranteed the first assignment to lhs?
2267 child_attrs = ["lhs", "rhs"]
2268 first = False
2270 def analyse_declarations(self, env):
2271 self.lhs.analyse_target_declaration(env)
2273 def analyse_types(self, env, use_temp = 0):
2274 self.rhs.analyse_types(env)
2275 self.lhs.analyse_target_types(env)
2276 self.lhs.gil_assignment_check(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)
2281 def allocate_rhs_temps(self, env):
2282 self.rhs.allocate_temps(env)
2284 def allocate_lhs_temps(self, env):
2285 self.lhs.allocate_target_temps(env, self.rhs)
2286 #self.lhs.release_target_temp(env)
2287 #self.rhs.release_temp(env)
2289 # def analyse_expressions_1(self, env, use_temp = 0):
2290 # self.rhs.analyse_types(env)
2291 # self.lhs.analyse_target_types(env)
2292 # self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2293 # if use_temp:
2294 # self.rhs = self.rhs.coerce_to_temp(env)
2295 # self.rhs.allocate_temps(env)
2297 # def analyse_expressions_2(self, env):
2298 # self.lhs.allocate_target_temps(env)
2299 # self.lhs.release_target_temp(env)
2300 # self.rhs.release_temp(env)
2302 def generate_rhs_evaluation_code(self, code):
2303 self.rhs.generate_evaluation_code(code)
2305 def generate_assignment_code(self, code):
2306 self.lhs.generate_assignment_code(self.rhs, code)
2308 def annotate(self, code):
2309 self.lhs.annotate(code)
2310 self.rhs.annotate(code)
2313 class CascadedAssignmentNode(AssignmentNode):
2314 # An assignment with multiple left hand sides:
2316 # a = b = c
2318 # lhs_list [ExprNode] Left hand sides
2319 # rhs ExprNode Right hand sides
2321 # Used internally:
2323 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2325 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2326 coerced_rhs_list = None
2328 def analyse_declarations(self, env):
2329 for lhs in self.lhs_list:
2330 lhs.analyse_target_declaration(env)
2332 def analyse_types(self, env, use_temp = 0):
2333 self.rhs.analyse_types(env)
2334 if use_temp:
2335 self.rhs = self.rhs.coerce_to_temp(env)
2336 else:
2337 self.rhs = self.rhs.coerce_to_simple(env)
2338 from ExprNodes import CloneNode
2339 self.coerced_rhs_list = []
2340 for lhs in self.lhs_list:
2341 lhs.analyse_target_types(env)
2342 lhs.gil_assignment_check(env)
2343 rhs = CloneNode(self.rhs)
2344 rhs = rhs.coerce_to(lhs.type, env)
2345 self.coerced_rhs_list.append(rhs)
2347 def allocate_rhs_temps(self, env):
2348 self.rhs.allocate_temps(env)
2350 def allocate_lhs_temps(self, env):
2351 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2352 rhs.allocate_temps(env)
2353 lhs.allocate_target_temps(env, rhs)
2354 #lhs.release_target_temp(env)
2355 #rhs.release_temp(env)
2356 self.rhs.release_temp(env)
2358 # def analyse_expressions_1(self, env, use_temp = 0):
2359 # self.rhs.analyse_types(env)
2360 # if use_temp:
2361 # self.rhs = self.rhs.coerce_to_temp(env)
2362 # else:
2363 # self.rhs = self.rhs.coerce_to_simple(env)
2364 # self.rhs.allocate_temps(env)
2366 # def analyse_expressions_2(self, env):
2367 # from ExprNodes import CloneNode
2368 # self.coerced_rhs_list = []
2369 # for lhs in self.lhs_list:
2370 # lhs.analyse_target_types(env)
2371 # rhs = CloneNode(self.rhs)
2372 # rhs = rhs.coerce_to(lhs.type, env)
2373 # self.coerced_rhs_list.append(rhs)
2374 # rhs.allocate_temps(env)
2375 # lhs.allocate_target_temps(env)
2376 # lhs.release_target_temp(env)
2377 # rhs.release_temp(env)
2378 # self.rhs.release_temp(env)
2380 def generate_rhs_evaluation_code(self, code):
2381 self.rhs.generate_evaluation_code(code)
2383 def generate_assignment_code(self, code):
2384 for i in range(len(self.lhs_list)):
2385 lhs = self.lhs_list[i]
2386 rhs = self.coerced_rhs_list[i]
2387 rhs.generate_evaluation_code(code)
2388 lhs.generate_assignment_code(rhs, code)
2389 # Assignment has disposed of the cloned RHS
2390 self.rhs.generate_disposal_code(code)
2392 def annotate(self, code):
2393 for i in range(len(self.lhs_list)):
2394 lhs = self.lhs_list[i].annotate(code)
2395 rhs = self.coerced_rhs_list[i].annotate(code)
2396 self.rhs.annotate(code)
2399 class ParallelAssignmentNode(AssignmentNode):
2400 # A combined packing/unpacking assignment:
2402 # a, b, c = d, e, f
2404 # This has been rearranged by the parser into
2406 # a = d ; b = e ; c = f
2408 # but we must evaluate all the right hand sides
2409 # before assigning to any of the left hand sides.
2411 # stats [AssignmentNode] The constituent assignments
2413 child_attrs = ["stats"]
2415 def analyse_declarations(self, env):
2416 for stat in self.stats:
2417 stat.analyse_declarations(env)
2419 def analyse_expressions(self, env):
2420 for stat in self.stats:
2421 stat.analyse_types(env, use_temp = 1)
2422 stat.allocate_rhs_temps(env)
2423 for stat in self.stats:
2424 stat.allocate_lhs_temps(env)
2426 # def analyse_expressions(self, env):
2427 # for stat in self.stats:
2428 # stat.analyse_expressions_1(env, use_temp = 1)
2429 # for stat in self.stats:
2430 # stat.analyse_expressions_2(env)
2432 def generate_execution_code(self, code):
2433 for stat in self.stats:
2434 stat.generate_rhs_evaluation_code(code)
2435 for stat in self.stats:
2436 stat.generate_assignment_code(code)
2438 def annotate(self, code):
2439 for stat in self.stats:
2440 stat.annotate(code)
2443 class InPlaceAssignmentNode(AssignmentNode):
2444 # An in place arithmatic operand:
2446 # a += b
2447 # a -= b
2448 # ...
2450 # lhs ExprNode Left hand side
2451 # rhs ExprNode Right hand side
2452 # op char one of "+-*/%^&|"
2453 # dup (ExprNode) copy of lhs used for operation (auto-generated)
2455 # This code is a bit tricky because in order to obey Python
2456 # semantics the sub-expressions (e.g. indices) of the lhs must
2457 # not be evaluated twice. So we must re-use the values calculated
2458 # in evaluation phase for the assignment phase as well.
2459 # Fortunately, the type of the lhs node is fairly constrained
2460 # (it must be a NameNode, AttributeNode, or IndexNode).
2462 child_attrs = ["lhs", "rhs"]
2463 dup = None
2465 def analyse_declarations(self, env):
2466 self.lhs.analyse_target_declaration(env)
2468 def analyse_types(self, env):
2469 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
2470 self.rhs.analyse_types(env)
2471 self.lhs.analyse_target_types(env)
2472 if Options.incref_local_binop and self.dup.type.is_pyobject:
2473 self.dup = self.dup.coerce_to_temp(env)
2475 def allocate_rhs_temps(self, env):
2476 import ExprNodes
2477 if self.lhs.type.is_pyobject:
2478 self.rhs = self.rhs.coerce_to_pyobject(env)
2479 elif self.rhs.type.is_pyobject:
2480 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2481 if self.lhs.type.is_pyobject:
2482 self.result = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
2483 self.result.allocate_temps(env)
2484 # if use_temp:
2485 # self.rhs = self.rhs.coerce_to_temp(env)
2486 self.rhs.allocate_temps(env)
2487 self.dup.allocate_subexpr_temps(env)
2488 self.dup.allocate_temp(env)
2490 def allocate_lhs_temps(self, env):
2491 self.lhs.allocate_target_temps(env, self.rhs)
2492 # self.lhs.release_target_temp(env)
2493 self.dup.release_temp(env)
2494 if self.dup.is_temp:
2495 self.dup.release_subexpr_temps(env)
2496 # self.rhs.release_temp(env)
2497 if self.lhs.type.is_pyobject:
2498 self.result.release_temp(env)
2500 def generate_execution_code(self, code):
2501 self.rhs.generate_evaluation_code(code)
2502 self.dup.generate_subexpr_evaluation_code(code)
2503 self.dup.generate_result_code(code)
2504 if self.operator == "**":
2505 extra = ", Py_None"
2506 else:
2507 extra = ""
2508 if self.lhs.type.is_pyobject:
2509 code.putln(
2510 "%s = %s(%s, %s%s); %s" % (
2511 self.result.result_code,
2512 self.py_operation_function(),
2513 self.dup.py_result(),
2514 self.rhs.py_result(),
2515 extra,
2516 code.error_goto_if_null(self.result.py_result(), self.pos)))
2517 self.result.generate_evaluation_code(code) # May be a type check...
2518 self.rhs.generate_disposal_code(code)
2519 self.dup.generate_disposal_code(code)
2520 self.lhs.generate_assignment_code(self.result, code)
2521 else:
2522 c_op = self.operator
2523 if c_op == "//":
2524 c_op = "/"
2525 elif c_op == "**":
2526 if self.lhs.type.is_int and self.rhs.type.is_int:
2527 error(self.pos, "** with two C int types is ambiguous")
2528 else:
2529 error(self.pos, "No C inplace power operator")
2530 # have to do assignment directly to avoid side-effects
2531 code.putln("%s %s= %s;" % (self.lhs.result_code, c_op, self.rhs.result_code) )
2532 self.rhs.generate_disposal_code(code)
2533 if self.dup.is_temp:
2534 self.dup.generate_subexpr_disposal_code(code)
2536 def create_dup_node(self, env):
2537 import ExprNodes
2538 self.dup = self.lhs
2539 self.dup.analyse_types(env)
2540 if isinstance(self.lhs, ExprNodes.NameNode):
2541 target_lhs = ExprNodes.NameNode(self.dup.pos, name = self.dup.name, is_temp = self.dup.is_temp, entry = self.dup.entry)
2542 elif isinstance(self.lhs, ExprNodes.AttributeNode):
2543 target_lhs = ExprNodes.AttributeNode(self.dup.pos, obj = ExprNodes.CloneNode(self.lhs.obj), attribute = self.dup.attribute, is_temp = self.dup.is_temp)
2544 elif isinstance(self.lhs, ExprNodes.IndexNode):
2545 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)
2546 self.lhs = target_lhs
2547 return self.dup
2549 def py_operation_function(self):
2550 return self.py_functions[self.operator]
2552 py_functions = {
2553 "|": "PyNumber_InPlaceOr",
2554 "^": "PyNumber_InPlaceXor",
2555 "&": "PyNumber_InPlaceAnd",
2556 "+": "PyNumber_InPlaceAdd",
2557 "-": "PyNumber_InPlaceSubtract",
2558 "*": "PyNumber_InPlaceMultiply",
2559 "/": "PyNumber_InPlaceDivide",
2560 "%": "PyNumber_InPlaceRemainder",
2561 "<<": "PyNumber_InPlaceLshift",
2562 ">>": "PyNumber_InPlaceRshift",
2563 "**": "PyNumber_InPlacePower",
2564 "//": "PyNumber_InPlaceFloorDivide",
2567 def annotate(self, code):
2568 self.lhs.annotate(code)
2569 self.rhs.annotate(code)
2570 self.dup.annotate(code)
2573 class PrintStatNode(StatNode):
2574 # print statement
2576 # arg_tuple TupleNode
2577 # append_newline boolean
2579 child_attrs = ["arg_tuple"]
2581 def analyse_expressions(self, env):
2582 self.arg_tuple.analyse_expressions(env)
2583 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
2584 self.arg_tuple.release_temp(env)
2585 env.use_utility_code(printing_utility_code)
2586 self.gil_check(env)
2588 gil_message = "Python print statement"
2590 def generate_execution_code(self, code):
2591 self.arg_tuple.generate_evaluation_code(code)
2592 code.putln(
2593 "if (__Pyx_Print(%s, %d) < 0) %s" % (
2594 self.arg_tuple.py_result(),
2595 self.append_newline,
2596 code.error_goto(self.pos)))
2597 self.arg_tuple.generate_disposal_code(code)
2599 def annotate(self, code):
2600 self.arg_tuple.annotate(code)
2603 class DelStatNode(StatNode):
2604 # del statement
2606 # args [ExprNode]
2608 child_attrs = ["args"]
2610 def analyse_declarations(self, env):
2611 for arg in self.args:
2612 arg.analyse_target_declaration(env)
2614 def analyse_expressions(self, env):
2615 for arg in self.args:
2616 arg.analyse_target_expression(env, None)
2617 if arg.type.is_pyobject:
2618 self.gil_check(env)
2619 else:
2620 error(arg.pos, "Deletion of non-Python object")
2621 #arg.release_target_temp(env)
2623 gil_message = "Deleting Python object"
2625 def generate_execution_code(self, code):
2626 for arg in self.args:
2627 if arg.type.is_pyobject:
2628 arg.generate_deletion_code(code)
2629 # else error reported earlier
2631 def annotate(self, code):
2632 for arg in self.args:
2633 arg.annotate(code)
2636 class PassStatNode(StatNode):
2637 # pass statement
2639 child_attrs = []
2641 def analyse_expressions(self, env):
2642 pass
2644 def generate_execution_code(self, code):
2645 pass
2648 class BreakStatNode(StatNode):
2650 child_attrs = []
2652 def analyse_expressions(self, env):
2653 pass
2655 def generate_execution_code(self, code):
2656 if not code.break_label:
2657 error(self.pos, "break statement not inside loop")
2658 else:
2659 #code.putln(
2660 # "goto %s;" %
2661 # code.break_label)
2662 code.put_goto(code.break_label)
2665 class ContinueStatNode(StatNode):
2667 child_attrs = []
2669 def analyse_expressions(self, env):
2670 pass
2672 def generate_execution_code(self, code):
2673 if code.in_try_finally:
2674 error(self.pos, "continue statement inside try of try...finally")
2675 elif not code.continue_label:
2676 error(self.pos, "continue statement not inside loop")
2677 else:
2678 code.put_goto(code.continue_label)
2681 class ReturnStatNode(StatNode):
2682 # return statement
2684 # value ExprNode or None
2685 # return_type PyrexType
2686 # temps_in_use [Entry] Temps in use at time of return
2688 child_attrs = ["value"]
2690 def analyse_expressions(self, env):
2691 return_type = env.return_type
2692 self.return_type = return_type
2693 self.temps_in_use = env.temps_in_use()
2694 if not return_type:
2695 error(self.pos, "Return not inside a function body")
2696 return
2697 if self.value:
2698 self.value.analyse_types(env)
2699 if return_type.is_void or return_type.is_returncode:
2700 error(self.value.pos,
2701 "Return with value in void function")
2702 else:
2703 self.value = self.value.coerce_to(env.return_type, env)
2704 self.value.allocate_temps(env)
2705 self.value.release_temp(env)
2706 else:
2707 if (not return_type.is_void
2708 and not return_type.is_pyobject
2709 and not return_type.is_returncode):
2710 error(self.pos, "Return value required")
2711 if return_type.is_pyobject:
2712 self.gil_check(env)
2714 gil_message = "Returning Python object"
2716 def generate_execution_code(self, code):
2717 code.mark_pos(self.pos)
2718 if not self.return_type:
2719 # error reported earlier
2720 return
2721 if self.value:
2722 self.value.generate_evaluation_code(code)
2723 self.value.make_owned_reference(code)
2724 code.putln(
2725 "%s = %s;" % (
2726 Naming.retval_cname,
2727 self.value.result_as(self.return_type)))
2728 self.value.generate_post_assignment_code(code)
2729 else:
2730 if self.return_type.is_pyobject:
2731 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
2732 elif self.return_type.is_returncode:
2733 code.putln(
2734 "%s = %s;" % (
2735 Naming.retval_cname,
2736 self.return_type.default_value))
2737 for entry in self.temps_in_use:
2738 code.put_var_decref_clear(entry)
2739 #code.putln(
2740 # "goto %s;" %
2741 # code.return_label)
2742 code.put_goto(code.return_label)
2744 def annotate(self, code):
2745 if self.value:
2746 self.value.annotate(code)
2749 class RaiseStatNode(StatNode):
2750 # raise statement
2752 # exc_type ExprNode or None
2753 # exc_value ExprNode or None
2754 # exc_tb ExprNode or None
2756 child_attrs = ["exc_type", "exc_value", "exc_tb"]
2758 def analyse_expressions(self, env):
2759 if self.exc_type:
2760 self.exc_type.analyse_types(env)
2761 self.exc_type = self.exc_type.coerce_to_pyobject(env)
2762 self.exc_type.allocate_temps(env)
2763 if self.exc_value:
2764 self.exc_value.analyse_types(env)
2765 self.exc_value = self.exc_value.coerce_to_pyobject(env)
2766 self.exc_value.allocate_temps(env)
2767 if self.exc_tb:
2768 self.exc_tb.analyse_types(env)
2769 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
2770 self.exc_tb.allocate_temps(env)
2771 if self.exc_type:
2772 self.exc_type.release_temp(env)
2773 if self.exc_value:
2774 self.exc_value.release_temp(env)
2775 if self.exc_tb:
2776 self.exc_tb.release_temp(env)
2777 env.use_utility_code(raise_utility_code)
2778 self.gil_check(env)
2780 gil_message = "Raising exception"
2782 def generate_execution_code(self, code):
2783 if self.exc_type:
2784 self.exc_type.generate_evaluation_code(code)
2785 type_code = self.exc_type.py_result()
2786 else:
2787 type_code = 0
2788 if self.exc_value:
2789 self.exc_value.generate_evaluation_code(code)
2790 value_code = self.exc_value.py_result()
2791 else:
2792 value_code = "0"
2793 if self.exc_tb:
2794 self.exc_tb.generate_evaluation_code(code)
2795 tb_code = self.exc_tb.py_result()
2796 else:
2797 tb_code = "0"
2798 if self.exc_type or self.exc_value or self.exc_tb:
2799 code.putln(
2800 "__Pyx_Raise(%s, %s, %s);" % (
2801 type_code,
2802 value_code,
2803 tb_code))
2804 else:
2805 code.putln(
2806 "__Pyx_ReRaise();")
2807 if self.exc_type:
2808 self.exc_type.generate_disposal_code(code)
2809 if self.exc_value:
2810 self.exc_value.generate_disposal_code(code)
2811 if self.exc_tb:
2812 self.exc_tb.generate_disposal_code(code)
2813 code.putln(
2814 code.error_goto(self.pos))
2816 def annotate(self, code):
2817 if self.exc_type:
2818 self.exc_type.annotate(code)
2819 if self.exc_value:
2820 self.exc_value.annotate(code)
2821 if self.exc_tb:
2822 self.exc_tb.annotate(code)
2825 class ReraiseStatNode(StatNode):
2827 child_attrs = []
2829 def analyse_expressions(self, env):
2830 self.gil_check(env)
2831 env.use_utility_code(raise_utility_code)
2833 gil_message = "Raising exception"
2835 def generate_execution_code(self, code):
2836 vars = code.exc_vars
2837 if vars:
2838 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
2839 code.putln(code.error_goto(self.pos))
2840 else:
2841 error(self.pos, "Reraise not inside except clause")
2844 class AssertStatNode(StatNode):
2845 # assert statement
2847 # cond ExprNode
2848 # value ExprNode or None
2850 child_attrs = ["cond", "value"]
2852 def analyse_expressions(self, env):
2853 self.cond = self.cond.analyse_boolean_expression(env)
2854 if self.value:
2855 self.value.analyse_types(env)
2856 self.value = self.value.coerce_to_pyobject(env)
2857 self.value.allocate_temps(env)
2858 self.cond.release_temp(env)
2859 if self.value:
2860 self.value.release_temp(env)
2861 self.gil_check(env)
2862 #env.recycle_pending_temps() # TEMPORARY
2864 gil_message = "Raising exception"
2866 def generate_execution_code(self, code):
2867 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
2868 self.cond.generate_evaluation_code(code)
2869 code.putln(
2870 "if (unlikely(!%s)) {" %
2871 self.cond.result_code)
2872 if self.value:
2873 self.value.generate_evaluation_code(code)
2874 code.putln(
2875 "PyErr_SetObject(PyExc_AssertionError, %s);" %
2876 self.value.py_result())
2877 self.value.generate_disposal_code(code)
2878 else:
2879 code.putln(
2880 "PyErr_SetNone(PyExc_AssertionError);")
2881 code.putln(
2882 code.error_goto(self.pos))
2883 code.putln(
2884 "}")
2885 self.cond.generate_disposal_code(code)
2886 code.putln("#endif")
2888 def annotate(self, code):
2889 self.cond.annotate(code)
2890 if self.value:
2891 self.value.annotate(code)
2894 class IfStatNode(StatNode):
2895 # if statement
2897 # if_clauses [IfClauseNode]
2898 # else_clause StatNode or None
2900 child_attrs = ["if_clauses", "else_clause"]
2902 def analyse_control_flow(self, env):
2903 env.start_branching(self.pos)
2904 for if_clause in self.if_clauses:
2905 if_clause.analyse_control_flow(env)
2906 env.next_branch(if_clause.end_pos())
2907 if self.else_clause:
2908 self.else_clause.analyse_control_flow(env)
2909 env.finish_branching(self.end_pos())
2911 def analyse_declarations(self, env):
2912 for if_clause in self.if_clauses:
2913 if_clause.analyse_declarations(env)
2914 if self.else_clause:
2915 self.else_clause.analyse_declarations(env)
2917 def analyse_expressions(self, env):
2918 for if_clause in self.if_clauses:
2919 if_clause.analyse_expressions(env)
2920 if self.else_clause:
2921 self.else_clause.analyse_expressions(env)
2923 def generate_execution_code(self, code):
2924 code.mark_pos(self.pos)
2925 end_label = code.new_label()
2926 for if_clause in self.if_clauses:
2927 if_clause.generate_execution_code(code, end_label)
2928 if self.else_clause:
2929 code.putln("/*else*/ {")
2930 self.else_clause.generate_execution_code(code)
2931 code.putln("}")
2932 code.put_label(end_label)
2934 def annotate(self, code):
2935 for if_clause in self.if_clauses:
2936 if_clause.annotate(code)
2937 if self.else_clause:
2938 self.else_clause.annotate(code)
2941 class IfClauseNode(Node):
2942 # if or elif clause in an if statement
2944 # condition ExprNode
2945 # body StatNode
2947 child_attrs = ["condition", "body"]
2949 def analyse_control_flow(self, env):
2950 self.body.analyse_control_flow(env)
2952 def analyse_declarations(self, env):
2953 self.condition.analyse_declarations(env)
2954 self.body.analyse_declarations(env)
2956 def analyse_expressions(self, env):
2957 self.condition = \
2958 self.condition.analyse_temp_boolean_expression(env)
2959 self.condition.release_temp(env)
2960 self.body.analyse_expressions(env)
2962 def generate_execution_code(self, code, end_label):
2963 self.condition.generate_evaluation_code(code)
2964 code.putln(
2965 "if (%s) {" %
2966 self.condition.result_code)
2967 self.body.generate_execution_code(code)
2968 #code.putln(
2969 # "goto %s;" %
2970 # end_label)
2971 code.put_goto(end_label)
2972 code.putln("}")
2974 def annotate(self, code):
2975 self.condition.annotate(code)
2976 self.body.annotate(code)
2979 class SwitchCaseNode(StatNode):
2980 # Generated in the optimization of an if-elif-else node
2982 # conditions [ExprNode]
2983 # body StatNode
2985 child_attrs = ['conditions', 'body']
2987 def generate_execution_code(self, code):
2988 for cond in self.conditions:
2989 code.putln("case %s:" % cond.calculate_result_code())
2990 self.body.generate_execution_code(code)
2991 code.putln("break;")
2993 def annotate(self, code):
2994 for cond in self.conditions:
2995 cond.annotate(code)
2996 body.annotate(code)
2998 class SwitchStatNode(StatNode):
2999 # Generated in the optimization of an if-elif-else node
3001 # test ExprNode
3002 # cases [SwitchCaseNode]
3003 # else_clause StatNode or None
3005 child_attrs = ['test', 'cases', 'else_clause']
3007 def generate_execution_code(self, code):
3008 code.putln("switch (%s) {" % self.test.calculate_result_code())
3009 for case in self.cases:
3010 case.generate_execution_code(code)
3011 if self.else_clause is not None:
3012 code.putln("default:")
3013 self.else_clause.generate_execution_code(code)
3014 code.putln("}")
3016 def annotate(self, code):
3017 self.test.annotate(code)
3018 for case in self.cases:
3019 case.annotate(code)
3020 self.else_clause.annotate(code)
3022 class LoopNode:
3024 def analyse_control_flow(self, env):
3025 env.start_branching(self.pos)
3026 self.body.analyse_control_flow(env)
3027 env.next_branch(self.body.end_pos())
3028 if self.else_clause:
3029 self.else_clause.analyse_control_flow(env)
3030 env.finish_branching(self.end_pos())
3033 class WhileStatNode(LoopNode, StatNode):
3034 # while statement
3036 # condition ExprNode
3037 # body StatNode
3038 # else_clause StatNode
3040 child_attrs = ["condition", "body", "else_clause"]
3042 def analyse_declarations(self, env):
3043 self.body.analyse_declarations(env)
3044 if self.else_clause:
3045 self.else_clause.analyse_declarations(env)
3047 def analyse_expressions(self, env):
3048 self.condition = \
3049 self.condition.analyse_temp_boolean_expression(env)
3050 self.condition.release_temp(env)
3051 #env.recycle_pending_temps() # TEMPORARY
3052 self.body.analyse_expressions(env)
3053 if self.else_clause:
3054 self.else_clause.analyse_expressions(env)
3056 def generate_execution_code(self, code):
3057 old_loop_labels = code.new_loop_labels()
3058 code.putln(
3059 "while (1) {")
3060 self.condition.generate_evaluation_code(code)
3061 code.putln(
3062 "if (!%s) break;" %
3063 self.condition.result_code)
3064 self.body.generate_execution_code(code)
3065 code.put_label(code.continue_label)
3066 code.putln("}")
3067 break_label = code.break_label
3068 code.set_loop_labels(old_loop_labels)
3069 if self.else_clause:
3070 code.putln("/*else*/ {")
3071 self.else_clause.generate_execution_code(code)
3072 code.putln("}")
3073 code.put_label(break_label)
3075 def annotate(self, code):
3076 self.condition.annotate(code)
3077 self.body.annotate(code)
3078 if self.else_clause:
3079 self.else_clause.annotate(code)
3082 def ForStatNode(pos, **kw):
3083 if kw.has_key('iterator'):
3084 return ForInStatNode(pos, **kw)
3085 else:
3086 return ForFromStatNode(pos, **kw)
3088 class ForInStatNode(LoopNode, StatNode):
3089 # for statement
3091 # target ExprNode
3092 # iterator IteratorNode
3093 # body StatNode
3094 # else_clause StatNode
3095 # item NextNode used internally
3097 child_attrs = ["target", "iterator", "body", "else_clause"]
3098 item = None
3100 def analyse_declarations(self, env):
3101 self.target.analyse_target_declaration(env)
3102 self.body.analyse_declarations(env)
3103 if self.else_clause:
3104 self.else_clause.analyse_declarations(env)
3106 def analyse_range_step(self, args):
3107 import ExprNodes
3108 # The direction must be determined at compile time to set relations.
3109 # Otherwise, return False.
3110 if len(args) < 3:
3111 self.step = ExprNodes.IntNode(pos = args[0].pos, value='1')
3112 self.relation1 = '<='
3113 self.relation2 = '<'
3114 return True
3115 else:
3116 step = args[2]
3117 if isinstance(step, ExprNodes.UnaryMinusNode) and isinstance(step.operand, ExprNodes.IntNode):
3118 step = ExprNodes.IntNode(pos = step.pos, value=str(-int(step.operand.value, 0)))
3119 if isinstance(step, ExprNodes.IntNode):
3120 step_value = int(step.value, 0)
3121 if step_value > 0:
3122 self.step = step
3123 self.relation1 = '<='
3124 self.relation2 = '<'
3125 return True
3126 elif step_value < 0:
3127 self.step = ExprNodes.IntNode(pos = step.pos, value=str(-step_value))
3128 self.relation1 = '>='
3129 self.relation2 = '>'
3130 return True
3131 return False
3134 def analyse_expressions(self, env):
3135 import ExprNodes
3136 self.target.analyse_target_types(env)
3137 if Options.convert_range and self.target.type.is_int:
3138 sequence = self.iterator.sequence
3139 if isinstance(sequence, ExprNodes.SimpleCallNode) \
3140 and sequence.self is None \
3141 and isinstance(sequence.function, ExprNodes.NameNode) \
3142 and (sequence.function.name == 'range' or sequence.function.name == 'xrange'):
3143 args = sequence.args
3144 # Make sure we can determine direction from step
3145 if self.analyse_range_step(args):
3146 # Mutate to ForFrom loop type
3147 self.__class__ = ForFromStatNode
3148 if len(args) == 1:
3149 self.bound1 = ExprNodes.IntNode(pos = sequence.pos, value='0')
3150 self.bound2 = args[0]
3151 else:
3152 self.bound1 = args[0]
3153 self.bound2 = args[1]
3154 ForFromStatNode.analyse_expressions(self, env)
3155 return
3157 self.iterator.analyse_expressions(env)
3158 self.item = ExprNodes.NextNode(self.iterator, env)
3159 self.item = self.item.coerce_to(self.target.type, env)
3160 self.item.allocate_temps(env)
3161 self.target.allocate_target_temps(env, self.item)
3162 #self.item.release_temp(env)
3163 #self.target.release_target_temp(env)
3164 self.body.analyse_expressions(env)
3165 if self.else_clause:
3166 self.else_clause.analyse_expressions(env)
3167 self.iterator.release_temp(env)
3169 def generate_execution_code(self, code):
3170 old_loop_labels = code.new_loop_labels()
3171 self.iterator.generate_evaluation_code(code)
3172 code.putln(
3173 "for (;;) {")
3174 self.item.generate_evaluation_code(code)
3175 self.target.generate_assignment_code(self.item, code)
3176 self.body.generate_execution_code(code)
3177 code.put_label(code.continue_label)
3178 code.putln(
3179 "}")
3180 break_label = code.break_label
3181 code.set_loop_labels(old_loop_labels)
3182 if self.else_clause:
3183 code.putln("/*else*/ {")
3184 self.else_clause.generate_execution_code(code)
3185 code.putln("}")
3186 code.put_label(break_label)
3187 self.iterator.generate_disposal_code(code)
3189 def annotate(self, code):
3190 self.target.annotate(code)
3191 self.iterator.annotate(code)
3192 self.body.annotate(code)
3193 if self.else_clause:
3194 self.else_clause.annotate(code)
3195 self.item.annotate(code)
3198 class ForFromStatNode(LoopNode, StatNode):
3199 # for name from expr rel name rel expr
3201 # target NameNode
3202 # bound1 ExprNode
3203 # relation1 string
3204 # relation2 string
3205 # bound2 ExprNode
3206 # step ExprNode or None
3207 # body StatNode
3208 # else_clause StatNode or None
3210 # Used internally:
3212 # is_py_target bool
3213 # loopvar_name string
3214 # py_loopvar_node PyTempNode or None
3215 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3217 def analyse_declarations(self, env):
3218 self.target.analyse_target_declaration(env)
3219 self.body.analyse_declarations(env)
3220 if self.else_clause:
3221 self.else_clause.analyse_declarations(env)
3223 def analyse_expressions(self, env):
3224 import ExprNodes
3225 self.target.analyse_target_types(env)
3226 self.bound1.analyse_types(env)
3227 self.bound2.analyse_types(env)
3228 if self.target.type.is_numeric:
3229 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3230 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3231 else:
3232 self.bound1 = self.bound1.coerce_to_integer(env)
3233 self.bound2 = self.bound2.coerce_to_integer(env)
3234 if self.step is not None:
3235 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3236 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3237 self.step.analyse_types(env)
3238 self.step = self.step.coerce_to_integer(env)
3239 if not (self.bound2.is_name or self.bound2.is_literal):
3240 self.bound2 = self.bound2.coerce_to_temp(env)
3241 target_type = self.target.type
3242 if not (target_type.is_pyobject or target_type.is_numeric):
3243 error(self.target.pos,
3244 "Integer for-loop variable must be of type int or Python object")
3245 #if not (target_type.is_pyobject
3246 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3247 # error(self.target.pos,
3248 # "Cannot assign integer to variable of type '%s'" % target_type)
3249 if target_type.is_numeric:
3250 self.is_py_target = 0
3251 self.loopvar_name = self.target.entry.cname
3252 self.py_loopvar_node = None
3253 else:
3254 self.is_py_target = 1
3255 c_loopvar_node = ExprNodes.TempNode(self.pos,
3256 PyrexTypes.c_long_type, env)
3257 c_loopvar_node.allocate_temps(env)
3258 self.loopvar_name = c_loopvar_node.result_code
3259 self.py_loopvar_node = \
3260 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3261 self.bound1.allocate_temps(env)
3262 self.bound2.allocate_temps(env)
3263 if self.step is not None:
3264 self.step.allocate_temps(env)
3265 if self.is_py_target:
3266 self.py_loopvar_node.allocate_temps(env)
3267 self.target.allocate_target_temps(env, self.py_loopvar_node)
3268 #self.target.release_target_temp(env)
3269 #self.py_loopvar_node.release_temp(env)
3270 self.body.analyse_expressions(env)
3271 if self.is_py_target:
3272 c_loopvar_node.release_temp(env)
3273 if self.else_clause:
3274 self.else_clause.analyse_expressions(env)
3275 self.bound1.release_temp(env)
3276 self.bound2.release_temp(env)
3277 if self.step is not None:
3278 self.step.release_temp(env)
3280 def generate_execution_code(self, code):
3281 old_loop_labels = code.new_loop_labels()
3282 self.bound1.generate_evaluation_code(code)
3283 self.bound2.generate_evaluation_code(code)
3284 offset, incop = self.relation_table[self.relation1]
3285 if self.step is not None:
3286 self.step.generate_evaluation_code(code)
3287 incop = "%s=%s" % (incop[0], self.step.result_code)
3288 code.putln(
3289 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3290 self.loopvar_name,
3291 self.bound1.result_code, offset,
3292 self.loopvar_name, self.relation2, self.bound2.result_code,
3293 self.loopvar_name, incop))
3294 if self.py_loopvar_node:
3295 self.py_loopvar_node.generate_evaluation_code(code)
3296 self.target.generate_assignment_code(self.py_loopvar_node, code)
3297 self.body.generate_execution_code(code)
3298 code.put_label(code.continue_label)
3299 code.putln("}")
3300 break_label = code.break_label
3301 code.set_loop_labels(old_loop_labels)
3302 if self.else_clause:
3303 code.putln("/*else*/ {")
3304 self.else_clause.generate_execution_code(code)
3305 code.putln("}")
3306 code.put_label(break_label)
3307 self.bound1.generate_disposal_code(code)
3308 self.bound2.generate_disposal_code(code)
3309 if self.step is not None:
3310 self.step.generate_disposal_code(code)
3312 relation_table = {
3313 # {relop : (initial offset, increment op)}
3314 '<=': ("", "++"),
3315 '<' : ("+1", "++"),
3316 '>=': ("", "--"),
3317 '>' : ("-1", "--")
3320 def annotate(self, code):
3321 self.target.annotate(code)
3322 self.bound1.annotate(code)
3323 self.bound2.annotate(code)
3324 if self.step:
3325 self.bound2.annotate(code)
3326 self.body.annotate(code)
3327 if self.else_clause:
3328 self.else_clause.annotate(code)
3331 class WithStatNode(StatNode):
3332 """
3333 Represents a Python with statement.
3335 This is only used at parse tree level; and is not present in
3336 analysis or generation phases.
3337 """
3338 # manager The with statement manager object
3339 # target Node (lhs expression)
3340 # body StatNode
3341 child_attrs = ["manager", "target", "body"]
3343 class TryExceptStatNode(StatNode):
3344 # try .. except statement
3346 # body StatNode
3347 # except_clauses [ExceptClauseNode]
3348 # else_clause StatNode or None
3349 # cleanup_list [Entry] temps to clean up on error
3351 child_attrs = ["body", "except_clauses", "else_clause"]
3353 def analyse_control_flow(self, env):
3354 env.start_branching(self.pos)
3355 self.body.analyse_control_flow(env)
3356 successful_try = env.control_flow # grab this for later
3357 env.next_branch(self.body.end_pos())
3358 env.finish_branching(self.body.end_pos())
3360 env.start_branching(self.except_clauses[0].pos)
3361 for except_clause in self.except_clauses:
3362 except_clause.analyse_control_flow(env)
3363 env.next_branch(except_clause.end_pos())
3365 # the else cause it executed only when the try clause finishes
3366 env.control_flow.incoming = successful_try
3367 if self.else_clause:
3368 self.else_clause.analyse_control_flow(env)
3369 env.finish_branching(self.end_pos())
3371 def analyse_declarations(self, env):
3372 self.body.analyse_declarations(env)
3373 for except_clause in self.except_clauses:
3374 except_clause.analyse_declarations(env)
3375 if self.else_clause:
3376 self.else_clause.analyse_declarations(env)
3377 self.gil_check(env)
3379 def analyse_expressions(self, env):
3381 self.body.analyse_expressions(env)
3382 self.cleanup_list = env.free_temp_entries[:]
3383 for except_clause in self.except_clauses:
3384 except_clause.analyse_expressions(env)
3385 if self.else_clause:
3386 self.else_clause.analyse_expressions(env)
3387 self.gil_check(env)
3389 gil_message = "Try-except statement"
3391 def generate_execution_code(self, code):
3392 old_error_label = code.new_error_label()
3393 our_error_label = code.error_label
3394 end_label = code.new_label()
3395 code.putln(
3396 "/*try:*/ {")
3397 self.body.generate_execution_code(code)
3398 code.putln(
3399 "}")
3400 code.error_label = old_error_label
3401 if self.else_clause:
3402 code.putln(
3403 "/*else:*/ {")
3404 self.else_clause.generate_execution_code(code)
3405 code.putln(
3406 "}")
3407 code.put_goto(end_label)
3408 code.put_label(our_error_label)
3409 code.put_var_xdecrefs_clear(self.cleanup_list)
3410 default_clause_seen = 0
3411 for except_clause in self.except_clauses:
3412 if not except_clause.pattern:
3413 default_clause_seen = 1
3414 else:
3415 if default_clause_seen:
3416 error(except_clause.pos, "Default except clause not last")
3417 except_clause.generate_handling_code(code, end_label)
3418 if not default_clause_seen:
3419 code.put_goto(code.error_label)
3420 code.put_label(end_label)
3422 def annotate(self, code):
3423 self.body.annotate(code)
3424 for except_node in self.except_clauses:
3425 except_node.annotate(code)
3426 if self.else_clause:
3427 self.else_clause.annotate(code)
3430 class ExceptClauseNode(Node):
3431 # Part of try ... except statement.
3433 # pattern ExprNode
3434 # target ExprNode or None
3435 # body StatNode
3436 # excinfo_target NameNode or None optional target for exception info
3437 # match_flag string result of exception match
3438 # exc_value ExcValueNode used internally
3439 # function_name string qualified name of enclosing function
3440 # exc_vars (string * 3) local exception variables
3442 # excinfo_target is never set by the parser, but can be set by a transform
3443 # in order to extract more extensive information about the exception as a
3444 # sys.exc_info()-style tuple into a target variable
3446 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
3448 exc_value = None
3449 excinfo_target = None
3451 def analyse_declarations(self, env):
3452 if self.target:
3453 self.target.analyse_target_declaration(env)
3454 if self.excinfo_target is not None:
3455 self.excinfo_target.analyse_target_declaration(env)
3456 self.body.analyse_declarations(env)
3458 def analyse_expressions(self, env):
3459 import ExprNodes
3460 genv = env.global_scope()
3461 self.function_name = env.qualified_name
3462 if self.pattern:
3463 self.pattern.analyse_expressions(env)
3464 self.pattern = self.pattern.coerce_to_pyobject(env)
3465 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
3466 self.pattern.release_temp(env)
3467 env.release_temp(self.match_flag)
3468 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
3469 if self.target:
3470 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
3471 self.exc_value.allocate_temps(env)
3472 self.target.analyse_target_expression(env, self.exc_value)
3473 if self.excinfo_target is not None:
3474 import ExprNodes
3475 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
3476 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
3477 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
3478 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
3479 ])
3480 self.excinfo_tuple.analyse_expressions(env)
3481 self.excinfo_tuple.allocate_temps(env)
3482 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
3484 self.body.analyse_expressions(env)
3485 for var in self.exc_vars:
3486 env.release_temp(var)
3487 env.use_utility_code(get_exception_utility_code)
3489 def generate_handling_code(self, code, end_label):
3490 code.mark_pos(self.pos)
3491 if self.pattern:
3492 self.pattern.generate_evaluation_code(code)
3493 code.putln(
3494 "%s = PyErr_ExceptionMatches(%s);" % (
3495 self.match_flag,
3496 self.pattern.py_result()))
3497 self.pattern.generate_disposal_code(code)
3498 code.putln(
3499 "if (%s) {" %
3500 self.match_flag)
3501 else:
3502 code.putln("/*except:*/ {")
3503 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
3504 # We always have to fetch the exception value even if
3505 # there is no target, because this also normalises the
3506 # exception and stores it in the thread state.
3507 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
3508 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
3509 code.error_goto(self.pos)))
3510 if self.target:
3511 self.exc_value.generate_evaluation_code(code)
3512 self.target.generate_assignment_code(self.exc_value, code)
3513 if self.excinfo_target is not None:
3514 self.excinfo_tuple.generate_evaluation_code(code)
3515 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
3517 old_exc_vars = code.exc_vars
3518 code.exc_vars = self.exc_vars
3519 self.body.generate_execution_code(code)
3520 code.exc_vars = old_exc_vars
3521 for var in self.exc_vars:
3522 code.putln("Py_DECREF(%s); %s = 0;" % (var, var))
3523 code.put_goto(end_label)
3524 code.putln(
3525 "}")
3527 def annotate(self, code):
3528 if self.pattern:
3529 self.pattern.annotate(code)
3530 if self.target:
3531 self.target.annotate(code)
3532 self.body.annotate(code)
3535 class TryFinallyStatNode(StatNode):
3536 # try ... finally statement
3538 # body StatNode
3539 # finally_clause StatNode
3541 # cleanup_list [Entry] temps to clean up on error
3543 # The plan is that we funnel all continue, break
3544 # return and error gotos into the beginning of the
3545 # finally block, setting a variable to remember which
3546 # one we're doing. At the end of the finally block, we
3547 # switch on the variable to figure out where to go.
3548 # In addition, if we're doing an error, we save the
3549 # exception on entry to the finally block and restore
3550 # it on exit.
3552 child_attrs = ["body", "finally_clause"]
3554 preserve_exception = 1
3556 disallow_continue_in_try_finally = 0
3557 # There doesn't seem to be any point in disallowing
3558 # continue in the try block, since we have no problem
3559 # handling it.
3561 def create_analysed(pos, env, body, finally_clause):
3562 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
3563 node.cleanup_list = []
3564 return node
3565 create_analysed = staticmethod(create_analysed)
3567 def analyse_control_flow(self, env):
3568 env.start_branching(self.pos)
3569 self.body.analyse_control_flow(env)
3570 env.next_branch(self.body.end_pos())
3571 env.finish_branching(self.body.end_pos())
3572 self.finally_clause.analyse_control_flow(env)
3574 def analyse_declarations(self, env):
3575 self.body.analyse_declarations(env)
3576 self.finally_clause.analyse_declarations(env)
3578 def analyse_expressions(self, env):
3579 self.body.analyse_expressions(env)
3580 self.cleanup_list = env.free_temp_entries[:]
3581 self.finally_clause.analyse_expressions(env)
3582 self.gil_check(env)
3584 gil_message = "Try-finally statement"
3586 def generate_execution_code(self, code):
3587 old_error_label = code.error_label
3588 old_labels = code.all_new_labels()
3589 new_labels = code.get_all_labels()
3590 new_error_label = code.error_label
3591 catch_label = code.new_label()
3592 code.putln(
3593 "/*try:*/ {")
3594 if self.disallow_continue_in_try_finally:
3595 was_in_try_finally = code.in_try_finally
3596 code.in_try_finally = 1
3597 self.body.generate_execution_code(code)
3598 if self.disallow_continue_in_try_finally:
3599 code.in_try_finally = was_in_try_finally
3600 code.putln(
3601 "}")
3602 code.putln(
3603 "/*finally:*/ {")
3604 cases_used = []
3605 error_label_used = 0
3606 for i, new_label in enumerate(new_labels):
3607 if new_label in code.labels_used:
3608 cases_used.append(i)
3609 if new_label == new_error_label:
3610 error_label_used = 1
3611 error_label_case = i
3612 if cases_used:
3613 code.putln(
3614 "int __pyx_why;")
3615 if error_label_used and self.preserve_exception:
3616 code.putln(
3617 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
3618 code.putln(
3619 "int %s;" % Naming.exc_lineno_name)
3620 code.use_label(catch_label)
3621 code.putln(
3622 "__pyx_why = 0; goto %s;" % catch_label)
3623 for i in cases_used:
3624 new_label = new_labels[i]
3625 #if new_label and new_label != "<try>":
3626 if new_label == new_error_label and self.preserve_exception:
3627 self.put_error_catcher(code,
3628 new_error_label, i+1, catch_label)
3629 else:
3630 code.putln(
3631 "%s: __pyx_why = %s; goto %s;" % (
3632 new_label,
3633 i+1,
3634 catch_label))
3635 code.put_label(catch_label)
3636 code.set_all_labels(old_labels)
3637 if error_label_used:
3638 code.new_error_label()
3639 finally_error_label = code.error_label
3640 self.finally_clause.generate_execution_code(code)
3641 if error_label_used:
3642 if finally_error_label in code.labels_used and self.preserve_exception:
3643 over_label = code.new_label()
3644 code.put_goto(over_label);
3645 code.put_label(finally_error_label)
3646 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
3647 for var in Naming.exc_vars:
3648 code.putln("Py_XDECREF(%s);" % var)
3649 code.putln("}")
3650 code.put_goto(old_error_label)
3651 code.put_label(over_label)
3652 code.error_label = old_error_label
3653 if cases_used:
3654 code.putln(
3655 "switch (__pyx_why) {")
3656 for i in cases_used:
3657 old_label = old_labels[i]
3658 if old_label == old_error_label and self.preserve_exception:
3659 self.put_error_uncatcher(code, i+1, old_error_label)
3660 else:
3661 code.use_label(old_label)
3662 code.putln(
3663 "case %s: goto %s;" % (
3664 i+1,
3665 old_label))
3666 code.putln(
3667 "}")
3668 code.putln(
3669 "}")
3671 def put_error_catcher(self, code, error_label, i, catch_label):
3672 code.putln(
3673 "%s: {" %
3674 error_label)
3675 code.putln(
3676 "__pyx_why = %s;" %
3677 i)
3678 code.put_var_xdecrefs_clear(self.cleanup_list)
3679 code.putln(
3680 "PyErr_Fetch(&%s, &%s, &%s);" %
3681 Naming.exc_vars)
3682 code.putln(
3683 "%s = %s;" % (
3684 Naming.exc_lineno_name, Naming.lineno_cname))
3685 #code.putln(
3686 # "goto %s;" %
3687 # catch_label)
3688 code.put_goto(catch_label)
3689 code.putln(
3690 "}")
3692 def put_error_uncatcher(self, code, i, error_label):
3693 code.putln(
3694 "case %s: {" %
3695 i)
3696 code.putln(
3697 "PyErr_Restore(%s, %s, %s);" %
3698 Naming.exc_vars)
3699 code.putln(
3700 "%s = %s;" % (
3701 Naming.lineno_cname, Naming.exc_lineno_name))
3702 for var in Naming.exc_vars:
3703 code.putln(
3704 "%s = 0;" %
3705 var)
3706 code.put_goto(error_label)
3707 code.putln(
3708 "}")
3710 def annotate(self, code):
3711 self.body.annotate(code)
3712 self.finally_clause.annotate(code)
3715 class GILStatNode(TryFinallyStatNode):
3716 # 'with gil' or 'with nogil' statement
3718 # state string 'gil' or 'nogil'
3720 child_attrs = []
3722 preserve_exception = 0
3724 def __init__(self, pos, state, body):
3725 self.state = state
3726 TryFinallyStatNode.__init__(self, pos,
3727 body = body,
3728 finally_clause = GILExitNode(pos, state = state))
3730 def analyse_expressions(self, env):
3731 was_nogil = env.nogil
3732 env.nogil = 1
3733 TryFinallyStatNode.analyse_expressions(self, env)
3734 env.nogil = was_nogil
3736 def gil_check(self, env):
3737 pass
3739 def generate_execution_code(self, code):
3740 code.putln("/*with %s:*/ {" % self.state)
3741 if self.state == 'gil':
3742 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
3743 else:
3744 code.putln("PyThreadState *_save;")
3745 code.putln("Py_UNBLOCK_THREADS")
3746 TryFinallyStatNode.generate_execution_code(self, code)
3747 code.putln("}")
3750 class GILExitNode(StatNode):
3751 # Used as the 'finally' block in a GILStatNode
3753 # state string 'gil' or 'nogil'
3755 child_attrs = []
3757 def analyse_expressions(self, env):
3758 pass
3760 def generate_execution_code(self, code):
3761 if self.state == 'gil':
3762 code.putln("PyGILState_Release();")
3763 else:
3764 code.putln("Py_BLOCK_THREADS")
3767 class CImportStatNode(StatNode):
3768 # cimport statement
3770 # module_name string Qualified name of module being imported
3771 # as_name string or None Name specified in "as" clause, if any
3773 child_attrs = []
3775 def analyse_declarations(self, env):
3776 if not env.is_module_scope:
3777 error(self.pos, "cimport only allowed at module level")
3778 return
3779 module_scope = env.find_module(self.module_name, self.pos)
3780 if "." in self.module_name:
3781 names = [EncodedString(name) for name in self.module_name.split(".")]
3782 top_name = names[0]
3783 top_module_scope = env.context.find_submodule(top_name)
3784 module_scope = top_module_scope
3785 for name in names[1:]:
3786 submodule_scope = module_scope.find_submodule(name)
3787 module_scope.declare_module(name, submodule_scope, self.pos)
3788 module_scope = submodule_scope
3789 if self.as_name:
3790 env.declare_module(self.as_name, module_scope, self.pos)
3791 else:
3792 env.declare_module(top_name, top_module_scope, self.pos)
3793 else:
3794 name = self.as_name or self.module_name
3795 env.declare_module(name, module_scope, self.pos)
3797 def analyse_expressions(self, env):
3798 pass
3800 def generate_execution_code(self, code):
3801 pass
3804 class FromCImportStatNode(StatNode):
3805 # from ... cimport statement
3807 # module_name string Qualified name of module
3808 # imported_names [(pos, name, as_name, kind)] Names to be imported
3810 child_attrs = []
3812 def analyse_declarations(self, env):
3813 if not env.is_module_scope:
3814 error(self.pos, "cimport only allowed at module level")
3815 return
3816 module_scope = env.find_module(self.module_name, self.pos)
3817 env.add_imported_module(module_scope)
3818 for pos, name, as_name, kind in self.imported_names:
3819 if name == "*":
3820 for local_name, entry in module_scope.entries.items():
3821 env.add_imported_entry(local_name, entry, pos)
3822 else:
3823 entry = module_scope.lookup(name)
3824 if entry:
3825 if kind and not self.declaration_matches(entry, kind):
3826 entry.redeclared(pos)
3827 else:
3828 if kind == 'struct' or kind == 'union':
3829 entry = module_scope.declare_struct_or_union(name,
3830 kind = kind, scope = None, typedef_flag = 0, pos = pos)
3831 elif kind == 'class':
3832 entry = module_scope.declare_c_class(name, pos = pos,
3833 module_name = self.module_name)
3834 else:
3835 error(pos, "Name '%s' not declared in module '%s'"
3836 % (name, self.module_name))
3838 if entry:
3839 local_name = as_name or name
3840 env.add_imported_entry(local_name, entry, pos)
3842 def declaration_matches(self, entry, kind):
3843 if not entry.is_type:
3844 return 0
3845 type = entry.type
3846 if kind == 'class':
3847 if not type.is_extension_type:
3848 return 0
3849 else:
3850 if not type.is_struct_or_union:
3851 return 0
3852 if kind <> type.kind:
3853 return 0
3854 return 1
3856 def analyse_expressions(self, env):
3857 pass
3859 def generate_execution_code(self, code):
3860 pass
3863 class FromImportStatNode(StatNode):
3864 # from ... import statement
3866 # module ImportNode
3867 # items [(string, NameNode)]
3868 # interned_items [(string, NameNode)]
3869 # item PyTempNode used internally
3870 # import_star boolean used internally
3872 child_attrs = ["module"]
3873 import_star = 0
3875 def analyse_declarations(self, env):
3876 for name, target in self.items:
3877 if name == "*":
3878 if not env.is_module_scope:
3879 error(self.pos, "import * only allowed at module level")
3880 return
3881 env.has_import_star = 1
3882 self.import_star = 1
3883 else:
3884 target.analyse_target_declaration(env)
3886 def analyse_expressions(self, env):
3887 import ExprNodes
3888 self.module.analyse_expressions(env)
3889 self.item = ExprNodes.PyTempNode(self.pos, env)
3890 self.item.allocate_temp(env)
3891 self.interned_items = []
3892 for name, target in self.items:
3893 if name == '*':
3894 for _, entry in env.entries.items():
3895 if not entry.is_type and entry.type.is_extension_type:
3896 env.use_utility_code(ExprNodes.type_test_utility_code)
3897 break
3898 else:
3899 self.interned_items.append(
3900 (env.intern_identifier(name), target))
3901 target.analyse_target_expression(env, None)
3902 #target.release_target_temp(env) # was release_temp ?!?
3903 self.module.release_temp(env)
3904 self.item.release_temp(env)
3906 def generate_execution_code(self, code):
3907 self.module.generate_evaluation_code(code)
3908 if self.import_star:
3909 code.putln(
3910 'if (%s(%s) < 0) %s;' % (
3911 Naming.import_star,
3912 self.module.py_result(),
3913 code.error_goto(self.pos)))
3914 for cname, target in self.interned_items:
3915 code.putln(
3916 '%s = PyObject_GetAttr(%s, %s); %s' % (
3917 self.item.result_code,
3918 self.module.py_result(),
3919 cname,
3920 code.error_goto_if_null(self.item.result_code, self.pos)))
3921 target.generate_assignment_code(self.item, code)
3922 self.module.generate_disposal_code(code)
3924 #------------------------------------------------------------------------------------
3926 # Runtime support code
3928 #------------------------------------------------------------------------------------
3930 utility_function_predeclarations = \
3931 """
3932 #ifdef __GNUC__
3933 #define INLINE __inline__
3934 #elif _WIN32
3935 #define INLINE __inline
3936 #else
3937 #define INLINE
3938 #endif
3940 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
3942 """ + """
3944 static int %(skip_dispatch_cname)s = 0;
3946 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
3948 if Options.gcc_branch_hints:
3949 branch_prediction_macros = \
3950 """
3951 #ifdef __GNUC__
3952 /* Test for GCC > 2.95 */
3953 #if __GNUC__ > 2 || \
3954 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
3955 #define likely(x) __builtin_expect(!!(x), 1)
3956 #define unlikely(x) __builtin_expect(!!(x), 0)
3957 #else /* __GNUC__ > 2 ... */
3958 #define likely(x) (x)
3959 #define unlikely(x) (x)
3960 #endif /* __GNUC__ > 2 ... */
3961 #else /* __GNUC__ */
3962 #define likely(x) (x)
3963 #define unlikely(x) (x)
3964 #endif /* __GNUC__ */
3965 """
3966 else:
3967 branch_prediction_macros = \
3968 """
3969 #define likely(x) (x)
3970 #define unlikely(x) (x)
3971 """
3973 #get_name_predeclaration = \
3974 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
3976 #get_name_interned_predeclaration = \
3977 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
3979 #------------------------------------------------------------------------------------
3981 printing_utility_code = [
3982 """
3983 static int __Pyx_Print(PyObject *, int); /*proto*/
3984 #if PY_MAJOR_VERSION >= 3
3985 static PyObject* %s = 0;
3986 static PyObject* %s = 0;
3987 #endif
3988 """ % (Naming.print_function, Naming.print_function_kwargs), r"""
3989 #if PY_MAJOR_VERSION < 3
3990 static PyObject *__Pyx_GetStdout(void) {
3991 PyObject *f = PySys_GetObject("stdout");
3992 if (!f) {
3993 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
3995 return f;
3998 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
3999 PyObject *f;
4000 PyObject* v;
4001 int i;
4003 if (!(f = __Pyx_GetStdout()))
4004 return -1;
4005 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4006 if (PyFile_SoftSpace(f, 1)) {
4007 if (PyFile_WriteString(" ", f) < 0)
4008 return -1;
4010 v = PyTuple_GET_ITEM(arg_tuple, i);
4011 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4012 return -1;
4013 if (PyString_Check(v)) {
4014 char *s = PyString_AsString(v);
4015 Py_ssize_t len = PyString_Size(v);
4016 if (len > 0 &&
4017 isspace(Py_CHARMASK(s[len-1])) &&
4018 s[len-1] != ' ')
4019 PyFile_SoftSpace(f, 0);
4022 if (newline) {
4023 if (PyFile_WriteString("\n", f) < 0)
4024 return -1;
4025 PyFile_SoftSpace(f, 0);
4027 return 0;
4030 #else /* Python 3 has a print function */
4031 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4032 PyObject* kwargs = 0;
4033 PyObject* result = 0;
4034 PyObject* end_string;
4035 if (!%(PRINT_FUNCTION)s) {
4036 %(PRINT_FUNCTION)s = PyObject_GetAttrString(%(BUILTINS)s, "print");
4037 if (!%(PRINT_FUNCTION)s)
4038 return -1;
4040 if (!newline) {
4041 if (!%(PRINT_KWARGS)s) {
4042 %(PRINT_KWARGS)s = PyDict_New();
4043 if (!%(PRINT_KWARGS)s)
4044 return -1;
4045 end_string = PyUnicode_FromStringAndSize(" ", 1);
4046 if (!end_string)
4047 return -1;
4048 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4049 Py_DECREF(end_string);
4050 return -1;
4052 Py_DECREF(end_string);
4054 kwargs = %(PRINT_KWARGS)s;
4056 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4057 if (!result)
4058 return -1;
4059 Py_DECREF(result);
4060 return 0;
4062 #endif
4063 """ % {'BUILTINS' : Naming.builtins_cname,
4064 'PRINT_FUNCTION' : Naming.print_function,
4065 'PRINT_KWARGS' : Naming.print_function_kwargs}
4068 #------------------------------------------------------------------------------------
4070 # The following function is based on do_raise() from ceval.c.
4072 raise_utility_code = [
4073 """
4074 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4075 ""","""
4076 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4077 Py_XINCREF(type);
4078 Py_XINCREF(value);
4079 Py_XINCREF(tb);
4080 /* First, check the traceback argument, replacing None with NULL. */
4081 if (tb == Py_None) {
4082 Py_DECREF(tb);
4083 tb = 0;
4085 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4086 PyErr_SetString(PyExc_TypeError,
4087 "raise: arg 3 must be a traceback or None");
4088 goto raise_error;
4090 /* Next, replace a missing value with None */
4091 if (value == NULL) {
4092 value = Py_None;
4093 Py_INCREF(value);
4095 #if PY_VERSION_HEX < 0x02050000
4096 if (!PyClass_Check(type))
4097 #else
4098 if (!PyType_Check(type))
4099 #endif
4101 /* Raising an instance. The value should be a dummy. */
4102 if (value != Py_None) {
4103 PyErr_SetString(PyExc_TypeError,
4104 "instance exception may not have a separate value");
4105 goto raise_error;
4107 /* Normalize to raise <class>, <instance> */
4108 Py_DECREF(value);
4109 value = type;
4110 #if PY_VERSION_HEX < 0x02050000
4111 if (PyInstance_Check(type)) {
4112 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4113 Py_INCREF(type);
4115 else {
4116 type = 0;
4117 PyErr_SetString(PyExc_TypeError,
4118 "raise: exception must be an old-style class or instance");
4119 goto raise_error;
4121 #else
4122 type = (PyObject*) Py_TYPE(type);
4123 Py_INCREF(type);
4124 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4125 PyErr_SetString(PyExc_TypeError,
4126 "raise: exception class must be a subclass of BaseException");
4127 goto raise_error;
4129 #endif
4131 PyErr_Restore(type, value, tb);
4132 return;
4133 raise_error:
4134 Py_XDECREF(value);
4135 Py_XDECREF(type);
4136 Py_XDECREF(tb);
4137 return;
4139 """]
4141 #------------------------------------------------------------------------------------
4143 reraise_utility_code = [
4144 """
4145 static void __Pyx_ReRaise(void); /*proto*/
4146 ""","""
4147 static void __Pyx_ReRaise(void) {
4148 PyThreadState *tstate = PyThreadState_Get();
4149 PyObject *type = tstate->exc_type;
4150 PyObject *value = tstate->exc_value;
4151 PyObject *tb = tstate->exc_traceback;
4152 Py_XINCREF(type);
4153 Py_XINCREF(value);
4154 Py_XINCREF(tb);
4155 PyErr_Restore(type, value, tb);
4157 """]
4159 #------------------------------------------------------------------------------------
4161 arg_type_test_utility_code = [
4162 """
4163 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name, int exact); /*proto*/
4164 ""","""
4165 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name, int exact) {
4166 if (!type) {
4167 PyErr_Format(PyExc_SystemError, "Missing type object");
4168 return 0;
4170 if (none_allowed && obj == Py_None) return 1;
4171 else if (exact) {
4172 if (Py_TYPE(obj) == type) return 1;
4174 else {
4175 if (PyObject_TypeCheck(obj, type)) return 1;
4177 PyErr_Format(PyExc_TypeError,
4178 "Argument '%s' has incorrect type (expected %s, got %s)",
4179 name, type->tp_name, Py_TYPE(obj)->tp_name);
4180 return 0;
4182 """]
4184 #------------------------------------------------------------------------------------
4186 # __Pyx_SplitStarArg splits the args tuple into two parts, one part
4187 # suitable for passing to PyArg_ParseTupleAndKeywords, and the other
4188 # containing any extra arguments. On success, replaces the borrowed
4189 # reference *args with references to a new tuple, and passes back a
4190 # new reference in *args2. Does not touch any of its arguments on
4191 # failure.
4193 get_stararg_utility_code = [
4194 """
4195 static INLINE int __Pyx_SplitStarArg(PyObject **args, Py_ssize_t nargs, PyObject **args2); /*proto*/
4196 ""","""
4197 static INLINE int __Pyx_SplitStarArg(
4198 PyObject **args,
4199 Py_ssize_t nargs,
4200 PyObject **args2)
4202 PyObject *args1 = 0;
4203 args1 = PyTuple_GetSlice(*args, 0, nargs);
4204 if (!args1) {
4205 *args2 = 0;
4206 return -1;
4208 *args2 = PyTuple_GetSlice(*args, nargs, PyTuple_GET_SIZE(*args));
4209 if (!*args2) {
4210 Py_DECREF(args1);
4211 return -1;
4213 *args = args1;
4214 return 0;
4216 """]
4218 #------------------------------------------------------------------------------------
4220 # __Pyx_RaiseArgtupleTooLong raises the correct exception when too
4221 # many positional arguments were found. This handles Py_ssize_t
4222 # formatting correctly.
4224 raise_argtuple_too_long_utility_code = [
4225 """
4226 static INLINE void __Pyx_RaiseArgtupleTooLong(Py_ssize_t num_expected, Py_ssize_t num_found); /*proto*/
4227 ""","""
4228 static INLINE void __Pyx_RaiseArgtupleTooLong(
4229 Py_ssize_t num_expected,
4230 Py_ssize_t num_found)
4232 const char* error_message =
4233 #if PY_VERSION_HEX < 0x02050000
4234 "function takes at most %d positional arguments (%d given)";
4235 #else
4236 "function takes at most %zd positional arguments (%zd given)";
4237 #endif
4238 PyErr_Format(PyExc_TypeError, error_message, num_expected, num_found);
4240 """]
4242 #------------------------------------------------------------------------------------
4244 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
4245 # were passed to a function, or if any keywords were passed to a
4246 # function that does not accept them.
4248 get_keyword_string_check_utility_code = [
4249 """
4250 static int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed); /*proto*/
4251 ""","""
4252 static int __Pyx_CheckKeywordStrings(
4253 PyObject *kwdict,
4254 const char* function_name,
4255 int kw_allowed)
4257 PyObject* key = 0;
4258 Py_ssize_t pos = 0;
4259 while (PyDict_Next(kwdict, &pos, &key, 0)) {
4260 #if PY_MAJOR_VERSION < 3
4261 if (unlikely(!PyString_Check(key))) {
4262 #else
4263 if (unlikely(!PyUnicode_Check(key))) {
4264 #endif
4265 PyErr_Format(PyExc_TypeError,
4266 "%s() keywords must be strings", function_name);
4267 return 0;
4270 if (unlikely(!kw_allowed) && unlikely(key)) {
4271 PyErr_Format(PyExc_TypeError,
4272 "'%s' is an invalid keyword argument for this function",
4273 #if PY_MAJOR_VERSION < 3
4274 PyString_AsString(key));
4275 #else
4276 PyUnicode_AsString(key));
4277 #endif
4278 return 0;
4280 return 1;
4282 """]
4284 #------------------------------------------------------------------------------------
4286 # __Pyx_SplitKeywords splits the kwds dict into two parts one part
4287 # suitable for passing to PyArg_ParseTupleAndKeywords, and the other
4288 # containing any extra arguments. On success, replaces the borrowed
4289 # reference *kwds with references to a new dict, and passes back a
4290 # new reference in *kwds2. Does not touch any of its arguments on
4291 # failure.
4293 # Any of *kwds and kwds2 may be 0 (but not kwds). If *kwds == 0, it
4294 # is not changed. If kwds2 == 0 and *kwds != 0, a new reference to
4295 # the same dictionary is passed back in *kwds.
4297 # If rqd_kwds is not 0, it is an array of booleans corresponding to
4298 # the names in kwd_list, indicating required keyword arguments. If
4299 # any of these are not present in kwds, an exception is raised.
4302 get_splitkeywords_utility_code = [
4303 """
4304 static int __Pyx_SplitKeywords(PyObject **kwds, char *kwd_list[], \
4305 PyObject **kwds2, char rqd_kwds[]); /*proto*/
4306 ""","""
4307 static int __Pyx_SplitKeywords(
4308 PyObject **kwds,
4309 char *kwd_list[],
4310 PyObject **kwds2,
4311 char rqd_kwds[])
4313 PyObject *s = 0, *x = 0, *kwds1 = 0;
4314 int i;
4315 char **p;
4317 if (*kwds) {
4318 kwds1 = PyDict_New();
4319 if (!kwds1)
4320 goto bad;
4321 *kwds2 = PyDict_Copy(*kwds);
4322 if (!*kwds2)
4323 goto bad;
4324 for (i = 0, p = kwd_list; *p; i++, p++) {
4325 #if PY_MAJOR_VERSION < 3
4326 s = PyString_FromString(*p);
4327 #else
4328 s = PyUnicode_FromString(*p);
4329 #endif
4330 x = PyDict_GetItem(*kwds, s);
4331 if (x) {
4332 if (PyDict_SetItem(kwds1, s, x) < 0)
4333 goto bad;
4334 if (PyDict_DelItem(*kwds2, s) < 0)
4335 goto bad;
4337 else if (rqd_kwds && rqd_kwds[i])
4338 goto missing_kwarg;
4339 Py_DECREF(s);
4341 s = 0;
4343 else {
4344 if (rqd_kwds) {
4345 for (i = 0, p = kwd_list; *p; i++, p++)
4346 if (rqd_kwds[i])
4347 goto missing_kwarg;
4349 *kwds2 = PyDict_New();
4350 if (!*kwds2)
4351 goto bad;
4354 *kwds = kwds1;
4355 return 0;
4356 missing_kwarg:
4357 PyErr_Format(PyExc_TypeError,
4358 "required keyword argument '%s' is missing", *p);
4359 bad:
4360 Py_XDECREF(s);
4361 Py_XDECREF(kwds1);
4362 Py_XDECREF(*kwds2);
4363 return -1;
4365 """]
4367 get_checkkeywords_utility_code = [
4368 """
4369 static INLINE int __Pyx_CheckRequiredKeywords(PyObject *kwds, char *kwd_list[],
4370 char rqd_kwds[]); /*proto*/
4371 ""","""
4372 static INLINE int __Pyx_CheckRequiredKeywords(
4373 PyObject *kwds,
4374 char *kwd_list[],
4375 char rqd_kwds[])
4377 int i;
4378 char **p;
4380 if (kwds) {
4381 for (i = 0, p = kwd_list; *p; i++, p++)
4382 if (rqd_kwds[i] && !PyDict_GetItemString(kwds, *p))
4383 goto missing_kwarg;
4385 else {
4386 for (i = 0, p = kwd_list; *p; i++, p++)
4387 if (rqd_kwds[i])
4388 goto missing_kwarg;
4391 return 0;
4392 missing_kwarg:
4393 PyErr_Format(PyExc_TypeError,
4394 "required keyword argument '%s' is missing", *p);
4395 return -1;
4397 """]
4399 #------------------------------------------------------------------------------------
4401 unraisable_exception_utility_code = [
4402 """
4403 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
4404 ""","""
4405 static void __Pyx_WriteUnraisable(const char *name) {
4406 PyObject *old_exc, *old_val, *old_tb;
4407 PyObject *ctx;
4408 PyErr_Fetch(&old_exc, &old_val, &old_tb);
4409 #if PY_MAJOR_VERSION < 3
4410 ctx = PyString_FromString(name);
4411 #else
4412 ctx = PyUnicode_FromString(name);
4413 #endif
4414 PyErr_Restore(old_exc, old_val, old_tb);
4415 if (!ctx)
4416 ctx = Py_None;
4417 PyErr_WriteUnraisable(ctx);
4419 """]
4421 #------------------------------------------------------------------------------------
4423 traceback_utility_code = [
4424 """
4425 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
4426 ""","""
4427 #include "compile.h"
4428 #include "frameobject.h"
4429 #include "traceback.h"
4431 static void __Pyx_AddTraceback(const char *funcname) {
4432 PyObject *py_srcfile = 0;
4433 PyObject *py_funcname = 0;
4434 PyObject *py_globals = 0;
4435 PyObject *empty_string = 0;
4436 PyCodeObject *py_code = 0;
4437 PyFrameObject *py_frame = 0;
4439 #if PY_MAJOR_VERSION < 3
4440 py_srcfile = PyString_FromString(%(FILENAME)s);
4441 #else
4442 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
4443 #endif
4444 if (!py_srcfile) goto bad;
4445 if (%(CLINENO)s) {
4446 #if PY_MAJOR_VERSION < 3
4447 py_funcname = PyString_FromFormat( "%%s (%%s:%%u)", funcname, %(CFILENAME)s, %(CLINENO)s);
4448 #else
4449 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%u)", funcname, %(CFILENAME)s, %(CLINENO)s);
4450 #endif
4452 else {
4453 #if PY_MAJOR_VERSION < 3
4454 py_funcname = PyString_FromString(funcname);
4455 #else
4456 py_funcname = PyUnicode_FromString(funcname);
4457 #endif
4459 if (!py_funcname) goto bad;
4460 py_globals = PyModule_GetDict(%(GLOBALS)s);
4461 if (!py_globals) goto bad;
4462 #if PY_MAJOR_VERSION < 3
4463 empty_string = PyString_FromStringAndSize("", 0);
4464 #else
4465 empty_string = PyBytes_FromStringAndSize("", 0);
4466 #endif
4467 if (!empty_string) goto bad;
4468 py_code = PyCode_New(
4469 0, /*int argcount,*/
4470 #if PY_MAJOR_VERSION >= 3
4471 0, /*int kwonlyargcount,*/
4472 #endif
4473 0, /*int nlocals,*/
4474 0, /*int stacksize,*/
4475 0, /*int flags,*/
4476 empty_string, /*PyObject *code,*/
4477 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
4478 %(EMPTY_TUPLE)s, /*PyObject *names,*/
4479 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
4480 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
4481 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
4482 py_srcfile, /*PyObject *filename,*/
4483 py_funcname, /*PyObject *name,*/
4484 %(LINENO)s, /*int firstlineno,*/
4485 empty_string /*PyObject *lnotab*/
4486 );
4487 if (!py_code) goto bad;
4488 py_frame = PyFrame_New(
4489 PyThreadState_Get(), /*PyThreadState *tstate,*/
4490 py_code, /*PyCodeObject *code,*/
4491 py_globals, /*PyObject *globals,*/
4492 0 /*PyObject *locals*/
4493 );
4494 if (!py_frame) goto bad;
4495 py_frame->f_lineno = %(LINENO)s;
4496 PyTraceBack_Here(py_frame);
4497 bad:
4498 Py_XDECREF(py_srcfile);
4499 Py_XDECREF(py_funcname);
4500 Py_XDECREF(empty_string);
4501 Py_XDECREF(py_code);
4502 Py_XDECREF(py_frame);
4504 """ % {
4505 'FILENAME': Naming.filename_cname,
4506 'LINENO': Naming.lineno_cname,
4507 'CFILENAME': Naming.cfilenm_cname,
4508 'CLINENO': Naming.clineno_cname,
4509 'GLOBALS': Naming.module_cname,
4510 'EMPTY_TUPLE' : Naming.empty_tuple,
4511 }]
4513 #------------------------------------------------------------------------------------
4515 set_vtable_utility_code = [
4516 """
4517 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
4518 ""","""
4519 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
4520 PyObject *pycobj = 0;
4521 int result;
4523 pycobj = PyCObject_FromVoidPtr(vtable, 0);
4524 if (!pycobj)
4525 goto bad;
4526 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
4527 goto bad;
4528 result = 0;
4529 goto done;
4531 bad:
4532 result = -1;
4533 done:
4534 Py_XDECREF(pycobj);
4535 return result;
4537 """]
4539 #------------------------------------------------------------------------------------
4541 get_vtable_utility_code = [
4542 """
4543 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
4544 """,r"""
4545 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
4546 int result;
4547 PyObject *pycobj;
4549 pycobj = PyMapping_GetItemString(dict, "__pyx_vtable__");
4550 if (!pycobj)
4551 goto bad;
4552 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
4553 if (!*(void **)vtabptr)
4554 goto bad;
4555 result = 0;
4556 goto done;
4558 bad:
4559 result = -1;
4560 done:
4561 Py_XDECREF(pycobj);
4562 return result;
4564 """]
4566 #------------------------------------------------------------------------------------
4568 init_string_tab_utility_code = [
4569 """
4570 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
4571 ""","""
4572 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
4573 while (t->p) {
4574 #if PY_MAJOR_VERSION < 3
4575 if (t->is_unicode && (!t->is_identifier)) {
4576 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
4577 } else if (t->intern) {
4578 *t->p = PyString_InternFromString(t->s);
4579 } else {
4580 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
4582 #else /* Python 3+ has unicode identifiers */
4583 if (t->is_identifier || (t->is_unicode && t->intern)) {
4584 *t->p = PyUnicode_InternFromString(t->s);
4585 } else if (t->is_unicode) {
4586 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
4587 } else {
4588 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
4590 #endif
4591 if (!*t->p)
4592 return -1;
4593 ++t;
4595 return 0;
4597 """]
4599 #------------------------------------------------------------------------------------
4601 get_exception_utility_code = [
4602 """
4603 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
4604 ""","""
4605 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
4606 PyObject *tmp_type, *tmp_value, *tmp_tb;
4607 PyThreadState *tstate = PyThreadState_Get();
4608 PyErr_Fetch(type, value, tb);
4609 PyErr_NormalizeException(type, value, tb);
4610 if (PyErr_Occurred())
4611 goto bad;
4612 Py_INCREF(*type);
4613 Py_INCREF(*value);
4614 Py_INCREF(*tb);
4615 tmp_type = tstate->exc_type;
4616 tmp_value = tstate->exc_value;
4617 tmp_tb = tstate->exc_traceback;
4618 tstate->exc_type = *type;
4619 tstate->exc_value = *value;
4620 tstate->exc_traceback = *tb;
4621 /* Make sure tstate is in a consistent state when we XDECREF
4622 these objects (XDECREF may run arbitrary code). */
4623 Py_XDECREF(tmp_type);
4624 Py_XDECREF(tmp_value);
4625 Py_XDECREF(tmp_tb);
4626 return 0;
4627 bad:
4628 Py_XDECREF(*type);
4629 Py_XDECREF(*value);
4630 Py_XDECREF(*tb);
4631 return -1;
4634 """]
4636 #------------------------------------------------------------------------------------