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