Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 1174:eedadcc8c22c

Use method to get result code, deferred to code generation time.
author Robert Bradshaw <robertwb@math.washington.edu>
date Tue Sep 23 13:48:06 2008 -0700 (3 years ago)
parents 947f6697b088
children 28b0311d6bff
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
16 from StringEncoding import EncodedString, escape_byte_string, split_docstring
17 import Options
18 import ControlFlow
20 from DebugFlags import debug_disposal_code
22 absolute_path_length = 0
24 def relative_position(pos):
25 """
26 We embed the relative filename in the generated C file, since we
27 don't want to have to regnerate and compile all the source code
28 whenever the Python install directory moves (which could happen,
29 e.g,. when distributing binaries.)
31 INPUT:
32 a position tuple -- (absolute filename, line number column position)
34 OUTPUT:
35 relative filename
36 line number
38 AUTHOR: William Stein
39 """
40 global absolute_path_length
41 if absolute_path_length==0:
42 absolute_path_length = len(os.path.abspath(os.getcwd()))
43 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
45 def embed_position(pos, docstring):
46 if not Options.embed_pos_in_docstring:
47 return docstring
48 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
49 if docstring is None:
50 # unicode string
51 return EncodedString(pos_line)
53 # make sure we can encode the filename in the docstring encoding
54 # otherwise make the docstring a unicode string
55 encoding = docstring.encoding
56 if encoding is not None:
57 try:
58 encoded_bytes = pos_line.encode(encoding)
59 except UnicodeEncodeError:
60 encoding = None
62 if not docstring:
63 # reuse the string encoding of the original docstring
64 doc = EncodedString(pos_line)
65 else:
66 doc = EncodedString(pos_line + u'\n' + docstring)
67 doc.encoding = encoding
68 return doc
70 class Node(object):
71 # pos (string, int, int) Source file position
72 # is_name boolean Is a NameNode
73 # is_literal boolean Is a ConstNode
75 is_name = 0
76 is_literal = 0
77 temps = None
79 # All descandants should set child_attrs to a list of the attributes
80 # containing nodes considered "children" in the tree. Each such attribute
81 # can either contain a single node or a list of nodes. See Visitor.py.
82 child_attrs = None
84 def __init__(self, pos, **kw):
85 self.pos = pos
86 self.__dict__.update(kw)
88 gil_message = "Operation"
90 def gil_check(self, env):
91 if env.nogil:
92 self.gil_error()
94 def gil_error(self):
95 error(self.pos, "%s not allowed without gil" % self.gil_message)
97 def clone_node(self):
98 """Clone the node. This is defined as a shallow copy, except for member lists
99 amongst the child attributes (from get_child_accessors) which are also
100 copied. Lists containing child nodes are thus seen as a way for the node
101 to hold multiple children directly; the list is not treated as a seperate
102 level in the tree."""
103 result = copy.copy(self)
104 for attrname in result.child_attrs:
105 value = getattr(result, attrname)
106 if isinstance(value, list):
107 setattr(result, attrname, [x for x in value])
108 return result
111 #
112 # There are 4 phases of parse tree processing, applied in order to
113 # all the statements in a given scope-block:
114 #
115 # (0) analyse_control_flow
116 # Create the control flow tree into which state can be asserted and
117 # queried.
118 #
119 # (1) analyse_declarations
120 # Make symbol table entries for all declarations at the current
121 # level, both explicit (def, cdef, etc.) and implicit (assignment
122 # to an otherwise undeclared name).
123 #
124 # (2) analyse_expressions
125 # Determine the result types of expressions and fill in the
126 # 'type' attribute of each ExprNode. Insert coercion nodes into the
127 # tree where needed to convert to and from Python objects.
128 # Allocate temporary locals for intermediate results. Fill
129 # in the 'result_code' attribute of each ExprNode with a C code
130 # fragment.
131 #
132 # (3) generate_code
133 # Emit C code for all declarations, statements and expressions.
134 # Recursively applies the 3 processing phases to the bodies of
135 # functions.
136 #
138 def analyse_control_flow(self, env):
139 pass
141 def analyse_declarations(self, env):
142 pass
144 def analyse_expressions(self, env):
145 raise InternalError("analyse_expressions not implemented for %s" % \
146 self.__class__.__name__)
148 def generate_code(self, code):
149 raise InternalError("generate_code not implemented for %s" % \
150 self.__class__.__name__)
152 def annotate(self, code):
153 # mro does the wrong thing
154 if isinstance(self, BlockNode):
155 self.body.annotate(code)
157 def end_pos(self):
158 if not self.child_attrs:
159 return self.pos
160 try:
161 return self._end_pos
162 except AttributeError:
163 pos = self.pos
164 for attr in self.child_attrs:
165 child = getattr(self, attr)
166 # Sometimes lists, sometimes nodes
167 if child is None:
168 pass
169 elif isinstance(child, list):
170 for c in child:
171 pos = max(pos, c.end_pos())
172 else:
173 pos = max(pos, child.end_pos())
174 self._end_pos = pos
175 return pos
177 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
178 if cutoff == 0:
179 return "<...nesting level cutoff...>"
180 if encountered is None:
181 encountered = set()
182 if id(self) in encountered:
183 return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
184 encountered.add(id(self))
186 def dump_child(x, level):
187 if isinstance(x, Node):
188 return x.dump(level, filter_out, cutoff-1, encountered)
189 elif isinstance(x, list):
190 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
191 else:
192 return repr(x)
195 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
196 if len(attrs) == 0:
197 return "<%s (%d)>" % (self.__class__.__name__, id(self))
198 else:
199 indent = " " * level
200 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
201 for key, value in attrs:
202 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
203 res += "%s>" % indent
204 return res
206 class CompilerDirectivesNode(Node):
207 """
208 Sets compiler directives for the children nodes
209 """
210 # directives {string:value} A dictionary holding the right value for
211 # *all* possible directives.
212 # body Node
213 child_attrs = ["body"]
215 def analyse_control_flow(self, env):
216 old = env.directives
217 env.directives = self.directives
218 self.body.analyse_control_flow(env)
219 env.directives = old
221 def analyse_declarations(self, env):
222 old = env.directives
223 env.directives = self.directives
224 self.body.analyse_declarations(env)
225 env.directives = old
227 def analyse_expressions(self, env):
228 old = env.directives
229 env.directives = self.directives
230 self.body.analyse_expressions(env)
231 env.directives = old
233 def generate_function_definitions(self, env, code):
234 env_old = env.directives
235 code_old = code.globalstate.directives
236 code.globalstate.directives = self.directives
237 self.body.generate_function_definitions(env, code)
238 env.directives = env_old
239 code.globalstate.directives = code_old
241 def generate_execution_code(self, code):
242 old = code.globalstate.directives
243 code.globalstate.directives = self.directives
244 self.body.generate_execution_code(code)
245 code.globalstate.directives = old
247 def annotate(self, code):
248 old = code.globalstate.directives
249 code.globalstate.directives = self.directives
250 self.body.annotate(code)
251 code.globalstate.directives = old
253 class BlockNode:
254 # Mixin class for nodes representing a declaration block.
256 def generate_const_definitions(self, env, code):
257 if env.const_entries:
258 for entry in env.const_entries:
259 if not entry.is_interned:
260 code.globalstate.add_const_definition(entry)
262 def generate_interned_string_decls(self, env, code):
263 entries = env.global_scope().new_interned_string_entries
264 if entries:
265 for entry in entries:
266 code.globalstate.add_interned_string_decl(entry)
267 del entries[:]
269 def generate_py_string_decls(self, env, code):
270 if env is None:
271 return # earlier error
272 entries = env.pystring_entries
273 if entries:
274 for entry in entries:
275 if not entry.is_interned:
276 code.globalstate.add_py_string_decl(entry)
278 def generate_interned_num_decls(self, env, code):
279 # Flush accumulated interned nums from the global scope
280 # and generate declarations for them.
281 genv = env.global_scope()
282 entries = genv.interned_nums
283 if entries:
284 for entry in entries:
285 code.globalstate.add_interned_num_decl(entry)
286 del entries[:]
288 def generate_cached_builtins_decls(self, env, code):
289 entries = env.global_scope().undeclared_cached_builtins
290 for entry in entries:
291 code.globalstate.add_cached_builtin_decl(entry)
292 del entries[:]
295 class StatListNode(Node):
296 # stats a list of StatNode
298 child_attrs = ["stats"]
300 def create_analysed(pos, env, *args, **kw):
301 node = StatListNode(pos, *args, **kw)
302 return node # No node-specific analysis necesarry
303 create_analysed = staticmethod(create_analysed)
305 def analyse_control_flow(self, env):
306 for stat in self.stats:
307 stat.analyse_control_flow(env)
309 def analyse_declarations(self, env):
310 #print "StatListNode.analyse_declarations" ###
311 for stat in self.stats:
312 stat.analyse_declarations(env)
314 def analyse_expressions(self, env):
315 #print "StatListNode.analyse_expressions" ###
316 for stat in self.stats:
317 stat.analyse_expressions(env)
319 def generate_function_definitions(self, env, code):
320 #print "StatListNode.generate_function_definitions" ###
321 for stat in self.stats:
322 stat.generate_function_definitions(env, code)
324 def generate_execution_code(self, code):
325 #print "StatListNode.generate_execution_code" ###
326 for stat in self.stats:
327 code.mark_pos(stat.pos)
328 stat.generate_execution_code(code)
330 def annotate(self, code):
331 for stat in self.stats:
332 stat.annotate(code)
335 class StatNode(Node):
336 #
337 # Code generation for statements is split into the following subphases:
338 #
339 # (1) generate_function_definitions
340 # Emit C code for the definitions of any structs,
341 # unions, enums and functions defined in the current
342 # scope-block.
343 #
344 # (2) generate_execution_code
345 # Emit C code for executable statements.
346 #
348 def generate_function_definitions(self, env, code):
349 pass
351 def generate_execution_code(self, code):
352 raise InternalError("generate_execution_code not implemented for %s" % \
353 self.__class__.__name__)
356 class CDefExternNode(StatNode):
357 # include_file string or None
358 # body StatNode
360 child_attrs = ["body"]
362 def analyse_declarations(self, env):
363 if self.include_file:
364 env.add_include_file(self.include_file)
365 old_cinclude_flag = env.in_cinclude
366 env.in_cinclude = 1
367 self.body.analyse_declarations(env)
368 env.in_cinclude = old_cinclude_flag
370 def analyse_expressions(self, env):
371 pass
373 def generate_execution_code(self, code):
374 pass
376 def annotate(self, code):
377 self.body.annotate(code)
380 class CDeclaratorNode(Node):
381 # Part of a C declaration.
382 #
383 # Processing during analyse_declarations phase:
384 #
385 # analyse
386 # Returns (name, type) pair where name is the
387 # CNameDeclaratorNode of the name being declared
388 # and type is the type it is being declared as.
389 #
390 # calling_convention string Calling convention of CFuncDeclaratorNode
391 # for which this is a base
393 child_attrs = []
395 calling_convention = ""
398 class CNameDeclaratorNode(CDeclaratorNode):
399 # name string The Pyrex name being declared
400 # cname string or None C name, if specified
401 # default ExprNode or None the value assigned on declaration
403 child_attrs = ['default']
405 default = None
407 def analyse(self, base_type, env, nonempty = 0):
408 if nonempty and self.name == '':
409 # May have mistaken the name for the type.
410 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
411 error(self.pos, "Missing argument name")
412 elif base_type.is_void:
413 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
414 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
415 base_type = py_object_type
416 self.type = base_type
417 return self, base_type
419 class CPtrDeclaratorNode(CDeclaratorNode):
420 # base CDeclaratorNode
422 child_attrs = ["base"]
424 def analyse(self, base_type, env, nonempty = 0):
425 if base_type.is_pyobject:
426 error(self.pos,
427 "Pointer base type cannot be a Python object")
428 ptr_type = PyrexTypes.c_ptr_type(base_type)
429 return self.base.analyse(ptr_type, env, nonempty = nonempty)
431 class CArrayDeclaratorNode(CDeclaratorNode):
432 # base CDeclaratorNode
433 # dimension ExprNode
435 child_attrs = ["base", "dimension"]
437 def analyse(self, base_type, env, nonempty = 0):
438 if self.dimension:
439 self.dimension.analyse_const_expression(env)
440 if not self.dimension.type.is_int:
441 error(self.dimension.pos, "Array dimension not integer")
442 size = self.dimension.result()
443 else:
444 size = None
445 if not base_type.is_complete():
446 error(self.pos,
447 "Array element type '%s' is incomplete" % base_type)
448 if base_type.is_pyobject:
449 error(self.pos,
450 "Array element cannot be a Python object")
451 if base_type.is_cfunction:
452 error(self.pos,
453 "Array element cannot be a function")
454 array_type = PyrexTypes.c_array_type(base_type, size)
455 return self.base.analyse(array_type, env, nonempty = nonempty)
458 class CFuncDeclaratorNode(CDeclaratorNode):
459 # base CDeclaratorNode
460 # args [CArgDeclNode]
461 # has_varargs boolean
462 # exception_value ConstNode
463 # exception_check boolean True if PyErr_Occurred check needed
464 # nogil boolean Can be called without gil
465 # with_gil boolean Acquire gil around function body
467 child_attrs = ["base", "args", "exception_value"]
469 overridable = 0
470 optional_arg_count = 0
472 def analyse(self, return_type, env, nonempty = 0):
473 if nonempty:
474 nonempty -= 1
475 func_type_args = []
476 for arg_node in self.args:
477 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
478 name = name_declarator.name
479 if name_declarator.cname:
480 error(self.pos,
481 "Function argument cannot have C name specification")
482 # Turn *[] argument into **
483 if type.is_array:
484 type = PyrexTypes.c_ptr_type(type.base_type)
485 # Catch attempted C-style func(void) decl
486 if type.is_void:
487 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
488 # if type.is_pyobject and self.nogil:
489 # error(self.pos,
490 # "Function with Python argument cannot be declared nogil")
491 func_type_args.append(
492 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
493 if arg_node.default:
494 self.optional_arg_count += 1
495 elif self.optional_arg_count:
496 error(self.pos, "Non-default argument follows default argument")
498 if self.optional_arg_count:
499 scope = StructOrUnionScope()
500 scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
501 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
502 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
503 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
504 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
505 kind = 'struct',
506 scope = scope,
507 typedef_flag = 0,
508 pos = self.pos,
509 cname = struct_cname)
510 self.op_args_struct.defined_in_pxd = 1
511 self.op_args_struct.used = 1
513 exc_val = None
514 exc_check = 0
515 if return_type.is_pyobject \
516 and (self.exception_value or self.exception_check) \
517 and self.exception_check != '+':
518 error(self.pos,
519 "Exception clause not allowed for function returning Python object")
520 else:
521 if self.exception_value:
522 self.exception_value.analyse_const_expression(env)
523 if self.exception_check == '+':
524 exc_val_type = self.exception_value.type
525 if not exc_val_type.is_error and \
526 not exc_val_type.is_pyobject and \
527 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
528 error(self.exception_value.pos,
529 "Exception value must be a Python exception or cdef function with no arguments.")
530 exc_val = self.exception_value
531 else:
532 exc_val = self.exception_value.result()
533 if not return_type.assignable_from(self.exception_value.type):
534 error(self.exception_value.pos,
535 "Exception value incompatible with function return type")
536 exc_check = self.exception_check
537 if return_type.is_array:
538 error(self.pos,
539 "Function cannot return an array")
540 if return_type.is_cfunction:
541 error(self.pos,
542 "Function cannot return a function")
543 func_type = PyrexTypes.CFuncType(
544 return_type, func_type_args, self.has_varargs,
545 optional_arg_count = self.optional_arg_count,
546 exception_value = exc_val, exception_check = exc_check,
547 calling_convention = self.base.calling_convention,
548 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
549 if self.optional_arg_count:
550 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
551 return self.base.analyse(func_type, env)
554 class CArgDeclNode(Node):
555 # Item in a function declaration argument list.
556 #
557 # base_type CBaseTypeNode
558 # declarator CDeclaratorNode
559 # not_none boolean Tagged with 'not None'
560 # default ExprNode or None
561 # default_entry Symtab.Entry Entry for the variable holding the default value
562 # default_result_code string cname or code fragment for default value
563 # is_self_arg boolean Is the "self" arg of an extension type method
564 # is_kw_only boolean Is a keyword-only argument
566 child_attrs = ["base_type", "declarator", "default"]
568 is_self_arg = 0
569 is_generic = 1
571 def analyse(self, env, nonempty = 0):
572 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
573 base_type = self.base_type.analyse(env)
574 return self.declarator.analyse(base_type, env, nonempty = nonempty)
576 def annotate(self, code):
577 if self.default:
578 self.default.annotate(code)
581 class CBaseTypeNode(Node):
582 # Abstract base class for C base type nodes.
583 #
584 # Processing during analyse_declarations phase:
585 #
586 # analyse
587 # Returns the type.
589 pass
591 class CSimpleBaseTypeNode(CBaseTypeNode):
592 # name string
593 # module_path [string] Qualifying name components
594 # is_basic_c_type boolean
595 # signed boolean
596 # longness integer
597 # is_self_arg boolean Is self argument of C method
599 child_attrs = []
601 def analyse(self, env):
602 # Return type descriptor.
603 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
604 type = None
605 if self.is_basic_c_type:
606 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
607 if not type:
608 error(self.pos, "Unrecognised type modifier combination")
609 elif self.name == "object" and not self.module_path:
610 type = py_object_type
611 elif self.name is None:
612 if self.is_self_arg and env.is_c_class_scope:
613 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
614 type = env.parent_type
615 else:
616 type = py_object_type
617 else:
618 scope = env.find_imported_module(self.module_path, self.pos)
619 if scope:
620 if scope.is_c_class_scope:
621 scope = scope.global_scope()
622 entry = scope.find(self.name, self.pos)
623 if entry and entry.is_type:
624 type = entry.type
625 else:
626 error(self.pos, "'%s' is not a type identifier" % self.name)
627 if type:
628 return type
629 else:
630 return PyrexTypes.error_type
632 class CBufferAccessTypeNode(CBaseTypeNode):
633 # After parsing:
634 # positional_args [ExprNode] List of positional arguments
635 # keyword_args DictNode Keyword arguments
636 # base_type_node CBaseTypeNode
638 # After analysis:
639 # type PyrexType.BufferType ...containing the right options
642 child_attrs = ["base_type_node", "positional_args",
643 "keyword_args", "dtype_node"]
645 dtype_node = None
647 def analyse(self, env):
648 base_type = self.base_type_node.analyse(env)
649 if base_type.is_error: return base_type
650 import Buffer
652 options = Buffer.analyse_buffer_options(
653 self.pos,
654 env,
655 self.positional_args,
656 self.keyword_args,
657 base_type.buffer_defaults)
659 self.type = PyrexTypes.BufferType(base_type, **options)
660 return self.type
662 class CComplexBaseTypeNode(CBaseTypeNode):
663 # base_type CBaseTypeNode
664 # declarator CDeclaratorNode
666 child_attrs = ["base_type", "declarator"]
668 def analyse(self, env):
669 base = self.base_type.analyse(env)
670 _, type = self.declarator.analyse(base, env)
671 return type
674 class CVarDefNode(StatNode):
675 # C variable definition or forward/extern function declaration.
676 #
677 # visibility 'private' or 'public' or 'extern'
678 # base_type CBaseTypeNode
679 # declarators [CDeclaratorNode]
680 # in_pxd boolean
681 # api boolean
682 # need_properties [entry]
684 child_attrs = ["base_type", "declarators"]
685 need_properties = ()
687 def analyse_declarations(self, env, dest_scope = None):
688 if not dest_scope:
689 dest_scope = env
690 self.dest_scope = dest_scope
691 base_type = self.base_type.analyse(env)
692 if (dest_scope.is_c_class_scope
693 and self.visibility == 'public'
694 and base_type.is_pyobject
695 and (base_type.is_builtin_type or base_type.is_extension_type)):
696 self.need_properties = []
697 need_property = True
698 visibility = 'private'
699 else:
700 need_property = False
701 visibility = self.visibility
703 for declarator in self.declarators:
704 name_declarator, type = declarator.analyse(base_type, env)
705 if not type.is_complete():
706 if not (self.visibility == 'extern' and type.is_array):
707 error(declarator.pos,
708 "Variable type '%s' is incomplete" % type)
709 if self.visibility == 'extern' and type.is_pyobject:
710 error(declarator.pos,
711 "Python object cannot be declared extern")
712 name = name_declarator.name
713 cname = name_declarator.cname
714 if name == '':
715 error(declarator.pos, "Missing name in declaration.")
716 return
717 if type.is_cfunction:
718 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
719 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
720 api = self.api)
721 else:
722 if self.in_pxd and self.visibility != 'extern':
723 error(self.pos,
724 "Only 'extern' C variable declaration allowed in .pxd file")
725 entry = dest_scope.declare_var(name, type, declarator.pos,
726 cname = cname, visibility = visibility, is_cdef = 1)
727 if need_property:
728 self.need_properties.append(entry)
729 entry.needs_property = 1
732 class CStructOrUnionDefNode(StatNode):
733 # name string
734 # cname string or None
735 # kind "struct" or "union"
736 # typedef_flag boolean
737 # visibility "public" or "private"
738 # in_pxd boolean
739 # attributes [CVarDefNode] or None
740 # entry Entry
742 child_attrs = ["attributes"]
744 def analyse_declarations(self, env):
745 scope = None
746 if self.attributes is not None:
747 scope = StructOrUnionScope(self.name)
748 self.entry = env.declare_struct_or_union(
749 self.name, self.kind, scope, self.typedef_flag, self.pos,
750 self.cname, visibility = self.visibility)
751 if self.attributes is not None:
752 if self.in_pxd and not env.in_cinclude:
753 self.entry.defined_in_pxd = 1
754 for attr in self.attributes:
755 attr.analyse_declarations(env, scope)
757 def analyse_expressions(self, env):
758 pass
760 def generate_execution_code(self, code):
761 pass
764 class CEnumDefNode(StatNode):
765 # name string or None
766 # cname string or None
767 # items [CEnumDefItemNode]
768 # typedef_flag boolean
769 # visibility "public" or "private"
770 # in_pxd boolean
771 # entry Entry
773 child_attrs = ["items"]
775 def analyse_declarations(self, env):
776 self.entry = env.declare_enum(self.name, self.pos,
777 cname = self.cname, typedef_flag = self.typedef_flag,
778 visibility = self.visibility)
779 if self.items is not None:
780 if self.in_pxd and not env.in_cinclude:
781 self.entry.defined_in_pxd = 1
782 for item in self.items:
783 item.analyse_declarations(env, self.entry)
785 def analyse_expressions(self, env):
786 if self.visibility == 'public':
787 self.temp = env.allocate_temp_pyobject()
788 env.release_temp(self.temp)
790 def generate_execution_code(self, code):
791 if self.visibility == 'public':
792 for item in self.entry.enum_values:
793 code.putln("%s = PyInt_FromLong(%s); %s" % (
794 self.temp,
795 item.cname,
796 code.error_goto_if_null(self.temp, item.pos)))
797 code.putln('if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
798 Naming.module_cname,
799 item.name,
800 self.temp,
801 code.error_goto(item.pos)))
802 code.putln("%s = 0;" % self.temp)
805 class CEnumDefItemNode(StatNode):
806 # name string
807 # cname string or None
808 # value ExprNode or None
810 child_attrs = ["value"]
812 def analyse_declarations(self, env, enum_entry):
813 if self.value:
814 self.value.analyse_const_expression(env)
815 if not self.value.type.is_int:
816 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
817 self.value.analyse_const_expression(env)
818 value = self.value.result()
819 else:
820 value = self.name
821 entry = env.declare_const(self.name, enum_entry.type,
822 value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
823 enum_entry.enum_values.append(entry)
826 class CTypeDefNode(StatNode):
827 # base_type CBaseTypeNode
828 # declarator CDeclaratorNode
829 # visibility "public" or "private"
830 # in_pxd boolean
832 child_attrs = ["base_type", "declarator"]
834 def analyse_declarations(self, env):
835 base = self.base_type.analyse(env)
836 name_declarator, type = self.declarator.analyse(base, env)
837 name = name_declarator.name
838 cname = name_declarator.cname
839 entry = env.declare_typedef(name, type, self.pos,
840 cname = cname, visibility = self.visibility)
841 if self.in_pxd and not env.in_cinclude:
842 entry.defined_in_pxd = 1
844 def analyse_expressions(self, env):
845 pass
846 def generate_execution_code(self, code):
847 pass
850 class FuncDefNode(StatNode, BlockNode):
851 # Base class for function definition nodes.
852 #
853 # return_type PyrexType
854 # #filename string C name of filename string const
855 # entry Symtab.Entry
856 # needs_closure boolean Whether or not this function has inner functions/classes/yield
858 py_func = None
859 assmt = None
860 needs_closure = False
862 def analyse_default_values(self, env):
863 genv = env.global_scope()
864 for arg in self.args:
865 if arg.default:
866 if arg.is_generic:
867 if not hasattr(arg, 'default_entry'):
868 arg.default.analyse_types(env)
869 arg.default = arg.default.coerce_to(arg.type, genv)
870 if arg.default.is_literal:
871 arg.default_entry = arg.default
872 arg.default_result_code = arg.default.calculate_result_code()
873 if arg.default.type != arg.type and not arg.type.is_int:
874 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
875 else:
876 arg.default.allocate_temps(genv)
877 arg.default_entry = genv.add_default_value(arg.type)
878 arg.default_entry.used = 1
879 arg.default_result_code = arg.default_entry.cname
880 else:
881 error(arg.pos,
882 "This argument cannot have a default value")
883 arg.default = None
885 def need_gil_acquisition(self, lenv):
886 return 0
888 def create_local_scope(self, env):
889 genv = env
890 while env.is_py_class_scope or env.is_c_class_scope:
891 env = env.outer_scope
892 if self.needs_closure:
893 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
894 else:
895 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
896 lenv.return_type = self.return_type
897 type = self.entry.type
898 if type.is_cfunction:
899 lenv.nogil = type.nogil and not type.with_gil
900 self.local_scope = lenv
901 return lenv
903 def generate_function_definitions(self, env, code):
904 import Buffer
906 lenv = self.local_scope
908 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
909 self.entry.scope.is_c_class_scope)
911 # Generate C code for header and body of function
912 code.enter_cfunc_scope()
913 code.return_from_error_cleanup_label = code.new_label()
915 # ----- Top-level constants used by this function
916 code.mark_pos(self.pos)
917 self.generate_interned_num_decls(lenv, code)
918 self.generate_interned_string_decls(lenv, code)
919 self.generate_py_string_decls(lenv, code)
920 self.generate_cached_builtins_decls(lenv, code)
921 #code.putln("")
922 #code.put_var_declarations(lenv.const_entries, static = 1)
923 self.generate_const_definitions(lenv, code)
924 # ----- Function header
925 code.putln("")
926 if self.py_func:
927 self.py_func.generate_function_header(code,
928 with_pymethdef = env.is_py_class_scope,
929 proto_only=True)
930 self.generate_function_header(code,
931 with_pymethdef = env.is_py_class_scope)
932 # ----- Local variable declarations
933 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
934 self.generate_argument_declarations(lenv, code)
935 if self.needs_closure:
936 code.putln("/* TODO: declare and create scope object */")
937 code.put_var_declarations(lenv.var_entries)
938 init = ""
939 if not self.return_type.is_void:
940 code.putln(
941 "%s%s;" %
942 (self.return_type.declaration_code(
943 Naming.retval_cname),
944 init))
945 tempvardecl_code = code.insertion_point()
946 self.generate_keyword_list(code)
947 # ----- Extern library function declarations
948 lenv.generate_library_function_declarations(code)
949 # ----- GIL acquisition
950 acquire_gil = self.need_gil_acquisition(lenv)
951 if acquire_gil:
952 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
953 # ----- Automatic lead-ins for certain special functions
954 if is_getbuffer_slot:
955 self.getbuffer_init(code)
956 # ----- Fetch arguments
957 self.generate_argument_parsing_code(env, code)
958 # If an argument is assigned to in the body, we must
959 # incref it to properly keep track of refcounts.
960 for entry in lenv.arg_entries:
961 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
962 code.put_var_incref(entry)
963 # ----- Initialise local variables
964 for entry in lenv.var_entries:
965 if entry.type.is_pyobject and entry.init_to_none and entry.used:
966 code.put_init_var_to_py_none(entry)
967 # ----- Initialise local buffer auxiliary variables
968 for entry in lenv.var_entries + lenv.arg_entries:
969 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
970 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
971 # ----- Check and convert arguments
972 self.generate_argument_type_tests(code)
973 # ----- Acquire buffer arguments
974 for entry in lenv.arg_entries:
975 if entry.type.is_buffer:
976 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
977 # ----- Function body
978 self.body.generate_execution_code(code)
979 # ----- Default return value
980 code.putln("")
981 if self.return_type.is_pyobject:
982 #if self.return_type.is_extension_type:
983 # lhs = "(PyObject *)%s" % Naming.retval_cname
984 #else:
985 lhs = Naming.retval_cname
986 code.put_init_to_py_none(lhs, self.return_type)
987 else:
988 val = self.return_type.default_value
989 if val:
990 code.putln("%s = %s;" % (Naming.retval_cname, val))
991 # ----- Error cleanup
992 if code.error_label in code.labels_used:
993 code.put_goto(code.return_label)
994 code.put_label(code.error_label)
995 code.put_var_xdecrefs(lenv.temp_entries)
997 # Clean up buffers -- this calls a Python function
998 # so need to save and restore error state
999 buffers_present = len(lenv.buffer_entries) > 0
1000 if buffers_present:
1001 code.globalstate.use_utility_code(restore_exception_utility_code)
1002 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1003 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1004 for entry in lenv.buffer_entries:
1005 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1006 #code.putln("%s = 0;" % entry.cname)
1007 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1009 err_val = self.error_value()
1010 exc_check = self.caller_will_check_exceptions()
1011 if err_val is not None or exc_check:
1012 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1013 else:
1014 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1015 % self.entry.qualified_name, 0)
1016 code.putln(
1017 '__Pyx_WriteUnraisable("%s");' %
1018 self.entry.qualified_name)
1019 env.use_utility_code(unraisable_exception_utility_code)
1020 env.use_utility_code(restore_exception_utility_code)
1021 default_retval = self.return_type.default_value
1022 if err_val is None and default_retval:
1023 err_val = default_retval
1024 if err_val is not None:
1025 code.putln(
1026 "%s = %s;" % (
1027 Naming.retval_cname,
1028 err_val))
1030 if is_getbuffer_slot:
1031 self.getbuffer_error_cleanup(code)
1033 # If we are using the non-error cleanup section we should
1034 # jump past it if we have an error. The if-test below determine
1035 # whether this section is used.
1036 if buffers_present or is_getbuffer_slot:
1037 code.put_goto(code.return_from_error_cleanup_label)
1040 # ----- Non-error return cleanup
1041 # If you add anything here, remember to add a condition to the
1042 # if-test above in the error block (so that it can jump past this
1043 # block).
1044 code.put_label(code.return_label)
1045 for entry in lenv.buffer_entries:
1046 if entry.used:
1047 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1048 if is_getbuffer_slot:
1049 self.getbuffer_normal_cleanup(code)
1050 # ----- Return cleanup for both error and no-error return
1051 code.put_label(code.return_from_error_cleanup_label)
1052 if not Options.init_local_none:
1053 for entry in lenv.var_entries:
1054 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1055 entry.xdecref_cleanup = 1
1056 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1057 # Decref any increfed args
1058 for entry in lenv.arg_entries:
1059 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1060 code.put_var_decref(entry)
1061 if acquire_gil:
1062 code.putln("PyGILState_Release(_save);")
1063 # code.putln("/* TODO: decref scope object */")
1064 # ----- Return
1065 if not self.return_type.is_void:
1066 code.putln("return %s;" % Naming.retval_cname)
1067 code.putln("}")
1068 # ----- Go back and insert temp variable declarations
1069 tempvardecl_code.put_var_declarations(lenv.temp_entries)
1070 tempvardecl_code.put_temp_declarations(code.funcstate)
1071 # ----- Python version
1072 code.exit_cfunc_scope()
1073 if self.py_func:
1074 self.py_func.generate_function_definitions(env, code)
1075 self.generate_wrapper_functions(code)
1077 def declare_argument(self, env, arg):
1078 if arg.type.is_void:
1079 error(arg.pos, "Invalid use of 'void'")
1080 elif not arg.type.is_complete() and not arg.type.is_array:
1081 error(arg.pos,
1082 "Argument type '%s' is incomplete" % arg.type)
1083 return env.declare_arg(arg.name, arg.type, arg.pos)
1085 def generate_wrapper_functions(self, code):
1086 pass
1088 def generate_execution_code(self, code):
1089 # Evaluate and store argument default values
1090 for arg in self.args:
1091 default = arg.default
1092 if default:
1093 if not default.is_literal:
1094 default.generate_evaluation_code(code)
1095 default.make_owned_reference(code)
1096 code.putln(
1097 "%s = %s;" % (
1098 arg.default_entry.cname,
1099 default.result_as(arg.default_entry.type)))
1100 if default.is_temp and default.type.is_pyobject:
1101 code.putln(
1102 "%s = 0;" %
1103 default.result())
1104 # For Python class methods, create and store function object
1105 if self.assmt:
1106 self.assmt.generate_execution_code(code)
1109 # Special code for the __getbuffer__ function
1111 def getbuffer_init(self, code):
1112 info = self.local_scope.arg_entries[1].cname
1113 # Python 3.0 betas have a bug in memoryview which makes it call
1114 # getbuffer with a NULL parameter. For now we work around this;
1115 # the following line should be removed when this bug is fixed.
1116 code.putln("if (%s == NULL) return 0;" % info)
1117 code.putln("%s->obj = Py_None; Py_INCREF(Py_None);" % info)
1119 def getbuffer_error_cleanup(self, code):
1120 info = self.local_scope.arg_entries[1].cname
1121 code.putln("Py_DECREF(%s->obj); %s->obj = NULL;" %
1122 (info, info))
1124 def getbuffer_normal_cleanup(self, code):
1125 info = self.local_scope.arg_entries[1].cname
1126 code.putln("if (%s->obj == Py_None) { Py_DECREF(Py_None); %s->obj = NULL; }" %
1127 (info, info))
1129 class CFuncDefNode(FuncDefNode):
1130 # C function definition.
1132 # modifiers ['inline']
1133 # visibility 'private' or 'public' or 'extern'
1134 # base_type CBaseTypeNode
1135 # declarator CDeclaratorNode
1136 # body StatListNode
1137 # api boolean
1139 # with_gil boolean Acquire GIL around body
1140 # type CFuncType
1141 # py_func wrapper for calling from Python
1142 # overridable whether or not this is a cpdef function
1144 child_attrs = ["base_type", "declarator", "body", "py_func"]
1146 def unqualified_name(self):
1147 return self.entry.name
1149 def analyse_declarations(self, env):
1150 base_type = self.base_type.analyse(env)
1151 # The 2 here is because we need both function and argument names.
1152 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1153 if not type.is_cfunction:
1154 error(self.pos,
1155 "Suite attached to non-function declaration")
1156 # Remember the actual type according to the function header
1157 # written here, because the type in the symbol table entry
1158 # may be different if we're overriding a C method inherited
1159 # from the base type of an extension type.
1160 self.type = type
1161 type.is_overridable = self.overridable
1162 declarator = self.declarator
1163 while not hasattr(declarator, 'args'):
1164 declarator = declarator.base
1165 self.args = declarator.args
1166 for formal_arg, type_arg in zip(self.args, type.args):
1167 formal_arg.type = type_arg.type
1168 formal_arg.cname = type_arg.cname
1169 name = name_declarator.name
1170 cname = name_declarator.cname
1171 self.entry = env.declare_cfunction(
1172 name, type, self.pos,
1173 cname = cname, visibility = self.visibility,
1174 defining = self.body is not None,
1175 api = self.api)
1176 self.return_type = type.return_type
1178 if self.overridable:
1179 import ExprNodes
1180 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1181 self.py_func = DefNode(pos = self.pos,
1182 name = self.entry.name,
1183 args = self.args,
1184 star_arg = None,
1185 starstar_arg = None,
1186 doc = self.doc,
1187 body = py_func_body,
1188 is_wrapper = 1)
1189 self.py_func.is_module_scope = env.is_module_scope
1190 self.py_func.analyse_declarations(env)
1191 self.entry.as_variable = self.py_func.entry
1192 # Reset scope entry the above cfunction
1193 env.entries[name] = self.entry
1194 self.py_func.interned_attr_cname = env.intern_identifier(
1195 self.py_func.entry.name)
1196 if not env.is_module_scope or Options.lookup_module_cpdef:
1197 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1198 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1200 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1201 import ExprNodes
1202 args = self.type.args
1203 if omit_optional_args:
1204 args = args[:len(args) - self.type.optional_arg_count]
1205 arg_names = [arg.name for arg in args]
1206 if is_module_scope:
1207 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1208 else:
1209 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1210 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1211 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1212 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)
1213 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1215 def declare_arguments(self, env):
1216 for arg in self.type.args:
1217 if not arg.name:
1218 error(arg.pos, "Missing argument name")
1219 self.declare_argument(env, arg)
1221 def need_gil_acquisition(self, lenv):
1222 type = self.type
1223 with_gil = self.type.with_gil
1224 if type.nogil and not with_gil:
1225 if type.return_type.is_pyobject:
1226 error(self.pos,
1227 "Function with Python return type cannot be declared nogil")
1228 for entry in lenv.var_entries + lenv.temp_entries:
1229 if entry.type.is_pyobject:
1230 error(self.pos, "Function declared nogil has Python locals or temporaries")
1231 return with_gil
1233 def analyse_expressions(self, env):
1234 self.analyse_default_values(env)
1235 if self.overridable:
1236 self.py_func.analyse_expressions(env)
1238 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1239 arg_decls = []
1240 type = self.type
1241 visibility = self.entry.visibility
1242 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1243 arg_decls.append(arg.declaration_code())
1244 if with_dispatch and self.overridable:
1245 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1246 if type.optional_arg_count and with_opt_args:
1247 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1248 if type.has_varargs:
1249 arg_decls.append("...")
1250 if not arg_decls:
1251 arg_decls = ["void"]
1252 if cname is None:
1253 cname = self.entry.func_cname
1254 entity = type.function_header_code(cname, string.join(arg_decls, ", "))
1255 if visibility == 'public':
1256 dll_linkage = "DL_EXPORT"
1257 else:
1258 dll_linkage = None
1259 header = self.return_type.declaration_code(entity,
1260 dll_linkage = dll_linkage)
1261 if visibility != 'private':
1262 storage_class = "%s " % Naming.extern_c_macro
1263 else:
1264 storage_class = "static "
1265 code.putln("%s%s %s {" % (
1266 storage_class,
1267 ' '.join(self.modifiers).upper(), # macro forms
1268 header))
1270 def generate_argument_declarations(self, env, code):
1271 for arg in self.args:
1272 if arg.default:
1273 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1275 def generate_keyword_list(self, code):
1276 pass
1278 def generate_argument_parsing_code(self, env, code):
1279 i = 0
1280 if self.type.optional_arg_count:
1281 code.putln('if (%s) {' % Naming.optional_args_cname)
1282 for arg in self.args:
1283 if arg.default:
1284 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1285 declarator = arg.declarator
1286 while not hasattr(declarator, 'name'):
1287 declarator = declarator.base
1288 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1289 i += 1
1290 for _ in range(self.type.optional_arg_count):
1291 code.putln('}')
1292 code.putln('}')
1294 def generate_argument_conversion_code(self, code):
1295 pass
1297 def generate_argument_type_tests(self, code):
1298 # Generate type tests for args whose type in a parent
1299 # class is a supertype of the declared type.
1300 for arg in self.type.args:
1301 if arg.needs_type_test:
1302 self.generate_arg_type_test(arg, code)
1304 def generate_arg_type_test(self, arg, code):
1305 # Generate type test for one argument.
1306 if arg.type.typeobj_is_available():
1307 typeptr_cname = arg.type.typeptr_cname
1308 arg_code = "((PyObject *)%s)" % arg.cname
1309 code.putln(
1310 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1311 arg_code,
1312 typeptr_cname,
1313 not arg.not_none,
1314 arg.name,
1315 type.is_builtin_type,
1316 code.error_goto(arg.pos)))
1317 else:
1318 error(arg.pos, "Cannot test type of extern C class "
1319 "without type object name specification")
1321 def error_value(self):
1322 if self.return_type.is_pyobject:
1323 return "0"
1324 else:
1325 #return None
1326 return self.entry.type.exception_value
1328 def caller_will_check_exceptions(self):
1329 return self.entry.type.exception_check
1331 def generate_wrapper_functions(self, code):
1332 # If the C signature of a function has changed, we need to generate
1333 # wrappers to put in the slots here.
1334 k = 0
1335 entry = self.entry
1336 func_type = entry.type
1337 while entry.prev_entry is not None:
1338 k += 1
1339 entry = entry.prev_entry
1340 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1341 code.putln()
1342 self.generate_function_header(code,
1343 0,
1344 with_dispatch = entry.type.is_overridable,
1345 with_opt_args = entry.type.optional_arg_count,
1346 cname = entry.func_cname)
1347 if not self.return_type.is_void:
1348 code.put('return ')
1349 args = self.type.args
1350 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1351 if entry.type.is_overridable:
1352 arglist.append(Naming.skip_dispatch_cname)
1353 elif func_type.is_overridable:
1354 arglist.append('0')
1355 if entry.type.optional_arg_count:
1356 arglist.append(Naming.optional_args_cname)
1357 elif func_type.optional_arg_count:
1358 arglist.append('NULL')
1359 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1360 code.putln('}')
1363 class PyArgDeclNode(Node):
1364 # Argument which must be a Python object (used
1365 # for * and ** arguments).
1367 # name string
1368 # entry Symtab.Entry
1369 child_attrs = []
1372 class DecoratorNode(Node):
1373 # A decorator
1375 # decorator NameNode or CallNode
1376 child_attrs = ['decorator']
1379 class DefNode(FuncDefNode):
1380 # A Python function definition.
1382 # name string the Python name of the function
1383 # decorators [DecoratorNode] list of decorators
1384 # args [CArgDeclNode] formal arguments
1385 # star_arg PyArgDeclNode or None * argument
1386 # starstar_arg PyArgDeclNode or None ** argument
1387 # doc EncodedString or None
1388 # body StatListNode
1390 # The following subnode is constructed internally
1391 # when the def statement is inside a Python class definition.
1393 # assmt AssignmentNode Function construction/assignment
1395 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1397 assmt = None
1398 num_kwonly_args = 0
1399 num_required_kw_args = 0
1400 reqd_kw_flags_cname = "0"
1401 is_wrapper = 0
1402 decorators = None
1404 def __init__(self, pos, **kwds):
1405 FuncDefNode.__init__(self, pos, **kwds)
1406 k = rk = r = 0
1407 for arg in self.args:
1408 if arg.kw_only:
1409 k += 1
1410 if not arg.default:
1411 rk += 1
1412 if not arg.default:
1413 r += 1
1414 self.num_kwonly_args = k
1415 self.num_required_kw_args = rk
1416 self.num_required_args = r
1418 entry = None
1420 def analyse_declarations(self, env):
1421 for arg in self.args:
1422 base_type = arg.base_type.analyse(env)
1423 name_declarator, type = \
1424 arg.declarator.analyse(base_type, env)
1425 arg.name = name_declarator.name
1426 if name_declarator.cname:
1427 error(self.pos,
1428 "Python function argument cannot have C name specification")
1429 arg.type = type.as_argument_type()
1430 arg.hdr_type = None
1431 arg.needs_conversion = 0
1432 arg.needs_type_test = 0
1433 arg.is_generic = 1
1434 if arg.not_none and not arg.type.is_extension_type:
1435 error(self.pos,
1436 "Only extension type arguments can have 'not None'")
1437 self.declare_pyfunction(env)
1438 self.analyse_signature(env)
1439 self.return_type = self.entry.signature.return_type()
1441 def analyse_signature(self, env):
1442 any_type_tests_needed = 0
1443 # Use the simpler calling signature for zero- and one-argument functions.
1444 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1445 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1446 if len(self.args) == 0:
1447 self.entry.signature = TypeSlots.pyfunction_noargs
1448 elif len(self.args) == 1:
1449 if self.args[0].default is None and not self.args[0].kw_only:
1450 self.entry.signature = TypeSlots.pyfunction_onearg
1451 elif self.entry.signature is TypeSlots.pymethod_signature:
1452 if len(self.args) == 1:
1453 self.entry.signature = TypeSlots.unaryfunc
1454 elif len(self.args) == 2:
1455 if self.args[1].default is None and not self.args[1].kw_only:
1456 self.entry.signature = TypeSlots.ibinaryfunc
1457 elif self.entry.is_special:
1458 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1459 sig = self.entry.signature
1460 nfixed = sig.num_fixed_args()
1461 for i in range(nfixed):
1462 if i < len(self.args):
1463 arg = self.args[i]
1464 arg.is_generic = 0
1465 if sig.is_self_arg(i):
1466 arg.is_self_arg = 1
1467 arg.hdr_type = arg.type = env.parent_type
1468 arg.needs_conversion = 0
1469 else:
1470 arg.hdr_type = sig.fixed_arg_type(i)
1471 if not arg.type.same_as(arg.hdr_type):
1472 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1473 arg.needs_type_test = 1
1474 any_type_tests_needed = 1
1475 else:
1476 arg.needs_conversion = 1
1477 if arg.needs_conversion:
1478 arg.hdr_cname = Naming.arg_prefix + arg.name
1479 else:
1480 arg.hdr_cname = Naming.var_prefix + arg.name
1481 else:
1482 self.bad_signature()
1483 return
1484 if nfixed < len(self.args):
1485 if not sig.has_generic_args:
1486 self.bad_signature()
1487 for arg in self.args:
1488 if arg.is_generic and \
1489 (arg.type.is_extension_type or arg.type.is_builtin_type):
1490 arg.needs_type_test = 1
1491 any_type_tests_needed = 1
1492 elif arg.type is PyrexTypes.c_py_ssize_t_type:
1493 # Want to use __index__ rather than __int__ method
1494 # that PyArg_ParseTupleAndKeywords calls
1495 arg.needs_conversion = 1
1496 arg.hdr_type = PyrexTypes.py_object_type
1497 arg.hdr_cname = Naming.arg_prefix + arg.name
1498 if any_type_tests_needed:
1499 env.use_utility_code(arg_type_test_utility_code)
1501 def bad_signature(self):
1502 sig = self.entry.signature
1503 expected_str = "%d" % sig.num_fixed_args()
1504 if sig.has_generic_args:
1505 expected_str = expected_str + " or more"
1506 name = self.name
1507 if name.startswith("__") and name.endswith("__"):
1508 desc = "Special method"
1509 else:
1510 desc = "Method"
1511 error(self.pos,
1512 "%s %s has wrong number of arguments "
1513 "(%d declared, %s expected)" % (
1514 desc, self.name, len(self.args), expected_str))
1516 def signature_has_nongeneric_args(self):
1517 argcount = len(self.args)
1518 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1519 return 0
1520 return 1
1522 def signature_has_generic_args(self):
1523 return self.entry.signature.has_generic_args
1525 def declare_pyfunction(self, env):
1526 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1527 name = self.name
1528 entry = env.lookup_here(self.name)
1529 if entry and entry.type.is_cfunction and not self.is_wrapper:
1530 warning(self.pos, "Overriding cdef method with def method.", 5)
1531 entry = env.declare_pyfunction(self.name, self.pos)
1532 self.entry = entry
1533 prefix = env.scope_prefix
1534 entry.func_cname = \
1535 Naming.pyfunc_prefix + prefix + name
1536 entry.pymethdef_cname = \
1537 Naming.pymethdef_prefix + prefix + name
1538 if Options.docstrings:
1539 entry.doc = embed_position(self.pos, self.doc)
1540 entry.doc_cname = \
1541 Naming.funcdoc_prefix + prefix + name
1542 else:
1543 entry.doc = None
1545 def declare_arguments(self, env):
1546 for arg in self.args:
1547 if not arg.name:
1548 error(arg.pos, "Missing argument name")
1549 if arg.needs_conversion:
1550 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1551 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1552 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1553 if arg.type.is_pyobject:
1554 arg.entry.init = "0"
1555 arg.entry.init_to_none = 0
1556 else:
1557 arg.entry = self.declare_argument(env, arg)
1558 arg.entry.used = 1
1559 arg.entry.is_self_arg = arg.is_self_arg
1560 if not arg.is_self_arg:
1561 arg.name_entry = env.get_string_const(
1562 arg.name, identifier = True)
1563 env.add_py_string(arg.name_entry, identifier = True)
1564 if arg.hdr_type:
1565 if arg.is_self_arg or \
1566 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1567 arg.entry.is_declared_generic = 1
1568 self.declare_python_arg(env, self.star_arg)
1569 self.declare_python_arg(env, self.starstar_arg)
1571 def declare_python_arg(self, env, arg):
1572 if arg:
1573 entry = env.declare_var(arg.name,
1574 PyrexTypes.py_object_type, arg.pos)
1575 entry.used = 1
1576 entry.init = "0"
1577 entry.init_to_none = 0
1578 entry.xdecref_cleanup = 1
1579 arg.entry = entry
1580 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1582 def analyse_expressions(self, env):
1583 self.analyse_default_values(env)
1584 if env.is_py_class_scope:
1585 self.synthesize_assignment_node(env)
1587 def synthesize_assignment_node(self, env):
1588 import ExprNodes
1589 self.assmt = SingleAssignmentNode(self.pos,
1590 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1591 rhs = ExprNodes.UnboundMethodNode(self.pos,
1592 class_cname = env.class_obj_cname,
1593 function = ExprNodes.PyCFunctionNode(self.pos,
1594 pymethdef_cname = self.entry.pymethdef_cname)))
1595 self.assmt.analyse_declarations(env)
1596 self.assmt.analyse_expressions(env)
1598 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1599 arg_code_list = []
1600 sig = self.entry.signature
1601 if sig.has_dummy_arg:
1602 arg_code_list.append(
1603 "PyObject *%s" % Naming.self_cname)
1604 for arg in self.args:
1605 if not arg.is_generic:
1606 if arg.is_self_arg:
1607 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1608 else:
1609 arg_code_list.append(
1610 arg.hdr_type.declaration_code(arg.hdr_cname))
1611 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1612 arg_code_list.append("PyObject *unused")
1613 if sig.has_generic_args:
1614 arg_code_list.append(
1615 "PyObject *%s, PyObject *%s"
1616 % (Naming.args_cname, Naming.kwds_cname))
1617 arg_code = ", ".join(arg_code_list)
1618 dc = self.return_type.declaration_code(self.entry.func_cname)
1619 header = "static %s(%s)" % (dc, arg_code)
1620 code.putln("%s; /*proto*/" % header)
1621 if proto_only:
1622 return
1623 if self.entry.doc and Options.docstrings:
1624 docstr = self.entry.doc
1625 if not isinstance(docstr, str):
1626 docstr = docstr.utf8encode()
1627 code.putln(
1628 'static char %s[] = "%s";' % (
1629 self.entry.doc_cname,
1630 split_docstring(escape_byte_string(docstr))))
1631 if with_pymethdef:
1632 code.put(
1633 "static PyMethodDef %s = " %
1634 self.entry.pymethdef_cname)
1635 code.put_pymethoddef(self.entry, ";")
1636 code.putln("%s {" % header)
1638 def generate_argument_declarations(self, env, code):
1639 for arg in self.args:
1640 if arg.is_generic: # or arg.needs_conversion:
1641 if arg.needs_conversion:
1642 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1643 else:
1644 code.put_var_declaration(arg.entry)
1646 def generate_keyword_list(self, code):
1647 if self.signature_has_generic_args() and \
1648 self.signature_has_nongeneric_args():
1649 code.put(
1650 "static PyObject **%s[] = {" %
1651 Naming.pykwdlist_cname)
1652 for arg in self.args:
1653 if arg.is_generic:
1654 code.put('&%s,' % arg.name_entry.pystring_cname)
1655 code.putln("0};")
1657 def generate_argument_parsing_code(self, env, code):
1658 # Generate PyArg_ParseTuple call for generic
1659 # arguments, if any.
1660 if self.entry.signature.has_dummy_arg:
1661 # get rid of unused argument warning
1662 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1664 old_error_label = code.new_error_label()
1665 our_error_label = code.error_label
1666 end_label = code.new_label("argument_unpacking_done")
1668 has_kwonly_args = self.num_kwonly_args > 0
1669 has_star_or_kw_args = self.star_arg is not None \
1670 or self.starstar_arg is not None or has_kwonly_args
1672 if not self.signature_has_generic_args():
1673 if has_star_or_kw_args:
1674 error(self.pos, "This method cannot have * or keyword arguments")
1675 self.generate_argument_conversion_code(code)
1677 elif not self.signature_has_nongeneric_args():
1678 # func(*args) or func(**kw) or func(*args, **kw)
1679 self.generate_stararg_copy_code(code)
1681 else:
1682 positional_args = []
1683 kw_only_args = []
1684 default_seen = 0
1685 for arg in self.args:
1686 arg_entry = arg.entry
1687 if arg.is_generic:
1688 if arg.default:
1689 code.putln(
1690 "%s = %s;" % (
1691 arg_entry.cname,
1692 arg.default_result_code))
1693 default_seen = 1
1694 if not arg.is_self_arg:
1695 if arg.kw_only:
1696 kw_only_args.append(arg)
1697 else:
1698 positional_args.append(arg)
1699 elif arg.kw_only:
1700 kw_only_args.append(arg)
1701 default_seen = 1
1702 elif default_seen:
1703 error(arg.pos, "Non-default argument following default argument")
1704 elif not arg.is_self_arg:
1705 positional_args.append(arg)
1706 if arg.needs_conversion:
1707 format = arg.hdr_type.parsetuple_format
1708 else:
1709 format = arg_entry.type.parsetuple_format
1710 if not format:
1711 error(arg.pos,
1712 "Cannot convert Python object argument to type '%s' (when parsing input arguments)"
1713 % arg.type)
1715 self.generate_tuple_and_keyword_parsing_code(
1716 positional_args, kw_only_args, end_label, code)
1718 code.error_label = old_error_label
1719 if code.label_used(our_error_label):
1720 if not code.label_used(end_label):
1721 code.put_goto(end_label)
1722 code.put_label(our_error_label)
1723 if has_star_or_kw_args:
1724 self.generate_arg_decref(self.star_arg, code)
1725 if self.starstar_arg:
1726 if self.starstar_arg.entry.xdecref_cleanup:
1727 code.put_var_xdecref(self.starstar_arg.entry)
1728 else:
1729 code.put_var_decref(self.starstar_arg.entry)
1730 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1731 code.putln("return %s;" % self.error_value())
1732 if code.label_used(end_label):
1733 code.put_label(end_label)
1735 def generate_arg_assignment(self, arg, item, code):
1736 if arg.type.is_pyobject:
1737 if arg.is_generic:
1738 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1739 code.putln("%s = %s;" % (arg.entry.cname, item))
1740 else:
1741 func = arg.type.from_py_function
1742 if func:
1743 code.putln("%s = %s(%s); %s" % (
1744 arg.entry.cname,
1745 func,
1746 item,
1747 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1748 else:
1749 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1751 def generate_arg_xdecref(self, arg, code):
1752 if arg:
1753 code.put_var_xdecref(arg.entry)
1755 def generate_arg_decref(self, arg, code):
1756 if arg:
1757 code.put_var_decref(arg.entry)
1759 def generate_stararg_copy_code(self, code):
1760 if not self.star_arg:
1761 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1762 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1763 Naming.args_cname)
1764 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
1765 self.name.utf8encode(), Naming.args_cname, self.error_value()))
1766 code.putln("}")
1768 code.globalstate.use_utility_code(keyword_string_check_utility_code)
1770 if self.starstar_arg:
1771 if self.star_arg:
1772 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
1773 else:
1774 kwarg_check = "%s" % Naming.kwds_cname
1775 else:
1776 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
1777 Naming.kwds_cname, Naming.kwds_cname)
1778 code.putln(
1779 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
1780 kwarg_check, Naming.kwds_cname, self.name,
1781 bool(self.starstar_arg), self.error_value()))
1783 if self.starstar_arg:
1784 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
1785 self.starstar_arg.entry.cname,
1786 Naming.kwds_cname,
1787 Naming.kwds_cname))
1788 code.putln("if (unlikely(!%s)) return %s;" % (
1789 self.starstar_arg.entry.cname, self.error_value()))
1790 self.starstar_arg.entry.xdecref_cleanup = 0
1792 if self.star_arg:
1793 code.put_incref(Naming.args_cname, py_object_type)
1794 code.putln("%s = %s;" % (
1795 self.star_arg.entry.cname,
1796 Naming.args_cname))
1797 self.star_arg.entry.xdecref_cleanup = 0
1799 def generate_tuple_and_keyword_parsing_code(self, positional_args,
1800 kw_only_args, success_label, code):
1801 argtuple_error_label = code.new_label("argtuple_error")
1803 min_positional_args = self.num_required_args - self.num_required_kw_args
1804 if len(self.args) > 0 and self.args[0].is_self_arg:
1805 min_positional_args -= 1
1806 max_positional_args = len(positional_args)
1807 has_fixed_positional_count = not self.star_arg and \
1808 min_positional_args == max_positional_args
1810 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
1811 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1812 if self.num_required_kw_args:
1813 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
1815 if self.starstar_arg or self.star_arg:
1816 self.generate_stararg_init_code(max_positional_args, code)
1818 # --- optimised code when we receive keyword arguments
1819 if self.num_required_kw_args:
1820 code.putln("if (likely(%s)) {" % Naming.kwds_cname)
1821 else:
1822 code.putln("if (unlikely(%s) && (PyDict_Size(%s) > 0)) {" % (
1823 Naming.kwds_cname, Naming.kwds_cname))
1824 self.generate_keyword_unpacking_code(
1825 min_positional_args, max_positional_args,
1826 has_fixed_positional_count,
1827 positional_args, kw_only_args, argtuple_error_label, code)
1829 # --- optimised code when we do not receive any keyword arguments
1830 if min_positional_args > 0 or min_positional_args == max_positional_args:
1831 # Python raises arg tuple related errors first, so we must
1832 # check the length here
1833 if min_positional_args == max_positional_args and not self.star_arg:
1834 compare = '!='
1835 else:
1836 compare = '<'
1837 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
1838 Naming.args_cname, compare, min_positional_args))
1839 code.put_goto(argtuple_error_label)
1841 if self.num_required_kw_args:
1842 # pure error case: keywords required but not passed
1843 if max_positional_args > min_positional_args and not self.star_arg:
1844 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
1845 Naming.args_cname, max_positional_args))
1846 code.put_goto(argtuple_error_label)
1847 code.putln('} else {')
1848 for i, arg in enumerate(kw_only_args):
1849 if not arg.default:
1850 # required keyword-only argument missing
1851 code.put('__Pyx_RaiseKeywordRequired("%s", *%s[%d]); ' % (
1852 self.name.utf8encode(), Naming.pykwdlist_cname,
1853 len(positional_args) + i))
1854 code.putln(code.error_goto(self.pos))
1855 break
1856 elif min_positional_args == max_positional_args:
1857 # parse the exact number of positional arguments from the
1858 # args tuple
1859 code.putln('} else {')
1860 for i, arg in enumerate(positional_args):
1861 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
1862 self.generate_arg_assignment(arg, item, code)
1863 else:
1864 # parse the positional arguments from the variable length
1865 # args tuple
1866 code.putln('} else {')
1867 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
1868 reversed_args = list(enumerate(positional_args))[::-1]
1869 for i, arg in reversed_args:
1870 if i >= min_positional_args-1:
1871 if min_positional_args > 1:
1872 code.putln('case %2d:' % (i+1)) # pure code beautification
1873 else:
1874 code.put('case %2d: ' % (i+1))
1875 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
1876 self.generate_arg_assignment(arg, item, code)
1877 if not self.star_arg:
1878 if min_positional_args == 0:
1879 code.put('case 0: ')
1880 code.putln('break;')
1881 code.put('default: ')
1882 code.put_goto(argtuple_error_label)
1883 code.putln('}')
1885 code.putln('}')
1887 if code.label_used(argtuple_error_label):
1888 code.put_goto(success_label)
1889 code.put_label(argtuple_error_label)
1890 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
1891 self.name.utf8encode(), has_fixed_positional_count,
1892 min_positional_args, max_positional_args,
1893 Naming.args_cname))
1894 code.putln(code.error_goto(self.pos))
1896 def generate_stararg_init_code(self, max_positional_args, code):
1897 if self.starstar_arg:
1898 self.starstar_arg.entry.xdecref_cleanup = 0
1899 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
1900 self.starstar_arg.entry.cname,
1901 self.starstar_arg.entry.cname,
1902 self.error_value()))
1903 if self.star_arg:
1904 self.star_arg.entry.xdecref_cleanup = 0
1905 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
1906 Naming.args_cname,
1907 max_positional_args))
1908 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
1909 self.star_arg.entry.cname, Naming.args_cname,
1910 max_positional_args, Naming.args_cname))
1911 if self.starstar_arg:
1912 code.putln("")
1913 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
1914 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
1915 code.putln('return %s;' % self.error_value())
1916 code.putln('}')
1917 else:
1918 code.putln("if (unlikely(!%s)) return %s;" % (
1919 self.star_arg.entry.cname, self.error_value()))
1920 code.putln('} else {')
1921 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
1922 code.put_incref(Naming.empty_tuple, py_object_type)
1923 code.putln('}')
1925 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
1926 has_fixed_positional_count, positional_args,
1927 kw_only_args, argtuple_error_label, code):
1928 all_args = tuple(positional_args) + tuple(kw_only_args)
1929 max_args = len(all_args)
1931 code.putln("PyObject* values[%d] = {%s};" % (
1932 max_args, ('0,'*max_args)[:-1]))
1933 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
1934 Naming.kwds_cname)
1936 # parse the tuple and check that it's not too long
1937 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
1938 if self.star_arg:
1939 code.putln('default:')
1940 for i in range(max_positional_args-1, -1, -1):
1941 code.put('case %2d: ' % (i+1))
1942 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
1943 i, Naming.args_cname, i))
1944 code.putln('case 0: break;')
1945 if not self.star_arg:
1946 code.put('default: ') # more arguments than allowed
1947 code.put_goto(argtuple_error_label)
1948 code.putln('}')
1950 # now fill up the arguments with values from the kw dict
1951 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
1952 for i, arg in enumerate(all_args):
1953 if i <= max_positional_args:
1954 if self.star_arg and i == max_positional_args:
1955 code.putln('default:')
1956 else:
1957 code.putln('case %2d:' % i)
1958 code.putln('values[%d] = PyDict_GetItem(%s, *%s[%d]);' % (
1959 i, Naming.kwds_cname, Naming.pykwdlist_cname, i))
1960 if i < min_positional_args:
1961 code.putln('if (likely(values[%d])) kw_args--;' % i);
1962 if i == 0:
1963 # special case: we know arg 0 is missing
1964 code.put('else ')
1965 code.put_goto(argtuple_error_label)
1966 else:
1967 # provide the correct number of values (args or
1968 # kwargs) that were passed into positional
1969 # arguments up to this point
1970 code.putln('else {')
1971 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
1972 self.name.utf8encode(), has_fixed_positional_count,
1973 min_positional_args, max_positional_args, i))
1974 code.putln(code.error_goto(self.pos))
1975 code.putln('}')
1976 else:
1977 code.putln('if (values[%d]) kw_args--;' % i);
1978 if arg.kw_only and not arg.default:
1979 code.putln('else {')
1980 code.put('__Pyx_RaiseKeywordRequired("%s", *%s[%d]); ' %(
1981 self.name.utf8encode(), Naming.pykwdlist_cname, i))
1982 code.putln(code.error_goto(self.pos))
1983 code.putln('}')
1984 code.putln('}')
1986 code.putln('if (unlikely(kw_args > 0)) {')
1987 # non-positional kw args left in the dict: **kwargs or error
1988 if self.star_arg:
1989 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
1990 Naming.args_cname, max_positional_args,
1991 Naming.args_cname, max_positional_args))
1992 pos_arg_count = "used_pos_args"
1993 else:
1994 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
1995 code.globalstate.use_utility_code(split_keywords_utility_code)
1996 code.put(
1997 'if (unlikely(__Pyx_SplitKeywords(%s, %s, %s, %s, "%s") < 0)) ' % (
1998 Naming.kwds_cname,
1999 Naming.pykwdlist_cname,
2000 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2001 pos_arg_count,
2002 self.name.utf8encode()))
2003 code.putln(code.error_goto(self.pos))
2004 code.putln('}')
2006 # convert arg values to their final type and assign them
2007 for i, arg in enumerate(all_args):
2008 if arg.default:
2009 code.putln("if (values[%d]) {" % i)
2010 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2011 if arg.default:
2012 code.putln('}')
2014 def generate_argument_conversion_code(self, code):
2015 # Generate code to convert arguments from
2016 # signature type to declared type, if needed.
2017 for arg in self.args:
2018 if arg.needs_conversion:
2019 self.generate_arg_conversion(arg, code)
2021 def generate_arg_conversion(self, arg, code):
2022 # Generate conversion code for one argument.
2023 old_type = arg.hdr_type
2024 new_type = arg.type
2025 if old_type.is_pyobject:
2026 if arg.default:
2027 code.putln("if (%s) {" % arg.hdr_cname)
2028 else:
2029 code.putln("assert(%s); {" % arg.hdr_cname)
2030 self.generate_arg_conversion_from_pyobject(arg, code)
2031 code.putln("}")
2032 elif new_type.is_pyobject:
2033 self.generate_arg_conversion_to_pyobject(arg, code)
2034 else:
2035 if new_type.assignable_from(old_type):
2036 code.putln(
2037 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2038 else:
2039 error(arg.pos,
2040 "Cannot convert 1 argument from '%s' to '%s'" %
2041 (old_type, new_type))
2043 def generate_arg_conversion_from_pyobject(self, arg, code):
2044 new_type = arg.type
2045 func = new_type.from_py_function
2046 # copied from CoerceFromPyTypeNode
2047 if func:
2048 code.putln("%s = %s(%s); %s" % (
2049 arg.entry.cname,
2050 func,
2051 arg.hdr_cname,
2052 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2053 else:
2054 error(arg.pos,
2055 "Cannot convert Python object argument to type '%s'"
2056 % new_type)
2058 def generate_arg_conversion_to_pyobject(self, arg, code):
2059 old_type = arg.hdr_type
2060 func = old_type.to_py_function
2061 if func:
2062 code.putln("%s = %s(%s); %s" % (
2063 arg.entry.cname,
2064 func,
2065 arg.hdr_cname,
2066 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2067 else:
2068 error(arg.pos,
2069 "Cannot convert argument of type '%s' to Python object"
2070 % old_type)
2072 def generate_argument_type_tests(self, code):
2073 # Generate type tests for args whose signature
2074 # type is PyObject * and whose declared type is
2075 # a subtype thereof.
2076 for arg in self.args:
2077 if arg.needs_type_test:
2078 self.generate_arg_type_test(arg, code)
2080 def generate_arg_type_test(self, arg, code):
2081 # Generate type test for one argument.
2082 if arg.type.typeobj_is_available():
2083 typeptr_cname = arg.type.typeptr_cname
2084 arg_code = "((PyObject *)%s)" % arg.entry.cname
2085 code.putln(
2086 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2087 arg_code,
2088 typeptr_cname,
2089 not arg.not_none,
2090 arg.name,
2091 arg.type.is_builtin_type,
2092 code.error_goto(arg.pos)))
2093 else:
2094 error(arg.pos, "Cannot test type of extern C class "
2095 "without type object name specification")
2097 def error_value(self):
2098 return self.entry.signature.error_value
2100 def caller_will_check_exceptions(self):
2101 return 1
2103 class OverrideCheckNode(StatNode):
2104 # A Node for dispatching to the def method if it
2105 # is overriden.
2107 # py_func
2109 # args
2110 # func_temp
2111 # body
2113 child_attrs = ['body']
2115 body = None
2117 def analyse_expressions(self, env):
2118 self.args = env.arg_entries
2119 if self.py_func.is_module_scope:
2120 first_arg = 0
2121 else:
2122 first_arg = 1
2123 import ExprNodes
2124 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2125 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2126 call_node = ExprNodes.SimpleCallNode(self.pos,
2127 function=self.func_node,
2128 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2129 self.body = ReturnStatNode(self.pos, value=call_node)
2130 self.body.analyse_expressions(env)
2132 def generate_execution_code(self, code):
2133 # Check to see if we are an extension type
2134 if self.py_func.is_module_scope:
2135 self_arg = "((PyObject *)%s)" % Naming.module_cname
2136 else:
2137 self_arg = "((PyObject *)%s)" % self.args[0].cname
2138 code.putln("/* Check if called by wrapper */")
2139 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2140 code.putln("/* Check if overriden in Python */")
2141 if self.py_func.is_module_scope:
2142 code.putln("else {")
2143 else:
2144 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2145 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2146 # need to get attribute manually--scope would return cdef method
2147 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2148 # It appears that this type is not anywhere exposed in the Python/C API
2149 is_builtin_function_or_method = '(strcmp(Py_TYPE(%s)->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result()
2150 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2151 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2152 self.body.generate_execution_code(code)
2153 code.putln('}')
2154 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2155 code.putln("}")
2157 class ClassDefNode(StatNode, BlockNode):
2158 pass
2160 class PyClassDefNode(ClassDefNode):
2161 # A Python class definition.
2163 # name EncodedString Name of the class
2164 # doc string or None
2165 # body StatNode Attribute definition code
2166 # entry Symtab.Entry
2167 # scope PyClassScope
2169 # The following subnodes are constructed internally:
2171 # dict DictNode Class dictionary
2172 # classobj ClassNode Class object
2173 # target NameNode Variable to assign class object to
2175 child_attrs = ["body", "dict", "classobj", "target"]
2177 def __init__(self, pos, name, bases, doc, body):
2178 StatNode.__init__(self, pos)
2179 self.name = name
2180 self.doc = doc
2181 self.body = body
2182 import ExprNodes
2183 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2184 if self.doc and Options.docstrings:
2185 doc = embed_position(self.pos, self.doc)
2186 doc_node = ExprNodes.StringNode(pos, value = doc)
2187 else:
2188 doc_node = None
2189 self.classobj = ExprNodes.ClassNode(pos, name = name,
2190 bases = bases, dict = self.dict, doc = doc_node)
2191 self.target = ExprNodes.NameNode(pos, name = name)
2193 def create_scope(self, env):
2194 genv = env
2195 while env.is_py_class_scope or env.is_c_class_scope:
2196 env = env.outer_scope
2197 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2198 return cenv
2200 def analyse_declarations(self, env):
2201 self.target.analyse_target_declaration(env)
2202 cenv = self.create_scope(env)
2203 cenv.class_obj_cname = self.target.entry.cname
2204 self.body.analyse_declarations(cenv)
2206 def analyse_expressions(self, env):
2207 self.dict.analyse_expressions(env)
2208 self.classobj.analyse_expressions(env)
2209 genv = env.global_scope()
2210 cenv = self.scope
2211 cenv.class_dict_cname = self.dict.result()
2212 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2213 self.body.analyse_expressions(cenv)
2214 self.target.analyse_target_expression(env, self.classobj)
2215 self.dict.release_temp(env)
2216 #self.classobj.release_temp(env)
2217 #self.target.release_target_temp(env)
2219 def generate_function_definitions(self, env, code):
2220 self.generate_py_string_decls(self.scope, code)
2221 self.body.generate_function_definitions(self.scope, code)
2223 def generate_execution_code(self, code):
2224 self.dict.generate_evaluation_code(code)
2225 self.classobj.generate_evaluation_code(code)
2226 self.body.generate_execution_code(code)
2227 self.target.generate_assignment_code(self.classobj, code)
2228 self.dict.generate_disposal_code(code)
2231 class CClassDefNode(ClassDefNode):
2232 # An extension type definition.
2234 # visibility 'private' or 'public' or 'extern'
2235 # typedef_flag boolean
2236 # api boolean
2237 # module_name string or None For import of extern type objects
2238 # class_name string Unqualified name of class
2239 # as_name string or None Name to declare as in this scope
2240 # base_class_module string or None Module containing the base class
2241 # base_class_name string or None Name of the base class
2242 # objstruct_name string or None Specified C name of object struct
2243 # typeobj_name string or None Specified C name of type object
2244 # in_pxd boolean Is in a .pxd file
2245 # doc string or None
2246 # body StatNode or None
2247 # entry Symtab.Entry
2248 # base_type PyExtensionType or None
2249 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2250 # buffer_defaults_pos
2252 child_attrs = ["body"]
2253 buffer_defaults_node = None
2254 buffer_defaults_pos = None
2256 def analyse_declarations(self, env):
2257 #print "CClassDefNode.analyse_declarations:", self.class_name
2258 #print "...visibility =", self.visibility
2259 #print "...module_name =", self.module_name
2261 import Buffer
2262 if self.buffer_defaults_node:
2263 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2264 env, [], self.buffer_defaults_node,
2265 need_complete=False)
2266 else:
2267 buffer_defaults = None
2269 if env.in_cinclude and not self.objstruct_name:
2270 error(self.pos, "Object struct name specification required for "
2271 "C class defined in 'extern from' block")
2272 self.base_type = None
2273 # Now that module imports are cached, we need to
2274 # import the modules for extern classes.
2275 if self.module_name:
2276 self.module = None
2277 for module in env.cimported_modules:
2278 if module.name == self.module_name:
2279 self.module = module
2280 if self.module is None:
2281 self.module = ModuleScope(self.module_name, None, env.context)
2282 self.module.has_extern_class = 1
2283 env.cimported_modules.append(self.module)
2285 if self.base_class_name:
2286 if self.base_class_module:
2287 base_class_scope = env.find_module(self.base_class_module, self.pos)
2288 else:
2289 base_class_scope = env
2290 if base_class_scope:
2291 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2292 if base_class_entry:
2293 if not base_class_entry.is_type:
2294 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2295 elif not base_class_entry.type.is_extension_type:
2296 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2297 elif not base_class_entry.type.is_complete():
2298 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2299 else:
2300 self.base_type = base_class_entry.type
2301 has_body = self.body is not None
2302 if self.module_name and self.visibility != 'extern':
2303 module_path = self.module_name.split(".")
2304 home_scope = env.find_imported_module(module_path, self.pos)
2305 if not home_scope:
2306 return
2307 else:
2308 home_scope = env
2309 self.entry = home_scope.declare_c_class(
2310 name = self.class_name,
2311 pos = self.pos,
2312 defining = has_body and self.in_pxd,
2313 implementing = has_body and not self.in_pxd,
2314 module_name = self.module_name,
2315 base_type = self.base_type,
2316 objstruct_cname = self.objstruct_name,
2317 typeobj_cname = self.typeobj_name,
2318 visibility = self.visibility,
2319 typedef_flag = self.typedef_flag,
2320 api = self.api,
2321 buffer_defaults = buffer_defaults)
2322 if home_scope is not env and self.visibility == 'extern':
2323 env.add_imported_entry(self.class_name, self.entry, pos)
2324 scope = self.entry.type.scope
2326 if self.doc and Options.docstrings:
2327 scope.doc = embed_position(self.pos, self.doc)
2329 if has_body:
2330 self.body.analyse_declarations(scope)
2331 if self.in_pxd:
2332 scope.defined = 1
2333 else:
2334 scope.implemented = 1
2335 env.allocate_vtable_names(self.entry)
2337 def analyse_expressions(self, env):
2338 if self.body:
2339 scope = self.entry.type.scope
2340 self.body.analyse_expressions(scope)
2342 def generate_function_definitions(self, env, code):
2343 self.generate_py_string_decls(self.entry.type.scope, code)
2344 if self.body:
2345 self.body.generate_function_definitions(
2346 self.entry.type.scope, code)
2348 def generate_execution_code(self, code):
2349 # This is needed to generate evaluation code for
2350 # default values of method arguments.
2351 if self.body:
2352 self.body.generate_execution_code(code)
2354 def annotate(self, code):
2355 if self.body:
2356 self.body.annotate(code)
2359 class PropertyNode(StatNode):
2360 # Definition of a property in an extension type.
2362 # name string
2363 # doc EncodedString or None Doc string
2364 # body StatListNode
2366 child_attrs = ["body"]
2368 def analyse_declarations(self, env):
2369 entry = env.declare_property(self.name, self.doc, self.pos)
2370 if entry:
2371 if self.doc and Options.docstrings:
2372 doc_entry = env.get_string_const(
2373 self.doc, identifier = False)
2374 entry.doc_cname = doc_entry.cname
2375 self.body.analyse_declarations(entry.scope)
2377 def analyse_expressions(self, env):
2378 self.body.analyse_expressions(env)
2380 def generate_function_definitions(self, env, code):
2381 self.body.generate_function_definitions(env, code)
2383 def generate_execution_code(self, code):
2384 pass
2386 def annotate(self, code):
2387 self.body.annotate(code)
2390 class GlobalNode(StatNode):
2391 # Global variable declaration.
2393 # names [string]
2395 child_attrs = []
2397 def analyse_declarations(self, env):
2398 for name in self.names:
2399 env.declare_global(name, self.pos)
2401 def analyse_expressions(self, env):
2402 pass
2404 def generate_execution_code(self, code):
2405 pass
2408 class ExprStatNode(StatNode):
2409 # Expression used as a statement.
2411 # expr ExprNode
2413 child_attrs = ["expr"]
2415 def analyse_expressions(self, env):
2416 self.expr.analyse_expressions(env)
2417 self.expr.release_temp(env)
2419 def generate_execution_code(self, code):
2420 self.expr.generate_evaluation_code(code)
2421 if not self.expr.is_temp and self.expr.result():
2422 code.putln("%s;" % self.expr.result())
2423 self.expr.generate_disposal_code(code)
2425 def annotate(self, code):
2426 self.expr.annotate(code)
2429 class AssignmentNode(StatNode):
2430 # Abstract base class for assignment nodes.
2432 # The analyse_expressions and generate_execution_code
2433 # phases of assignments are split into two sub-phases
2434 # each, to enable all the right hand sides of a
2435 # parallel assignment to be evaluated before assigning
2436 # to any of the left hand sides.
2438 def analyse_expressions(self, env):
2439 self.analyse_types(env)
2440 self.allocate_rhs_temps(env)
2441 self.allocate_lhs_temps(env)
2443 # def analyse_expressions(self, env):
2444 # self.analyse_expressions_1(env)
2445 # self.analyse_expressions_2(env)
2447 def generate_execution_code(self, code):
2448 self.generate_rhs_evaluation_code(code)
2449 self.generate_assignment_code(code)
2452 class SingleAssignmentNode(AssignmentNode):
2453 # The simplest case:
2455 # a = b
2457 # lhs ExprNode Left hand side
2458 # rhs ExprNode Right hand side
2459 # first bool Is this guaranteed the first assignment to lhs?
2461 child_attrs = ["lhs", "rhs"]
2462 first = False
2464 def analyse_declarations(self, env):
2465 self.lhs.analyse_target_declaration(env)
2467 def analyse_types(self, env, use_temp = 0):
2468 self.rhs.analyse_types(env)
2469 self.lhs.analyse_target_types(env)
2470 self.lhs.gil_assignment_check(env)
2471 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2472 if use_temp:
2473 self.rhs = self.rhs.coerce_to_temp(env)
2475 def allocate_rhs_temps(self, env):
2476 self.rhs.allocate_temps(env)
2478 def allocate_lhs_temps(self, env):
2479 self.lhs.allocate_target_temps(env, self.rhs)
2480 #self.lhs.release_target_temp(env)
2481 #self.rhs.release_temp(env)
2483 # def analyse_expressions_1(self, env, use_temp = 0):
2484 # self.rhs.analyse_types(env)
2485 # self.lhs.analyse_target_types(env)
2486 # self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2487 # if use_temp:
2488 # self.rhs = self.rhs.coerce_to_temp(env)
2489 # self.rhs.allocate_temps(env)
2491 # def analyse_expressions_2(self, env):
2492 # self.lhs.allocate_target_temps(env)
2493 # self.lhs.release_target_temp(env)
2494 # self.rhs.release_temp(env)
2496 def generate_rhs_evaluation_code(self, code):
2497 self.rhs.generate_evaluation_code(code)
2499 def generate_assignment_code(self, code):
2500 self.lhs.generate_assignment_code(self.rhs, code)
2502 def annotate(self, code):
2503 self.lhs.annotate(code)
2504 self.rhs.annotate(code)
2507 class CascadedAssignmentNode(AssignmentNode):
2508 # An assignment with multiple left hand sides:
2510 # a = b = c
2512 # lhs_list [ExprNode] Left hand sides
2513 # rhs ExprNode Right hand sides
2515 # Used internally:
2517 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2519 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2520 coerced_rhs_list = None
2522 def analyse_declarations(self, env):
2523 for lhs in self.lhs_list:
2524 lhs.analyse_target_declaration(env)
2526 def analyse_types(self, env, use_temp = 0):
2527 self.rhs.analyse_types(env)
2528 if use_temp:
2529 self.rhs = self.rhs.coerce_to_temp(env)
2530 else:
2531 self.rhs = self.rhs.coerce_to_simple(env)
2532 from ExprNodes import CloneNode
2533 self.coerced_rhs_list = []
2534 for lhs in self.lhs_list:
2535 lhs.analyse_target_types(env)
2536 lhs.gil_assignment_check(env)
2537 rhs = CloneNode(self.rhs)
2538 rhs = rhs.coerce_to(lhs.type, env)
2539 self.coerced_rhs_list.append(rhs)
2541 def allocate_rhs_temps(self, env):
2542 self.rhs.allocate_temps(env)
2544 def allocate_lhs_temps(self, env):
2545 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2546 rhs.allocate_temps(env)
2547 lhs.allocate_target_temps(env, rhs)
2548 #lhs.release_target_temp(env)
2549 #rhs.release_temp(env)
2550 self.rhs.release_temp(env)
2552 # def analyse_expressions_1(self, env, use_temp = 0):
2553 # self.rhs.analyse_types(env)
2554 # if use_temp:
2555 # self.rhs = self.rhs.coerce_to_temp(env)
2556 # else:
2557 # self.rhs = self.rhs.coerce_to_simple(env)
2558 # self.rhs.allocate_temps(env)
2560 # def analyse_expressions_2(self, env):
2561 # from ExprNodes import CloneNode
2562 # self.coerced_rhs_list = []
2563 # for lhs in self.lhs_list:
2564 # lhs.analyse_target_types(env)
2565 # rhs = CloneNode(self.rhs)
2566 # rhs = rhs.coerce_to(lhs.type, env)
2567 # self.coerced_rhs_list.append(rhs)
2568 # rhs.allocate_temps(env)
2569 # lhs.allocate_target_temps(env)
2570 # lhs.release_target_temp(env)
2571 # rhs.release_temp(env)
2572 # self.rhs.release_temp(env)
2574 def generate_rhs_evaluation_code(self, code):
2575 self.rhs.generate_evaluation_code(code)
2577 def generate_assignment_code(self, code):
2578 for i in range(len(self.lhs_list)):
2579 lhs = self.lhs_list[i]
2580 rhs = self.coerced_rhs_list[i]
2581 rhs.generate_evaluation_code(code)
2582 lhs.generate_assignment_code(rhs, code)
2583 # Assignment has disposed of the cloned RHS
2584 self.rhs.generate_disposal_code(code)
2586 def annotate(self, code):
2587 for i in range(len(self.lhs_list)):
2588 lhs = self.lhs_list[i].annotate(code)
2589 rhs = self.coerced_rhs_list[i].annotate(code)
2590 self.rhs.annotate(code)
2593 class ParallelAssignmentNode(AssignmentNode):
2594 # A combined packing/unpacking assignment:
2596 # a, b, c = d, e, f
2598 # This has been rearranged by the parser into
2600 # a = d ; b = e ; c = f
2602 # but we must evaluate all the right hand sides
2603 # before assigning to any of the left hand sides.
2605 # stats [AssignmentNode] The constituent assignments
2607 child_attrs = ["stats"]
2609 def analyse_declarations(self, env):
2610 for stat in self.stats:
2611 stat.analyse_declarations(env)
2613 def analyse_expressions(self, env):
2614 for stat in self.stats:
2615 stat.analyse_types(env, use_temp = 1)
2616 stat.allocate_rhs_temps(env)
2617 for stat in self.stats:
2618 stat.allocate_lhs_temps(env)
2620 # def analyse_expressions(self, env):
2621 # for stat in self.stats:
2622 # stat.analyse_expressions_1(env, use_temp = 1)
2623 # for stat in self.stats:
2624 # stat.analyse_expressions_2(env)
2626 def generate_execution_code(self, code):
2627 for stat in self.stats:
2628 stat.generate_rhs_evaluation_code(code)
2629 for stat in self.stats:
2630 stat.generate_assignment_code(code)
2632 def annotate(self, code):
2633 for stat in self.stats:
2634 stat.annotate(code)
2637 class InPlaceAssignmentNode(AssignmentNode):
2638 # An in place arithmatic operand:
2640 # a += b
2641 # a -= b
2642 # ...
2644 # lhs ExprNode Left hand side
2645 # rhs ExprNode Right hand side
2646 # op char one of "+-*/%^&|"
2647 # dup (ExprNode) copy of lhs used for operation (auto-generated)
2649 # This code is a bit tricky because in order to obey Python
2650 # semantics the sub-expressions (e.g. indices) of the lhs must
2651 # not be evaluated twice. So we must re-use the values calculated
2652 # in evaluation phase for the assignment phase as well.
2653 # Fortunately, the type of the lhs node is fairly constrained
2654 # (it must be a NameNode, AttributeNode, or IndexNode).
2656 child_attrs = ["lhs", "rhs"]
2657 dup = None
2659 def analyse_declarations(self, env):
2660 self.lhs.analyse_target_declaration(env)
2662 def analyse_types(self, env):
2663 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
2664 self.rhs.analyse_types(env)
2665 self.lhs.analyse_target_types(env)
2666 if Options.incref_local_binop and self.dup.type.is_pyobject:
2667 self.dup = self.dup.coerce_to_temp(env)
2669 def allocate_rhs_temps(self, env):
2670 import ExprNodes
2671 if self.lhs.type.is_pyobject:
2672 self.rhs = self.rhs.coerce_to_pyobject(env)
2673 elif self.rhs.type.is_pyobject:
2674 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2675 if self.lhs.type.is_pyobject:
2676 self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
2677 self.result_value.allocate_temps(env)
2678 # if use_temp:
2679 # self.rhs = self.rhs.coerce_to_temp(env)
2680 self.rhs.allocate_temps(env)
2681 self.dup.allocate_subexpr_temps(env)
2682 self.dup.allocate_temp(env)
2684 def allocate_lhs_temps(self, env):
2685 self.lhs.allocate_target_temps(env, self.rhs)
2686 # self.lhs.release_target_temp(env)
2687 self.dup.release_temp(env)
2688 if self.dup.is_temp:
2689 self.dup.release_subexpr_temps(env)
2690 # self.rhs.release_temp(env)
2691 if self.lhs.type.is_pyobject:
2692 self.result_value.release_temp(env)
2694 def generate_execution_code(self, code):
2695 self.rhs.generate_evaluation_code(code)
2696 self.dup.generate_subexpr_evaluation_code(code)
2697 # self.dup.generate_result_code is run only if it is not buffer access
2698 if self.operator == "**":
2699 extra = ", Py_None"
2700 else:
2701 extra = ""
2702 import ExprNodes
2703 if self.lhs.type.is_pyobject:
2704 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
2705 error(self.pos, "In-place operators not allowed on object buffers in this release.")
2706 self.dup.generate_result_code(code)
2707 code.putln(
2708 "%s = %s(%s, %s%s); %s" % (
2709 self.result_value.result(),
2710 self.py_operation_function(),
2711 self.dup.py_result(),
2712 self.rhs.py_result(),
2713 extra,
2714 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
2715 self.result_value.generate_evaluation_code(code) # May be a type check...
2716 self.rhs.generate_disposal_code(code)
2717 self.dup.generate_disposal_code(code)
2718 self.lhs.generate_assignment_code(self.result_value, code)
2719 else:
2720 c_op = self.operator
2721 if c_op == "//":
2722 c_op = "/"
2723 elif c_op == "**":
2724 if self.lhs.type.is_int and self.rhs.type.is_int:
2725 error(self.pos, "** with two C int types is ambiguous")
2726 else:
2727 error(self.pos, "No C inplace power operator")
2728 # have to do assignment directly to avoid side-effects
2729 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
2730 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
2731 else:
2732 self.dup.generate_result_code(code)
2733 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
2734 self.rhs.generate_disposal_code(code)
2735 if self.dup.is_temp:
2736 self.dup.generate_subexpr_disposal_code(code)
2738 def create_dup_node(self, env):
2739 import ExprNodes
2740 self.dup = self.lhs
2741 self.dup.analyse_types(env)
2742 if isinstance(self.lhs, ExprNodes.NameNode):
2743 target_lhs = ExprNodes.NameNode(self.dup.pos,
2744 name = self.dup.name,
2745 is_temp = self.dup.is_temp,
2746 entry = self.dup.entry)
2747 elif isinstance(self.lhs, ExprNodes.AttributeNode):
2748 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
2749 obj = ExprNodes.CloneNode(self.lhs.obj),
2750 attribute = self.dup.attribute,
2751 is_temp = self.dup.is_temp)
2752 elif isinstance(self.lhs, ExprNodes.IndexNode):
2753 if self.lhs.index:
2754 index = ExprNodes.CloneNode(self.lhs.index)
2755 else:
2756 index = None
2757 if self.lhs.indices:
2758 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
2759 else:
2760 indices = []
2761 target_lhs = ExprNodes.IndexNode(self.dup.pos,
2762 base = ExprNodes.CloneNode(self.dup.base),
2763 index = index,
2764 indices = indices,
2765 is_temp = self.dup.is_temp)
2766 self.lhs = target_lhs
2767 return self.dup
2769 def py_operation_function(self):
2770 return self.py_functions[self.operator]
2772 py_functions = {
2773 "|": "PyNumber_InPlaceOr",
2774 "^": "PyNumber_InPlaceXor",
2775 "&": "PyNumber_InPlaceAnd",
2776 "+": "PyNumber_InPlaceAdd",
2777 "-": "PyNumber_InPlaceSubtract",
2778 "*": "PyNumber_InPlaceMultiply",
2779 "/": "PyNumber_InPlaceDivide",
2780 "%": "PyNumber_InPlaceRemainder",
2781 "<<": "PyNumber_InPlaceLshift",
2782 ">>": "PyNumber_InPlaceRshift",
2783 "**": "PyNumber_InPlacePower",
2784 "//": "PyNumber_InPlaceFloorDivide",
2787 def annotate(self, code):
2788 self.lhs.annotate(code)
2789 self.rhs.annotate(code)
2790 self.dup.annotate(code)
2793 class PrintStatNode(StatNode):
2794 # print statement
2796 # arg_tuple TupleNode
2797 # append_newline boolean
2799 child_attrs = ["arg_tuple"]
2801 def analyse_expressions(self, env):
2802 self.arg_tuple.analyse_expressions(env)
2803 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
2804 self.arg_tuple.release_temp(env)
2805 env.use_utility_code(printing_utility_code)
2806 self.gil_check(env)
2808 gil_message = "Python print statement"
2810 def generate_execution_code(self, code):
2811 self.arg_tuple.generate_evaluation_code(code)
2812 code.putln(
2813 "if (__Pyx_Print(%s, %d) < 0) %s" % (
2814 self.arg_tuple.py_result(),
2815 self.append_newline,
2816 code.error_goto(self.pos)))
2817 self.arg_tuple.generate_disposal_code(code)
2819 def annotate(self, code):
2820 self.arg_tuple.annotate(code)
2823 class DelStatNode(StatNode):
2824 # del statement
2826 # args [ExprNode]
2828 child_attrs = ["args"]
2830 def analyse_declarations(self, env):
2831 for arg in self.args:
2832 arg.analyse_target_declaration(env)
2834 def analyse_expressions(self, env):
2835 for arg in self.args:
2836 arg.analyse_target_expression(env, None)
2837 if arg.type.is_pyobject:
2838 self.gil_check(env)
2839 else:
2840 error(arg.pos, "Deletion of non-Python object")
2841 #arg.release_target_temp(env)
2843 gil_message = "Deleting Python object"
2845 def generate_execution_code(self, code):
2846 for arg in self.args:
2847 if arg.type.is_pyobject:
2848 arg.generate_deletion_code(code)
2849 # else error reported earlier
2851 def annotate(self, code):
2852 for arg in self.args:
2853 arg.annotate(code)
2856 class PassStatNode(StatNode):
2857 # pass statement
2859 child_attrs = []
2861 def analyse_expressions(self, env):
2862 pass
2864 def generate_execution_code(self, code):
2865 pass
2868 class BreakStatNode(StatNode):
2870 child_attrs = []
2872 def analyse_expressions(self, env):
2873 pass
2875 def generate_execution_code(self, code):
2876 if not code.break_label:
2877 error(self.pos, "break statement not inside loop")
2878 else:
2879 #code.putln(
2880 # "goto %s;" %
2881 # code.break_label)
2882 code.put_goto(code.break_label)
2885 class ContinueStatNode(StatNode):
2887 child_attrs = []
2889 def analyse_expressions(self, env):
2890 pass
2892 def generate_execution_code(self, code):
2893 if code.funcstate.in_try_finally:
2894 error(self.pos, "continue statement inside try of try...finally")
2895 elif not code.continue_label:
2896 error(self.pos, "continue statement not inside loop")
2897 else:
2898 code.put_goto(code.continue_label)
2901 class ReturnStatNode(StatNode):
2902 # return statement
2904 # value ExprNode or None
2905 # return_type PyrexType
2906 # temps_in_use [Entry] Temps in use at time of return
2908 child_attrs = ["value"]
2910 def analyse_expressions(self, env):
2911 return_type = env.return_type
2912 self.return_type = return_type
2913 self.temps_in_use = env.temps_in_use()
2914 if not return_type:
2915 error(self.pos, "Return not inside a function body")
2916 return
2917 if self.value:
2918 self.value.analyse_types(env)
2919 if return_type.is_void or return_type.is_returncode:
2920 error(self.value.pos,
2921 "Return with value in void function")
2922 else:
2923 self.value = self.value.coerce_to(env.return_type, env)
2924 self.value.allocate_temps(env)
2925 self.value.release_temp(env)
2926 else:
2927 if (not return_type.is_void
2928 and not return_type.is_pyobject
2929 and not return_type.is_returncode):
2930 error(self.pos, "Return value required")
2931 if return_type.is_pyobject:
2932 self.gil_check(env)
2934 gil_message = "Returning Python object"
2936 def generate_execution_code(self, code):
2937 code.mark_pos(self.pos)
2938 if not self.return_type:
2939 # error reported earlier
2940 return
2941 if self.value:
2942 self.value.generate_evaluation_code(code)
2943 self.value.make_owned_reference(code)
2944 code.putln(
2945 "%s = %s;" % (
2946 Naming.retval_cname,
2947 self.value.result_as(self.return_type)))
2948 self.value.generate_post_assignment_code(code)
2949 else:
2950 if self.return_type.is_pyobject:
2951 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
2952 elif self.return_type.is_returncode:
2953 code.putln(
2954 "%s = %s;" % (
2955 Naming.retval_cname,
2956 self.return_type.default_value))
2957 for entry in self.temps_in_use:
2958 code.put_var_decref_clear(entry)
2959 #code.putln(
2960 # "goto %s;" %
2961 # code.return_label)
2962 code.put_goto(code.return_label)
2964 def annotate(self, code):
2965 if self.value:
2966 self.value.annotate(code)
2969 class RaiseStatNode(StatNode):
2970 # raise statement
2972 # exc_type ExprNode or None
2973 # exc_value ExprNode or None
2974 # exc_tb ExprNode or None
2976 child_attrs = ["exc_type", "exc_value", "exc_tb"]
2978 def analyse_expressions(self, env):
2979 if self.exc_type:
2980 self.exc_type.analyse_types(env)
2981 self.exc_type = self.exc_type.coerce_to_pyobject(env)
2982 self.exc_type.allocate_temps(env)
2983 if self.exc_value:
2984 self.exc_value.analyse_types(env)
2985 self.exc_value = self.exc_value.coerce_to_pyobject(env)
2986 self.exc_value.allocate_temps(env)
2987 if self.exc_tb:
2988 self.exc_tb.analyse_types(env)
2989 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
2990 self.exc_tb.allocate_temps(env)
2991 if self.exc_type:
2992 self.exc_type.release_temp(env)
2993 if self.exc_value:
2994 self.exc_value.release_temp(env)
2995 if self.exc_tb:
2996 self.exc_tb.release_temp(env)
2997 env.use_utility_code(raise_utility_code)
2998 env.use_utility_code(restore_exception_utility_code)
2999 self.gil_check(env)
3001 gil_message = "Raising exception"
3003 def generate_execution_code(self, code):
3004 if self.exc_type:
3005 self.exc_type.generate_evaluation_code(code)
3006 type_code = self.exc_type.py_result()
3007 else:
3008 type_code = 0
3009 if self.exc_value:
3010 self.exc_value.generate_evaluation_code(code)
3011 value_code = self.exc_value.py_result()
3012 else:
3013 value_code = "0"
3014 if self.exc_tb:
3015 self.exc_tb.generate_evaluation_code(code)
3016 tb_code = self.exc_tb.py_result()
3017 else:
3018 tb_code = "0"
3019 if self.exc_type or self.exc_value or self.exc_tb:
3020 code.putln(
3021 "__Pyx_Raise(%s, %s, %s);" % (
3022 type_code,
3023 value_code,
3024 tb_code))
3025 else:
3026 code.putln(
3027 "__Pyx_ReRaise();")
3028 if self.exc_type:
3029 self.exc_type.generate_disposal_code(code)
3030 if self.exc_value:
3031 self.exc_value.generate_disposal_code(code)
3032 if self.exc_tb:
3033 self.exc_tb.generate_disposal_code(code)
3034 code.putln(
3035 code.error_goto(self.pos))
3037 def annotate(self, code):
3038 if self.exc_type:
3039 self.exc_type.annotate(code)
3040 if self.exc_value:
3041 self.exc_value.annotate(code)
3042 if self.exc_tb:
3043 self.exc_tb.annotate(code)
3046 class ReraiseStatNode(StatNode):
3048 child_attrs = []
3050 def analyse_expressions(self, env):
3051 self.gil_check(env)
3052 env.use_utility_code(raise_utility_code)
3053 env.use_utility_code(restore_exception_utility_code)
3055 gil_message = "Raising exception"
3057 def generate_execution_code(self, code):
3058 vars = code.funcstate.exc_vars
3059 if vars:
3060 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3061 code.putln(code.error_goto(self.pos))
3062 else:
3063 error(self.pos, "Reraise not inside except clause")
3066 class AssertStatNode(StatNode):
3067 # assert statement
3069 # cond ExprNode
3070 # value ExprNode or None
3072 child_attrs = ["cond", "value"]
3074 def analyse_expressions(self, env):
3075 self.cond = self.cond.analyse_boolean_expression(env)
3076 if self.value:
3077 self.value.analyse_types(env)
3078 self.value = self.value.coerce_to_pyobject(env)
3079 self.value.allocate_temps(env)
3080 self.cond.release_temp(env)
3081 if self.value:
3082 self.value.release_temp(env)
3083 self.gil_check(env)
3084 #env.recycle_pending_temps() # TEMPORARY
3086 gil_message = "Raising exception"
3088 def generate_execution_code(self, code):
3089 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3090 self.cond.generate_evaluation_code(code)
3091 code.putln(
3092 "if (unlikely(!%s)) {" %
3093 self.cond.result())
3094 if self.value:
3095 self.value.generate_evaluation_code(code)
3096 code.putln(
3097 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3098 self.value.py_result())
3099 self.value.generate_disposal_code(code)
3100 else:
3101 code.putln(
3102 "PyErr_SetNone(PyExc_AssertionError);")
3103 code.putln(
3104 code.error_goto(self.pos))
3105 code.putln(
3106 "}")
3107 self.cond.generate_disposal_code(code)
3108 code.putln("#endif")
3110 def annotate(self, code):
3111 self.cond.annotate(code)
3112 if self.value:
3113 self.value.annotate(code)
3116 class IfStatNode(StatNode):
3117 # if statement
3119 # if_clauses [IfClauseNode]
3120 # else_clause StatNode or None
3122 child_attrs = ["if_clauses", "else_clause"]
3124 def analyse_control_flow(self, env):
3125 env.start_branching(self.pos)
3126 for if_clause in self.if_clauses:
3127 if_clause.analyse_control_flow(env)
3128 env.next_branch(if_clause.end_pos())
3129 if self.else_clause:
3130 self.else_clause.analyse_control_flow(env)
3131 env.finish_branching(self.end_pos())
3133 def analyse_declarations(self, env):
3134 for if_clause in self.if_clauses:
3135 if_clause.analyse_declarations(env)
3136 if self.else_clause:
3137 self.else_clause.analyse_declarations(env)
3139 def analyse_expressions(self, env):
3140 for if_clause in self.if_clauses:
3141 if_clause.analyse_expressions(env)
3142 if self.else_clause:
3143 self.else_clause.analyse_expressions(env)
3145 def generate_execution_code(self, code):
3146 code.mark_pos(self.pos)
3147 end_label = code.new_label()
3148 for if_clause in self.if_clauses:
3149 if_clause.generate_execution_code(code, end_label)
3150 if self.else_clause:
3151 code.putln("/*else*/ {")
3152 self.else_clause.generate_execution_code(code)
3153 code.putln("}")
3154 code.put_label(end_label)
3156 def annotate(self, code):
3157 for if_clause in self.if_clauses:
3158 if_clause.annotate(code)
3159 if self.else_clause:
3160 self.else_clause.annotate(code)
3163 class IfClauseNode(Node):
3164 # if or elif clause in an if statement
3166 # condition ExprNode
3167 # body StatNode
3169 child_attrs = ["condition", "body"]
3171 def analyse_control_flow(self, env):
3172 self.body.analyse_control_flow(env)
3174 def analyse_declarations(self, env):
3175 self.condition.analyse_declarations(env)
3176 self.body.analyse_declarations(env)
3178 def analyse_expressions(self, env):
3179 self.condition = \
3180 self.condition.analyse_temp_boolean_expression(env)
3181 self.condition.release_temp(env)
3182 self.body.analyse_expressions(env)
3184 def generate_execution_code(self, code, end_label):
3185 self.condition.generate_evaluation_code(code)
3186 code.putln(
3187 "if (%s) {" %
3188 self.condition.result())
3189 self.body.generate_execution_code(code)
3190 #code.putln(
3191 # "goto %s;" %
3192 # end_label)
3193 code.put_goto(end_label)
3194 code.putln("}")
3196 def annotate(self, code):
3197 self.condition.annotate(code)
3198 self.body.annotate(code)
3201 class SwitchCaseNode(StatNode):
3202 # Generated in the optimization of an if-elif-else node
3204 # conditions [ExprNode]
3205 # body StatNode
3207 child_attrs = ['conditions', 'body']
3209 def generate_execution_code(self, code):
3210 for cond in self.conditions:
3211 code.putln("case %s:" % cond.calculate_result_code())
3212 self.body.generate_execution_code(code)
3213 code.putln("break;")
3215 def annotate(self, code):
3216 for cond in self.conditions:
3217 cond.annotate(code)
3218 self.body.annotate(code)
3220 class SwitchStatNode(StatNode):
3221 # Generated in the optimization of an if-elif-else node
3223 # test ExprNode
3224 # cases [SwitchCaseNode]
3225 # else_clause StatNode or None
3227 child_attrs = ['test', 'cases', 'else_clause']
3229 def generate_execution_code(self, code):
3230 code.putln("switch (%s) {" % self.test.calculate_result_code())
3231 for case in self.cases:
3232 case.generate_execution_code(code)
3233 if self.else_clause is not None:
3234 code.putln("default:")
3235 self.else_clause.generate_execution_code(code)
3236 code.putln("}")
3238 def annotate(self, code):
3239 self.test.annotate(code)
3240 for case in self.cases:
3241 case.annotate(code)
3242 if self.else_clause is not None:
3243 self.else_clause.annotate(code)
3245 class LoopNode:
3247 def analyse_control_flow(self, env):
3248 env.start_branching(self.pos)
3249 self.body.analyse_control_flow(env)
3250 env.next_branch(self.body.end_pos())
3251 if self.else_clause:
3252 self.else_clause.analyse_control_flow(env)
3253 env.finish_branching(self.end_pos())
3256 class WhileStatNode(LoopNode, StatNode):
3257 # while statement
3259 # condition ExprNode
3260 # body StatNode
3261 # else_clause StatNode
3263 child_attrs = ["condition", "body", "else_clause"]
3265 def analyse_declarations(self, env):
3266 self.body.analyse_declarations(env)
3267 if self.else_clause:
3268 self.else_clause.analyse_declarations(env)
3270 def analyse_expressions(self, env):
3271 self.condition = \
3272 self.condition.analyse_temp_boolean_expression(env)
3273 self.condition.release_temp(env)
3274 #env.recycle_pending_temps() # TEMPORARY
3275 self.body.analyse_expressions(env)
3276 if self.else_clause:
3277 self.else_clause.analyse_expressions(env)
3279 def generate_execution_code(self, code):
3280 old_loop_labels = code.new_loop_labels()
3281 code.putln(
3282 "while (1) {")
3283 self.condition.generate_evaluation_code(code)
3284 code.putln(
3285 "if (!%s) break;" %
3286 self.condition.result())
3287 self.body.generate_execution_code(code)
3288 code.put_label(code.continue_label)
3289 code.putln("}")
3290 break_label = code.break_label
3291 code.set_loop_labels(old_loop_labels)
3292 if self.else_clause:
3293 code.putln("/*else*/ {")
3294 self.else_clause.generate_execution_code(code)
3295 code.putln("}")
3296 code.put_label(break_label)
3298 def annotate(self, code):
3299 self.condition.annotate(code)
3300 self.body.annotate(code)
3301 if self.else_clause:
3302 self.else_clause.annotate(code)
3305 def ForStatNode(pos, **kw):
3306 if kw.has_key('iterator'):
3307 return ForInStatNode(pos, **kw)
3308 else:
3309 return ForFromStatNode(pos, **kw)
3311 class ForInStatNode(LoopNode, StatNode):
3312 # for statement
3314 # target ExprNode
3315 # iterator IteratorNode
3316 # body StatNode
3317 # else_clause StatNode
3318 # item NextNode used internally
3320 child_attrs = ["target", "iterator", "body", "else_clause"]
3321 item = None
3323 def analyse_declarations(self, env):
3324 self.target.analyse_target_declaration(env)
3325 self.body.analyse_declarations(env)
3326 if self.else_clause:
3327 self.else_clause.analyse_declarations(env)
3329 def analyse_range_step(self, args):
3330 import ExprNodes
3331 # The direction must be determined at compile time to set relations.
3332 # Otherwise, return False.
3333 if len(args) < 3:
3334 self.step = ExprNodes.IntNode(pos = args[0].pos, value='1')
3335 self.relation1 = '<='
3336 self.relation2 = '<'
3337 return True
3338 else:
3339 step = args[2]
3340 if isinstance(step, ExprNodes.UnaryMinusNode) and isinstance(step.operand, ExprNodes.IntNode):
3341 step = ExprNodes.IntNode(pos = step.pos, value=str(-int(step.operand.value, 0)))
3342 if isinstance(step, ExprNodes.IntNode):
3343 step_value = int(step.value, 0)
3344 if step_value > 0:
3345 self.step = step
3346 self.relation1 = '<='
3347 self.relation2 = '<'
3348 return True
3349 elif step_value < 0:
3350 self.step = ExprNodes.IntNode(pos = step.pos, value=str(-step_value))
3351 self.relation1 = '>='
3352 self.relation2 = '>'
3353 return True
3354 return False
3357 def analyse_expressions(self, env):
3358 import ExprNodes
3359 self.target.analyse_target_types(env)
3360 if Options.convert_range and self.target.type.is_int:
3361 sequence = self.iterator.sequence
3362 if isinstance(sequence, ExprNodes.SimpleCallNode) \
3363 and sequence.self is None \
3364 and isinstance(sequence.function, ExprNodes.NameNode) \
3365 and (sequence.function.name == 'range' or sequence.function.name == 'xrange'):
3366 args = sequence.args
3367 # Make sure we can determine direction from step
3368 if self.analyse_range_step(args):
3369 # Mutate to ForFrom loop type
3370 self.__class__ = ForFromStatNode
3371 if len(args) == 1:
3372 self.bound1 = ExprNodes.IntNode(pos = sequence.pos, value='0')
3373 self.bound2 = args[0]
3374 else:
3375 self.bound1 = args[0]
3376 self.bound2 = args[1]
3377 ForFromStatNode.analyse_expressions(self, env)
3378 return
3380 self.iterator.analyse_expressions(env)
3381 self.item = ExprNodes.NextNode(self.iterator, env)
3382 self.item = self.item.coerce_to(self.target.type, env)
3383 self.item.allocate_temps(env)
3384 self.target.allocate_target_temps(env, self.item)
3385 #self.item.release_temp(env)
3386 #self.target.release_target_temp(env)
3387 self.body.analyse_expressions(env)
3388 if self.else_clause:
3389 self.else_clause.analyse_expressions(env)
3390 self.iterator.release_temp(env)
3392 def generate_execution_code(self, code):
3393 old_loop_labels = code.new_loop_labels()
3394 self.iterator.generate_evaluation_code(code)
3395 code.putln(
3396 "for (;;) {")
3397 self.item.generate_evaluation_code(code)
3398 self.target.generate_assignment_code(self.item, code)
3399 self.body.generate_execution_code(code)
3400 code.put_label(code.continue_label)
3401 code.putln(
3402 "}")
3403 break_label = code.break_label
3404 code.set_loop_labels(old_loop_labels)
3405 if self.else_clause:
3406 code.putln("/*else*/ {")
3407 self.else_clause.generate_execution_code(code)
3408 code.putln("}")
3409 code.put_label(break_label)
3410 self.iterator.generate_disposal_code(code)
3412 def annotate(self, code):
3413 self.target.annotate(code)
3414 self.iterator.annotate(code)
3415 self.body.annotate(code)
3416 if self.else_clause:
3417 self.else_clause.annotate(code)
3418 self.item.annotate(code)
3421 class ForFromStatNode(LoopNode, StatNode):
3422 # for name from expr rel name rel expr
3424 # target NameNode
3425 # bound1 ExprNode
3426 # relation1 string
3427 # relation2 string
3428 # bound2 ExprNode
3429 # step ExprNode or None
3430 # body StatNode
3431 # else_clause StatNode or None
3433 # Used internally:
3435 # is_py_target bool
3436 # loopvar_name string
3437 # py_loopvar_node PyTempNode or None
3438 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3440 def analyse_declarations(self, env):
3441 self.target.analyse_target_declaration(env)
3442 self.body.analyse_declarations(env)
3443 if self.else_clause:
3444 self.else_clause.analyse_declarations(env)
3446 def analyse_expressions(self, env):
3447 import ExprNodes
3448 self.target.analyse_target_types(env)
3449 self.bound1.analyse_types(env)
3450 self.bound2.analyse_types(env)
3451 if self.target.type.is_numeric:
3452 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3453 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3454 else:
3455 self.bound1 = self.bound1.coerce_to_integer(env)
3456 self.bound2 = self.bound2.coerce_to_integer(env)
3457 if self.step is not None:
3458 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3459 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3460 self.step.analyse_types(env)
3461 self.step = self.step.coerce_to_integer(env)
3462 if not (self.bound2.is_name or self.bound2.is_literal):
3463 self.bound2 = self.bound2.coerce_to_temp(env)
3464 target_type = self.target.type
3465 if not (target_type.is_pyobject or target_type.is_numeric):
3466 error(self.target.pos,
3467 "Integer for-loop variable must be of type int or Python object")
3468 #if not (target_type.is_pyobject
3469 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3470 # error(self.target.pos,
3471 # "Cannot assign integer to variable of type '%s'" % target_type)
3472 if target_type.is_numeric:
3473 self.is_py_target = 0
3474 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3475 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3476 self.loopvar_name = self.target.entry.cname
3477 self.py_loopvar_node = None
3478 else:
3479 self.is_py_target = 1
3480 c_loopvar_node = ExprNodes.TempNode(self.pos,
3481 PyrexTypes.c_long_type, env)
3482 c_loopvar_node.allocate_temps(env)
3483 self.loopvar_name = c_loopvar_node.result()
3484 self.py_loopvar_node = \
3485 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3486 self.bound1.allocate_temps(env)
3487 self.bound2.allocate_temps(env)
3488 if self.step is not None:
3489 self.step.allocate_temps(env)
3490 if self.is_py_target:
3491 self.py_loopvar_node.allocate_temps(env)
3492 self.target.allocate_target_temps(env, self.py_loopvar_node)
3493 #self.target.release_target_temp(env)
3494 #self.py_loopvar_node.release_temp(env)
3495 self.body.analyse_expressions(env)
3496 if self.is_py_target:
3497 c_loopvar_node.release_temp(env)
3498 if self.else_clause:
3499 self.else_clause.analyse_expressions(env)
3500 self.bound1.release_temp(env)
3501 self.bound2.release_temp(env)
3502 if self.step is not None:
3503 self.step.release_temp(env)
3505 def generate_execution_code(self, code):
3506 old_loop_labels = code.new_loop_labels()
3507 self.bound1.generate_evaluation_code(code)
3508 self.bound2.generate_evaluation_code(code)
3509 offset, incop = self.relation_table[self.relation1]
3510 if self.step is not None:
3511 self.step.generate_evaluation_code(code)
3512 incop = "%s=%s" % (incop[0], self.step.result())
3513 code.putln(
3514 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3515 self.loopvar_name,
3516 self.bound1.result(), offset,
3517 self.loopvar_name, self.relation2, self.bound2.result(),
3518 self.loopvar_name, incop))
3519 if self.py_loopvar_node:
3520 self.py_loopvar_node.generate_evaluation_code(code)
3521 self.target.generate_assignment_code(self.py_loopvar_node, code)
3522 self.body.generate_execution_code(code)
3523 code.put_label(code.continue_label)
3524 code.putln("}")
3525 break_label = code.break_label
3526 code.set_loop_labels(old_loop_labels)
3527 if self.else_clause:
3528 code.putln("/*else*/ {")
3529 self.else_clause.generate_execution_code(code)
3530 code.putln("}")
3531 code.put_label(break_label)
3532 self.bound1.generate_disposal_code(code)
3533 self.bound2.generate_disposal_code(code)
3534 if self.step is not None:
3535 self.step.generate_disposal_code(code)
3537 relation_table = {
3538 # {relop : (initial offset, increment op)}
3539 '<=': ("", "++"),
3540 '<' : ("+1", "++"),
3541 '>=': ("", "--"),
3542 '>' : ("-1", "--")
3545 def annotate(self, code):
3546 self.target.annotate(code)
3547 self.bound1.annotate(code)
3548 self.bound2.annotate(code)
3549 if self.step:
3550 self.bound2.annotate(code)
3551 self.body.annotate(code)
3552 if self.else_clause:
3553 self.else_clause.annotate(code)
3556 class WithStatNode(StatNode):
3557 """
3558 Represents a Python with statement.
3560 This is only used at parse tree level; and is not present in
3561 analysis or generation phases.
3562 """
3563 # manager The with statement manager object
3564 # target Node (lhs expression)
3565 # body StatNode
3566 child_attrs = ["manager", "target", "body"]
3568 class TryExceptStatNode(StatNode):
3569 # try .. except statement
3571 # body StatNode
3572 # except_clauses [ExceptClauseNode]
3573 # else_clause StatNode or None
3574 # cleanup_list [Entry] temps to clean up on error
3576 child_attrs = ["body", "except_clauses", "else_clause"]
3578 def analyse_control_flow(self, env):
3579 env.start_branching(self.pos)
3580 self.body.analyse_control_flow(env)
3581 successful_try = env.control_flow # grab this for later
3582 env.next_branch(self.body.end_pos())
3583 env.finish_branching(self.body.end_pos())
3585 env.start_branching(self.except_clauses[0].pos)
3586 for except_clause in self.except_clauses:
3587 except_clause.analyse_control_flow(env)
3588 env.next_branch(except_clause.end_pos())
3590 # the else cause it executed only when the try clause finishes
3591 env.control_flow.incoming = successful_try
3592 if self.else_clause:
3593 self.else_clause.analyse_control_flow(env)
3594 env.finish_branching(self.end_pos())
3596 def analyse_declarations(self, env):
3597 self.body.analyse_declarations(env)
3598 for except_clause in self.except_clauses:
3599 except_clause.analyse_declarations(env)
3600 if self.else_clause:
3601 self.else_clause.analyse_declarations(env)
3602 self.gil_check(env)
3603 env.use_utility_code(reset_exception_utility_code)
3605 def analyse_expressions(self, env):
3606 self.body.analyse_expressions(env)
3607 self.cleanup_list = env.free_temp_entries[:]
3608 default_clause_seen = 0
3609 for except_clause in self.except_clauses:
3610 except_clause.analyse_expressions(env)
3611 if default_clause_seen:
3612 error(except_clause.pos, "default 'except:' must be last")
3613 if not except_clause.pattern:
3614 default_clause_seen = 1
3615 self.has_default_clause = default_clause_seen
3616 if self.else_clause:
3617 self.else_clause.analyse_expressions(env)
3618 self.gil_check(env)
3620 gil_message = "Try-except statement"
3622 def generate_execution_code(self, code):
3623 old_return_label = code.return_label
3624 old_error_label = code.new_error_label()
3625 our_error_label = code.error_label
3626 except_end_label = code.new_label('exception_handled')
3627 except_error_label = code.new_label('except_error')
3628 except_return_label = code.new_label('except_return')
3629 try_end_label = code.new_label('try')
3631 code.putln("{")
3632 code.putln("PyObject %s;" %
3633 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
3634 code.putln("__Pyx_ExceptionSave(%s);" %
3635 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
3636 code.putln(
3637 "/*try:*/ {")
3638 self.body.generate_execution_code(code)
3639 code.putln(
3640 "}")
3641 code.error_label = except_error_label
3642 code.return_label = except_return_label
3643 if self.else_clause:
3644 code.putln(
3645 "/*else:*/ {")
3646 self.else_clause.generate_execution_code(code)
3647 code.putln(
3648 "}")
3649 code.put_goto(try_end_label)
3650 code.put_label(our_error_label)
3651 code.put_var_xdecrefs_clear(self.cleanup_list)
3652 for except_clause in self.except_clauses:
3653 except_clause.generate_handling_code(code, except_end_label)
3655 error_label_used = code.label_used(except_error_label)
3656 if error_label_used or not self.has_default_clause:
3657 if error_label_used:
3658 code.put_label(except_error_label)
3659 for var in Naming.exc_save_vars:
3660 code.put_xdecref(var, py_object_type)
3661 code.put_goto(old_error_label)
3663 if code.label_used(except_return_label):
3664 code.put_label(except_return_label)
3665 code.putln("__Pyx_ExceptionReset(%s);" %
3666 ', '.join(Naming.exc_save_vars))
3667 code.put_goto(old_return_label)
3669 if code.label_used(except_end_label):
3670 code.put_label(except_end_label)
3671 code.putln("__Pyx_ExceptionReset(%s);" %
3672 ', '.join(Naming.exc_save_vars))
3673 code.put_label(try_end_label)
3674 code.putln("}")
3676 code.return_label = old_return_label
3677 code.error_label = old_error_label
3679 def annotate(self, code):
3680 self.body.annotate(code)
3681 for except_node in self.except_clauses:
3682 except_node.annotate(code)
3683 if self.else_clause:
3684 self.else_clause.annotate(code)
3687 class ExceptClauseNode(Node):
3688 # Part of try ... except statement.
3690 # pattern ExprNode
3691 # target ExprNode or None
3692 # body StatNode
3693 # excinfo_target NameNode or None optional target for exception info
3694 # match_flag string result of exception match
3695 # exc_value ExcValueNode used internally
3696 # function_name string qualified name of enclosing function
3697 # exc_vars (string * 3) local exception variables
3699 # excinfo_target is never set by the parser, but can be set by a transform
3700 # in order to extract more extensive information about the exception as a
3701 # sys.exc_info()-style tuple into a target variable
3703 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
3705 exc_value = None
3706 excinfo_target = None
3708 def analyse_declarations(self, env):
3709 if self.target:
3710 self.target.analyse_target_declaration(env)
3711 if self.excinfo_target is not None:
3712 self.excinfo_target.analyse_target_declaration(env)
3713 self.body.analyse_declarations(env)
3715 def analyse_expressions(self, env):
3716 import ExprNodes
3717 genv = env.global_scope()
3718 self.function_name = env.qualified_name
3719 if self.pattern:
3720 self.pattern.analyse_expressions(env)
3721 self.pattern = self.pattern.coerce_to_pyobject(env)
3722 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
3723 self.pattern.release_temp(env)
3724 env.release_temp(self.match_flag)
3725 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
3726 if self.target:
3727 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
3728 self.exc_value.allocate_temps(env)
3729 self.target.analyse_target_expression(env, self.exc_value)
3730 if self.excinfo_target is not None:
3731 import ExprNodes
3732 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
3733 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
3734 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
3735 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
3736 ])
3737 self.excinfo_tuple.analyse_expressions(env)
3738 self.excinfo_tuple.allocate_temps(env)
3739 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
3741 self.body.analyse_expressions(env)
3742 for var in self.exc_vars:
3743 env.release_temp(var)
3744 env.use_utility_code(get_exception_utility_code)
3745 env.use_utility_code(restore_exception_utility_code)
3747 def generate_handling_code(self, code, end_label):
3748 code.mark_pos(self.pos)
3749 if self.pattern:
3750 self.pattern.generate_evaluation_code(code)
3751 code.putln(
3752 "%s = PyErr_ExceptionMatches(%s);" % (
3753 self.match_flag,
3754 self.pattern.py_result()))
3755 self.pattern.generate_disposal_code(code)
3756 code.putln(
3757 "if (%s) {" %
3758 self.match_flag)
3759 else:
3760 code.putln("/*except:*/ {")
3761 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
3762 # We always have to fetch the exception value even if
3763 # there is no target, because this also normalises the
3764 # exception and stores it in the thread state.
3765 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
3766 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
3767 code.error_goto(self.pos)))
3768 if self.target:
3769 self.exc_value.generate_evaluation_code(code)
3770 self.target.generate_assignment_code(self.exc_value, code)
3771 if self.excinfo_target is not None:
3772 self.excinfo_tuple.generate_evaluation_code(code)
3773 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
3775 old_exc_vars = code.funcstate.exc_vars
3776 code.funcstate.exc_vars = self.exc_vars
3777 self.body.generate_execution_code(code)
3778 code.funcstate.exc_vars = old_exc_vars
3779 for var in self.exc_vars:
3780 code.putln("Py_DECREF(%s); %s = 0;" % (var, var))
3781 code.put_goto(end_label)
3782 code.putln(
3783 "}")
3785 def annotate(self, code):
3786 if self.pattern:
3787 self.pattern.annotate(code)
3788 if self.target:
3789 self.target.annotate(code)
3790 self.body.annotate(code)
3793 class TryFinallyStatNode(StatNode):
3794 # try ... finally statement
3796 # body StatNode
3797 # finally_clause StatNode
3799 # cleanup_list [Entry] temps to clean up on error
3801 # The plan is that we funnel all continue, break
3802 # return and error gotos into the beginning of the
3803 # finally block, setting a variable to remember which
3804 # one we're doing. At the end of the finally block, we
3805 # switch on the variable to figure out where to go.
3806 # In addition, if we're doing an error, we save the
3807 # exception on entry to the finally block and restore
3808 # it on exit.
3810 child_attrs = ["body", "finally_clause"]
3812 preserve_exception = 1
3814 disallow_continue_in_try_finally = 0
3815 # There doesn't seem to be any point in disallowing
3816 # continue in the try block, since we have no problem
3817 # handling it.
3819 def create_analysed(pos, env, body, finally_clause):
3820 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
3821 node.cleanup_list = []
3822 return node
3823 create_analysed = staticmethod(create_analysed)
3825 def analyse_control_flow(self, env):
3826 env.start_branching(self.pos)
3827 self.body.analyse_control_flow(env)
3828 env.next_branch(self.body.end_pos())
3829 env.finish_branching(self.body.end_pos())
3830 self.finally_clause.analyse_control_flow(env)
3832 def analyse_declarations(self, env):
3833 self.body.analyse_declarations(env)
3834 self.finally_clause.analyse_declarations(env)
3836 def analyse_expressions(self, env):
3837 self.body.analyse_expressions(env)
3838 self.cleanup_list = env.free_temp_entries[:]
3839 self.finally_clause.analyse_expressions(env)
3840 self.gil_check(env)
3842 gil_message = "Try-finally statement"
3844 def generate_execution_code(self, code):
3845 old_error_label = code.error_label
3846 old_labels = code.all_new_labels()
3847 new_labels = code.get_all_labels()
3848 new_error_label = code.error_label
3849 catch_label = code.new_label()
3850 code.putln(
3851 "/*try:*/ {")
3852 if self.disallow_continue_in_try_finally:
3853 was_in_try_finally = code.funcstate.in_try_finally
3854 code.funcstate.in_try_finally = 1
3855 self.body.generate_execution_code(code)
3856 if self.disallow_continue_in_try_finally:
3857 code.funcstate.in_try_finally = was_in_try_finally
3858 code.putln(
3859 "}")
3860 code.putln(
3861 "/*finally:*/ {")
3862 cases_used = []
3863 error_label_used = 0
3864 for i, new_label in enumerate(new_labels):
3865 if new_label in code.labels_used:
3866 cases_used.append(i)
3867 if new_label == new_error_label:
3868 error_label_used = 1
3869 error_label_case = i
3870 if cases_used:
3871 code.putln(
3872 "int __pyx_why;")
3873 if error_label_used and self.preserve_exception:
3874 code.putln(
3875 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
3876 code.putln(
3877 "int %s;" % Naming.exc_lineno_name)
3878 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
3879 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
3880 code.putln(exc_var_init_zero)
3881 else:
3882 exc_var_init_zero = None
3883 code.use_label(catch_label)
3884 code.putln(
3885 "__pyx_why = 0; goto %s;" % catch_label)
3886 for i in cases_used:
3887 new_label = new_labels[i]
3888 #if new_label and new_label != "<try>":
3889 if new_label == new_error_label and self.preserve_exception:
3890 self.put_error_catcher(code,
3891 new_error_label, i+1, catch_label)
3892 else:
3893 code.put('%s: ' % new_label)
3894 if exc_var_init_zero:
3895 code.putln(exc_var_init_zero)
3896 code.putln("__pyx_why = %s; goto %s;" % (
3897 i+1,
3898 catch_label))
3899 code.put_label(catch_label)
3900 code.set_all_labels(old_labels)
3901 if error_label_used:
3902 code.new_error_label()
3903 finally_error_label = code.error_label
3904 self.finally_clause.generate_execution_code(code)
3905 if error_label_used:
3906 if finally_error_label in code.labels_used and self.preserve_exception:
3907 over_label = code.new_label()
3908 code.put_goto(over_label);
3909 code.put_label(finally_error_label)
3910 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
3911 for var in Naming.exc_vars:
3912 code.putln("Py_XDECREF(%s);" % var)
3913 code.putln("}")
3914 code.put_goto(old_error_label)
3915 code.put_label(over_label)
3916 code.error_label = old_error_label
3917 if cases_used:
3918 code.putln(
3919 "switch (__pyx_why) {")
3920 for i in cases_used:
3921 old_label = old_labels[i]
3922 if old_label == old_error_label and self.preserve_exception:
3923 self.put_error_uncatcher(code, i+1, old_error_label)
3924 else:
3925 code.use_label(old_label)
3926 code.putln(
3927 "case %s: goto %s;" % (
3928 i+1,
3929 old_label))
3930 code.putln(
3931 "}")
3932 code.putln(
3933 "}")
3935 def put_error_catcher(self, code, error_label, i, catch_label):
3936 code.globalstate.use_utility_code(restore_exception_utility_code)
3937 code.putln(
3938 "%s: {" %
3939 error_label)
3940 code.putln(
3941 "__pyx_why = %s;" %
3942 i)
3943 code.put_var_xdecrefs_clear(self.cleanup_list)
3944 code.putln(
3945 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
3946 Naming.exc_vars)
3947 code.putln(
3948 "%s = %s;" % (
3949 Naming.exc_lineno_name, Naming.lineno_cname))
3950 #code.putln(
3951 # "goto %s;" %
3952 # catch_label)
3953 code.put_goto(catch_label)
3954 code.putln(
3955 "}")
3957 def put_error_uncatcher(self, code, i, error_label):
3958 code.globalstate.use_utility_code(restore_exception_utility_code)
3959 code.putln(
3960 "case %s: {" %
3961 i)
3962 code.putln(
3963 "__Pyx_ErrRestore(%s, %s, %s);" %
3964 Naming.exc_vars)
3965 code.putln(
3966 "%s = %s;" % (
3967 Naming.lineno_cname, Naming.exc_lineno_name))
3968 for var in Naming.exc_vars:
3969 code.putln(
3970 "%s = 0;" %
3971 var)
3972 code.put_goto(error_label)
3973 code.putln(
3974 "}")
3976 def annotate(self, code):
3977 self.body.annotate(code)
3978 self.finally_clause.annotate(code)
3981 class GILStatNode(TryFinallyStatNode):
3982 # 'with gil' or 'with nogil' statement
3984 # state string 'gil' or 'nogil'
3986 child_attrs = []
3988 preserve_exception = 0
3990 def __init__(self, pos, state, body):
3991 self.state = state
3992 TryFinallyStatNode.__init__(self, pos,
3993 body = body,
3994 finally_clause = GILExitNode(pos, state = state))
3996 def analyse_expressions(self, env):
3997 was_nogil = env.nogil
3998 env.nogil = 1
3999 TryFinallyStatNode.analyse_expressions(self, env)
4000 env.nogil = was_nogil
4002 def gil_check(self, env):
4003 pass
4005 def generate_execution_code(self, code):
4006 code.putln("/*with %s:*/ {" % self.state)
4007 if self.state == 'gil':
4008 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
4009 else:
4010 code.putln("PyThreadState *_save;")
4011 code.putln("Py_UNBLOCK_THREADS")
4012 TryFinallyStatNode.generate_execution_code(self, code)
4013 code.putln("}")
4016 class GILExitNode(StatNode):
4017 # Used as the 'finally' block in a GILStatNode
4019 # state string 'gil' or 'nogil'
4021 child_attrs = []
4023 def analyse_expressions(self, env):
4024 pass
4026 def generate_execution_code(self, code):
4027 if self.state == 'gil':
4028 code.putln("PyGILState_Release();")
4029 else:
4030 code.putln("Py_BLOCK_THREADS")
4033 class CImportStatNode(StatNode):
4034 # cimport statement
4036 # module_name string Qualified name of module being imported
4037 # as_name string or None Name specified in "as" clause, if any
4039 child_attrs = []
4041 def analyse_declarations(self, env):
4042 if not env.is_module_scope:
4043 error(self.pos, "cimport only allowed at module level")
4044 return
4045 module_scope = env.find_module(self.module_name, self.pos)
4046 if "." in self.module_name:
4047 names = [EncodedString(name) for name in self.module_name.split(".")]
4048 top_name = names[0]
4049 top_module_scope = env.context.find_submodule(top_name)
4050 module_scope = top_module_scope
4051 for name in names[1:]:
4052 submodule_scope = module_scope.find_submodule(name)
4053 module_scope.declare_module(name, submodule_scope, self.pos)
4054 module_scope = submodule_scope
4055 if self.as_name:
4056 env.declare_module(self.as_name, module_scope, self.pos)
4057 else:
4058 env.declare_module(top_name, top_module_scope, self.pos)
4059 else:
4060 name = self.as_name or self.module_name
4061 env.declare_module(name, module_scope, self.pos)
4063 def analyse_expressions(self, env):
4064 pass
4066 def generate_execution_code(self, code):
4067 pass
4070 class FromCImportStatNode(StatNode):
4071 # from ... cimport statement
4073 # module_name string Qualified name of module
4074 # imported_names [(pos, name, as_name, kind)] Names to be imported
4076 child_attrs = []
4078 def analyse_declarations(self, env):
4079 if not env.is_module_scope:
4080 error(self.pos, "cimport only allowed at module level")
4081 return
4082 module_scope = env.find_module(self.module_name, self.pos)
4083 env.add_imported_module(module_scope)
4084 for pos, name, as_name, kind in self.imported_names:
4085 if name == "*":
4086 for local_name, entry in module_scope.entries.items():
4087 env.add_imported_entry(local_name, entry, pos)
4088 else:
4089 entry = module_scope.lookup(name)
4090 if entry:
4091 if kind and not self.declaration_matches(entry, kind):
4092 entry.redeclared(pos)
4093 else:
4094 if kind == 'struct' or kind == 'union':
4095 entry = module_scope.declare_struct_or_union(name,
4096 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4097 elif kind == 'class':
4098 entry = module_scope.declare_c_class(name, pos = pos,
4099 module_name = self.module_name)
4100 else:
4101 error(pos, "Name '%s' not declared in module '%s'"
4102 % (name, self.module_name))
4104 if entry:
4105 local_name = as_name or name
4106 env.add_imported_entry(local_name, entry, pos)
4108 def declaration_matches(self, entry, kind):
4109 if not entry.is_type:
4110 return 0
4111 type = entry.type
4112 if kind == 'class':
4113 if not type.is_extension_type:
4114 return 0
4115 else:
4116 if not type.is_struct_or_union:
4117 return 0
4118 if kind <> type.kind:
4119 return 0
4120 return 1
4122 def analyse_expressions(self, env):
4123 pass
4125 def generate_execution_code(self, code):
4126 pass
4129 class FromImportStatNode(StatNode):
4130 # from ... import statement
4132 # module ImportNode
4133 # items [(string, NameNode)]
4134 # interned_items [(string, NameNode)]
4135 # item PyTempNode used internally
4136 # import_star boolean used internally
4138 child_attrs = ["module"]
4139 import_star = 0
4141 def analyse_declarations(self, env):
4142 for name, target in self.items:
4143 if name == "*":
4144 if not env.is_module_scope:
4145 error(self.pos, "import * only allowed at module level")
4146 return
4147 env.has_import_star = 1
4148 self.import_star = 1
4149 else:
4150 target.analyse_target_declaration(env)
4152 def analyse_expressions(self, env):
4153 import ExprNodes
4154 self.module.analyse_expressions(env)
4155 self.item = ExprNodes.PyTempNode(self.pos, env)
4156 self.item.allocate_temp(env)
4157 self.interned_items = []
4158 for name, target in self.items:
4159 if name == '*':
4160 for _, entry in env.entries.items():
4161 if not entry.is_type and entry.type.is_extension_type:
4162 env.use_utility_code(ExprNodes.type_test_utility_code)
4163 break
4164 else:
4165 self.interned_items.append(
4166 (env.intern_identifier(name), target))
4167 target.analyse_target_expression(env, None)
4168 #target.release_target_temp(env) # was release_temp ?!?
4169 self.module.release_temp(env)
4170 self.item.release_temp(env)
4172 def generate_execution_code(self, code):
4173 self.module.generate_evaluation_code(code)
4174 if self.import_star:
4175 code.putln(
4176 'if (%s(%s) < 0) %s;' % (
4177 Naming.import_star,
4178 self.module.py_result(),
4179 code.error_goto(self.pos)))
4180 for cname, target in self.interned_items:
4181 code.putln(
4182 '%s = PyObject_GetAttr(%s, %s); %s' % (
4183 self.item.result(),
4184 self.module.py_result(),
4185 cname,
4186 code.error_goto_if_null(self.item.result(), self.pos)))
4187 target.generate_assignment_code(self.item, code)
4188 self.module.generate_disposal_code(code)
4191 #------------------------------------------------------------------------------------
4193 # Runtime support code
4195 #------------------------------------------------------------------------------------
4197 utility_function_predeclarations = \
4198 """
4199 #ifdef __GNUC__
4200 #define INLINE __inline__
4201 #elif _WIN32
4202 #define INLINE __inline
4203 #else
4204 #define INLINE
4205 #endif
4207 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4209 """ + """
4211 static int %(skip_dispatch_cname)s = 0;
4213 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4215 if Options.gcc_branch_hints:
4216 branch_prediction_macros = \
4217 """
4218 #ifdef __GNUC__
4219 /* Test for GCC > 2.95 */
4220 #if __GNUC__ > 2 || \
4221 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4222 #define likely(x) __builtin_expect(!!(x), 1)
4223 #define unlikely(x) __builtin_expect(!!(x), 0)
4224 #else /* __GNUC__ > 2 ... */
4225 #define likely(x) (x)
4226 #define unlikely(x) (x)
4227 #endif /* __GNUC__ > 2 ... */
4228 #else /* __GNUC__ */
4229 #define likely(x) (x)
4230 #define unlikely(x) (x)
4231 #endif /* __GNUC__ */
4232 """
4233 else:
4234 branch_prediction_macros = \
4235 """
4236 #define likely(x) (x)
4237 #define unlikely(x) (x)
4238 """
4240 #get_name_predeclaration = \
4241 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4243 #get_name_interned_predeclaration = \
4244 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4246 #------------------------------------------------------------------------------------
4248 printing_utility_code = [
4249 """
4250 static int __Pyx_Print(PyObject *, int); /*proto*/
4251 #if PY_MAJOR_VERSION >= 3
4252 static PyObject* %s = 0;
4253 static PyObject* %s = 0;
4254 #endif
4255 """ % (Naming.print_function, Naming.print_function_kwargs), r"""
4256 #if PY_MAJOR_VERSION < 3
4257 static PyObject *__Pyx_GetStdout(void) {
4258 PyObject *f = PySys_GetObject("stdout");
4259 if (!f) {
4260 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4262 return f;
4265 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4266 PyObject *f;
4267 PyObject* v;
4268 int i;
4270 if (!(f = __Pyx_GetStdout()))
4271 return -1;
4272 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4273 if (PyFile_SoftSpace(f, 1)) {
4274 if (PyFile_WriteString(" ", f) < 0)
4275 return -1;
4277 v = PyTuple_GET_ITEM(arg_tuple, i);
4278 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4279 return -1;
4280 if (PyString_Check(v)) {
4281 char *s = PyString_AsString(v);
4282 Py_ssize_t len = PyString_Size(v);
4283 if (len > 0 &&
4284 isspace(Py_CHARMASK(s[len-1])) &&
4285 s[len-1] != ' ')
4286 PyFile_SoftSpace(f, 0);
4289 if (newline) {
4290 if (PyFile_WriteString("\n", f) < 0)
4291 return -1;
4292 PyFile_SoftSpace(f, 0);
4294 return 0;
4297 #else /* Python 3 has a print function */
4298 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4299 PyObject* kwargs = 0;
4300 PyObject* result = 0;
4301 PyObject* end_string;
4302 if (!%(PRINT_FUNCTION)s) {
4303 %(PRINT_FUNCTION)s = PyObject_GetAttrString(%(BUILTINS)s, "print");
4304 if (!%(PRINT_FUNCTION)s)
4305 return -1;
4307 if (!newline) {
4308 if (!%(PRINT_KWARGS)s) {
4309 %(PRINT_KWARGS)s = PyDict_New();
4310 if (!%(PRINT_KWARGS)s)
4311 return -1;
4312 end_string = PyUnicode_FromStringAndSize(" ", 1);
4313 if (!end_string)
4314 return -1;
4315 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4316 Py_DECREF(end_string);
4317 return -1;
4319 Py_DECREF(end_string);
4321 kwargs = %(PRINT_KWARGS)s;
4323 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4324 if (!result)
4325 return -1;
4326 Py_DECREF(result);
4327 return 0;
4329 #endif
4330 """ % {'BUILTINS' : Naming.builtins_cname,
4331 'PRINT_FUNCTION' : Naming.print_function,
4332 'PRINT_KWARGS' : Naming.print_function_kwargs}
4335 #------------------------------------------------------------------------------------
4337 # The following function is based on do_raise() from ceval.c.
4339 raise_utility_code = [
4340 """
4341 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4342 ""","""
4343 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4344 Py_XINCREF(type);
4345 Py_XINCREF(value);
4346 Py_XINCREF(tb);
4347 /* First, check the traceback argument, replacing None with NULL. */
4348 if (tb == Py_None) {
4349 Py_DECREF(tb);
4350 tb = 0;
4352 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4353 PyErr_SetString(PyExc_TypeError,
4354 "raise: arg 3 must be a traceback or None");
4355 goto raise_error;
4357 /* Next, replace a missing value with None */
4358 if (value == NULL) {
4359 value = Py_None;
4360 Py_INCREF(value);
4362 #if PY_VERSION_HEX < 0x02050000
4363 if (!PyClass_Check(type))
4364 #else
4365 if (!PyType_Check(type))
4366 #endif
4368 /* Raising an instance. The value should be a dummy. */
4369 if (value != Py_None) {
4370 PyErr_SetString(PyExc_TypeError,
4371 "instance exception may not have a separate value");
4372 goto raise_error;
4374 /* Normalize to raise <class>, <instance> */
4375 Py_DECREF(value);
4376 value = type;
4377 #if PY_VERSION_HEX < 0x02050000
4378 if (PyInstance_Check(type)) {
4379 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4380 Py_INCREF(type);
4382 else {
4383 type = 0;
4384 PyErr_SetString(PyExc_TypeError,
4385 "raise: exception must be an old-style class or instance");
4386 goto raise_error;
4388 #else
4389 type = (PyObject*) Py_TYPE(type);
4390 Py_INCREF(type);
4391 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4392 PyErr_SetString(PyExc_TypeError,
4393 "raise: exception class must be a subclass of BaseException");
4394 goto raise_error;
4396 #endif
4398 __Pyx_ErrRestore(type, value, tb);
4399 return;
4400 raise_error:
4401 Py_XDECREF(value);
4402 Py_XDECREF(type);
4403 Py_XDECREF(tb);
4404 return;
4406 """]
4408 #------------------------------------------------------------------------------------
4410 reraise_utility_code = [
4411 """
4412 static void __Pyx_ReRaise(void); /*proto*/
4413 ""","""
4414 static void __Pyx_ReRaise(void) {
4415 PyThreadState *tstate = PyThreadState_Get();
4416 PyObject *type = tstate->exc_type;
4417 PyObject *value = tstate->exc_value;
4418 PyObject *tb = tstate->exc_traceback;
4419 Py_XINCREF(type);
4420 Py_XINCREF(value);
4421 Py_XINCREF(tb);
4422 __Pyx_ErrRestore(type, value, tb);
4424 """]
4426 #------------------------------------------------------------------------------------
4428 arg_type_test_utility_code = [
4429 """
4430 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4431 const char *name, int exact); /*proto*/
4432 ""","""
4433 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4434 const char *name, int exact)
4436 if (!type) {
4437 PyErr_Format(PyExc_SystemError, "Missing type object");
4438 return 0;
4440 if (none_allowed && obj == Py_None) return 1;
4441 else if (exact) {
4442 if (Py_TYPE(obj) == type) return 1;
4444 else {
4445 if (PyObject_TypeCheck(obj, type)) return 1;
4447 PyErr_Format(PyExc_TypeError,
4448 "Argument '%s' has incorrect type (expected %s, got %s)",
4449 name, type->tp_name, Py_TYPE(obj)->tp_name);
4450 return 0;
4452 """]
4454 #------------------------------------------------------------------------------------
4456 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
4457 # many or too few positional arguments were found. This handles
4458 # Py_ssize_t formatting correctly.
4460 raise_argtuple_invalid_utility_code = [
4461 """
4462 static INLINE void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
4463 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
4464 ""","""
4465 static INLINE void __Pyx_RaiseArgtupleInvalid(
4466 const char* func_name,
4467 int exact,
4468 Py_ssize_t num_min,
4469 Py_ssize_t num_max,
4470 Py_ssize_t num_found)
4472 Py_ssize_t num_expected;
4473 const char *number, *more_or_less;
4475 if (num_found < num_min) {
4476 num_expected = num_min;
4477 more_or_less = "at least";
4478 } else {
4479 num_expected = num_max;
4480 more_or_less = "at most";
4482 if (exact) {
4483 more_or_less = "exactly";
4485 number = (num_expected == 1) ? "" : "s";
4486 PyErr_Format(PyExc_TypeError,
4487 #if PY_VERSION_HEX < 0x02050000
4488 "%s() takes %s %d positional argument%s (%d given)",
4489 #else
4490 "%s() takes %s %zd positional argument%s (%zd given)",
4491 #endif
4492 func_name, more_or_less, num_expected, number, num_found);
4494 """]
4496 raise_keyword_required_utility_code = [
4497 """
4498 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
4499 ""","""
4500 static INLINE void __Pyx_RaiseKeywordRequired(
4501 const char* func_name,
4502 PyObject* kw_name)
4504 PyErr_Format(PyExc_TypeError,
4505 #if PY_MAJOR_VERSION >= 3
4506 "%s() needs keyword-only argument %U", func_name, kw_name);
4507 #else
4508 "%s() needs keyword-only argument %s", func_name,
4509 PyString_AS_STRING(kw_name));
4510 #endif
4512 """]
4514 raise_double_keywords_utility_code = [
4515 """
4516 static INLINE void __Pyx_RaiseDoubleKeywordsError(
4517 const char* func_name, PyObject* kw_name); /*proto*/
4518 ""","""
4519 static INLINE void __Pyx_RaiseDoubleKeywordsError(
4520 const char* func_name,
4521 PyObject* kw_name)
4523 PyErr_Format(PyExc_TypeError,
4524 #if PY_MAJOR_VERSION >= 3
4525 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
4526 #else
4527 "%s() got multiple values for keyword argument '%s'", func_name,
4528 PyString_AS_STRING(kw_name));
4529 #endif
4531 """]
4533 #------------------------------------------------------------------------------------
4535 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
4536 # were passed to a function, or if any keywords were passed to a
4537 # function that does not accept them.
4539 keyword_string_check_utility_code = [
4540 """
4541 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
4542 const char* function_name, int kw_allowed); /*proto*/
4543 ""","""
4544 static INLINE int __Pyx_CheckKeywordStrings(
4545 PyObject *kwdict,
4546 const char* function_name,
4547 int kw_allowed)
4549 PyObject* key = 0;
4550 Py_ssize_t pos = 0;
4551 while (PyDict_Next(kwdict, &pos, &key, 0)) {
4552 #if PY_MAJOR_VERSION < 3
4553 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
4554 #else
4555 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
4556 #endif
4557 goto invalid_keyword_type;
4559 if ((!kw_allowed) && unlikely(key))
4560 goto invalid_keyword;
4561 return 1;
4562 invalid_keyword_type:
4563 PyErr_Format(PyExc_TypeError,
4564 "%s() keywords must be strings", function_name);
4565 return 0;
4566 invalid_keyword:
4567 PyErr_Format(PyExc_TypeError,
4568 #if PY_MAJOR_VERSION < 3
4569 "%s() got an unexpected keyword argument '%s'",
4570 function_name, PyString_AsString(key));
4571 #else
4572 "%s() got an unexpected keyword argument '%U'",
4573 function_name, key);
4574 #endif
4575 return 0;
4577 """]
4579 #------------------------------------------------------------------------------------
4581 # __Pyx_SplitKeywords copies the keyword arguments that are not named
4582 # in argnames[] from the kwds dict into kwds2. If kwds2 is NULL,
4583 # these keywords will raise an invalid keyword error.
4585 # Three kinds of errors are checked: 1) non-string keywords, 2)
4586 # unexpected keywords and 3) overlap with positional arguments.
4588 # If num_posargs is greater 0, it denotes the number of positional
4589 # arguments that were passed and that must therefore not appear
4590 # amongst the keywords as well.
4592 # This method does not check for required keyword arguments.
4595 split_keywords_utility_code = [
4596 """
4597 static int __Pyx_SplitKeywords(PyObject *kwds, PyObject **argnames[], \
4598 PyObject *kwds2, Py_ssize_t num_pos_args, const char* function_name); /*proto*/
4599 ""","""
4600 static int __Pyx_SplitKeywords(
4601 PyObject *kwds,
4602 PyObject **argnames[],
4603 PyObject *kwds2,
4604 Py_ssize_t num_pos_args,
4605 const char* function_name)
4607 PyObject *key = 0, *value = 0;
4608 Py_ssize_t pos = 0;
4609 PyObject*** name;
4611 while (PyDict_Next(kwds, &pos, &key, &value)) {
4612 #if PY_MAJOR_VERSION < 3
4613 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
4614 #else
4615 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
4616 #endif
4617 goto invalid_keyword_type;
4618 } else {
4619 name = argnames;
4620 while (*name && (**name != key)) name++;
4621 if (!*name) {
4622 for (name = argnames; *name; name++) {
4623 #if PY_MAJOR_VERSION >= 3
4624 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
4625 PyUnicode_Compare(**name, key) == 0) break;
4626 #else
4627 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
4628 strcmp(PyString_AS_STRING(**name),
4629 PyString_AS_STRING(key)) == 0) break;
4630 #endif
4632 if (!*name) {
4633 if (kwds2) {
4634 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
4635 } else {
4636 goto invalid_keyword;
4640 if (*name && ((name-argnames) < num_pos_args))
4641 goto arg_passed_twice;
4644 return 0;
4645 arg_passed_twice:
4646 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
4647 goto bad;
4648 invalid_keyword_type:
4649 PyErr_Format(PyExc_TypeError,
4650 "%s() keywords must be strings", function_name);
4651 goto bad;
4652 invalid_keyword:
4653 PyErr_Format(PyExc_TypeError,
4654 #if PY_MAJOR_VERSION < 3
4655 "%s() got an unexpected keyword argument '%s'",
4656 function_name, PyString_AsString(key));
4657 #else
4658 "%s() got an unexpected keyword argument '%U'",
4659 function_name, key);
4660 #endif
4661 bad:
4662 return -1;
4664 """]
4666 #------------------------------------------------------------------------------------
4668 unraisable_exception_utility_code = [
4669 """
4670 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
4671 ""","""
4672 static void __Pyx_WriteUnraisable(const char *name) {
4673 PyObject *old_exc, *old_val, *old_tb;
4674 PyObject *ctx;
4675 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
4676 #if PY_MAJOR_VERSION < 3
4677 ctx = PyString_FromString(name);
4678 #else
4679 ctx = PyUnicode_FromString(name);
4680 #endif
4681 __Pyx_ErrRestore(old_exc, old_val, old_tb);
4682 if (!ctx) {
4683 PyErr_WriteUnraisable(Py_None);
4684 } else {
4685 PyErr_WriteUnraisable(ctx);
4686 Py_DECREF(ctx);
4689 """]
4691 #------------------------------------------------------------------------------------
4693 traceback_utility_code = [
4694 """
4695 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
4696 ""","""
4697 #include "compile.h"
4698 #include "frameobject.h"
4699 #include "traceback.h"
4701 static void __Pyx_AddTraceback(const char *funcname) {
4702 PyObject *py_srcfile = 0;
4703 PyObject *py_funcname = 0;
4704 PyObject *py_globals = 0;
4705 PyObject *empty_string = 0;
4706 PyCodeObject *py_code = 0;
4707 PyFrameObject *py_frame = 0;
4709 #if PY_MAJOR_VERSION < 3
4710 py_srcfile = PyString_FromString(%(FILENAME)s);
4711 #else
4712 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
4713 #endif
4714 if (!py_srcfile) goto bad;
4715 if (%(CLINENO)s) {
4716 #if PY_MAJOR_VERSION < 3
4717 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
4718 #else
4719 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
4720 #endif
4722 else {
4723 #if PY_MAJOR_VERSION < 3
4724 py_funcname = PyString_FromString(funcname);
4725 #else
4726 py_funcname = PyUnicode_FromString(funcname);
4727 #endif
4729 if (!py_funcname) goto bad;
4730 py_globals = PyModule_GetDict(%(GLOBALS)s);
4731 if (!py_globals) goto bad;
4732 #if PY_MAJOR_VERSION < 3
4733 empty_string = PyString_FromStringAndSize("", 0);
4734 #else
4735 empty_string = PyBytes_FromStringAndSize("", 0);
4736 #endif
4737 if (!empty_string) goto bad;
4738 py_code = PyCode_New(
4739 0, /*int argcount,*/
4740 #if PY_MAJOR_VERSION >= 3
4741 0, /*int kwonlyargcount,*/
4742 #endif
4743 0, /*int nlocals,*/
4744 0, /*int stacksize,*/
4745 0, /*int flags,*/
4746 empty_string, /*PyObject *code,*/
4747 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
4748 %(EMPTY_TUPLE)s, /*PyObject *names,*/
4749 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
4750 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
4751 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
4752 py_srcfile, /*PyObject *filename,*/
4753 py_funcname, /*PyObject *name,*/
4754 %(LINENO)s, /*int firstlineno,*/
4755 empty_string /*PyObject *lnotab*/
4756 );
4757 if (!py_code) goto bad;
4758 py_frame = PyFrame_New(
4759 PyThreadState_GET(), /*PyThreadState *tstate,*/
4760 py_code, /*PyCodeObject *code,*/
4761 py_globals, /*PyObject *globals,*/
4762 0 /*PyObject *locals*/
4763 );
4764 if (!py_frame) goto bad;
4765 py_frame->f_lineno = %(LINENO)s;
4766 PyTraceBack_Here(py_frame);
4767 bad:
4768 Py_XDECREF(py_srcfile);
4769 Py_XDECREF(py_funcname);
4770 Py_XDECREF(empty_string);
4771 Py_XDECREF(py_code);
4772 Py_XDECREF(py_frame);
4774 """ % {
4775 'FILENAME': Naming.filename_cname,
4776 'LINENO': Naming.lineno_cname,
4777 'CFILENAME': Naming.cfilenm_cname,
4778 'CLINENO': Naming.clineno_cname,
4779 'GLOBALS': Naming.module_cname,
4780 'EMPTY_TUPLE' : Naming.empty_tuple,
4781 }]
4783 restore_exception_utility_code = [
4784 """
4785 void INLINE __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4786 void INLINE __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
4787 ""","""
4788 void INLINE __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
4789 PyObject *tmp_type, *tmp_value, *tmp_tb;
4790 PyThreadState *tstate = PyThreadState_GET();
4792 tmp_type = tstate->curexc_type;
4793 tmp_value = tstate->curexc_value;
4794 tmp_tb = tstate->curexc_traceback;
4795 tstate->curexc_type = type;
4796 tstate->curexc_value = value;
4797 tstate->curexc_traceback = tb;
4798 Py_XDECREF(tmp_type);
4799 Py_XDECREF(tmp_value);
4800 Py_XDECREF(tmp_tb);
4803 void INLINE __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
4804 PyThreadState *tstate = PyThreadState_GET();
4805 *type = tstate->curexc_type;
4806 *value = tstate->curexc_value;
4807 *tb = tstate->curexc_traceback;
4809 tstate->curexc_type = 0;
4810 tstate->curexc_value = 0;
4811 tstate->curexc_traceback = 0;
4814 """]
4816 #------------------------------------------------------------------------------------
4818 set_vtable_utility_code = [
4819 """
4820 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
4821 ""","""
4822 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
4823 PyObject *pycobj = 0;
4824 int result;
4826 pycobj = PyCObject_FromVoidPtr(vtable, 0);
4827 if (!pycobj)
4828 goto bad;
4829 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
4830 goto bad;
4831 result = 0;
4832 goto done;
4834 bad:
4835 result = -1;
4836 done:
4837 Py_XDECREF(pycobj);
4838 return result;
4840 """]
4842 #------------------------------------------------------------------------------------
4844 get_vtable_utility_code = [
4845 """
4846 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
4847 """,r"""
4848 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
4849 int result;
4850 PyObject *pycobj;
4852 pycobj = PyMapping_GetItemString(dict, "__pyx_vtable__");
4853 if (!pycobj)
4854 goto bad;
4855 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
4856 if (!*(void **)vtabptr)
4857 goto bad;
4858 result = 0;
4859 goto done;
4861 bad:
4862 result = -1;
4863 done:
4864 Py_XDECREF(pycobj);
4865 return result;
4867 """]
4869 #------------------------------------------------------------------------------------
4871 init_string_tab_utility_code = [
4872 """
4873 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
4874 ""","""
4875 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
4876 while (t->p) {
4877 #if PY_MAJOR_VERSION < 3
4878 if (t->is_unicode && (!t->is_identifier)) {
4879 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
4880 } else if (t->intern) {
4881 *t->p = PyString_InternFromString(t->s);
4882 } else {
4883 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
4885 #else /* Python 3+ has unicode identifiers */
4886 if (t->is_identifier || (t->is_unicode && t->intern)) {
4887 *t->p = PyUnicode_InternFromString(t->s);
4888 } else if (t->is_unicode) {
4889 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
4890 } else {
4891 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
4893 #endif
4894 if (!*t->p)
4895 return -1;
4896 ++t;
4898 return 0;
4900 """]
4902 #------------------------------------------------------------------------------------
4904 get_exception_utility_code = [
4905 """
4906 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
4907 ""","""
4908 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
4909 PyObject *tmp_type, *tmp_value, *tmp_tb;
4910 PyThreadState *tstate = PyThreadState_GET();
4911 __Pyx_ErrFetch(type, value, tb);
4912 PyErr_NormalizeException(type, value, tb);
4913 if (PyErr_Occurred())
4914 goto bad;
4915 Py_INCREF(*type);
4916 Py_INCREF(*value);
4917 Py_INCREF(*tb);
4918 tmp_type = tstate->exc_type;
4919 tmp_value = tstate->exc_value;
4920 tmp_tb = tstate->exc_traceback;
4921 tstate->exc_type = *type;
4922 tstate->exc_value = *value;
4923 tstate->exc_traceback = *tb;
4924 /* Make sure tstate is in a consistent state when we XDECREF
4925 these objects (XDECREF may run arbitrary code). */
4926 Py_XDECREF(tmp_type);
4927 Py_XDECREF(tmp_value);
4928 Py_XDECREF(tmp_tb);
4929 return 0;
4930 bad:
4931 Py_XDECREF(*type);
4932 Py_XDECREF(*value);
4933 Py_XDECREF(*tb);
4934 return -1;
4937 """]
4939 #------------------------------------------------------------------------------------
4941 reset_exception_utility_code = [
4942 """
4943 void INLINE __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
4944 void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4945 ""","""
4946 void INLINE __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
4947 PyThreadState *tstate = PyThreadState_GET();
4948 *type = tstate->exc_type;
4949 *value = tstate->exc_value;
4950 *tb = tstate->exc_traceback;
4951 Py_XINCREF(*type);
4952 Py_XINCREF(*value);
4953 Py_XINCREF(*tb);
4956 void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
4957 PyObject *tmp_type, *tmp_value, *tmp_tb;
4958 PyThreadState *tstate = PyThreadState_GET();
4959 tmp_type = tstate->exc_type;
4960 tmp_value = tstate->exc_value;
4961 tmp_tb = tstate->exc_traceback;
4962 tstate->exc_type = type;
4963 tstate->exc_value = value;
4964 tstate->exc_traceback = tb;
4965 Py_XDECREF(tmp_type);
4966 Py_XDECREF(tmp_value);
4967 Py_XDECREF(tmp_tb);
4969 """]
4971 #------------------------------------------------------------------------------------