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