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