Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 1299:e99159c5354b

Fix trac #107.
author Robert Bradshaw <robertwb@math.washington.edu>
date Tue Nov 04 11:58:29 2008 -0800 (3 years ago)
parents 96f15e379330
children 393a919e3f46 ef9d2c680684
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, UtilityCode
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 else:
415 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
416 base_type = py_object_type
417 self.type = base_type
418 return self, base_type
420 class CPtrDeclaratorNode(CDeclaratorNode):
421 # base CDeclaratorNode
423 child_attrs = ["base"]
425 def analyse(self, base_type, env, nonempty = 0):
426 if base_type.is_pyobject:
427 error(self.pos,
428 "Pointer base type cannot be a Python object")
429 ptr_type = PyrexTypes.c_ptr_type(base_type)
430 return self.base.analyse(ptr_type, env, nonempty = nonempty)
432 class CArrayDeclaratorNode(CDeclaratorNode):
433 # base CDeclaratorNode
434 # dimension ExprNode
436 child_attrs = ["base", "dimension"]
438 def analyse(self, base_type, env, nonempty = 0):
439 if self.dimension:
440 self.dimension.analyse_const_expression(env)
441 if not self.dimension.type.is_int:
442 error(self.dimension.pos, "Array dimension not integer")
443 size = self.dimension.result()
444 else:
445 size = None
446 if not base_type.is_complete():
447 error(self.pos,
448 "Array element type '%s' is incomplete" % base_type)
449 if base_type.is_pyobject:
450 error(self.pos,
451 "Array element cannot be a Python object")
452 if base_type.is_cfunction:
453 error(self.pos,
454 "Array element cannot be a function")
455 array_type = PyrexTypes.c_array_type(base_type, size)
456 return self.base.analyse(array_type, env, nonempty = nonempty)
459 class CFuncDeclaratorNode(CDeclaratorNode):
460 # base CDeclaratorNode
461 # args [CArgDeclNode]
462 # has_varargs boolean
463 # exception_value ConstNode
464 # exception_check boolean True if PyErr_Occurred check needed
465 # nogil boolean Can be called without gil
466 # with_gil boolean Acquire gil around function body
468 child_attrs = ["base", "args", "exception_value"]
470 overridable = 0
471 optional_arg_count = 0
473 def analyse(self, return_type, env, nonempty = 0):
474 if nonempty:
475 nonempty -= 1
476 func_type_args = []
477 for arg_node in self.args:
478 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
479 name = name_declarator.name
480 if name_declarator.cname:
481 error(self.pos,
482 "Function argument cannot have C name specification")
483 # Turn *[] argument into **
484 if type.is_array:
485 type = PyrexTypes.c_ptr_type(type.base_type)
486 # Catch attempted C-style func(void) decl
487 if type.is_void:
488 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
489 # if type.is_pyobject and self.nogil:
490 # error(self.pos,
491 # "Function with Python argument cannot be declared nogil")
492 func_type_args.append(
493 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
494 if arg_node.default:
495 self.optional_arg_count += 1
496 elif self.optional_arg_count:
497 error(self.pos, "Non-default argument follows default argument")
499 if self.optional_arg_count:
500 scope = StructOrUnionScope()
501 scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
502 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
503 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
504 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
505 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
506 kind = 'struct',
507 scope = scope,
508 typedef_flag = 0,
509 pos = self.pos,
510 cname = struct_cname)
511 self.op_args_struct.defined_in_pxd = 1
512 self.op_args_struct.used = 1
514 exc_val = None
515 exc_check = 0
516 if return_type.is_pyobject \
517 and (self.exception_value or self.exception_check) \
518 and self.exception_check != '+':
519 error(self.pos,
520 "Exception clause not allowed for function returning Python object")
521 else:
522 if self.exception_value:
523 self.exception_value.analyse_const_expression(env)
524 if self.exception_check == '+':
525 exc_val_type = self.exception_value.type
526 if not exc_val_type.is_error and \
527 not exc_val_type.is_pyobject and \
528 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
529 error(self.exception_value.pos,
530 "Exception value must be a Python exception or cdef function with no arguments.")
531 exc_val = self.exception_value
532 else:
533 exc_val = self.exception_value.result()
534 if not return_type.assignable_from(self.exception_value.type):
535 error(self.exception_value.pos,
536 "Exception value incompatible with function return type")
537 exc_check = self.exception_check
538 if return_type.is_array:
539 error(self.pos,
540 "Function cannot return an array")
541 if return_type.is_cfunction:
542 error(self.pos,
543 "Function cannot return a function")
544 func_type = PyrexTypes.CFuncType(
545 return_type, func_type_args, self.has_varargs,
546 optional_arg_count = self.optional_arg_count,
547 exception_value = exc_val, exception_check = exc_check,
548 calling_convention = self.base.calling_convention,
549 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
550 if self.optional_arg_count:
551 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
552 return self.base.analyse(func_type, env)
555 class CArgDeclNode(Node):
556 # Item in a function declaration argument list.
557 #
558 # base_type CBaseTypeNode
559 # declarator CDeclaratorNode
560 # not_none boolean Tagged with 'not None'
561 # default ExprNode or None
562 # default_entry Symtab.Entry Entry for the variable holding the default value
563 # default_result_code string cname or code fragment for default value
564 # is_self_arg boolean Is the "self" arg of an extension type method
565 # is_kw_only boolean Is a keyword-only argument
567 child_attrs = ["base_type", "declarator", "default"]
569 is_self_arg = 0
570 is_generic = 1
571 type = None
572 name_declarator = None
574 def analyse(self, env, nonempty = 0):
575 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
576 if self.type is None:
577 # The parser may missinterpret names as types...
578 # We fix that here.
579 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
580 if nonempty:
581 self.declarator.name = self.base_type.name
582 self.base_type.name = None
583 self.base_type.is_basic_c_type = False
584 could_be_name = True
585 else:
586 could_be_name = False
587 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
588 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
589 self.declarator.name = self.base_type.arg_name
590 return self.declarator.analyse(base_type, env, nonempty = nonempty)
591 else:
592 return self.name_declarator, self.type
594 def annotate(self, code):
595 if self.default:
596 self.default.annotate(code)
599 class CBaseTypeNode(Node):
600 # Abstract base class for C base type nodes.
601 #
602 # Processing during analyse_declarations phase:
603 #
604 # analyse
605 # Returns the type.
607 pass
609 class CAnalysedBaseTypeNode(Node):
610 # type type
612 child_attrs = []
614 def analyse(self, env, could_be_name = False):
615 return self.type
617 class CSimpleBaseTypeNode(CBaseTypeNode):
618 # name string
619 # module_path [string] Qualifying name components
620 # is_basic_c_type boolean
621 # signed boolean
622 # longness integer
623 # is_self_arg boolean Is self argument of C method
625 child_attrs = []
626 arg_name = None # in case the argument name was interpreted as a type
628 def analyse(self, env, could_be_name = False):
629 # Return type descriptor.
630 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
631 type = None
632 if self.is_basic_c_type:
633 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
634 if not type:
635 error(self.pos, "Unrecognised type modifier combination")
636 elif self.name == "object" and not self.module_path:
637 type = py_object_type
638 elif self.name is None:
639 if self.is_self_arg and env.is_c_class_scope:
640 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
641 type = env.parent_type
642 else:
643 type = py_object_type
644 else:
645 if self.module_path:
646 scope = env.find_imported_module(self.module_path, self.pos)
647 else:
648 scope = env
649 if scope:
650 if scope.is_c_class_scope:
651 scope = scope.global_scope()
652 entry = scope.lookup(self.name)
653 if entry and entry.is_type:
654 type = entry.type
655 elif could_be_name:
656 if self.is_self_arg and env.is_c_class_scope:
657 type = env.parent_type
658 else:
659 type = py_object_type
660 self.arg_name = self.name
661 else:
662 error(self.pos, "'%s' is not a type identifier" % self.name)
663 if type:
664 return type
665 else:
666 return PyrexTypes.error_type
668 class CBufferAccessTypeNode(CBaseTypeNode):
669 # After parsing:
670 # positional_args [ExprNode] List of positional arguments
671 # keyword_args DictNode Keyword arguments
672 # base_type_node CBaseTypeNode
674 # After analysis:
675 # type PyrexType.BufferType ...containing the right options
678 child_attrs = ["base_type_node", "positional_args",
679 "keyword_args", "dtype_node"]
681 dtype_node = None
683 def analyse(self, env, could_be_name = False):
684 base_type = self.base_type_node.analyse(env)
685 if base_type.is_error: return base_type
686 import Buffer
688 options = Buffer.analyse_buffer_options(
689 self.pos,
690 env,
691 self.positional_args,
692 self.keyword_args,
693 base_type.buffer_defaults)
695 self.type = PyrexTypes.BufferType(base_type, **options)
696 return self.type
698 class CComplexBaseTypeNode(CBaseTypeNode):
699 # base_type CBaseTypeNode
700 # declarator CDeclaratorNode
702 child_attrs = ["base_type", "declarator"]
704 def analyse(self, env, could_be_name = False):
705 base = self.base_type.analyse(env, could_be_name)
706 _, type = self.declarator.analyse(base, env)
707 return type
710 class CVarDefNode(StatNode):
711 # C variable definition or forward/extern function declaration.
712 #
713 # visibility 'private' or 'public' or 'extern'
714 # base_type CBaseTypeNode
715 # declarators [CDeclaratorNode]
716 # in_pxd boolean
717 # api boolean
718 # need_properties [entry]
720 child_attrs = ["base_type", "declarators"]
721 need_properties = ()
723 def analyse_declarations(self, env, dest_scope = None):
724 if not dest_scope:
725 dest_scope = env
726 self.dest_scope = dest_scope
727 base_type = self.base_type.analyse(env)
728 if (dest_scope.is_c_class_scope
729 and self.visibility == 'public'
730 and base_type.is_pyobject
731 and (base_type.is_builtin_type or base_type.is_extension_type)):
732 self.need_properties = []
733 need_property = True
734 visibility = 'private'
735 else:
736 need_property = False
737 visibility = self.visibility
739 for declarator in self.declarators:
740 name_declarator, type = declarator.analyse(base_type, env)
741 if not type.is_complete():
742 if not (self.visibility == 'extern' and type.is_array):
743 error(declarator.pos,
744 "Variable type '%s' is incomplete" % type)
745 if self.visibility == 'extern' and type.is_pyobject:
746 error(declarator.pos,
747 "Python object cannot be declared extern")
748 name = name_declarator.name
749 cname = name_declarator.cname
750 if name == '':
751 error(declarator.pos, "Missing name in declaration.")
752 return
753 if type.is_cfunction:
754 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
755 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
756 api = self.api)
757 else:
758 if self.in_pxd and self.visibility != 'extern':
759 error(self.pos,
760 "Only 'extern' C variable declaration allowed in .pxd file")
761 entry = dest_scope.declare_var(name, type, declarator.pos,
762 cname = cname, visibility = visibility, is_cdef = 1)
763 if need_property:
764 self.need_properties.append(entry)
765 entry.needs_property = 1
768 class CStructOrUnionDefNode(StatNode):
769 # name string
770 # cname string or None
771 # kind "struct" or "union"
772 # typedef_flag boolean
773 # visibility "public" or "private"
774 # in_pxd boolean
775 # attributes [CVarDefNode] or None
776 # entry Entry
778 child_attrs = ["attributes"]
780 def analyse_declarations(self, env):
781 scope = None
782 if self.attributes is not None:
783 scope = StructOrUnionScope(self.name)
784 self.entry = env.declare_struct_or_union(
785 self.name, self.kind, scope, self.typedef_flag, self.pos,
786 self.cname, visibility = self.visibility)
787 if self.attributes is not None:
788 if self.in_pxd and not env.in_cinclude:
789 self.entry.defined_in_pxd = 1
790 for attr in self.attributes:
791 attr.analyse_declarations(env, scope)
793 def analyse_expressions(self, env):
794 pass
796 def generate_execution_code(self, code):
797 pass
800 class CEnumDefNode(StatNode):
801 # name string or None
802 # cname string or None
803 # items [CEnumDefItemNode]
804 # typedef_flag boolean
805 # visibility "public" or "private"
806 # in_pxd boolean
807 # entry Entry
809 child_attrs = ["items"]
811 def analyse_declarations(self, env):
812 self.entry = env.declare_enum(self.name, self.pos,
813 cname = self.cname, typedef_flag = self.typedef_flag,
814 visibility = self.visibility)
815 if self.items is not None:
816 if self.in_pxd and not env.in_cinclude:
817 self.entry.defined_in_pxd = 1
818 for item in self.items:
819 item.analyse_declarations(env, self.entry)
821 def analyse_expressions(self, env):
822 if self.visibility == 'public':
823 self.temp = env.allocate_temp_pyobject()
824 env.release_temp(self.temp)
826 def generate_execution_code(self, code):
827 if self.visibility == 'public':
828 for item in self.entry.enum_values:
829 code.putln("%s = PyInt_FromLong(%s); %s" % (
830 self.temp,
831 item.cname,
832 code.error_goto_if_null(self.temp, item.pos)))
833 code.putln('if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
834 Naming.module_cname,
835 item.name,
836 self.temp,
837 code.error_goto(item.pos)))
838 code.putln("%s = 0;" % self.temp)
841 class CEnumDefItemNode(StatNode):
842 # name string
843 # cname string or None
844 # value ExprNode or None
846 child_attrs = ["value"]
848 def analyse_declarations(self, env, enum_entry):
849 if self.value:
850 self.value.analyse_const_expression(env)
851 if not self.value.type.is_int:
852 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
853 self.value.analyse_const_expression(env)
854 value = self.value.result()
855 else:
856 value = self.name
857 entry = env.declare_const(self.name, enum_entry.type,
858 value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
859 enum_entry.enum_values.append(entry)
862 class CTypeDefNode(StatNode):
863 # base_type CBaseTypeNode
864 # declarator CDeclaratorNode
865 # visibility "public" or "private"
866 # in_pxd boolean
868 child_attrs = ["base_type", "declarator"]
870 def analyse_declarations(self, env):
871 base = self.base_type.analyse(env)
872 name_declarator, type = self.declarator.analyse(base, env)
873 name = name_declarator.name
874 cname = name_declarator.cname
875 entry = env.declare_typedef(name, type, self.pos,
876 cname = cname, visibility = self.visibility)
877 if self.in_pxd and not env.in_cinclude:
878 entry.defined_in_pxd = 1
880 def analyse_expressions(self, env):
881 pass
882 def generate_execution_code(self, code):
883 pass
886 class FuncDefNode(StatNode, BlockNode):
887 # Base class for function definition nodes.
888 #
889 # return_type PyrexType
890 # #filename string C name of filename string const
891 # entry Symtab.Entry
892 # needs_closure boolean Whether or not this function has inner functions/classes/yield
894 py_func = None
895 assmt = None
896 needs_closure = False
898 def analyse_default_values(self, env):
899 genv = env.global_scope()
900 for arg in self.args:
901 if arg.default:
902 if arg.is_generic:
903 if not hasattr(arg, 'default_entry'):
904 arg.default.analyse_types(env)
905 arg.default = arg.default.coerce_to(arg.type, genv)
906 if arg.default.is_literal:
907 arg.default_entry = arg.default
908 arg.default_result_code = arg.default.calculate_result_code()
909 if arg.default.type != arg.type and not arg.type.is_int:
910 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
911 else:
912 arg.default.allocate_temps(genv)
913 arg.default_entry = genv.add_default_value(arg.type)
914 arg.default_entry.used = 1
915 arg.default_result_code = arg.default_entry.cname
916 else:
917 error(arg.pos,
918 "This argument cannot have a default value")
919 arg.default = None
921 def need_gil_acquisition(self, lenv):
922 return 0
924 def create_local_scope(self, env):
925 genv = env
926 while env.is_py_class_scope or env.is_c_class_scope:
927 env = env.outer_scope
928 if self.needs_closure:
929 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
930 else:
931 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
932 lenv.return_type = self.return_type
933 type = self.entry.type
934 if type.is_cfunction:
935 lenv.nogil = type.nogil and not type.with_gil
936 self.local_scope = lenv
937 return lenv
939 def generate_function_definitions(self, env, code):
940 import Buffer
942 lenv = self.local_scope
944 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
945 self.entry.scope.is_c_class_scope)
947 # Generate C code for header and body of function
948 code.enter_cfunc_scope()
949 code.return_from_error_cleanup_label = code.new_label()
951 # ----- Top-level constants used by this function
952 code.mark_pos(self.pos)
953 self.generate_interned_num_decls(lenv, code)
954 self.generate_interned_string_decls(lenv, code)
955 self.generate_py_string_decls(lenv, code)
956 self.generate_cached_builtins_decls(lenv, code)
957 #code.putln("")
958 #code.put_var_declarations(lenv.const_entries, static = 1)
959 self.generate_const_definitions(lenv, code)
960 # ----- Function header
961 code.putln("")
962 if self.py_func:
963 self.py_func.generate_function_header(code,
964 with_pymethdef = env.is_py_class_scope,
965 proto_only=True)
966 self.generate_function_header(code,
967 with_pymethdef = env.is_py_class_scope)
968 # ----- Local variable declarations
969 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
970 self.generate_argument_declarations(lenv, code)
971 if self.needs_closure:
972 code.putln("/* TODO: declare and create scope object */")
973 code.put_var_declarations(lenv.var_entries)
974 init = ""
975 if not self.return_type.is_void:
976 code.putln(
977 "%s%s;" %
978 (self.return_type.declaration_code(
979 Naming.retval_cname),
980 init))
981 tempvardecl_code = code.insertion_point()
982 self.generate_keyword_list(code)
983 # ----- Extern library function declarations
984 lenv.generate_library_function_declarations(code)
985 # ----- GIL acquisition
986 acquire_gil = self.need_gil_acquisition(lenv)
987 if acquire_gil:
988 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
989 # ----- Automatic lead-ins for certain special functions
990 if is_getbuffer_slot:
991 self.getbuffer_init(code)
992 # ----- Fetch arguments
993 self.generate_argument_parsing_code(env, code)
994 # If an argument is assigned to in the body, we must
995 # incref it to properly keep track of refcounts.
996 for entry in lenv.arg_entries:
997 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
998 code.put_var_incref(entry)
999 # ----- Initialise local variables
1000 for entry in lenv.var_entries:
1001 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1002 code.put_init_var_to_py_none(entry)
1003 # ----- Initialise local buffer auxiliary variables
1004 for entry in lenv.var_entries + lenv.arg_entries:
1005 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1006 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1007 # ----- Check and convert arguments
1008 self.generate_argument_type_tests(code)
1009 # ----- Acquire buffer arguments
1010 for entry in lenv.arg_entries:
1011 if entry.type.is_buffer:
1012 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1013 # ----- Function body
1014 self.body.generate_execution_code(code)
1015 # ----- Default return value
1016 code.putln("")
1017 if self.return_type.is_pyobject:
1018 #if self.return_type.is_extension_type:
1019 # lhs = "(PyObject *)%s" % Naming.retval_cname
1020 #else:
1021 lhs = Naming.retval_cname
1022 code.put_init_to_py_none(lhs, self.return_type)
1023 else:
1024 val = self.return_type.default_value
1025 if val:
1026 code.putln("%s = %s;" % (Naming.retval_cname, val))
1027 # ----- Error cleanup
1028 if code.error_label in code.labels_used:
1029 code.put_goto(code.return_label)
1030 code.put_label(code.error_label)
1031 code.put_var_xdecrefs(lenv.temp_entries)
1033 # Clean up buffers -- this calls a Python function
1034 # so need to save and restore error state
1035 buffers_present = len(lenv.buffer_entries) > 0
1036 if buffers_present:
1037 code.globalstate.use_utility_code(restore_exception_utility_code)
1038 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1039 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1040 for entry in lenv.buffer_entries:
1041 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1042 #code.putln("%s = 0;" % entry.cname)
1043 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1045 err_val = self.error_value()
1046 exc_check = self.caller_will_check_exceptions()
1047 if err_val is not None or exc_check:
1048 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1049 else:
1050 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1051 % self.entry.qualified_name, 0)
1052 code.putln(
1053 '__Pyx_WriteUnraisable("%s");' %
1054 self.entry.qualified_name)
1055 env.use_utility_code(unraisable_exception_utility_code)
1056 env.use_utility_code(restore_exception_utility_code)
1057 default_retval = self.return_type.default_value
1058 if err_val is None and default_retval:
1059 err_val = default_retval
1060 if err_val is not None:
1061 code.putln(
1062 "%s = %s;" % (
1063 Naming.retval_cname,
1064 err_val))
1066 if is_getbuffer_slot:
1067 self.getbuffer_error_cleanup(code)
1069 # If we are using the non-error cleanup section we should
1070 # jump past it if we have an error. The if-test below determine
1071 # whether this section is used.
1072 if buffers_present or is_getbuffer_slot:
1073 code.put_goto(code.return_from_error_cleanup_label)
1076 # ----- Non-error return cleanup
1077 # If you add anything here, remember to add a condition to the
1078 # if-test above in the error block (so that it can jump past this
1079 # block).
1080 code.put_label(code.return_label)
1081 for entry in lenv.buffer_entries:
1082 if entry.used:
1083 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1084 if is_getbuffer_slot:
1085 self.getbuffer_normal_cleanup(code)
1086 # ----- Return cleanup for both error and no-error return
1087 code.put_label(code.return_from_error_cleanup_label)
1088 if not Options.init_local_none:
1089 for entry in lenv.var_entries:
1090 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1091 entry.xdecref_cleanup = 1
1092 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1093 # Decref any increfed args
1094 for entry in lenv.arg_entries:
1095 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1096 code.put_var_decref(entry)
1097 if acquire_gil:
1098 code.putln("PyGILState_Release(_save);")
1099 # code.putln("/* TODO: decref scope object */")
1100 # ----- Return
1101 if not self.return_type.is_void:
1102 code.putln("return %s;" % Naming.retval_cname)
1103 code.putln("}")
1104 # ----- Go back and insert temp variable declarations
1105 tempvardecl_code.put_var_declarations(lenv.temp_entries)
1106 tempvardecl_code.put_temp_declarations(code.funcstate)
1107 # ----- Python version
1108 code.exit_cfunc_scope()
1109 if self.py_func:
1110 self.py_func.generate_function_definitions(env, code)
1111 self.generate_wrapper_functions(code)
1113 def declare_argument(self, env, arg):
1114 if arg.type.is_void:
1115 error(arg.pos, "Invalid use of 'void'")
1116 elif not arg.type.is_complete() and not arg.type.is_array:
1117 error(arg.pos,
1118 "Argument type '%s' is incomplete" % arg.type)
1119 return env.declare_arg(arg.name, arg.type, arg.pos)
1121 def generate_wrapper_functions(self, code):
1122 pass
1124 def generate_execution_code(self, code):
1125 # Evaluate and store argument default values
1126 for arg in self.args:
1127 default = arg.default
1128 if default:
1129 if not default.is_literal:
1130 default.generate_evaluation_code(code)
1131 default.make_owned_reference(code)
1132 code.putln(
1133 "%s = %s;" % (
1134 arg.default_entry.cname,
1135 default.result_as(arg.default_entry.type)))
1136 if default.is_temp and default.type.is_pyobject:
1137 code.putln(
1138 "%s = 0;" %
1139 default.result())
1140 # For Python class methods, create and store function object
1141 if self.assmt:
1142 self.assmt.generate_execution_code(code)
1145 # Special code for the __getbuffer__ function
1147 def getbuffer_init(self, code):
1148 info = self.local_scope.arg_entries[1].cname
1149 # Python 3.0 betas have a bug in memoryview which makes it call
1150 # getbuffer with a NULL parameter. For now we work around this;
1151 # the following line should be removed when this bug is fixed.
1152 code.putln("if (%s == NULL) return 0;" % info)
1153 code.putln("%s->obj = Py_None; Py_INCREF(Py_None);" % info)
1155 def getbuffer_error_cleanup(self, code):
1156 info = self.local_scope.arg_entries[1].cname
1157 code.putln("Py_DECREF(%s->obj); %s->obj = NULL;" %
1158 (info, info))
1160 def getbuffer_normal_cleanup(self, code):
1161 info = self.local_scope.arg_entries[1].cname
1162 code.putln("if (%s->obj == Py_None) { Py_DECREF(Py_None); %s->obj = NULL; }" %
1163 (info, info))
1165 class CFuncDefNode(FuncDefNode):
1166 # C function definition.
1168 # modifiers ['inline']
1169 # visibility 'private' or 'public' or 'extern'
1170 # base_type CBaseTypeNode
1171 # declarator CDeclaratorNode
1172 # body StatListNode
1173 # api boolean
1175 # with_gil boolean Acquire GIL around body
1176 # type CFuncType
1177 # py_func wrapper for calling from Python
1178 # overridable whether or not this is a cpdef function
1180 child_attrs = ["base_type", "declarator", "body", "py_func"]
1182 def unqualified_name(self):
1183 return self.entry.name
1185 def analyse_declarations(self, env):
1186 if 'locals' in env.directives:
1187 directive_locals = env.directives['locals']
1188 else:
1189 directive_locals = {}
1190 self.directive_locals = directive_locals
1191 base_type = self.base_type.analyse(env)
1192 # The 2 here is because we need both function and argument names.
1193 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1194 if not type.is_cfunction:
1195 error(self.pos,
1196 "Suite attached to non-function declaration")
1197 # Remember the actual type according to the function header
1198 # written here, because the type in the symbol table entry
1199 # may be different if we're overriding a C method inherited
1200 # from the base type of an extension type.
1201 self.type = type
1202 type.is_overridable = self.overridable
1203 declarator = self.declarator
1204 while not hasattr(declarator, 'args'):
1205 declarator = declarator.base
1206 self.args = declarator.args
1207 for formal_arg, type_arg in zip(self.args, type.args):
1208 formal_arg.type = type_arg.type
1209 formal_arg.cname = type_arg.cname
1210 name = name_declarator.name
1211 cname = name_declarator.cname
1212 self.entry = env.declare_cfunction(
1213 name, type, self.pos,
1214 cname = cname, visibility = self.visibility,
1215 defining = self.body is not None,
1216 api = self.api)
1217 self.return_type = type.return_type
1219 if self.overridable:
1220 import ExprNodes
1221 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1222 self.py_func = DefNode(pos = self.pos,
1223 name = self.entry.name,
1224 args = self.args,
1225 star_arg = None,
1226 starstar_arg = None,
1227 doc = self.doc,
1228 body = py_func_body,
1229 is_wrapper = 1)
1230 self.py_func.is_module_scope = env.is_module_scope
1231 self.py_func.analyse_declarations(env)
1232 self.entry.as_variable = self.py_func.entry
1233 # Reset scope entry the above cfunction
1234 env.entries[name] = self.entry
1235 self.py_func.interned_attr_cname = env.intern_identifier(
1236 self.py_func.entry.name)
1237 if not env.is_module_scope or Options.lookup_module_cpdef:
1238 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1239 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1241 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1242 import ExprNodes
1243 args = self.type.args
1244 if omit_optional_args:
1245 args = args[:len(args) - self.type.optional_arg_count]
1246 arg_names = [arg.name for arg in args]
1247 if is_module_scope:
1248 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1249 else:
1250 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1251 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1252 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1253 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)
1254 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1256 def declare_arguments(self, env):
1257 for arg in self.type.args:
1258 if not arg.name:
1259 error(arg.pos, "Missing argument name")
1260 self.declare_argument(env, arg)
1262 def need_gil_acquisition(self, lenv):
1263 type = self.type
1264 with_gil = self.type.with_gil
1265 if type.nogil and not with_gil:
1266 if type.return_type.is_pyobject:
1267 error(self.pos,
1268 "Function with Python return type cannot be declared nogil")
1269 for entry in lenv.var_entries + lenv.temp_entries:
1270 if entry.type.is_pyobject:
1271 error(self.pos, "Function declared nogil has Python locals or temporaries")
1272 return with_gil
1274 def analyse_expressions(self, env):
1275 self.analyse_default_values(env)
1276 if self.overridable:
1277 self.py_func.analyse_expressions(env)
1279 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1280 arg_decls = []
1281 type = self.type
1282 visibility = self.entry.visibility
1283 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1284 arg_decls.append(arg.declaration_code())
1285 if with_dispatch and self.overridable:
1286 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1287 if type.optional_arg_count and with_opt_args:
1288 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1289 if type.has_varargs:
1290 arg_decls.append("...")
1291 if not arg_decls:
1292 arg_decls = ["void"]
1293 if cname is None:
1294 cname = self.entry.func_cname
1295 entity = type.function_header_code(cname, string.join(arg_decls, ", "))
1296 if visibility == 'public':
1297 dll_linkage = "DL_EXPORT"
1298 else:
1299 dll_linkage = None
1300 header = self.return_type.declaration_code(entity,
1301 dll_linkage = dll_linkage)
1302 if visibility == 'extern':
1303 storage_class = "%s " % Naming.extern_c_macro
1304 elif visibility == 'public':
1305 storage_class = ""
1306 else:
1307 storage_class = "static "
1308 code.putln("%s%s %s {" % (
1309 storage_class,
1310 ' '.join(self.modifiers).upper(), # macro forms
1311 header))
1313 def generate_argument_declarations(self, env, code):
1314 for arg in self.args:
1315 if arg.default:
1316 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1318 def generate_keyword_list(self, code):
1319 pass
1321 def generate_argument_parsing_code(self, env, code):
1322 i = 0
1323 if self.type.optional_arg_count:
1324 code.putln('if (%s) {' % Naming.optional_args_cname)
1325 for arg in self.args:
1326 if arg.default:
1327 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1328 declarator = arg.declarator
1329 while not hasattr(declarator, 'name'):
1330 declarator = declarator.base
1331 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1332 i += 1
1333 for _ in range(self.type.optional_arg_count):
1334 code.putln('}')
1335 code.putln('}')
1337 def generate_argument_conversion_code(self, code):
1338 pass
1340 def generate_argument_type_tests(self, code):
1341 # Generate type tests for args whose type in a parent
1342 # class is a supertype of the declared type.
1343 for arg in self.type.args:
1344 if arg.needs_type_test:
1345 self.generate_arg_type_test(arg, code)
1347 def generate_arg_type_test(self, arg, code):
1348 # Generate type test for one argument.
1349 if arg.type.typeobj_is_available():
1350 typeptr_cname = arg.type.typeptr_cname
1351 arg_code = "((PyObject *)%s)" % arg.cname
1352 code.putln(
1353 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1354 arg_code,
1355 typeptr_cname,
1356 not arg.not_none,
1357 arg.name,
1358 type.is_builtin_type,
1359 code.error_goto(arg.pos)))
1360 else:
1361 error(arg.pos, "Cannot test type of extern C class "
1362 "without type object name specification")
1364 def error_value(self):
1365 if self.return_type.is_pyobject:
1366 return "0"
1367 else:
1368 #return None
1369 return self.entry.type.exception_value
1371 def caller_will_check_exceptions(self):
1372 return self.entry.type.exception_check
1374 def generate_wrapper_functions(self, code):
1375 # If the C signature of a function has changed, we need to generate
1376 # wrappers to put in the slots here.
1377 k = 0
1378 entry = self.entry
1379 func_type = entry.type
1380 while entry.prev_entry is not None:
1381 k += 1
1382 entry = entry.prev_entry
1383 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1384 code.putln()
1385 self.generate_function_header(code,
1386 0,
1387 with_dispatch = entry.type.is_overridable,
1388 with_opt_args = entry.type.optional_arg_count,
1389 cname = entry.func_cname)
1390 if not self.return_type.is_void:
1391 code.put('return ')
1392 args = self.type.args
1393 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1394 if entry.type.is_overridable:
1395 arglist.append(Naming.skip_dispatch_cname)
1396 elif func_type.is_overridable:
1397 arglist.append('0')
1398 if entry.type.optional_arg_count:
1399 arglist.append(Naming.optional_args_cname)
1400 elif func_type.optional_arg_count:
1401 arglist.append('NULL')
1402 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1403 code.putln('}')
1406 class PyArgDeclNode(Node):
1407 # Argument which must be a Python object (used
1408 # for * and ** arguments).
1410 # name string
1411 # entry Symtab.Entry
1412 child_attrs = []
1415 class DecoratorNode(Node):
1416 # A decorator
1418 # decorator NameNode or CallNode
1419 child_attrs = ['decorator']
1422 class DefNode(FuncDefNode):
1423 # A Python function definition.
1425 # name string the Python name of the function
1426 # decorators [DecoratorNode] list of decorators
1427 # args [CArgDeclNode] formal arguments
1428 # star_arg PyArgDeclNode or None * argument
1429 # starstar_arg PyArgDeclNode or None ** argument
1430 # doc EncodedString or None
1431 # body StatListNode
1433 # The following subnode is constructed internally
1434 # when the def statement is inside a Python class definition.
1436 # assmt AssignmentNode Function construction/assignment
1438 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1440 assmt = None
1441 num_kwonly_args = 0
1442 num_required_kw_args = 0
1443 reqd_kw_flags_cname = "0"
1444 is_wrapper = 0
1445 decorators = None
1446 entry = None
1449 def __init__(self, pos, **kwds):
1450 FuncDefNode.__init__(self, pos, **kwds)
1451 k = rk = r = 0
1452 for arg in self.args:
1453 if arg.kw_only:
1454 k += 1
1455 if not arg.default:
1456 rk += 1
1457 if not arg.default:
1458 r += 1
1459 self.num_kwonly_args = k
1460 self.num_required_kw_args = rk
1461 self.num_required_args = r
1463 def as_cfunction(self, cfunc):
1464 if self.star_arg:
1465 error(self.star_arg.pos, "cdef function cannot have star argument")
1466 if self.starstar_arg:
1467 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1468 if len(self.args) != len(cfunc.type.args) or cfunc.type.has_varargs:
1469 error(self.pos, "wrong number of arguments")
1470 error(declarator.pos, "previous declaration here")
1471 for formal_arg, type_arg in zip(self.args, cfunc.type.args):
1472 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1473 if type is PyrexTypes.py_object_type or formal_arg.is_self:
1474 formal_arg.type = type_arg.type
1475 formal_arg.name_declarator = name_declarator
1476 import ExprNodes
1477 if cfunc.type.exception_value is None:
1478 exception_value = None
1479 else:
1480 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc.type.exception_value, type=cfunc.type.return_type)
1481 declarator = CFuncDeclaratorNode(self.pos,
1482 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1483 args = self.args,
1484 has_varargs = False,
1485 exception_check = cfunc.type.exception_check,
1486 exception_value = exception_value,
1487 with_gil = cfunc.type.with_gil,
1488 nogil = cfunc.type.nogil)
1489 return CFuncDefNode(self.pos,
1490 modifiers = [],
1491 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc.type.return_type),
1492 declarator = declarator,
1493 body = self.body,
1494 doc = self.doc,
1495 overridable = cfunc.type.is_overridable,
1496 type = cfunc.type,
1497 with_gil = cfunc.type.with_gil,
1498 nogil = cfunc.type.nogil,
1499 visibility = 'private',
1500 api = False)
1502 def analyse_declarations(self, env):
1503 if 'locals' in env.directives:
1504 directive_locals = env.directives['locals']
1505 else:
1506 directive_locals = {}
1507 self.directive_locals = directive_locals
1508 for arg in self.args:
1509 base_type = arg.base_type.analyse(env)
1510 name_declarator, type = \
1511 arg.declarator.analyse(base_type, env)
1512 arg.name = name_declarator.name
1513 if arg.name in directive_locals:
1514 type_node = directive_locals[arg.name]
1515 other_type = type_node.analyse_as_type(env)
1516 if other_type is None:
1517 error(type_node.pos, "Not a type")
1518 elif (type is not PyrexTypes.py_object_type
1519 and not type.same_as(other_type)):
1520 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1521 error(type_node.pos, "Previous declaration here")
1522 else:
1523 type = other_type
1524 if name_declarator.cname:
1525 error(self.pos,
1526 "Python function argument cannot have C name specification")
1527 arg.type = type.as_argument_type()
1528 arg.hdr_type = None
1529 arg.needs_conversion = 0
1530 arg.needs_type_test = 0
1531 arg.is_generic = 1
1532 if arg.not_none and not arg.type.is_extension_type:
1533 error(self.pos,
1534 "Only extension type arguments can have 'not None'")
1535 self.declare_pyfunction(env)
1536 self.analyse_signature(env)
1537 self.return_type = self.entry.signature.return_type()
1539 def analyse_signature(self, env):
1540 any_type_tests_needed = 0
1541 # Use the simpler calling signature for zero- and one-argument functions.
1542 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1543 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1544 if len(self.args) == 0:
1545 self.entry.signature = TypeSlots.pyfunction_noargs
1546 elif len(self.args) == 1:
1547 if self.args[0].default is None and not self.args[0].kw_only:
1548 self.entry.signature = TypeSlots.pyfunction_onearg
1549 elif self.entry.signature is TypeSlots.pymethod_signature:
1550 if len(self.args) == 1:
1551 self.entry.signature = TypeSlots.unaryfunc
1552 elif len(self.args) == 2:
1553 if self.args[1].default is None and not self.args[1].kw_only:
1554 self.entry.signature = TypeSlots.ibinaryfunc
1555 elif self.entry.is_special:
1556 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1557 sig = self.entry.signature
1558 nfixed = sig.num_fixed_args()
1559 for i in range(nfixed):
1560 if i < len(self.args):
1561 arg = self.args[i]
1562 arg.is_generic = 0
1563 if sig.is_self_arg(i):
1564 arg.is_self_arg = 1
1565 arg.hdr_type = arg.type = env.parent_type
1566 arg.needs_conversion = 0
1567 else:
1568 arg.hdr_type = sig.fixed_arg_type(i)
1569 if not arg.type.same_as(arg.hdr_type):
1570 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1571 arg.needs_type_test = 1
1572 any_type_tests_needed = 1
1573 else:
1574 arg.needs_conversion = 1
1575 if arg.needs_conversion:
1576 arg.hdr_cname = Naming.arg_prefix + arg.name
1577 else:
1578 arg.hdr_cname = Naming.var_prefix + arg.name
1579 else:
1580 self.bad_signature()
1581 return
1582 if nfixed < len(self.args):
1583 if not sig.has_generic_args:
1584 self.bad_signature()
1585 for arg in self.args:
1586 if arg.is_generic and \
1587 (arg.type.is_extension_type or arg.type.is_builtin_type):
1588 arg.needs_type_test = 1
1589 any_type_tests_needed = 1
1590 elif arg.type is PyrexTypes.c_py_ssize_t_type:
1591 # Want to use __index__ rather than __int__ method
1592 # that PyArg_ParseTupleAndKeywords calls
1593 arg.needs_conversion = 1
1594 arg.hdr_type = PyrexTypes.py_object_type
1595 arg.hdr_cname = Naming.arg_prefix + arg.name
1596 if any_type_tests_needed:
1597 env.use_utility_code(arg_type_test_utility_code)
1599 def bad_signature(self):
1600 sig = self.entry.signature
1601 expected_str = "%d" % sig.num_fixed_args()
1602 if sig.has_generic_args:
1603 expected_str = expected_str + " or more"
1604 name = self.name
1605 if name.startswith("__") and name.endswith("__"):
1606 desc = "Special method"
1607 else:
1608 desc = "Method"
1609 error(self.pos,
1610 "%s %s has wrong number of arguments "
1611 "(%d declared, %s expected)" % (
1612 desc, self.name, len(self.args), expected_str))
1614 def signature_has_nongeneric_args(self):
1615 argcount = len(self.args)
1616 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1617 return 0
1618 return 1
1620 def signature_has_generic_args(self):
1621 return self.entry.signature.has_generic_args
1623 def declare_pyfunction(self, env):
1624 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1625 name = self.name
1626 entry = env.lookup_here(self.name)
1627 if entry and entry.type.is_cfunction and not self.is_wrapper:
1628 warning(self.pos, "Overriding cdef method with def method.", 5)
1629 entry = env.declare_pyfunction(self.name, self.pos)
1630 self.entry = entry
1631 prefix = env.scope_prefix
1632 entry.func_cname = \
1633 Naming.pyfunc_prefix + prefix + name
1634 entry.pymethdef_cname = \
1635 Naming.pymethdef_prefix + prefix + name
1636 if Options.docstrings:
1637 entry.doc = embed_position(self.pos, self.doc)
1638 entry.doc_cname = \
1639 Naming.funcdoc_prefix + prefix + name
1640 else:
1641 entry.doc = None
1643 def declare_arguments(self, env):
1644 for arg in self.args:
1645 if not arg.name:
1646 error(arg.pos, "Missing argument name")
1647 if arg.needs_conversion:
1648 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1649 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1650 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1651 if arg.type.is_pyobject:
1652 arg.entry.init = "0"
1653 arg.entry.init_to_none = 0
1654 else:
1655 arg.entry = self.declare_argument(env, arg)
1656 arg.entry.used = 1
1657 arg.entry.is_self_arg = arg.is_self_arg
1658 if not arg.is_self_arg:
1659 arg.name_entry = env.get_string_const(
1660 arg.name, identifier = True)
1661 env.add_py_string(arg.name_entry, identifier = True)
1662 if arg.hdr_type:
1663 if arg.is_self_arg or \
1664 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1665 arg.entry.is_declared_generic = 1
1666 self.declare_python_arg(env, self.star_arg)
1667 self.declare_python_arg(env, self.starstar_arg)
1669 def declare_python_arg(self, env, arg):
1670 if arg:
1671 entry = env.declare_var(arg.name,
1672 PyrexTypes.py_object_type, arg.pos)
1673 entry.used = 1
1674 entry.init = "0"
1675 entry.init_to_none = 0
1676 entry.xdecref_cleanup = 1
1677 arg.entry = entry
1678 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1680 def analyse_expressions(self, env):
1681 self.analyse_default_values(env)
1682 if env.is_py_class_scope:
1683 self.synthesize_assignment_node(env)
1685 def synthesize_assignment_node(self, env):
1686 import ExprNodes
1687 self.assmt = SingleAssignmentNode(self.pos,
1688 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1689 rhs = ExprNodes.UnboundMethodNode(self.pos,
1690 class_cname = env.class_obj_cname,
1691 function = ExprNodes.PyCFunctionNode(self.pos,
1692 pymethdef_cname = self.entry.pymethdef_cname)))
1693 self.assmt.analyse_declarations(env)
1694 self.assmt.analyse_expressions(env)
1696 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1697 arg_code_list = []
1698 sig = self.entry.signature
1699 if sig.has_dummy_arg:
1700 arg_code_list.append(
1701 "PyObject *%s" % Naming.self_cname)
1702 for arg in self.args:
1703 if not arg.is_generic:
1704 if arg.is_self_arg:
1705 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1706 else:
1707 arg_code_list.append(
1708 arg.hdr_type.declaration_code(arg.hdr_cname))
1709 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1710 arg_code_list.append("PyObject *unused")
1711 if sig.has_generic_args:
1712 arg_code_list.append(
1713 "PyObject *%s, PyObject *%s"
1714 % (Naming.args_cname, Naming.kwds_cname))
1715 arg_code = ", ".join(arg_code_list)
1716 dc = self.return_type.declaration_code(self.entry.func_cname)
1717 header = "static %s(%s)" % (dc, arg_code)
1718 code.putln("%s; /*proto*/" % header)
1719 if proto_only:
1720 return
1721 if self.entry.doc and Options.docstrings:
1722 docstr = self.entry.doc
1723 if not isinstance(docstr, str):
1724 docstr = docstr.utf8encode()
1725 code.putln(
1726 'static char %s[] = "%s";' % (
1727 self.entry.doc_cname,
1728 split_docstring(escape_byte_string(docstr))))
1729 if with_pymethdef:
1730 code.put(
1731 "static PyMethodDef %s = " %
1732 self.entry.pymethdef_cname)
1733 code.put_pymethoddef(self.entry, ";")
1734 code.putln("%s {" % header)
1736 def generate_argument_declarations(self, env, code):
1737 for arg in self.args:
1738 if arg.is_generic: # or arg.needs_conversion:
1739 if arg.needs_conversion:
1740 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1741 else:
1742 code.put_var_declaration(arg.entry)
1744 def generate_keyword_list(self, code):
1745 if self.signature_has_generic_args() and \
1746 self.signature_has_nongeneric_args():
1747 code.put(
1748 "static PyObject **%s[] = {" %
1749 Naming.pykwdlist_cname)
1750 for arg in self.args:
1751 if arg.is_generic:
1752 code.put('&%s,' % arg.name_entry.pystring_cname)
1753 code.putln("0};")
1755 def generate_argument_parsing_code(self, env, code):
1756 # Generate PyArg_ParseTuple call for generic
1757 # arguments, if any.
1758 if self.entry.signature.has_dummy_arg:
1759 # get rid of unused argument warning
1760 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1762 old_error_label = code.new_error_label()
1763 our_error_label = code.error_label
1764 end_label = code.new_label("argument_unpacking_done")
1766 has_kwonly_args = self.num_kwonly_args > 0
1767 has_star_or_kw_args = self.star_arg is not None \
1768 or self.starstar_arg is not None or has_kwonly_args
1770 if not self.signature_has_generic_args():
1771 if has_star_or_kw_args:
1772 error(self.pos, "This method cannot have * or keyword arguments")
1773 self.generate_argument_conversion_code(code)
1775 elif not self.signature_has_nongeneric_args():
1776 # func(*args) or func(**kw) or func(*args, **kw)
1777 self.generate_stararg_copy_code(code)
1779 else:
1780 positional_args = []
1781 kw_only_args = []
1782 default_seen = 0
1783 for arg in self.args:
1784 arg_entry = arg.entry
1785 if arg.is_generic:
1786 if arg.default:
1787 code.putln(
1788 "%s = %s;" % (
1789 arg_entry.cname,
1790 arg.default_result_code))
1791 default_seen = 1
1792 if not arg.is_self_arg:
1793 if arg.kw_only:
1794 kw_only_args.append(arg)
1795 else:
1796 positional_args.append(arg)
1797 elif arg.kw_only:
1798 kw_only_args.append(arg)
1799 default_seen = 1
1800 elif default_seen:
1801 error(arg.pos, "Non-default argument following default argument")
1802 elif not arg.is_self_arg:
1803 positional_args.append(arg)
1804 if arg.needs_conversion:
1805 format = arg.hdr_type.parsetuple_format
1806 else:
1807 format = arg_entry.type.parsetuple_format
1808 if not format:
1809 error(arg.pos,
1810 "Cannot convert Python object argument to type '%s' (when parsing input arguments)"
1811 % arg.type)
1813 self.generate_tuple_and_keyword_parsing_code(
1814 positional_args, kw_only_args, end_label, code)
1816 code.error_label = old_error_label
1817 if code.label_used(our_error_label):
1818 if not code.label_used(end_label):
1819 code.put_goto(end_label)
1820 code.put_label(our_error_label)
1821 if has_star_or_kw_args:
1822 self.generate_arg_decref(self.star_arg, code)
1823 if self.starstar_arg:
1824 if self.starstar_arg.entry.xdecref_cleanup:
1825 code.put_var_xdecref(self.starstar_arg.entry)
1826 else:
1827 code.put_var_decref(self.starstar_arg.entry)
1828 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1829 code.putln("return %s;" % self.error_value())
1830 if code.label_used(end_label):
1831 code.put_label(end_label)
1833 def generate_arg_assignment(self, arg, item, code):
1834 if arg.type.is_pyobject:
1835 if arg.is_generic:
1836 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1837 code.putln("%s = %s;" % (arg.entry.cname, item))
1838 else:
1839 func = arg.type.from_py_function
1840 if func:
1841 code.putln("%s = %s(%s); %s" % (
1842 arg.entry.cname,
1843 func,
1844 item,
1845 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1846 else:
1847 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1849 def generate_arg_xdecref(self, arg, code):
1850 if arg:
1851 code.put_var_xdecref(arg.entry)
1853 def generate_arg_decref(self, arg, code):
1854 if arg:
1855 code.put_var_decref(arg.entry)
1857 def generate_stararg_copy_code(self, code):
1858 if not self.star_arg:
1859 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1860 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1861 Naming.args_cname)
1862 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
1863 self.name.utf8encode(), Naming.args_cname, self.error_value()))
1864 code.putln("}")
1866 code.globalstate.use_utility_code(keyword_string_check_utility_code)
1868 if self.starstar_arg:
1869 if self.star_arg:
1870 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
1871 else:
1872 kwarg_check = "%s" % Naming.kwds_cname
1873 else:
1874 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
1875 Naming.kwds_cname, Naming.kwds_cname)
1876 code.putln(
1877 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
1878 kwarg_check, Naming.kwds_cname, self.name,
1879 bool(self.starstar_arg), self.error_value()))
1881 if self.starstar_arg:
1882 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
1883 self.starstar_arg.entry.cname,
1884 Naming.kwds_cname,
1885 Naming.kwds_cname))
1886 code.putln("if (unlikely(!%s)) return %s;" % (
1887 self.starstar_arg.entry.cname, self.error_value()))
1888 self.starstar_arg.entry.xdecref_cleanup = 0
1890 if self.star_arg:
1891 code.put_incref(Naming.args_cname, py_object_type)
1892 code.putln("%s = %s;" % (
1893 self.star_arg.entry.cname,
1894 Naming.args_cname))
1895 self.star_arg.entry.xdecref_cleanup = 0
1897 def generate_tuple_and_keyword_parsing_code(self, positional_args,
1898 kw_only_args, success_label, code):
1899 argtuple_error_label = code.new_label("argtuple_error")
1901 min_positional_args = self.num_required_args - self.num_required_kw_args
1902 if len(self.args) > 0 and self.args[0].is_self_arg:
1903 min_positional_args -= 1
1904 max_positional_args = len(positional_args)
1905 has_fixed_positional_count = not self.star_arg and \
1906 min_positional_args == max_positional_args
1908 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
1909 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1910 if self.num_required_kw_args:
1911 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
1913 if self.starstar_arg or self.star_arg:
1914 self.generate_stararg_init_code(max_positional_args, code)
1916 # --- optimised code when we receive keyword arguments
1917 if self.num_required_kw_args:
1918 likely_hint = "likely"
1919 else:
1920 likely_hint = "unlikely"
1921 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
1922 self.generate_keyword_unpacking_code(
1923 min_positional_args, max_positional_args,
1924 has_fixed_positional_count,
1925 positional_args, kw_only_args, argtuple_error_label, code)
1927 # --- optimised code when we do not receive any keyword arguments
1928 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
1929 # Python raises arg tuple related errors first, so we must
1930 # check the length here
1931 if min_positional_args == max_positional_args and not self.star_arg:
1932 compare = '!='
1933 else:
1934 compare = '<'
1935 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
1936 Naming.args_cname, compare, min_positional_args))
1937 code.put_goto(argtuple_error_label)
1939 if self.num_required_kw_args:
1940 # pure error case: keywords required but not passed
1941 if max_positional_args > min_positional_args and not self.star_arg:
1942 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
1943 Naming.args_cname, max_positional_args))
1944 code.put_goto(argtuple_error_label)
1945 code.putln('} else {')
1946 for i, arg in enumerate(kw_only_args):
1947 if not arg.default:
1948 # required keyword-only argument missing
1949 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
1950 self.name.utf8encode(),
1951 arg.name_entry.pystring_cname))
1952 code.putln(code.error_goto(self.pos))
1953 break
1955 elif min_positional_args == max_positional_args:
1956 # parse the exact number of positional arguments from the
1957 # args tuple
1958 code.putln('} else {')
1959 for i, arg in enumerate(positional_args):
1960 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
1961 self.generate_arg_assignment(arg, item, code)
1963 else:
1964 # parse the positional arguments from the variable length
1965 # args tuple
1966 code.putln('} else {')
1967 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
1968 if self.star_arg:
1969 code.putln('default:')
1970 reversed_args = list(enumerate(positional_args))[::-1]
1971 for i, arg in reversed_args:
1972 if i >= min_positional_args-1:
1973 if min_positional_args > 1:
1974 code.putln('case %2d:' % (i+1)) # pure code beautification
1975 else:
1976 code.put('case %2d: ' % (i+1))
1977 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
1978 self.generate_arg_assignment(arg, item, code)
1979 if min_positional_args == 0:
1980 code.put('case 0: ')
1981 code.putln('break;')
1982 if self.star_arg:
1983 if min_positional_args:
1984 for i in range(min_positional_args-1, -1, -1):
1985 code.putln('case %2d:' % i)
1986 code.put_goto(argtuple_error_label)
1987 else:
1988 code.put('default: ')
1989 code.put_goto(argtuple_error_label)
1990 code.putln('}')
1992 code.putln('}')
1994 if code.label_used(argtuple_error_label):
1995 code.put_goto(success_label)
1996 code.put_label(argtuple_error_label)
1997 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
1998 self.name.utf8encode(), has_fixed_positional_count,
1999 min_positional_args, max_positional_args,
2000 Naming.args_cname))
2001 code.putln(code.error_goto(self.pos))
2003 def generate_stararg_init_code(self, max_positional_args, code):
2004 if self.starstar_arg:
2005 self.starstar_arg.entry.xdecref_cleanup = 0
2006 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2007 self.starstar_arg.entry.cname,
2008 self.starstar_arg.entry.cname,
2009 self.error_value()))
2010 if self.star_arg:
2011 self.star_arg.entry.xdecref_cleanup = 0
2012 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2013 Naming.args_cname,
2014 max_positional_args))
2015 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2016 self.star_arg.entry.cname, Naming.args_cname,
2017 max_positional_args, Naming.args_cname))
2018 if self.starstar_arg:
2019 code.putln("")
2020 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2021 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2022 code.putln('return %s;' % self.error_value())
2023 code.putln('}')
2024 else:
2025 code.putln("if (unlikely(!%s)) return %s;" % (
2026 self.star_arg.entry.cname, self.error_value()))
2027 code.putln('} else {')
2028 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2029 code.put_incref(Naming.empty_tuple, py_object_type)
2030 code.putln('}')
2032 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2033 has_fixed_positional_count, positional_args,
2034 kw_only_args, argtuple_error_label, code):
2035 all_args = tuple(positional_args) + tuple(kw_only_args)
2036 max_args = len(all_args)
2038 code.putln("PyObject* values[%d] = {%s};" % (
2039 max_args, ('0,'*max_args)[:-1]))
2040 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2041 Naming.kwds_cname)
2043 # parse the tuple and check that it's not too long
2044 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2045 if self.star_arg:
2046 code.putln('default:')
2047 for i in range(max_positional_args-1, -1, -1):
2048 code.put('case %2d: ' % (i+1))
2049 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2050 i, Naming.args_cname, i))
2051 code.putln('case 0: break;')
2052 if not self.star_arg:
2053 code.put('default: ') # more arguments than allowed
2054 code.put_goto(argtuple_error_label)
2055 code.putln('}')
2057 # now fill up the required arguments with values from the kw dict
2058 last_required_arg = -1
2059 for i, arg in enumerate(all_args):
2060 if not arg.default:
2061 last_required_arg = i
2062 if last_required_arg >= 0:
2063 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2064 for i, arg in enumerate(all_args[:last_required_arg+1]):
2065 if i <= max_positional_args:
2066 if self.star_arg and i == max_positional_args:
2067 code.putln('default:')
2068 else:
2069 code.putln('case %2d:' % i)
2070 if arg.default:
2071 # handled in ParseOptionalKeywords() below
2072 continue
2073 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2074 i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2075 if i < min_positional_args:
2076 code.putln('if (likely(values[%d])) kw_args--;' % i);
2077 if i == 0:
2078 # special case: we know arg 0 is missing
2079 code.put('else ')
2080 code.put_goto(argtuple_error_label)
2081 else:
2082 # print the correct number of values (args or
2083 # kwargs) that were passed into positional
2084 # arguments up to this point
2085 code.putln('else {')
2086 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2087 self.name.utf8encode(), has_fixed_positional_count,
2088 min_positional_args, max_positional_args, i))
2089 code.putln(code.error_goto(self.pos))
2090 code.putln('}')
2091 else:
2092 code.putln('if (values[%d]) kw_args--;' % i);
2093 if arg.kw_only and not arg.default:
2094 code.putln('else {')
2095 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2096 self.name.utf8encode(), arg.name_entry.pystring_cname))
2097 code.putln(code.error_goto(self.pos))
2098 code.putln('}')
2099 code.putln('}')
2101 code.putln('if (unlikely(kw_args > 0)) {')
2102 # non-positional kw args left in dict: default args, **kwargs or error
2103 if self.star_arg:
2104 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2105 Naming.args_cname, max_positional_args,
2106 Naming.args_cname, max_positional_args))
2107 pos_arg_count = "used_pos_args"
2108 else:
2109 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2110 code.globalstate.use_utility_code(parse_keywords_utility_code)
2111 code.put(
2112 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2113 Naming.kwds_cname,
2114 Naming.pykwdlist_cname,
2115 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2116 pos_arg_count,
2117 self.name.utf8encode()))
2118 code.putln(code.error_goto(self.pos))
2119 code.putln('}')
2121 # convert arg values to their final type and assign them
2122 for i, arg in enumerate(all_args):
2123 if arg.default:
2124 code.putln("if (values[%d]) {" % i)
2125 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2126 if arg.default:
2127 code.putln('}')
2129 def generate_argument_conversion_code(self, code):
2130 # Generate code to convert arguments from
2131 # signature type to declared type, if needed.
2132 for arg in self.args:
2133 if arg.needs_conversion:
2134 self.generate_arg_conversion(arg, code)
2136 def generate_arg_conversion(self, arg, code):
2137 # Generate conversion code for one argument.
2138 old_type = arg.hdr_type
2139 new_type = arg.type
2140 if old_type.is_pyobject:
2141 if arg.default:
2142 code.putln("if (%s) {" % arg.hdr_cname)
2143 else:
2144 code.putln("assert(%s); {" % arg.hdr_cname)
2145 self.generate_arg_conversion_from_pyobject(arg, code)
2146 code.putln("}")
2147 elif new_type.is_pyobject:
2148 self.generate_arg_conversion_to_pyobject(arg, code)
2149 else:
2150 if new_type.assignable_from(old_type):
2151 code.putln(
2152 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2153 else:
2154 error(arg.pos,
2155 "Cannot convert 1 argument from '%s' to '%s'" %
2156 (old_type, new_type))
2158 def generate_arg_conversion_from_pyobject(self, arg, code):
2159 new_type = arg.type
2160 func = new_type.from_py_function
2161 # copied from CoerceFromPyTypeNode
2162 if func:
2163 code.putln("%s = %s(%s); %s" % (
2164 arg.entry.cname,
2165 func,
2166 arg.hdr_cname,
2167 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2168 else:
2169 error(arg.pos,
2170 "Cannot convert Python object argument to type '%s'"
2171 % new_type)
2173 def generate_arg_conversion_to_pyobject(self, arg, code):
2174 old_type = arg.hdr_type
2175 func = old_type.to_py_function
2176 if func:
2177 code.putln("%s = %s(%s); %s" % (
2178 arg.entry.cname,
2179 func,
2180 arg.hdr_cname,
2181 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2182 else:
2183 error(arg.pos,
2184 "Cannot convert argument of type '%s' to Python object"
2185 % old_type)
2187 def generate_argument_type_tests(self, code):
2188 # Generate type tests for args whose signature
2189 # type is PyObject * and whose declared type is
2190 # a subtype thereof.
2191 for arg in self.args:
2192 if arg.needs_type_test:
2193 self.generate_arg_type_test(arg, code)
2195 def generate_arg_type_test(self, arg, code):
2196 # Generate type test for one argument.
2197 if arg.type.typeobj_is_available():
2198 typeptr_cname = arg.type.typeptr_cname
2199 arg_code = "((PyObject *)%s)" % arg.entry.cname
2200 code.putln(
2201 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2202 arg_code,
2203 typeptr_cname,
2204 not arg.not_none,
2205 arg.name,
2206 arg.type.is_builtin_type,
2207 code.error_goto(arg.pos)))
2208 else:
2209 error(arg.pos, "Cannot test type of extern C class "
2210 "without type object name specification")
2212 def error_value(self):
2213 return self.entry.signature.error_value
2215 def caller_will_check_exceptions(self):
2216 return 1
2218 class OverrideCheckNode(StatNode):
2219 # A Node for dispatching to the def method if it
2220 # is overriden.
2222 # py_func
2224 # args
2225 # func_temp
2226 # body
2228 child_attrs = ['body']
2230 body = None
2232 def analyse_expressions(self, env):
2233 self.args = env.arg_entries
2234 if self.py_func.is_module_scope:
2235 first_arg = 0
2236 else:
2237 first_arg = 1
2238 import ExprNodes
2239 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2240 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2241 call_node = ExprNodes.SimpleCallNode(self.pos,
2242 function=self.func_node,
2243 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2244 self.body = ReturnStatNode(self.pos, value=call_node)
2245 self.body.analyse_expressions(env)
2247 def generate_execution_code(self, code):
2248 # Check to see if we are an extension type
2249 if self.py_func.is_module_scope:
2250 self_arg = "((PyObject *)%s)" % Naming.module_cname
2251 else:
2252 self_arg = "((PyObject *)%s)" % self.args[0].cname
2253 code.putln("/* Check if called by wrapper */")
2254 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2255 code.putln("/* Check if overriden in Python */")
2256 if self.py_func.is_module_scope:
2257 code.putln("else {")
2258 else:
2259 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2260 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2261 # need to get attribute manually--scope would return cdef method
2262 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2263 # It appears that this type is not anywhere exposed in the Python/C API
2264 is_builtin_function_or_method = '(strcmp(Py_TYPE(%s)->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result()
2265 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2266 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2267 self.body.generate_execution_code(code)
2268 code.putln('}')
2269 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2270 code.putln("}")
2272 class ClassDefNode(StatNode, BlockNode):
2273 pass
2275 class PyClassDefNode(ClassDefNode):
2276 # A Python class definition.
2278 # name EncodedString Name of the class
2279 # doc string or None
2280 # body StatNode Attribute definition code
2281 # entry Symtab.Entry
2282 # scope PyClassScope
2284 # The following subnodes are constructed internally:
2286 # dict DictNode Class dictionary
2287 # classobj ClassNode Class object
2288 # target NameNode Variable to assign class object to
2290 child_attrs = ["body", "dict", "classobj", "target"]
2292 def __init__(self, pos, name, bases, doc, body):
2293 StatNode.__init__(self, pos)
2294 self.name = name
2295 self.doc = doc
2296 self.body = body
2297 import ExprNodes
2298 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2299 if self.doc and Options.docstrings:
2300 doc = embed_position(self.pos, self.doc)
2301 doc_node = ExprNodes.StringNode(pos, value = doc)
2302 else:
2303 doc_node = None
2304 self.classobj = ExprNodes.ClassNode(pos, name = name,
2305 bases = bases, dict = self.dict, doc = doc_node)
2306 self.target = ExprNodes.NameNode(pos, name = name)
2308 def as_cclass(self):
2309 """
2310 Return this node as if it were declared as an extension class"
2311 """
2312 bases = self.classobj.bases.args
2313 if len(bases) == 0:
2314 base_class_name = None
2315 base_class_module = None
2316 elif len(bases) == 1:
2317 base = bases[0]
2318 path = []
2319 while isinstance(base, ExprNodes.AttributeNode):
2320 path.insert(0, base.attribute)
2321 base = base.obj
2322 if isinstance(base, ExprNodes.NameNode):
2323 path.insert(0, base.name)
2324 base_class_name = path[-1]
2325 if len(path) > 1:
2326 base_class_module = u'.'.join(path[:-1])
2327 else:
2328 base_class_module = None
2329 else:
2330 error(self.classobj.bases.args.pos, "Invalid base class")
2331 else:
2332 error(self.classobj.bases.args.pos, "C class may only have one base class")
2333 return None
2335 return CClassDefNode(self.pos,
2336 visibility = 'private',
2337 module_name = None,
2338 class_name = self.name,
2339 base_class_module = base_class_module,
2340 base_class_name = base_class_name,
2341 body = self.body,
2342 in_pxd = False,
2343 doc = self.doc)
2345 def create_scope(self, env):
2346 genv = env
2347 while env.is_py_class_scope or env.is_c_class_scope:
2348 env = env.outer_scope
2349 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2350 return cenv
2352 def analyse_declarations(self, env):
2353 self.target.analyse_target_declaration(env)
2354 cenv = self.create_scope(env)
2355 cenv.class_obj_cname = self.target.entry.cname
2356 self.body.analyse_declarations(cenv)
2358 def analyse_expressions(self, env):
2359 self.dict.analyse_expressions(env)
2360 self.classobj.analyse_expressions(env)
2361 genv = env.global_scope()
2362 cenv = self.scope
2363 cenv.class_dict_cname = self.dict.result()
2364 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2365 self.body.analyse_expressions(cenv)
2366 self.target.analyse_target_expression(env, self.classobj)
2367 self.dict.release_temp(env)
2368 #self.classobj.release_temp(env)
2369 #self.target.release_target_temp(env)
2371 def generate_function_definitions(self, env, code):
2372 self.generate_py_string_decls(self.scope, code)
2373 self.body.generate_function_definitions(self.scope, code)
2375 def generate_execution_code(self, code):
2376 self.dict.generate_evaluation_code(code)
2377 self.classobj.generate_evaluation_code(code)
2378 self.body.generate_execution_code(code)
2379 self.target.generate_assignment_code(self.classobj, code)
2380 self.dict.generate_disposal_code(code)
2383 class CClassDefNode(ClassDefNode):
2384 # An extension type definition.
2386 # visibility 'private' or 'public' or 'extern'
2387 # typedef_flag boolean
2388 # api boolean
2389 # module_name string or None For import of extern type objects
2390 # class_name string Unqualified name of class
2391 # as_name string or None Name to declare as in this scope
2392 # base_class_module string or None Module containing the base class
2393 # base_class_name string or None Name of the base class
2394 # objstruct_name string or None Specified C name of object struct
2395 # typeobj_name string or None Specified C name of type object
2396 # in_pxd boolean Is in a .pxd file
2397 # doc string or None
2398 # body StatNode or None
2399 # entry Symtab.Entry
2400 # base_type PyExtensionType or None
2401 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2402 # buffer_defaults_pos
2404 child_attrs = ["body"]
2405 buffer_defaults_node = None
2406 buffer_defaults_pos = None
2407 typedef_flag = False
2408 api = False
2409 objstruct_name = None
2410 typeobj_name = None
2412 def analyse_declarations(self, env):
2413 #print "CClassDefNode.analyse_declarations:", self.class_name
2414 #print "...visibility =", self.visibility
2415 #print "...module_name =", self.module_name
2417 import Buffer
2418 if self.buffer_defaults_node:
2419 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2420 env, [], self.buffer_defaults_node,
2421 need_complete=False)
2422 else:
2423 buffer_defaults = None
2425 if env.in_cinclude and not self.objstruct_name:
2426 error(self.pos, "Object struct name specification required for "
2427 "C class defined in 'extern from' block")
2428 self.base_type = None
2429 # Now that module imports are cached, we need to
2430 # import the modules for extern classes.
2431 if self.module_name:
2432 self.module = None
2433 for module in env.cimported_modules:
2434 if module.name == self.module_name:
2435 self.module = module
2436 if self.module is None:
2437 self.module = ModuleScope(self.module_name, None, env.context)
2438 self.module.has_extern_class = 1
2439 env.cimported_modules.append(self.module)
2441 if self.base_class_name:
2442 if self.base_class_module:
2443 base_class_scope = env.find_module(self.base_class_module, self.pos)
2444 else:
2445 base_class_scope = env
2446 if base_class_scope:
2447 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2448 if base_class_entry:
2449 if not base_class_entry.is_type:
2450 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2451 elif not base_class_entry.type.is_extension_type:
2452 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2453 elif not base_class_entry.type.is_complete():
2454 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2455 else:
2456 self.base_type = base_class_entry.type
2457 has_body = self.body is not None
2458 if self.module_name and self.visibility != 'extern':
2459 module_path = self.module_name.split(".")
2460 home_scope = env.find_imported_module(module_path, self.pos)
2461 if not home_scope:
2462 return
2463 else:
2464 home_scope = env
2465 self.entry = home_scope.declare_c_class(
2466 name = self.class_name,
2467 pos = self.pos,
2468 defining = has_body and self.in_pxd,
2469 implementing = has_body and not self.in_pxd,
2470 module_name = self.module_name,
2471 base_type = self.base_type,
2472 objstruct_cname = self.objstruct_name,
2473 typeobj_cname = self.typeobj_name,
2474 visibility = self.visibility,
2475 typedef_flag = self.typedef_flag,
2476 api = self.api,
2477 buffer_defaults = buffer_defaults)
2478 if home_scope is not env and self.visibility == 'extern':
2479 env.add_imported_entry(self.class_name, self.entry, pos)
2480 scope = self.entry.type.scope
2482 if self.doc and Options.docstrings:
2483 scope.doc = embed_position(self.pos, self.doc)
2485 if has_body:
2486 self.body.analyse_declarations(scope)
2487 if self.in_pxd:
2488 scope.defined = 1
2489 else:
2490 scope.implemented = 1
2491 env.allocate_vtable_names(self.entry)
2493 def analyse_expressions(self, env):
2494 if self.body:
2495 scope = self.entry.type.scope
2496 self.body.analyse_expressions(scope)
2498 def generate_function_definitions(self, env, code):
2499 self.generate_py_string_decls(self.entry.type.scope, code)
2500 if self.body:
2501 self.body.generate_function_definitions(
2502 self.entry.type.scope, code)
2504 def generate_execution_code(self, code):
2505 # This is needed to generate evaluation code for
2506 # default values of method arguments.
2507 if self.body:
2508 self.body.generate_execution_code(code)
2510 def annotate(self, code):
2511 if self.body:
2512 self.body.annotate(code)
2515 class PropertyNode(StatNode):
2516 # Definition of a property in an extension type.
2518 # name string
2519 # doc EncodedString or None Doc string
2520 # body StatListNode
2522 child_attrs = ["body"]
2524 def analyse_declarations(self, env):
2525 entry = env.declare_property(self.name, self.doc, self.pos)
2526 if entry:
2527 if self.doc and Options.docstrings:
2528 doc_entry = env.get_string_const(
2529 self.doc, identifier = False)
2530 entry.doc_cname = doc_entry.cname
2531 self.body.analyse_declarations(entry.scope)
2533 def analyse_expressions(self, env):
2534 self.body.analyse_expressions(env)
2536 def generate_function_definitions(self, env, code):
2537 self.body.generate_function_definitions(env, code)
2539 def generate_execution_code(self, code):
2540 pass
2542 def annotate(self, code):
2543 self.body.annotate(code)
2546 class GlobalNode(StatNode):
2547 # Global variable declaration.
2549 # names [string]
2551 child_attrs = []
2553 def analyse_declarations(self, env):
2554 for name in self.names:
2555 env.declare_global(name, self.pos)
2557 def analyse_expressions(self, env):
2558 pass
2560 def generate_execution_code(self, code):
2561 pass
2564 class ExprStatNode(StatNode):
2565 # Expression used as a statement.
2567 # expr ExprNode
2569 child_attrs = ["expr"]
2571 def analyse_declarations(self, env):
2572 import ExprNodes
2573 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2574 func = self.expr.function.as_cython_attribute()
2575 if func == u'declare':
2576 args, kwds = self.expr.explicit_args_kwds()
2577 if len(args):
2578 error(self.expr.pos, "Variable names must be specified.")
2579 for var, type_node in kwds.key_value_pairs:
2580 type = type_node.analyse_as_type(env)
2581 if type is None:
2582 error(type_node.pos, "Unknown type")
2583 else:
2584 env.declare_var(var.value, type, var.pos, is_cdef = True)
2585 self.__class__ = PassStatNode
2587 def analyse_expressions(self, env):
2588 self.expr.analyse_expressions(env)
2589 self.expr.release_temp(env)
2591 def generate_execution_code(self, code):
2592 self.expr.generate_evaluation_code(code)
2593 if not self.expr.is_temp and self.expr.result():
2594 code.putln("%s;" % self.expr.result())
2595 self.expr.generate_disposal_code(code)
2597 def annotate(self, code):
2598 self.expr.annotate(code)
2601 class AssignmentNode(StatNode):
2602 # Abstract base class for assignment nodes.
2604 # The analyse_expressions and generate_execution_code
2605 # phases of assignments are split into two sub-phases
2606 # each, to enable all the right hand sides of a
2607 # parallel assignment to be evaluated before assigning
2608 # to any of the left hand sides.
2610 def analyse_expressions(self, env):
2611 self.analyse_types(env)
2612 self.allocate_rhs_temps(env)
2613 self.allocate_lhs_temps(env)
2615 # def analyse_expressions(self, env):
2616 # self.analyse_expressions_1(env)
2617 # self.analyse_expressions_2(env)
2619 def generate_execution_code(self, code):
2620 self.generate_rhs_evaluation_code(code)
2621 self.generate_assignment_code(code)
2624 class SingleAssignmentNode(AssignmentNode):
2625 # The simplest case:
2627 # a = b
2629 # lhs ExprNode Left hand side
2630 # rhs ExprNode Right hand side
2631 # first bool Is this guaranteed the first assignment to lhs?
2633 child_attrs = ["lhs", "rhs"]
2634 first = False
2635 declaration_only = False
2637 def analyse_declarations(self, env):
2638 import ExprNodes
2640 # handle declarations of the form x = cython.foo()
2641 if isinstance(self.rhs, ExprNodes.CallNode):
2642 func_name = self.rhs.function.as_cython_attribute()
2643 if func_name:
2644 args, kwds = self.rhs.explicit_args_kwds()
2646 if func_name in ['declare', 'typedef']:
2647 if len(args) > 2 or kwds is not None:
2648 error(rhs.pos, "Can only declare one type at a time.")
2649 return
2650 type = args[0].analyse_as_type(env)
2651 if type is None:
2652 error(args[0].pos, "Unknown type")
2653 return
2654 lhs = self.lhs
2655 if func_name == 'declare':
2656 if isinstance(lhs, ExprNodes.NameNode):
2657 vars = [(lhs.name, lhs.pos)]
2658 elif isinstance(lhs, ExprNodes.TupleNode):
2659 vars = [(var.name, var.pos) for var in lhs.args]
2660 else:
2661 error(lhs.pos, "Invalid declaration")
2662 return
2663 for var, pos in vars:
2664 env.declare_var(var, type, pos, is_cdef = True)
2665 if len(args) == 2:
2666 # we have a value
2667 self.rhs = args[1]
2668 else:
2669 self.declaration_only = True
2670 else:
2671 self.declaration_only = True
2672 if not isinstance(lhs, ExprNodes.NameNode):
2673 error(lhs.pos, "Invalid declaration.")
2674 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2676 elif func_name in ['struct', 'union']:
2677 self.declaration_only = True
2678 if len(args) > 0 or kwds is None:
2679 error(rhs.pos, "Struct or union members must be given by name.")
2680 return
2681 members = []
2682 for member, type_node in kwds.key_value_pairs:
2683 type = type_node.analyse_as_type(env)
2684 if type is None:
2685 error(type_node.pos, "Unknown type")
2686 else:
2687 members.append((member.value, type, member.pos))
2688 if len(members) < len(kwds.key_value_pairs):
2689 return
2690 if not isinstance(self.lhs, ExprNodes.NameNode):
2691 error(self.lhs.pos, "Invalid declaration.")
2692 name = self.lhs.name
2693 scope = StructOrUnionScope(name)
2694 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2695 for member, type, pos in members:
2696 scope.declare_var(member, type, pos)
2698 if self.declaration_only:
2699 return
2700 else:
2701 self.lhs.analyse_target_declaration(env)
2703 def analyse_types(self, env, use_temp = 0):
2704 self.rhs.analyse_types(env)
2705 self.lhs.analyse_target_types(env)
2706 self.lhs.gil_assignment_check(env)
2707 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2708 if use_temp:
2709 self.rhs = self.rhs.coerce_to_temp(env)
2711 def allocate_rhs_temps(self, env):
2712 self.rhs.allocate_temps(env)
2714 def allocate_lhs_temps(self, env):
2715 self.lhs.allocate_target_temps(env, self.rhs)
2716 #self.lhs.release_target_temp(env)
2717 #self.rhs.release_temp(env)
2719 # def analyse_expressions_1(self, env, use_temp = 0):
2720 # self.rhs.analyse_types(env)
2721 # self.lhs.analyse_target_types(env)
2722 # self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2723 # if use_temp:
2724 # self.rhs = self.rhs.coerce_to_temp(env)
2725 # self.rhs.allocate_temps(env)
2727 # def analyse_expressions_2(self, env):
2728 # self.lhs.allocate_target_temps(env)
2729 # self.lhs.release_target_temp(env)
2730 # self.rhs.release_temp(env)
2732 def generate_rhs_evaluation_code(self, code):
2733 self.rhs.generate_evaluation_code(code)
2735 def generate_assignment_code(self, code):
2736 self.lhs.generate_assignment_code(self.rhs, code)
2738 def annotate(self, code):
2739 self.lhs.annotate(code)
2740 self.rhs.annotate(code)
2743 class CascadedAssignmentNode(AssignmentNode):
2744 # An assignment with multiple left hand sides:
2746 # a = b = c
2748 # lhs_list [ExprNode] Left hand sides
2749 # rhs ExprNode Right hand sides
2751 # Used internally:
2753 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2755 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2756 coerced_rhs_list = None
2758 def analyse_declarations(self, env):
2759 for lhs in self.lhs_list:
2760 lhs.analyse_target_declaration(env)
2762 def analyse_types(self, env, use_temp = 0):
2763 self.rhs.analyse_types(env)
2764 if use_temp:
2765 self.rhs = self.rhs.coerce_to_temp(env)
2766 else:
2767 self.rhs = self.rhs.coerce_to_simple(env)
2768 from ExprNodes import CloneNode
2769 self.coerced_rhs_list = []
2770 for lhs in self.lhs_list:
2771 lhs.analyse_target_types(env)
2772 lhs.gil_assignment_check(env)
2773 rhs = CloneNode(self.rhs)
2774 rhs = rhs.coerce_to(lhs.type, env)
2775 self.coerced_rhs_list.append(rhs)
2777 def allocate_rhs_temps(self, env):
2778 self.rhs.allocate_temps(env)
2780 def allocate_lhs_temps(self, env):
2781 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2782 rhs.allocate_temps(env)
2783 lhs.allocate_target_temps(env, rhs)
2784 #lhs.release_target_temp(env)
2785 #rhs.release_temp(env)
2786 self.rhs.release_temp(env)
2788 # def analyse_expressions_1(self, env, use_temp = 0):
2789 # self.rhs.analyse_types(env)
2790 # if use_temp:
2791 # self.rhs = self.rhs.coerce_to_temp(env)
2792 # else:
2793 # self.rhs = self.rhs.coerce_to_simple(env)
2794 # self.rhs.allocate_temps(env)
2796 # def analyse_expressions_2(self, env):
2797 # from ExprNodes import CloneNode
2798 # self.coerced_rhs_list = []
2799 # for lhs in self.lhs_list:
2800 # lhs.analyse_target_types(env)
2801 # rhs = CloneNode(self.rhs)
2802 # rhs = rhs.coerce_to(lhs.type, env)
2803 # self.coerced_rhs_list.append(rhs)
2804 # rhs.allocate_temps(env)
2805 # lhs.allocate_target_temps(env)
2806 # lhs.release_target_temp(env)
2807 # rhs.release_temp(env)
2808 # self.rhs.release_temp(env)
2810 def generate_rhs_evaluation_code(self, code):
2811 self.rhs.generate_evaluation_code(code)
2813 def generate_assignment_code(self, code):
2814 for i in range(len(self.lhs_list)):
2815 lhs = self.lhs_list[i]
2816 rhs = self.coerced_rhs_list[i]
2817 rhs.generate_evaluation_code(code)
2818 lhs.generate_assignment_code(rhs, code)
2819 # Assignment has disposed of the cloned RHS
2820 self.rhs.generate_disposal_code(code)
2822 def annotate(self, code):
2823 for i in range(len(self.lhs_list)):
2824 lhs = self.lhs_list[i].annotate(code)
2825 rhs = self.coerced_rhs_list[i].annotate(code)
2826 self.rhs.annotate(code)
2829 class ParallelAssignmentNode(AssignmentNode):
2830 # A combined packing/unpacking assignment:
2832 # a, b, c = d, e, f
2834 # This has been rearranged by the parser into
2836 # a = d ; b = e ; c = f
2838 # but we must evaluate all the right hand sides
2839 # before assigning to any of the left hand sides.
2841 # stats [AssignmentNode] The constituent assignments
2843 child_attrs = ["stats"]
2845 def analyse_declarations(self, env):
2846 for stat in self.stats:
2847 stat.analyse_declarations(env)
2849 def analyse_expressions(self, env):
2850 for stat in self.stats:
2851 stat.analyse_types(env, use_temp = 1)
2852 stat.allocate_rhs_temps(env)
2853 for stat in self.stats:
2854 stat.allocate_lhs_temps(env)
2856 # def analyse_expressions(self, env):
2857 # for stat in self.stats:
2858 # stat.analyse_expressions_1(env, use_temp = 1)
2859 # for stat in self.stats:
2860 # stat.analyse_expressions_2(env)
2862 def generate_execution_code(self, code):
2863 for stat in self.stats:
2864 stat.generate_rhs_evaluation_code(code)
2865 for stat in self.stats:
2866 stat.generate_assignment_code(code)
2868 def annotate(self, code):
2869 for stat in self.stats:
2870 stat.annotate(code)
2873 class InPlaceAssignmentNode(AssignmentNode):
2874 # An in place arithmatic operand:
2876 # a += b
2877 # a -= b
2878 # ...
2880 # lhs ExprNode Left hand side
2881 # rhs ExprNode Right hand side
2882 # op char one of "+-*/%^&|"
2883 # dup (ExprNode) copy of lhs used for operation (auto-generated)
2885 # This code is a bit tricky because in order to obey Python
2886 # semantics the sub-expressions (e.g. indices) of the lhs must
2887 # not be evaluated twice. So we must re-use the values calculated
2888 # in evaluation phase for the assignment phase as well.
2889 # Fortunately, the type of the lhs node is fairly constrained
2890 # (it must be a NameNode, AttributeNode, or IndexNode).
2892 child_attrs = ["lhs", "rhs"]
2893 dup = None
2895 def analyse_declarations(self, env):
2896 self.lhs.analyse_target_declaration(env)
2898 def analyse_types(self, env):
2899 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
2900 self.rhs.analyse_types(env)
2901 self.lhs.analyse_target_types(env)
2902 if Options.incref_local_binop and self.dup.type.is_pyobject:
2903 self.dup = self.dup.coerce_to_temp(env)
2905 def allocate_rhs_temps(self, env):
2906 import ExprNodes
2907 if self.lhs.type.is_pyobject:
2908 self.rhs = self.rhs.coerce_to_pyobject(env)
2909 elif self.rhs.type.is_pyobject:
2910 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2911 if self.lhs.type.is_pyobject:
2912 self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
2913 self.result_value.allocate_temps(env)
2914 # if use_temp:
2915 # self.rhs = self.rhs.coerce_to_temp(env)
2916 self.rhs.allocate_temps(env)
2917 self.dup.allocate_subexpr_temps(env)
2918 self.dup.allocate_temp(env)
2920 def allocate_lhs_temps(self, env):
2921 self.lhs.allocate_target_temps(env, self.rhs)
2922 # self.lhs.release_target_temp(env)
2923 self.dup.release_temp(env)
2924 if self.dup.is_temp:
2925 self.dup.release_subexpr_temps(env)
2926 # self.rhs.release_temp(env)
2927 if self.lhs.type.is_pyobject:
2928 self.result_value.release_temp(env)
2930 def generate_execution_code(self, code):
2931 self.rhs.generate_evaluation_code(code)
2932 self.dup.generate_subexpr_evaluation_code(code)
2933 # self.dup.generate_result_code is run only if it is not buffer access
2934 if self.operator == "**":
2935 extra = ", Py_None"
2936 else:
2937 extra = ""
2938 import ExprNodes
2939 if self.lhs.type.is_pyobject:
2940 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
2941 error(self.pos, "In-place operators not allowed on object buffers in this release.")
2942 self.dup.generate_result_code(code)
2943 code.putln(
2944 "%s = %s(%s, %s%s); %s" % (
2945 self.result_value.result(),
2946 self.py_operation_function(),
2947 self.dup.py_result(),
2948 self.rhs.py_result(),
2949 extra,
2950 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
2951 self.result_value.generate_evaluation_code(code) # May be a type check...
2952 self.rhs.generate_disposal_code(code)
2953 self.dup.generate_disposal_code(code)
2954 self.lhs.generate_assignment_code(self.result_value, code)
2955 else:
2956 c_op = self.operator
2957 if c_op == "//":
2958 c_op = "/"
2959 elif c_op == "**":
2960 if self.lhs.type.is_int and self.rhs.type.is_int:
2961 error(self.pos, "** with two C int types is ambiguous")
2962 else:
2963 error(self.pos, "No C inplace power operator")
2964 # have to do assignment directly to avoid side-effects
2965 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
2966 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
2967 else:
2968 self.dup.generate_result_code(code)
2969 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
2970 self.rhs.generate_disposal_code(code)
2971 if self.dup.is_temp:
2972 self.dup.generate_subexpr_disposal_code(code)
2974 def create_dup_node(self, env):
2975 import ExprNodes
2976 self.dup = self.lhs
2977 self.dup.analyse_types(env)
2978 if isinstance(self.lhs, ExprNodes.NameNode):
2979 target_lhs = ExprNodes.NameNode(self.dup.pos,
2980 name = self.dup.name,
2981 is_temp = self.dup.is_temp,
2982 entry = self.dup.entry)
2983 elif isinstance(self.lhs, ExprNodes.AttributeNode):
2984 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
2985 obj = ExprNodes.CloneNode(self.lhs.obj),
2986 attribute = self.dup.attribute,
2987 is_temp = self.dup.is_temp)
2988 elif isinstance(self.lhs, ExprNodes.IndexNode):
2989 if self.lhs.index:
2990 index = ExprNodes.CloneNode(self.lhs.index)
2991 else:
2992 index = None
2993 if self.lhs.indices:
2994 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
2995 else:
2996 indices = []
2997 target_lhs = ExprNodes.IndexNode(self.dup.pos,
2998 base = ExprNodes.CloneNode(self.dup.base),
2999 index = index,
3000 indices = indices,
3001 is_temp = self.dup.is_temp)
3002 self.lhs = target_lhs
3003 return self.dup
3005 def py_operation_function(self):
3006 return self.py_functions[self.operator]
3008 py_functions = {
3009 "|": "PyNumber_InPlaceOr",
3010 "^": "PyNumber_InPlaceXor",
3011 "&": "PyNumber_InPlaceAnd",
3012 "+": "PyNumber_InPlaceAdd",
3013 "-": "PyNumber_InPlaceSubtract",
3014 "*": "PyNumber_InPlaceMultiply",
3015 "/": "PyNumber_InPlaceDivide",
3016 "%": "PyNumber_InPlaceRemainder",
3017 "<<": "PyNumber_InPlaceLshift",
3018 ">>": "PyNumber_InPlaceRshift",
3019 "**": "PyNumber_InPlacePower",
3020 "//": "PyNumber_InPlaceFloorDivide",
3023 def annotate(self, code):
3024 self.lhs.annotate(code)
3025 self.rhs.annotate(code)
3026 self.dup.annotate(code)
3029 class PrintStatNode(StatNode):
3030 # print statement
3032 # arg_tuple TupleNode
3033 # append_newline boolean
3035 child_attrs = ["arg_tuple"]
3037 def analyse_expressions(self, env):
3038 self.arg_tuple.analyse_expressions(env)
3039 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3040 self.arg_tuple.release_temp(env)
3041 env.use_utility_code(printing_utility_code)
3042 self.gil_check(env)
3044 gil_message = "Python print statement"
3046 def generate_execution_code(self, code):
3047 self.arg_tuple.generate_evaluation_code(code)
3048 code.putln(
3049 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3050 self.arg_tuple.py_result(),
3051 self.append_newline,
3052 code.error_goto(self.pos)))
3053 self.arg_tuple.generate_disposal_code(code)
3055 def annotate(self, code):
3056 self.arg_tuple.annotate(code)
3059 class DelStatNode(StatNode):
3060 # del statement
3062 # args [ExprNode]
3064 child_attrs = ["args"]
3066 def analyse_declarations(self, env):
3067 for arg in self.args:
3068 arg.analyse_target_declaration(env)
3070 def analyse_expressions(self, env):
3071 for arg in self.args:
3072 arg.analyse_target_expression(env, None)
3073 if arg.type.is_pyobject:
3074 self.gil_check(env)
3075 else:
3076 error(arg.pos, "Deletion of non-Python object")
3077 #arg.release_target_temp(env)
3079 gil_message = "Deleting Python object"
3081 def generate_execution_code(self, code):
3082 for arg in self.args:
3083 if arg.type.is_pyobject:
3084 arg.generate_deletion_code(code)
3085 # else error reported earlier
3087 def annotate(self, code):
3088 for arg in self.args:
3089 arg.annotate(code)
3092 class PassStatNode(StatNode):
3093 # pass statement
3095 child_attrs = []
3097 def analyse_expressions(self, env):
3098 pass
3100 def generate_execution_code(self, code):
3101 pass
3104 class BreakStatNode(StatNode):
3106 child_attrs = []
3108 def analyse_expressions(self, env):
3109 pass
3111 def generate_execution_code(self, code):
3112 if not code.break_label:
3113 error(self.pos, "break statement not inside loop")
3114 else:
3115 #code.putln(
3116 # "goto %s;" %
3117 # code.break_label)
3118 code.put_goto(code.break_label)
3121 class ContinueStatNode(StatNode):
3123 child_attrs = []
3125 def analyse_expressions(self, env):
3126 pass
3128 def generate_execution_code(self, code):
3129 if code.funcstate.in_try_finally:
3130 error(self.pos, "continue statement inside try of try...finally")
3131 elif not code.continue_label:
3132 error(self.pos, "continue statement not inside loop")
3133 else:
3134 code.put_goto(code.continue_label)
3137 class ReturnStatNode(StatNode):
3138 # return statement
3140 # value ExprNode or None
3141 # return_type PyrexType
3142 # temps_in_use [Entry] Temps in use at time of return
3144 child_attrs = ["value"]
3146 def analyse_expressions(self, env):
3147 return_type = env.return_type
3148 self.return_type = return_type
3149 self.temps_in_use = env.temps_in_use()
3150 if not return_type:
3151 error(self.pos, "Return not inside a function body")
3152 return
3153 if self.value:
3154 self.value.analyse_types(env)
3155 if return_type.is_void or return_type.is_returncode:
3156 error(self.value.pos,
3157 "Return with value in void function")
3158 else:
3159 self.value = self.value.coerce_to(env.return_type, env)
3160 self.value.allocate_temps(env)
3161 self.value.release_temp(env)
3162 else:
3163 if (not return_type.is_void
3164 and not return_type.is_pyobject
3165 and not return_type.is_returncode):
3166 error(self.pos, "Return value required")
3167 if return_type.is_pyobject:
3168 self.gil_check(env)
3170 gil_message = "Returning Python object"
3172 def generate_execution_code(self, code):
3173 code.mark_pos(self.pos)
3174 if not self.return_type:
3175 # error reported earlier
3176 return
3177 if self.value:
3178 self.value.generate_evaluation_code(code)
3179 self.value.make_owned_reference(code)
3180 code.putln(
3181 "%s = %s;" % (
3182 Naming.retval_cname,
3183 self.value.result_as(self.return_type)))
3184 self.value.generate_post_assignment_code(code)
3185 else:
3186 if self.return_type.is_pyobject:
3187 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3188 elif self.return_type.is_returncode:
3189 code.putln(
3190 "%s = %s;" % (
3191 Naming.retval_cname,
3192 self.return_type.default_value))
3193 for entry in self.temps_in_use:
3194 code.put_var_decref_clear(entry)
3195 #code.putln(
3196 # "goto %s;" %
3197 # code.return_label)
3198 code.put_goto(code.return_label)
3200 def annotate(self, code):
3201 if self.value:
3202 self.value.annotate(code)
3205 class RaiseStatNode(StatNode):
3206 # raise statement
3208 # exc_type ExprNode or None
3209 # exc_value ExprNode or None
3210 # exc_tb ExprNode or None
3212 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3214 def analyse_expressions(self, env):
3215 if self.exc_type:
3216 self.exc_type.analyse_types(env)
3217 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3218 self.exc_type.allocate_temps(env)
3219 if self.exc_value:
3220 self.exc_value.analyse_types(env)
3221 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3222 self.exc_value.allocate_temps(env)
3223 if self.exc_tb:
3224 self.exc_tb.analyse_types(env)
3225 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3226 self.exc_tb.allocate_temps(env)
3227 if self.exc_type:
3228 self.exc_type.release_temp(env)
3229 if self.exc_value:
3230 self.exc_value.release_temp(env)
3231 if self.exc_tb:
3232 self.exc_tb.release_temp(env)
3233 env.use_utility_code(raise_utility_code)
3234 env.use_utility_code(restore_exception_utility_code)
3235 self.gil_check(env)
3237 gil_message = "Raising exception"
3239 def generate_execution_code(self, code):
3240 if self.exc_type:
3241 self.exc_type.generate_evaluation_code(code)
3242 type_code = self.exc_type.py_result()
3243 else:
3244 type_code = 0
3245 if self.exc_value:
3246 self.exc_value.generate_evaluation_code(code)
3247 value_code = self.exc_value.py_result()
3248 else:
3249 value_code = "0"
3250 if self.exc_tb:
3251 self.exc_tb.generate_evaluation_code(code)
3252 tb_code = self.exc_tb.py_result()
3253 else:
3254 tb_code = "0"
3255 if self.exc_type or self.exc_value or self.exc_tb:
3256 code.putln(
3257 "__Pyx_Raise(%s, %s, %s);" % (
3258 type_code,
3259 value_code,
3260 tb_code))
3261 else:
3262 code.putln(
3263 "__Pyx_ReRaise();")
3264 if self.exc_type:
3265 self.exc_type.generate_disposal_code(code)
3266 if self.exc_value:
3267 self.exc_value.generate_disposal_code(code)
3268 if self.exc_tb:
3269 self.exc_tb.generate_disposal_code(code)
3270 code.putln(
3271 code.error_goto(self.pos))
3273 def annotate(self, code):
3274 if self.exc_type:
3275 self.exc_type.annotate(code)
3276 if self.exc_value:
3277 self.exc_value.annotate(code)
3278 if self.exc_tb:
3279 self.exc_tb.annotate(code)
3282 class ReraiseStatNode(StatNode):
3284 child_attrs = []
3286 def analyse_expressions(self, env):
3287 self.gil_check(env)
3288 env.use_utility_code(raise_utility_code)
3289 env.use_utility_code(restore_exception_utility_code)
3291 gil_message = "Raising exception"
3293 def generate_execution_code(self, code):
3294 vars = code.funcstate.exc_vars
3295 if vars:
3296 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3297 code.putln(code.error_goto(self.pos))
3298 else:
3299 error(self.pos, "Reraise not inside except clause")
3302 class AssertStatNode(StatNode):
3303 # assert statement
3305 # cond ExprNode
3306 # value ExprNode or None
3308 child_attrs = ["cond", "value"]
3310 def analyse_expressions(self, env):
3311 self.cond = self.cond.analyse_boolean_expression(env)
3312 if self.value:
3313 self.value.analyse_types(env)
3314 self.value = self.value.coerce_to_pyobject(env)
3315 self.value.allocate_temps(env)
3316 self.cond.release_temp(env)
3317 if self.value:
3318 self.value.release_temp(env)
3319 self.gil_check(env)
3320 #env.recycle_pending_temps() # TEMPORARY
3322 gil_message = "Raising exception"
3324 def generate_execution_code(self, code):
3325 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3326 self.cond.generate_evaluation_code(code)
3327 code.putln(
3328 "if (unlikely(!%s)) {" %
3329 self.cond.result())
3330 if self.value:
3331 self.value.generate_evaluation_code(code)
3332 code.putln(
3333 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3334 self.value.py_result())
3335 self.value.generate_disposal_code(code)
3336 else:
3337 code.putln(
3338 "PyErr_SetNone(PyExc_AssertionError);")
3339 code.putln(
3340 code.error_goto(self.pos))
3341 code.putln(
3342 "}")
3343 self.cond.generate_disposal_code(code)
3344 code.putln("#endif")
3346 def annotate(self, code):
3347 self.cond.annotate(code)
3348 if self.value:
3349 self.value.annotate(code)
3352 class IfStatNode(StatNode):
3353 # if statement
3355 # if_clauses [IfClauseNode]
3356 # else_clause StatNode or None
3358 child_attrs = ["if_clauses", "else_clause"]
3360 def analyse_control_flow(self, env):
3361 env.start_branching(self.pos)
3362 for if_clause in self.if_clauses:
3363 if_clause.analyse_control_flow(env)
3364 env.next_branch(if_clause.end_pos())
3365 if self.else_clause:
3366 self.else_clause.analyse_control_flow(env)
3367 env.finish_branching(self.end_pos())
3369 def analyse_declarations(self, env):
3370 for if_clause in self.if_clauses:
3371 if_clause.analyse_declarations(env)
3372 if self.else_clause:
3373 self.else_clause.analyse_declarations(env)
3375 def analyse_expressions(self, env):
3376 for if_clause in self.if_clauses:
3377 if_clause.analyse_expressions(env)
3378 if self.else_clause:
3379 self.else_clause.analyse_expressions(env)
3381 def generate_execution_code(self, code):
3382 code.mark_pos(self.pos)
3383 end_label = code.new_label()
3384 for if_clause in self.if_clauses:
3385 if_clause.generate_execution_code(code, end_label)
3386 if self.else_clause:
3387 code.putln("/*else*/ {")
3388 self.else_clause.generate_execution_code(code)
3389 code.putln("}")
3390 code.put_label(end_label)
3392 def annotate(self, code):
3393 for if_clause in self.if_clauses:
3394 if_clause.annotate(code)
3395 if self.else_clause:
3396 self.else_clause.annotate(code)
3399 class IfClauseNode(Node):
3400 # if or elif clause in an if statement
3402 # condition ExprNode
3403 # body StatNode
3405 child_attrs = ["condition", "body"]
3407 def analyse_control_flow(self, env):
3408 self.body.analyse_control_flow(env)
3410 def analyse_declarations(self, env):
3411 self.condition.analyse_declarations(env)
3412 self.body.analyse_declarations(env)
3414 def analyse_expressions(self, env):
3415 self.condition = \
3416 self.condition.analyse_temp_boolean_expression(env)
3417 self.condition.release_temp(env)
3418 self.body.analyse_expressions(env)
3420 def generate_execution_code(self, code, end_label):
3421 self.condition.generate_evaluation_code(code)
3422 code.putln(
3423 "if (%s) {" %
3424 self.condition.result())
3425 self.body.generate_execution_code(code)
3426 #code.putln(
3427 # "goto %s;" %
3428 # end_label)
3429 code.put_goto(end_label)
3430 code.putln("}")
3432 def annotate(self, code):
3433 self.condition.annotate(code)
3434 self.body.annotate(code)
3437 class SwitchCaseNode(StatNode):
3438 # Generated in the optimization of an if-elif-else node
3440 # conditions [ExprNode]
3441 # body StatNode
3443 child_attrs = ['conditions', 'body']
3445 def generate_execution_code(self, code):
3446 for cond in self.conditions:
3447 code.putln("case %s:" % cond.calculate_result_code())
3448 self.body.generate_execution_code(code)
3449 code.putln("break;")
3451 def annotate(self, code):
3452 for cond in self.conditions:
3453 cond.annotate(code)
3454 self.body.annotate(code)
3456 class SwitchStatNode(StatNode):
3457 # Generated in the optimization of an if-elif-else node
3459 # test ExprNode
3460 # cases [SwitchCaseNode]
3461 # else_clause StatNode or None
3463 child_attrs = ['test', 'cases', 'else_clause']
3465 def generate_execution_code(self, code):
3466 code.putln("switch (%s) {" % self.test.calculate_result_code())
3467 for case in self.cases:
3468 case.generate_execution_code(code)
3469 if self.else_clause is not None:
3470 code.putln("default:")
3471 self.else_clause.generate_execution_code(code)
3472 code.putln("}")
3474 def annotate(self, code):
3475 self.test.annotate(code)
3476 for case in self.cases:
3477 case.annotate(code)
3478 if self.else_clause is not None:
3479 self.else_clause.annotate(code)
3481 class LoopNode:
3483 def analyse_control_flow(self, env):
3484 env.start_branching(self.pos)
3485 self.body.analyse_control_flow(env)
3486 env.next_branch(self.body.end_pos())
3487 if self.else_clause:
3488 self.else_clause.analyse_control_flow(env)
3489 env.finish_branching(self.end_pos())
3492 class WhileStatNode(LoopNode, StatNode):
3493 # while statement
3495 # condition ExprNode
3496 # body StatNode
3497 # else_clause StatNode
3499 child_attrs = ["condition", "body", "else_clause"]
3501 def analyse_declarations(self, env):
3502 self.body.analyse_declarations(env)
3503 if self.else_clause:
3504 self.else_clause.analyse_declarations(env)
3506 def analyse_expressions(self, env):
3507 self.condition = \
3508 self.condition.analyse_temp_boolean_expression(env)
3509 self.condition.release_temp(env)
3510 #env.recycle_pending_temps() # TEMPORARY
3511 self.body.analyse_expressions(env)
3512 if self.else_clause:
3513 self.else_clause.analyse_expressions(env)
3515 def generate_execution_code(self, code):
3516 old_loop_labels = code.new_loop_labels()
3517 code.putln(
3518 "while (1) {")
3519 self.condition.generate_evaluation_code(code)
3520 code.putln(
3521 "if (!%s) break;" %
3522 self.condition.result())
3523 self.body.generate_execution_code(code)
3524 code.put_label(code.continue_label)
3525 code.putln("}")
3526 break_label = code.break_label
3527 code.set_loop_labels(old_loop_labels)
3528 if self.else_clause:
3529 code.putln("/*else*/ {")
3530 self.else_clause.generate_execution_code(code)
3531 code.putln("}")
3532 code.put_label(break_label)
3534 def annotate(self, code):
3535 self.condition.annotate(code)
3536 self.body.annotate(code)
3537 if self.else_clause:
3538 self.else_clause.annotate(code)
3541 def ForStatNode(pos, **kw):
3542 if kw.has_key('iterator'):
3543 return ForInStatNode(pos, **kw)
3544 else:
3545 return ForFromStatNode(pos, **kw)
3547 class ForInStatNode(LoopNode, StatNode):
3548 # for statement
3550 # target ExprNode
3551 # iterator IteratorNode
3552 # body StatNode
3553 # else_clause StatNode
3554 # item NextNode used internally
3556 child_attrs = ["target", "iterator", "body", "else_clause"]
3557 item = None
3559 def analyse_declarations(self, env):
3560 self.target.analyse_target_declaration(env)
3561 self.body.analyse_declarations(env)
3562 if self.else_clause:
3563 self.else_clause.analyse_declarations(env)
3565 def analyse_range_step(self, args):
3566 import ExprNodes
3567 # The direction must be determined at compile time to set relations.
3568 # Otherwise, return False.
3569 if len(args) < 3:
3570 self.step = ExprNodes.IntNode(pos = args[0].pos, value='1')
3571 self.relation1 = '<='
3572 self.relation2 = '<'
3573 return True
3574 else:
3575 step = args[2]
3576 if isinstance(step, ExprNodes.UnaryMinusNode) and isinstance(step.operand, ExprNodes.IntNode):
3577 step = ExprNodes.IntNode(pos = step.pos, value=str(-int(step.operand.value, 0)))
3578 if isinstance(step, ExprNodes.IntNode):
3579 step_value = int(step.value, 0)
3580 if step_value > 0:
3581 self.step = step
3582 self.relation1 = '<='
3583 self.relation2 = '<'
3584 return True
3585 elif step_value < 0:
3586 self.step = ExprNodes.IntNode(pos = step.pos, value=str(-step_value))
3587 self.relation1 = '>='
3588 self.relation2 = '>'
3589 return True
3590 return False
3593 def analyse_expressions(self, env):
3594 import ExprNodes
3595 self.target.analyse_target_types(env)
3596 if Options.convert_range and self.target.type.is_int:
3597 sequence = self.iterator.sequence
3598 if isinstance(sequence, ExprNodes.SimpleCallNode) \
3599 and sequence.self is None \
3600 and isinstance(sequence.function, ExprNodes.NameNode) \
3601 and (sequence.function.name == 'range' or sequence.function.name == 'xrange'):
3602 args = sequence.args
3603 # Make sure we can determine direction from step
3604 if self.analyse_range_step(args):
3605 # Mutate to ForFrom loop type
3606 self.__class__ = ForFromStatNode
3607 if len(args) == 1:
3608 self.bound1 = ExprNodes.IntNode(pos = sequence.pos, value='0')
3609 self.bound2 = args[0]
3610 else:
3611 self.bound1 = args[0]
3612 self.bound2 = args[1]
3613 ForFromStatNode.analyse_expressions(self, env)
3614 return
3616 self.iterator.analyse_expressions(env)
3617 self.item = ExprNodes.NextNode(self.iterator, env)
3618 self.item = self.item.coerce_to(self.target.type, env)
3619 self.item.allocate_temps(env)
3620 self.target.allocate_target_temps(env, self.item)
3621 #self.item.release_temp(env)
3622 #self.target.release_target_temp(env)
3623 self.body.analyse_expressions(env)
3624 if self.else_clause:
3625 self.else_clause.analyse_expressions(env)
3626 self.iterator.release_temp(env)
3628 def generate_execution_code(self, code):
3629 old_loop_labels = code.new_loop_labels()
3630 self.iterator.generate_evaluation_code(code)
3631 code.putln(
3632 "for (;;) {")
3633 self.item.generate_evaluation_code(code)
3634 self.target.generate_assignment_code(self.item, code)
3635 self.body.generate_execution_code(code)
3636 code.put_label(code.continue_label)
3637 code.putln(
3638 "}")
3639 break_label = code.break_label
3640 code.set_loop_labels(old_loop_labels)
3641 if self.else_clause:
3642 code.putln("/*else*/ {")
3643 self.else_clause.generate_execution_code(code)
3644 code.putln("}")
3645 code.put_label(break_label)
3646 self.iterator.generate_disposal_code(code)
3648 def annotate(self, code):
3649 self.target.annotate(code)
3650 self.iterator.annotate(code)
3651 self.body.annotate(code)
3652 if self.else_clause:
3653 self.else_clause.annotate(code)
3654 self.item.annotate(code)
3657 class ForFromStatNode(LoopNode, StatNode):
3658 # for name from expr rel name rel expr
3660 # target NameNode
3661 # bound1 ExprNode
3662 # relation1 string
3663 # relation2 string
3664 # bound2 ExprNode
3665 # step ExprNode or None
3666 # body StatNode
3667 # else_clause StatNode or None
3669 # Used internally:
3671 # is_py_target bool
3672 # loopvar_name string
3673 # py_loopvar_node PyTempNode or None
3674 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3676 def analyse_declarations(self, env):
3677 self.target.analyse_target_declaration(env)
3678 self.body.analyse_declarations(env)
3679 if self.else_clause:
3680 self.else_clause.analyse_declarations(env)
3682 def analyse_expressions(self, env):
3683 import ExprNodes
3684 self.target.analyse_target_types(env)
3685 self.bound1.analyse_types(env)
3686 self.bound2.analyse_types(env)
3687 if self.target.type.is_numeric:
3688 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3689 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3690 else:
3691 self.bound1 = self.bound1.coerce_to_integer(env)
3692 self.bound2 = self.bound2.coerce_to_integer(env)
3693 if self.step is not None:
3694 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3695 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3696 self.step.analyse_types(env)
3697 self.step = self.step.coerce_to_integer(env)
3698 if not (self.bound2.is_name or self.bound2.is_literal):
3699 self.bound2 = self.bound2.coerce_to_temp(env)
3700 target_type = self.target.type
3701 if not (target_type.is_pyobject or target_type.is_numeric):
3702 error(self.target.pos,
3703 "Integer for-loop variable must be of type int or Python object")
3704 #if not (target_type.is_pyobject
3705 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3706 # error(self.target.pos,
3707 # "Cannot assign integer to variable of type '%s'" % target_type)
3708 if target_type.is_numeric:
3709 self.is_py_target = 0
3710 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3711 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3712 self.loopvar_name = self.target.entry.cname
3713 self.py_loopvar_node = None
3714 else:
3715 self.is_py_target = 1
3716 c_loopvar_node = ExprNodes.TempNode(self.pos,
3717 PyrexTypes.c_long_type, env)
3718 c_loopvar_node.allocate_temps(env)
3719 self.loopvar_name = c_loopvar_node.result()
3720 self.py_loopvar_node = \
3721 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3722 self.bound1.allocate_temps(env)
3723 self.bound2.allocate_temps(env)
3724 if self.step is not None:
3725 self.step.allocate_temps(env)
3726 if self.is_py_target:
3727 self.py_loopvar_node.allocate_temps(env)
3728 self.target.allocate_target_temps(env, self.py_loopvar_node)
3729 #self.target.release_target_temp(env)
3730 #self.py_loopvar_node.release_temp(env)
3731 self.body.analyse_expressions(env)
3732 if self.is_py_target:
3733 c_loopvar_node.release_temp(env)
3734 if self.else_clause:
3735 self.else_clause.analyse_expressions(env)
3736 self.bound1.release_temp(env)
3737 self.bound2.release_temp(env)
3738 if self.step is not None:
3739 self.step.release_temp(env)
3741 def generate_execution_code(self, code):
3742 old_loop_labels = code.new_loop_labels()
3743 self.bound1.generate_evaluation_code(code)
3744 self.bound2.generate_evaluation_code(code)
3745 offset, incop = self.relation_table[self.relation1]
3746 if self.step is not None:
3747 self.step.generate_evaluation_code(code)
3748 incop = "%s=%s" % (incop[0], self.step.result())
3749 code.putln(
3750 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3751 self.loopvar_name,
3752 self.bound1.result(), offset,
3753 self.loopvar_name, self.relation2, self.bound2.result(),
3754 self.loopvar_name, incop))
3755 if self.py_loopvar_node:
3756 self.py_loopvar_node.generate_evaluation_code(code)
3757 self.target.generate_assignment_code(self.py_loopvar_node, code)
3758 self.body.generate_execution_code(code)
3759 code.put_label(code.continue_label)
3760 code.putln("}")
3761 break_label = code.break_label
3762 code.set_loop_labels(old_loop_labels)
3763 if self.else_clause:
3764 code.putln("/*else*/ {")
3765 self.else_clause.generate_execution_code(code)
3766 code.putln("}")
3767 code.put_label(break_label)
3768 self.bound1.generate_disposal_code(code)
3769 self.bound2.generate_disposal_code(code)
3770 if self.step is not None:
3771 self.step.generate_disposal_code(code)
3773 relation_table = {
3774 # {relop : (initial offset, increment op)}
3775 '<=': ("", "++"),
3776 '<' : ("+1", "++"),
3777 '>=': ("", "--"),
3778 '>' : ("-1", "--")
3781 def annotate(self, code):
3782 self.target.annotate(code)
3783 self.bound1.annotate(code)
3784 self.bound2.annotate(code)
3785 if self.step:
3786 self.bound2.annotate(code)
3787 self.body.annotate(code)
3788 if self.else_clause:
3789 self.else_clause.annotate(code)
3792 class WithStatNode(StatNode):
3793 """
3794 Represents a Python with statement.
3796 This is only used at parse tree level; and is not present in
3797 analysis or generation phases.
3798 """
3799 # manager The with statement manager object
3800 # target Node (lhs expression)
3801 # body StatNode
3802 child_attrs = ["manager", "target", "body"]
3804 class TryExceptStatNode(StatNode):
3805 # try .. except statement
3807 # body StatNode
3808 # except_clauses [ExceptClauseNode]
3809 # else_clause StatNode or None
3810 # cleanup_list [Entry] temps to clean up on error
3812 child_attrs = ["body", "except_clauses", "else_clause"]
3814 def analyse_control_flow(self, env):
3815 env.start_branching(self.pos)
3816 self.body.analyse_control_flow(env)
3817 successful_try = env.control_flow # grab this for later
3818 env.next_branch(self.body.end_pos())
3819 env.finish_branching(self.body.end_pos())
3821 env.start_branching(self.except_clauses[0].pos)
3822 for except_clause in self.except_clauses:
3823 except_clause.analyse_control_flow(env)
3824 env.next_branch(except_clause.end_pos())
3826 # the else cause it executed only when the try clause finishes
3827 env.control_flow.incoming = successful_try
3828 if self.else_clause:
3829 self.else_clause.analyse_control_flow(env)
3830 env.finish_branching(self.end_pos())
3832 def analyse_declarations(self, env):
3833 self.body.analyse_declarations(env)
3834 for except_clause in self.except_clauses:
3835 except_clause.analyse_declarations(env)
3836 if self.else_clause:
3837 self.else_clause.analyse_declarations(env)
3838 self.gil_check(env)
3839 env.use_utility_code(reset_exception_utility_code)
3841 def analyse_expressions(self, env):
3842 self.body.analyse_expressions(env)
3843 self.cleanup_list = env.free_temp_entries[:]
3844 default_clause_seen = 0
3845 for except_clause in self.except_clauses:
3846 except_clause.analyse_expressions(env)
3847 if default_clause_seen:
3848 error(except_clause.pos, "default 'except:' must be last")
3849 if not except_clause.pattern:
3850 default_clause_seen = 1
3851 self.has_default_clause = default_clause_seen
3852 if self.else_clause:
3853 self.else_clause.analyse_expressions(env)
3854 self.gil_check(env)
3856 gil_message = "Try-except statement"
3858 def generate_execution_code(self, code):
3859 old_return_label = code.return_label
3860 old_error_label = code.new_error_label()
3861 our_error_label = code.error_label
3862 except_end_label = code.new_label('exception_handled')
3863 except_error_label = code.new_label('except_error')
3864 except_return_label = code.new_label('except_return')
3865 try_end_label = code.new_label('try')
3867 code.putln("{")
3868 code.putln("PyObject %s;" %
3869 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
3870 code.putln("__Pyx_ExceptionSave(%s);" %
3871 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
3872 code.putln(
3873 "/*try:*/ {")
3874 self.body.generate_execution_code(code)
3875 code.putln(
3876 "}")
3877 code.error_label = except_error_label
3878 code.return_label = except_return_label
3879 if self.else_clause:
3880 code.putln(
3881 "/*else:*/ {")
3882 self.else_clause.generate_execution_code(code)
3883 code.putln(
3884 "}")
3885 code.put_goto(try_end_label)
3886 code.put_label(our_error_label)
3887 code.put_var_xdecrefs_clear(self.cleanup_list)
3888 for except_clause in self.except_clauses:
3889 except_clause.generate_handling_code(code, except_end_label)
3891 error_label_used = code.label_used(except_error_label)
3892 if error_label_used or not self.has_default_clause:
3893 if error_label_used:
3894 code.put_label(except_error_label)
3895 for var in Naming.exc_save_vars:
3896 code.put_xdecref(var, py_object_type)
3897 code.put_goto(old_error_label)
3899 if code.label_used(except_return_label):
3900 code.put_label(except_return_label)
3901 code.putln("__Pyx_ExceptionReset(%s);" %
3902 ', '.join(Naming.exc_save_vars))
3903 code.put_goto(old_return_label)
3905 if code.label_used(except_end_label):
3906 code.put_label(except_end_label)
3907 code.putln("__Pyx_ExceptionReset(%s);" %
3908 ', '.join(Naming.exc_save_vars))
3909 code.put_label(try_end_label)
3910 code.putln("}")
3912 code.return_label = old_return_label
3913 code.error_label = old_error_label
3915 def annotate(self, code):
3916 self.body.annotate(code)
3917 for except_node in self.except_clauses:
3918 except_node.annotate(code)
3919 if self.else_clause:
3920 self.else_clause.annotate(code)
3923 class ExceptClauseNode(Node):
3924 # Part of try ... except statement.
3926 # pattern ExprNode
3927 # target ExprNode or None
3928 # body StatNode
3929 # excinfo_target NameNode or None optional target for exception info
3930 # match_flag string result of exception match
3931 # exc_value ExcValueNode used internally
3932 # function_name string qualified name of enclosing function
3933 # exc_vars (string * 3) local exception variables
3935 # excinfo_target is never set by the parser, but can be set by a transform
3936 # in order to extract more extensive information about the exception as a
3937 # sys.exc_info()-style tuple into a target variable
3939 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
3941 exc_value = None
3942 excinfo_target = None
3944 def analyse_declarations(self, env):
3945 if self.target:
3946 self.target.analyse_target_declaration(env)
3947 if self.excinfo_target is not None:
3948 self.excinfo_target.analyse_target_declaration(env)
3949 self.body.analyse_declarations(env)
3951 def analyse_expressions(self, env):
3952 import ExprNodes
3953 genv = env.global_scope()
3954 self.function_name = env.qualified_name
3955 if self.pattern:
3956 self.pattern.analyse_expressions(env)
3957 self.pattern = self.pattern.coerce_to_pyobject(env)
3958 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
3959 self.pattern.release_temp(env)
3960 env.release_temp(self.match_flag)
3961 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
3962 if self.target:
3963 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
3964 self.exc_value.allocate_temps(env)
3965 self.target.analyse_target_expression(env, self.exc_value)
3966 if self.excinfo_target is not None:
3967 import ExprNodes
3968 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
3969 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
3970 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
3971 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
3972 ])
3973 self.excinfo_tuple.analyse_expressions(env)
3974 self.excinfo_tuple.allocate_temps(env)
3975 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
3977 self.body.analyse_expressions(env)
3978 for var in self.exc_vars:
3979 env.release_temp(var)
3980 env.use_utility_code(get_exception_utility_code)
3981 env.use_utility_code(restore_exception_utility_code)
3983 def generate_handling_code(self, code, end_label):
3984 code.mark_pos(self.pos)
3985 if self.pattern:
3986 self.pattern.generate_evaluation_code(code)
3987 code.putln(
3988 "%s = PyErr_ExceptionMatches(%s);" % (
3989 self.match_flag,
3990 self.pattern.py_result()))
3991 self.pattern.generate_disposal_code(code)
3992 code.putln(
3993 "if (%s) {" %
3994 self.match_flag)
3995 else:
3996 code.putln("/*except:*/ {")
3997 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
3998 # We always have to fetch the exception value even if
3999 # there is no target, because this also normalises the
4000 # exception and stores it in the thread state.
4001 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
4002 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4003 code.error_goto(self.pos)))
4004 if self.target:
4005 self.exc_value.generate_evaluation_code(code)
4006 self.target.generate_assignment_code(self.exc_value, code)
4007 if self.excinfo_target is not None:
4008 self.excinfo_tuple.generate_evaluation_code(code)
4009 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4011 old_exc_vars = code.funcstate.exc_vars
4012 code.funcstate.exc_vars = self.exc_vars
4013 self.body.generate_execution_code(code)
4014 code.funcstate.exc_vars = old_exc_vars
4015 for var in self.exc_vars:
4016 code.putln("Py_DECREF(%s); %s = 0;" % (var, var))
4017 code.put_goto(end_label)
4018 code.putln(
4019 "}")
4021 def annotate(self, code):
4022 if self.pattern:
4023 self.pattern.annotate(code)
4024 if self.target:
4025 self.target.annotate(code)
4026 self.body.annotate(code)
4029 class TryFinallyStatNode(StatNode):
4030 # try ... finally statement
4032 # body StatNode
4033 # finally_clause StatNode
4035 # cleanup_list [Entry] temps to clean up on error
4037 # The plan is that we funnel all continue, break
4038 # return and error gotos into the beginning of the
4039 # finally block, setting a variable to remember which
4040 # one we're doing. At the end of the finally block, we
4041 # switch on the variable to figure out where to go.
4042 # In addition, if we're doing an error, we save the
4043 # exception on entry to the finally block and restore
4044 # it on exit.
4046 child_attrs = ["body", "finally_clause"]
4048 preserve_exception = 1
4050 disallow_continue_in_try_finally = 0
4051 # There doesn't seem to be any point in disallowing
4052 # continue in the try block, since we have no problem
4053 # handling it.
4055 def create_analysed(pos, env, body, finally_clause):
4056 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4057 node.cleanup_list = []
4058 return node
4059 create_analysed = staticmethod(create_analysed)
4061 def analyse_control_flow(self, env):
4062 env.start_branching(self.pos)
4063 self.body.analyse_control_flow(env)
4064 env.next_branch(self.body.end_pos())
4065 env.finish_branching(self.body.end_pos())
4066 self.finally_clause.analyse_control_flow(env)
4068 def analyse_declarations(self, env):
4069 self.body.analyse_declarations(env)
4070 self.finally_clause.analyse_declarations(env)
4072 def analyse_expressions(self, env):
4073 self.body.analyse_expressions(env)
4074 self.cleanup_list = env.free_temp_entries[:]
4075 self.finally_clause.analyse_expressions(env)
4076 self.gil_check(env)
4078 gil_message = "Try-finally statement"
4080 def generate_execution_code(self, code):
4081 old_error_label = code.error_label
4082 old_labels = code.all_new_labels()
4083 new_labels = code.get_all_labels()
4084 new_error_label = code.error_label
4085 catch_label = code.new_label()
4086 code.putln(
4087 "/*try:*/ {")
4088 if self.disallow_continue_in_try_finally:
4089 was_in_try_finally = code.funcstate.in_try_finally
4090 code.funcstate.in_try_finally = 1
4091 self.body.generate_execution_code(code)
4092 if self.disallow_continue_in_try_finally:
4093 code.funcstate.in_try_finally = was_in_try_finally
4094 code.putln(
4095 "}")
4096 code.putln(
4097 "/*finally:*/ {")
4098 cases_used = []
4099 error_label_used = 0
4100 for i, new_label in enumerate(new_labels):
4101 if new_label in code.labels_used:
4102 cases_used.append(i)
4103 if new_label == new_error_label:
4104 error_label_used = 1
4105 error_label_case = i
4106 if cases_used:
4107 code.putln(
4108 "int __pyx_why;")
4109 if error_label_used and self.preserve_exception:
4110 code.putln(
4111 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4112 code.putln(
4113 "int %s;" % Naming.exc_lineno_name)
4114 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4115 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4116 code.putln(exc_var_init_zero)
4117 else:
4118 exc_var_init_zero = None
4119 code.use_label(catch_label)
4120 code.putln(
4121 "__pyx_why = 0; goto %s;" % catch_label)
4122 for i in cases_used:
4123 new_label = new_labels[i]
4124 #if new_label and new_label != "<try>":
4125 if new_label == new_error_label and self.preserve_exception:
4126 self.put_error_catcher(code,
4127 new_error_label, i+1, catch_label)
4128 else:
4129 code.put('%s: ' % new_label)
4130 if exc_var_init_zero:
4131 code.putln(exc_var_init_zero)
4132 code.putln("__pyx_why = %s; goto %s;" % (
4133 i+1,
4134 catch_label))
4135 code.put_label(catch_label)
4136 code.set_all_labels(old_labels)
4137 if error_label_used:
4138 code.new_error_label()
4139 finally_error_label = code.error_label
4140 self.finally_clause.generate_execution_code(code)
4141 if error_label_used:
4142 if finally_error_label in code.labels_used and self.preserve_exception:
4143 over_label = code.new_label()
4144 code.put_goto(over_label);
4145 code.put_label(finally_error_label)
4146 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4147 for var in Naming.exc_vars:
4148 code.putln("Py_XDECREF(%s);" % var)
4149 code.putln("}")
4150 code.put_goto(old_error_label)
4151 code.put_label(over_label)
4152 code.error_label = old_error_label
4153 if cases_used:
4154 code.putln(
4155 "switch (__pyx_why) {")
4156 for i in cases_used:
4157 old_label = old_labels[i]
4158 if old_label == old_error_label and self.preserve_exception:
4159 self.put_error_uncatcher(code, i+1, old_error_label)
4160 else:
4161 code.use_label(old_label)
4162 code.putln(
4163 "case %s: goto %s;" % (
4164 i+1,
4165 old_label))
4166 code.putln(
4167 "}")
4168 code.putln(
4169 "}")
4171 def put_error_catcher(self, code, error_label, i, catch_label):
4172 code.globalstate.use_utility_code(restore_exception_utility_code)
4173 code.putln(
4174 "%s: {" %
4175 error_label)
4176 code.putln(
4177 "__pyx_why = %s;" %
4178 i)
4179 code.put_var_xdecrefs_clear(self.cleanup_list)
4180 code.putln(
4181 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4182 Naming.exc_vars)
4183 code.putln(
4184 "%s = %s;" % (
4185 Naming.exc_lineno_name, Naming.lineno_cname))
4186 #code.putln(
4187 # "goto %s;" %
4188 # catch_label)
4189 code.put_goto(catch_label)
4190 code.putln(
4191 "}")
4193 def put_error_uncatcher(self, code, i, error_label):
4194 code.globalstate.use_utility_code(restore_exception_utility_code)
4195 code.putln(
4196 "case %s: {" %
4197 i)
4198 code.putln(
4199 "__Pyx_ErrRestore(%s, %s, %s);" %
4200 Naming.exc_vars)
4201 code.putln(
4202 "%s = %s;" % (
4203 Naming.lineno_cname, Naming.exc_lineno_name))
4204 for var in Naming.exc_vars:
4205 code.putln(
4206 "%s = 0;" %
4207 var)
4208 code.put_goto(error_label)
4209 code.putln(
4210 "}")
4212 def annotate(self, code):
4213 self.body.annotate(code)
4214 self.finally_clause.annotate(code)
4217 class GILStatNode(TryFinallyStatNode):
4218 # 'with gil' or 'with nogil' statement
4220 # state string 'gil' or 'nogil'
4222 child_attrs = []
4224 preserve_exception = 0
4226 def __init__(self, pos, state, body):
4227 self.state = state
4228 TryFinallyStatNode.__init__(self, pos,
4229 body = body,
4230 finally_clause = GILExitNode(pos, state = state))
4232 def analyse_expressions(self, env):
4233 was_nogil = env.nogil
4234 env.nogil = 1
4235 TryFinallyStatNode.analyse_expressions(self, env)
4236 env.nogil = was_nogil
4238 def gil_check(self, env):
4239 pass
4241 def generate_execution_code(self, code):
4242 code.putln("/*with %s:*/ {" % self.state)
4243 if self.state == 'gil':
4244 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
4245 else:
4246 code.putln("PyThreadState *_save;")
4247 code.putln("Py_UNBLOCK_THREADS")
4248 TryFinallyStatNode.generate_execution_code(self, code)
4249 code.putln("}")
4252 class GILExitNode(StatNode):
4253 # Used as the 'finally' block in a GILStatNode
4255 # state string 'gil' or 'nogil'
4257 child_attrs = []
4259 def analyse_expressions(self, env):
4260 pass
4262 def generate_execution_code(self, code):
4263 if self.state == 'gil':
4264 code.putln("PyGILState_Release();")
4265 else:
4266 code.putln("Py_BLOCK_THREADS")
4269 class CImportStatNode(StatNode):
4270 # cimport statement
4272 # module_name string Qualified name of module being imported
4273 # as_name string or None Name specified in "as" clause, if any
4275 child_attrs = []
4277 def analyse_declarations(self, env):
4278 if not env.is_module_scope:
4279 error(self.pos, "cimport only allowed at module level")
4280 return
4281 module_scope = env.find_module(self.module_name, self.pos)
4282 if "." in self.module_name:
4283 names = [EncodedString(name) for name in self.module_name.split(".")]
4284 top_name = names[0]
4285 top_module_scope = env.context.find_submodule(top_name)
4286 module_scope = top_module_scope
4287 for name in names[1:]:
4288 submodule_scope = module_scope.find_submodule(name)
4289 module_scope.declare_module(name, submodule_scope, self.pos)
4290 module_scope = submodule_scope
4291 if self.as_name:
4292 env.declare_module(self.as_name, module_scope, self.pos)
4293 else:
4294 env.declare_module(top_name, top_module_scope, self.pos)
4295 else:
4296 name = self.as_name or self.module_name
4297 env.declare_module(name, module_scope, self.pos)
4299 def analyse_expressions(self, env):
4300 pass
4302 def generate_execution_code(self, code):
4303 pass
4306 class FromCImportStatNode(StatNode):
4307 # from ... cimport statement
4309 # module_name string Qualified name of module
4310 # imported_names [(pos, name, as_name, kind)] Names to be imported
4312 child_attrs = []
4314 def analyse_declarations(self, env):
4315 if not env.is_module_scope:
4316 error(self.pos, "cimport only allowed at module level")
4317 return
4318 module_scope = env.find_module(self.module_name, self.pos)
4319 env.add_imported_module(module_scope)
4320 for pos, name, as_name, kind in self.imported_names:
4321 if name == "*":
4322 for local_name, entry in module_scope.entries.items():
4323 env.add_imported_entry(local_name, entry, pos)
4324 else:
4325 entry = module_scope.lookup(name)
4326 if entry:
4327 if kind and not self.declaration_matches(entry, kind):
4328 entry.redeclared(pos)
4329 else:
4330 if kind == 'struct' or kind == 'union':
4331 entry = module_scope.declare_struct_or_union(name,
4332 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4333 elif kind == 'class':
4334 entry = module_scope.declare_c_class(name, pos = pos,
4335 module_name = self.module_name)
4336 else:
4337 error(pos, "Name '%s' not declared in module '%s'"
4338 % (name, self.module_name))
4340 if entry:
4341 local_name = as_name or name
4342 env.add_imported_entry(local_name, entry, pos)
4344 def declaration_matches(self, entry, kind):
4345 if not entry.is_type:
4346 return 0
4347 type = entry.type
4348 if kind == 'class':
4349 if not type.is_extension_type:
4350 return 0
4351 else:
4352 if not type.is_struct_or_union:
4353 return 0
4354 if kind <> type.kind:
4355 return 0
4356 return 1
4358 def analyse_expressions(self, env):
4359 pass
4361 def generate_execution_code(self, code):
4362 pass
4365 class FromImportStatNode(StatNode):
4366 # from ... import statement
4368 # module ImportNode
4369 # items [(string, NameNode)]
4370 # interned_items [(string, NameNode)]
4371 # item PyTempNode used internally
4372 # import_star boolean used internally
4374 child_attrs = ["module"]
4375 import_star = 0
4377 def analyse_declarations(self, env):
4378 for name, target in self.items:
4379 if name == "*":
4380 if not env.is_module_scope:
4381 error(self.pos, "import * only allowed at module level")
4382 return
4383 env.has_import_star = 1
4384 self.import_star = 1
4385 else:
4386 target.analyse_target_declaration(env)
4388 def analyse_expressions(self, env):
4389 import ExprNodes
4390 self.module.analyse_expressions(env)
4391 self.item = ExprNodes.PyTempNode(self.pos, env)
4392 self.item.allocate_temp(env)
4393 self.interned_items = []
4394 for name, target in self.items:
4395 if name == '*':
4396 for _, entry in env.entries.items():
4397 if not entry.is_type and entry.type.is_extension_type:
4398 env.use_utility_code(ExprNodes.type_test_utility_code)
4399 break
4400 else:
4401 self.interned_items.append(
4402 (env.intern_identifier(name), target))
4403 target.analyse_target_expression(env, None)
4404 #target.release_target_temp(env) # was release_temp ?!?
4405 self.module.release_temp(env)
4406 self.item.release_temp(env)
4408 def generate_execution_code(self, code):
4409 self.module.generate_evaluation_code(code)
4410 if self.import_star:
4411 code.putln(
4412 'if (%s(%s) < 0) %s;' % (
4413 Naming.import_star,
4414 self.module.py_result(),
4415 code.error_goto(self.pos)))
4416 for cname, target in self.interned_items:
4417 code.putln(
4418 '%s = PyObject_GetAttr(%s, %s); %s' % (
4419 self.item.result(),
4420 self.module.py_result(),
4421 cname,
4422 code.error_goto_if_null(self.item.result(), self.pos)))
4423 target.generate_assignment_code(self.item, code)
4424 self.module.generate_disposal_code(code)
4428 #------------------------------------------------------------------------------------
4430 # Runtime support code
4432 #------------------------------------------------------------------------------------
4434 utility_function_predeclarations = \
4435 """
4436 #ifdef __GNUC__
4437 #define INLINE __inline__
4438 #elif _WIN32
4439 #define INLINE __inline
4440 #else
4441 #define INLINE
4442 #endif
4444 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4446 """ + """
4448 static int %(skip_dispatch_cname)s = 0;
4450 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4452 if Options.gcc_branch_hints:
4453 branch_prediction_macros = \
4454 """
4455 #ifdef __GNUC__
4456 /* Test for GCC > 2.95 */
4457 #if __GNUC__ > 2 || \
4458 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4459 #define likely(x) __builtin_expect(!!(x), 1)
4460 #define unlikely(x) __builtin_expect(!!(x), 0)
4461 #else /* __GNUC__ > 2 ... */
4462 #define likely(x) (x)
4463 #define unlikely(x) (x)
4464 #endif /* __GNUC__ > 2 ... */
4465 #else /* __GNUC__ */
4466 #define likely(x) (x)
4467 #define unlikely(x) (x)
4468 #endif /* __GNUC__ */
4469 """
4470 else:
4471 branch_prediction_macros = \
4472 """
4473 #define likely(x) (x)
4474 #define unlikely(x) (x)
4475 """
4477 #get_name_predeclaration = \
4478 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4480 #get_name_interned_predeclaration = \
4481 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4483 #------------------------------------------------------------------------------------
4485 printing_utility_code = UtilityCode(
4486 proto = """
4487 static int __Pyx_Print(PyObject *, int); /*proto*/
4488 #if PY_MAJOR_VERSION >= 3
4489 static PyObject* %s = 0;
4490 static PyObject* %s = 0;
4491 #endif
4492 """ % (Naming.print_function, Naming.print_function_kwargs),
4493 impl = r"""
4494 #if PY_MAJOR_VERSION < 3
4495 static PyObject *__Pyx_GetStdout(void) {
4496 PyObject *f = PySys_GetObject("stdout");
4497 if (!f) {
4498 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4500 return f;
4503 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4504 PyObject *f;
4505 PyObject* v;
4506 int i;
4508 if (!(f = __Pyx_GetStdout()))
4509 return -1;
4510 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4511 if (PyFile_SoftSpace(f, 1)) {
4512 if (PyFile_WriteString(" ", f) < 0)
4513 return -1;
4515 v = PyTuple_GET_ITEM(arg_tuple, i);
4516 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4517 return -1;
4518 if (PyString_Check(v)) {
4519 char *s = PyString_AsString(v);
4520 Py_ssize_t len = PyString_Size(v);
4521 if (len > 0 &&
4522 isspace(Py_CHARMASK(s[len-1])) &&
4523 s[len-1] != ' ')
4524 PyFile_SoftSpace(f, 0);
4527 if (newline) {
4528 if (PyFile_WriteString("\n", f) < 0)
4529 return -1;
4530 PyFile_SoftSpace(f, 0);
4532 return 0;
4535 #else /* Python 3 has a print function */
4536 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4537 PyObject* kwargs = 0;
4538 PyObject* result = 0;
4539 PyObject* end_string;
4540 if (!%(PRINT_FUNCTION)s) {
4541 %(PRINT_FUNCTION)s = PyObject_GetAttrString(%(BUILTINS)s, "print");
4542 if (!%(PRINT_FUNCTION)s)
4543 return -1;
4545 if (!newline) {
4546 if (!%(PRINT_KWARGS)s) {
4547 %(PRINT_KWARGS)s = PyDict_New();
4548 if (!%(PRINT_KWARGS)s)
4549 return -1;
4550 end_string = PyUnicode_FromStringAndSize(" ", 1);
4551 if (!end_string)
4552 return -1;
4553 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4554 Py_DECREF(end_string);
4555 return -1;
4557 Py_DECREF(end_string);
4559 kwargs = %(PRINT_KWARGS)s;
4561 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4562 if (!result)
4563 return -1;
4564 Py_DECREF(result);
4565 return 0;
4567 #endif
4568 """ % {'BUILTINS' : Naming.builtins_cname,
4569 'PRINT_FUNCTION' : Naming.print_function,
4570 'PRINT_KWARGS' : Naming.print_function_kwargs}
4573 #------------------------------------------------------------------------------------
4575 # The following function is based on do_raise() from ceval.c.
4577 raise_utility_code = UtilityCode(
4578 proto = """
4579 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4580 """,
4581 impl = """
4582 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4583 Py_XINCREF(type);
4584 Py_XINCREF(value);
4585 Py_XINCREF(tb);
4586 /* First, check the traceback argument, replacing None with NULL. */
4587 if (tb == Py_None) {
4588 Py_DECREF(tb);
4589 tb = 0;
4591 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4592 PyErr_SetString(PyExc_TypeError,
4593 "raise: arg 3 must be a traceback or None");
4594 goto raise_error;
4596 /* Next, replace a missing value with None */
4597 if (value == NULL) {
4598 value = Py_None;
4599 Py_INCREF(value);
4601 #if PY_VERSION_HEX < 0x02050000
4602 if (!PyClass_Check(type))
4603 #else
4604 if (!PyType_Check(type))
4605 #endif
4607 /* Raising an instance. The value should be a dummy. */
4608 if (value != Py_None) {
4609 PyErr_SetString(PyExc_TypeError,
4610 "instance exception may not have a separate value");
4611 goto raise_error;
4613 /* Normalize to raise <class>, <instance> */
4614 Py_DECREF(value);
4615 value = type;
4616 #if PY_VERSION_HEX < 0x02050000
4617 if (PyInstance_Check(type)) {
4618 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4619 Py_INCREF(type);
4621 else {
4622 type = 0;
4623 PyErr_SetString(PyExc_TypeError,
4624 "raise: exception must be an old-style class or instance");
4625 goto raise_error;
4627 #else
4628 type = (PyObject*) Py_TYPE(type);
4629 Py_INCREF(type);
4630 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4631 PyErr_SetString(PyExc_TypeError,
4632 "raise: exception class must be a subclass of BaseException");
4633 goto raise_error;
4635 #endif
4637 __Pyx_ErrRestore(type, value, tb);
4638 return;
4639 raise_error:
4640 Py_XDECREF(value);
4641 Py_XDECREF(type);
4642 Py_XDECREF(tb);
4643 return;
4645 """)
4647 #------------------------------------------------------------------------------------
4649 reraise_utility_code = UtilityCode(
4650 proto = """
4651 static void __Pyx_ReRaise(void); /*proto*/
4652 """,
4653 impl = """
4654 static void __Pyx_ReRaise(void) {
4655 PyThreadState *tstate = PyThreadState_Get();
4656 PyObject *type = tstate->exc_type;
4657 PyObject *value = tstate->exc_value;
4658 PyObject *tb = tstate->exc_traceback;
4659 Py_XINCREF(type);
4660 Py_XINCREF(value);
4661 Py_XINCREF(tb);
4662 __Pyx_ErrRestore(type, value, tb);
4664 """)
4666 #------------------------------------------------------------------------------------
4668 arg_type_test_utility_code = UtilityCode(
4669 proto = """
4670 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4671 const char *name, int exact); /*proto*/
4672 """,
4673 impl = """
4674 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4675 const char *name, int exact)
4677 if (!type) {
4678 PyErr_Format(PyExc_SystemError, "Missing type object");
4679 return 0;
4681 if (none_allowed && obj == Py_None) return 1;
4682 else if (exact) {
4683 if (Py_TYPE(obj) == type) return 1;
4685 else {
4686 if (PyObject_TypeCheck(obj, type)) return 1;
4688 PyErr_Format(PyExc_TypeError,
4689 "Argument '%s' has incorrect type (expected %s, got %s)",
4690 name, type->tp_name, Py_TYPE(obj)->tp_name);
4691 return 0;
4693 """)
4695 #------------------------------------------------------------------------------------
4697 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
4698 # many or too few positional arguments were found. This handles
4699 # Py_ssize_t formatting correctly.
4701 raise_argtuple_invalid_utility_code = UtilityCode(
4702 proto = """
4703 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
4704 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
4705 """,
4706 impl = """
4707 static void __Pyx_RaiseArgtupleInvalid(
4708 const char* func_name,
4709 int exact,
4710 Py_ssize_t num_min,
4711 Py_ssize_t num_max,
4712 Py_ssize_t num_found)
4714 Py_ssize_t num_expected;
4715 const char *number, *more_or_less;
4717 if (num_found < num_min) {
4718 num_expected = num_min;
4719 more_or_less = "at least";
4720 } else {
4721 num_expected = num_max;
4722 more_or_less = "at most";
4724 if (exact) {
4725 more_or_less = "exactly";
4727 number = (num_expected == 1) ? "" : "s";
4728 PyErr_Format(PyExc_TypeError,
4729 #if PY_VERSION_HEX < 0x02050000
4730 "%s() takes %s %d positional argument%s (%d given)",
4731 #else
4732 "%s() takes %s %zd positional argument%s (%zd given)",
4733 #endif
4734 func_name, more_or_less, num_expected, number, num_found);
4736 """)
4738 raise_keyword_required_utility_code = UtilityCode(
4739 proto = """
4740 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
4741 """,
4742 impl = """
4743 static INLINE void __Pyx_RaiseKeywordRequired(
4744 const char* func_name,
4745 PyObject* kw_name)
4747 PyErr_Format(PyExc_TypeError,
4748 #if PY_MAJOR_VERSION >= 3
4749 "%s() needs keyword-only argument %U", func_name, kw_name);
4750 #else
4751 "%s() needs keyword-only argument %s", func_name,
4752 PyString_AS_STRING(kw_name));
4753 #endif
4755 """)
4757 raise_double_keywords_utility_code = UtilityCode(
4758 proto = """
4759 static void __Pyx_RaiseDoubleKeywordsError(
4760 const char* func_name, PyObject* kw_name); /*proto*/
4761 """,
4762 impl = """
4763 static void __Pyx_RaiseDoubleKeywordsError(
4764 const char* func_name,
4765 PyObject* kw_name)
4767 PyErr_Format(PyExc_TypeError,
4768 #if PY_MAJOR_VERSION >= 3
4769 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
4770 #else
4771 "%s() got multiple values for keyword argument '%s'", func_name,
4772 PyString_AS_STRING(kw_name));
4773 #endif
4775 """)
4777 #------------------------------------------------------------------------------------
4779 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
4780 # were passed to a function, or if any keywords were passed to a
4781 # function that does not accept them.
4783 keyword_string_check_utility_code = UtilityCode(
4784 proto = """
4785 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
4786 const char* function_name, int kw_allowed); /*proto*/
4787 """,
4788 impl = """
4789 static INLINE int __Pyx_CheckKeywordStrings(
4790 PyObject *kwdict,
4791 const char* function_name,
4792 int kw_allowed)
4794 PyObject* key = 0;
4795 Py_ssize_t pos = 0;
4796 while (PyDict_Next(kwdict, &pos, &key, 0)) {
4797 #if PY_MAJOR_VERSION < 3
4798 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
4799 #else
4800 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
4801 #endif
4802 goto invalid_keyword_type;
4804 if ((!kw_allowed) && unlikely(key))
4805 goto invalid_keyword;
4806 return 1;
4807 invalid_keyword_type:
4808 PyErr_Format(PyExc_TypeError,
4809 "%s() keywords must be strings", function_name);
4810 return 0;
4811 invalid_keyword:
4812 PyErr_Format(PyExc_TypeError,
4813 #if PY_MAJOR_VERSION < 3
4814 "%s() got an unexpected keyword argument '%s'",
4815 function_name, PyString_AsString(key));
4816 #else
4817 "%s() got an unexpected keyword argument '%U'",
4818 function_name, key);
4819 #endif
4820 return 0;
4822 """)
4824 #------------------------------------------------------------------------------------
4826 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
4827 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
4828 # keywords will raise an invalid keyword error.
4830 # Three kinds of errors are checked: 1) non-string keywords, 2)
4831 # unexpected keywords and 3) overlap with positional arguments.
4833 # If num_posargs is greater 0, it denotes the number of positional
4834 # arguments that were passed and that must therefore not appear
4835 # amongst the keywords as well.
4837 # This method does not check for required keyword arguments.
4840 parse_keywords_utility_code = UtilityCode(
4841 proto = """
4842 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
4843 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
4844 const char* function_name); /*proto*/
4845 """,
4846 impl = """
4847 static int __Pyx_ParseOptionalKeywords(
4848 PyObject *kwds,
4849 PyObject **argnames[],
4850 PyObject *kwds2,
4851 PyObject *values[],
4852 Py_ssize_t num_pos_args,
4853 const char* function_name)
4855 PyObject *key = 0, *value = 0;
4856 Py_ssize_t pos = 0;
4857 PyObject*** name;
4858 PyObject*** first_kw_arg = argnames + num_pos_args;
4860 while (PyDict_Next(kwds, &pos, &key, &value)) {
4861 #if PY_MAJOR_VERSION < 3
4862 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
4863 #else
4864 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
4865 #endif
4866 goto invalid_keyword_type;
4867 } else {
4868 name = argnames;
4869 while (*name && (**name != key)) name++;
4870 if (*name) {
4871 if (name < first_kw_arg) goto arg_passed_twice;
4872 values[name-argnames] = value;
4873 } else {
4874 for (name = first_kw_arg; *name; name++) {
4875 #if PY_MAJOR_VERSION >= 3
4876 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
4877 PyUnicode_Compare(**name, key) == 0) break;
4878 #else
4879 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
4880 strcmp(PyString_AS_STRING(**name),
4881 PyString_AS_STRING(key)) == 0) break;
4882 #endif
4884 if (*name) {
4885 values[name-argnames] = value;
4886 } else {
4887 /* unexpected keyword found */
4888 for (name=argnames; name != first_kw_arg; name++) {
4889 if (**name == key) goto arg_passed_twice;
4890 #if PY_MAJOR_VERSION >= 3
4891 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
4892 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
4893 #else
4894 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
4895 strcmp(PyString_AS_STRING(**name),
4896 PyString_AS_STRING(key)) == 0) goto arg_passed_twice;
4897 #endif
4899 if (kwds2) {
4900 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
4901 } else {
4902 goto invalid_keyword;
4908 return 0;
4909 arg_passed_twice:
4910 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
4911 goto bad;
4912 invalid_keyword_type:
4913 PyErr_Format(PyExc_TypeError,
4914 "%s() keywords must be strings", function_name);
4915 goto bad;
4916 invalid_keyword:
4917 PyErr_Format(PyExc_TypeError,
4918 #if PY_MAJOR_VERSION < 3
4919 "%s() got an unexpected keyword argument '%s'",
4920 function_name, PyString_AsString(key));
4921 #else
4922 "%s() got an unexpected keyword argument '%U'",
4923 function_name, key);
4924 #endif
4925 bad:
4926 return -1;
4928 """)
4930 #------------------------------------------------------------------------------------
4932 unraisable_exception_utility_code = UtilityCode(
4933 proto = """
4934 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
4935 """,
4936 impl = """
4937 static void __Pyx_WriteUnraisable(const char *name) {
4938 PyObject *old_exc, *old_val, *old_tb;
4939 PyObject *ctx;
4940 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
4941 #if PY_MAJOR_VERSION < 3
4942 ctx = PyString_FromString(name);
4943 #else
4944 ctx = PyUnicode_FromString(name);
4945 #endif
4946 __Pyx_ErrRestore(old_exc, old_val, old_tb);
4947 if (!ctx) {
4948 PyErr_WriteUnraisable(Py_None);
4949 } else {
4950 PyErr_WriteUnraisable(ctx);
4951 Py_DECREF(ctx);
4954 """)
4956 #------------------------------------------------------------------------------------
4958 traceback_utility_code = UtilityCode(
4959 proto = """
4960 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
4961 """,
4962 impl = """
4963 #include "compile.h"
4964 #include "frameobject.h"
4965 #include "traceback.h"
4967 static void __Pyx_AddTraceback(const char *funcname) {
4968 PyObject *py_srcfile = 0;
4969 PyObject *py_funcname = 0;
4970 PyObject *py_globals = 0;
4971 PyObject *empty_string = 0;
4972 PyCodeObject *py_code = 0;
4973 PyFrameObject *py_frame = 0;
4975 #if PY_MAJOR_VERSION < 3
4976 py_srcfile = PyString_FromString(%(FILENAME)s);
4977 #else
4978 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
4979 #endif
4980 if (!py_srcfile) goto bad;
4981 if (%(CLINENO)s) {
4982 #if PY_MAJOR_VERSION < 3
4983 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
4984 #else
4985 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
4986 #endif
4988 else {
4989 #if PY_MAJOR_VERSION < 3
4990 py_funcname = PyString_FromString(funcname);
4991 #else
4992 py_funcname = PyUnicode_FromString(funcname);
4993 #endif
4995 if (!py_funcname) goto bad;
4996 py_globals = PyModule_GetDict(%(GLOBALS)s);
4997 if (!py_globals) goto bad;
4998 #if PY_MAJOR_VERSION < 3
4999 empty_string = PyString_FromStringAndSize("", 0);
5000 #else
5001 empty_string = PyBytes_FromStringAndSize("", 0);
5002 #endif
5003 if (!empty_string) goto bad;
5004 py_code = PyCode_New(
5005 0, /*int argcount,*/
5006 #if PY_MAJOR_VERSION >= 3
5007 0, /*int kwonlyargcount,*/
5008 #endif
5009 0, /*int nlocals,*/
5010 0, /*int stacksize,*/
5011 0, /*int flags,*/
5012 empty_string, /*PyObject *code,*/
5013 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5014 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5015 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5016 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5017 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5018 py_srcfile, /*PyObject *filename,*/
5019 py_funcname, /*PyObject *name,*/
5020 %(LINENO)s, /*int firstlineno,*/
5021 empty_string /*PyObject *lnotab*/
5022 );
5023 if (!py_code) goto bad;
5024 py_frame = PyFrame_New(
5025 PyThreadState_GET(), /*PyThreadState *tstate,*/
5026 py_code, /*PyCodeObject *code,*/
5027 py_globals, /*PyObject *globals,*/
5028 0 /*PyObject *locals*/
5029 );
5030 if (!py_frame) goto bad;
5031 py_frame->f_lineno = %(LINENO)s;
5032 PyTraceBack_Here(py_frame);
5033 bad:
5034 Py_XDECREF(py_srcfile);
5035 Py_XDECREF(py_funcname);
5036 Py_XDECREF(empty_string);
5037 Py_XDECREF(py_code);
5038 Py_XDECREF(py_frame);
5040 """ % {
5041 'FILENAME': Naming.filename_cname,
5042 'LINENO': Naming.lineno_cname,
5043 'CFILENAME': Naming.cfilenm_cname,
5044 'CLINENO': Naming.clineno_cname,
5045 'GLOBALS': Naming.module_cname,
5046 'EMPTY_TUPLE' : Naming.empty_tuple,
5047 })
5049 restore_exception_utility_code = UtilityCode(
5050 proto = """
5051 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5052 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5053 """,
5054 impl = """
5055 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5056 PyObject *tmp_type, *tmp_value, *tmp_tb;
5057 PyThreadState *tstate = PyThreadState_GET();
5059 tmp_type = tstate->curexc_type;
5060 tmp_value = tstate->curexc_value;
5061 tmp_tb = tstate->curexc_traceback;
5062 tstate->curexc_type = type;
5063 tstate->curexc_value = value;
5064 tstate->curexc_traceback = tb;
5065 Py_XDECREF(tmp_type);
5066 Py_XDECREF(tmp_value);
5067 Py_XDECREF(tmp_tb);
5070 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5071 PyThreadState *tstate = PyThreadState_GET();
5072 *type = tstate->curexc_type;
5073 *value = tstate->curexc_value;
5074 *tb = tstate->curexc_traceback;
5076 tstate->curexc_type = 0;
5077 tstate->curexc_value = 0;
5078 tstate->curexc_traceback = 0;
5081 """)
5083 #------------------------------------------------------------------------------------
5085 set_vtable_utility_code = UtilityCode(
5086 proto = """
5087 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5088 """,
5089 impl = """
5090 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5091 PyObject *pycobj = 0;
5092 int result;
5094 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5095 if (!pycobj)
5096 goto bad;
5097 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5098 goto bad;
5099 result = 0;
5100 goto done;
5102 bad:
5103 result = -1;
5104 done:
5105 Py_XDECREF(pycobj);
5106 return result;
5108 """)
5110 #------------------------------------------------------------------------------------
5112 get_vtable_utility_code = UtilityCode(
5113 proto = """
5114 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5115 """,
5116 impl = r"""
5117 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5118 int result;
5119 PyObject *pycobj;
5121 pycobj = PyMapping_GetItemString(dict, "__pyx_vtable__");
5122 if (!pycobj)
5123 goto bad;
5124 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5125 if (!*(void **)vtabptr)
5126 goto bad;
5127 result = 0;
5128 goto done;
5130 bad:
5131 result = -1;
5132 done:
5133 Py_XDECREF(pycobj);
5134 return result;
5136 """)
5138 #------------------------------------------------------------------------------------
5140 init_string_tab_utility_code = UtilityCode(
5141 proto = """
5142 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5143 """,
5144 impl = """
5145 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5146 while (t->p) {
5147 #if PY_MAJOR_VERSION < 3
5148 if (t->is_unicode && (!t->is_identifier)) {
5149 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5150 } else if (t->intern) {
5151 *t->p = PyString_InternFromString(t->s);
5152 } else {
5153 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5155 #else /* Python 3+ has unicode identifiers */
5156 if (t->is_identifier || (t->is_unicode && t->intern)) {
5157 *t->p = PyUnicode_InternFromString(t->s);
5158 } else if (t->is_unicode) {
5159 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5160 } else {
5161 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5163 #endif
5164 if (!*t->p)
5165 return -1;
5166 ++t;
5168 return 0;
5170 """)
5172 #------------------------------------------------------------------------------------
5174 get_exception_utility_code = UtilityCode(
5175 proto = """
5176 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5177 """,
5178 impl = """
5179 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5180 PyObject *tmp_type, *tmp_value, *tmp_tb;
5181 PyThreadState *tstate = PyThreadState_GET();
5182 __Pyx_ErrFetch(type, value, tb);
5183 PyErr_NormalizeException(type, value, tb);
5184 if (PyErr_Occurred())
5185 goto bad;
5186 Py_INCREF(*type);
5187 Py_INCREF(*value);
5188 Py_INCREF(*tb);
5189 tmp_type = tstate->exc_type;
5190 tmp_value = tstate->exc_value;
5191 tmp_tb = tstate->exc_traceback;
5192 tstate->exc_type = *type;
5193 tstate->exc_value = *value;
5194 tstate->exc_traceback = *tb;
5195 /* Make sure tstate is in a consistent state when we XDECREF
5196 these objects (XDECREF may run arbitrary code). */
5197 Py_XDECREF(tmp_type);
5198 Py_XDECREF(tmp_value);
5199 Py_XDECREF(tmp_tb);
5200 return 0;
5201 bad:
5202 Py_XDECREF(*type);
5203 Py_XDECREF(*value);
5204 Py_XDECREF(*tb);
5205 return -1;
5208 """)
5210 #------------------------------------------------------------------------------------
5212 reset_exception_utility_code = UtilityCode(
5213 proto = """
5214 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5215 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5216 """,
5217 impl = """
5218 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5219 PyThreadState *tstate = PyThreadState_GET();
5220 *type = tstate->exc_type;
5221 *value = tstate->exc_value;
5222 *tb = tstate->exc_traceback;
5223 Py_XINCREF(*type);
5224 Py_XINCREF(*value);
5225 Py_XINCREF(*tb);
5228 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5229 PyObject *tmp_type, *tmp_value, *tmp_tb;
5230 PyThreadState *tstate = PyThreadState_GET();
5231 tmp_type = tstate->exc_type;
5232 tmp_value = tstate->exc_value;
5233 tmp_tb = tstate->exc_traceback;
5234 tstate->exc_type = type;
5235 tstate->exc_value = value;
5236 tstate->exc_traceback = tb;
5237 Py_XDECREF(tmp_type);
5238 Py_XDECREF(tmp_value);
5239 Py_XDECREF(tmp_tb);
5241 """)
5243 #------------------------------------------------------------------------------------