Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 1880:3aac44b1f28a

Fix bad self argument crash in cpdef methods (#165)
author Robert Bradshaw <robertwb@math.washington.edu>
date Wed Mar 25 15:00:06 2009 -0700 (3 years ago)
parents 0bd3bfd487a5
children dc7359d237b9
line source
1 #
2 # Pyrex - Parse tree nodes
3 #
5 import sys, os, time, copy
7 import Code
8 import Builtin
9 from Errors import error, warning, InternalError
10 import Naming
11 import PyrexTypes
12 import TypeSlots
13 from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType
14 from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
15 StructOrUnionScope, PyClassScope, CClassScope
16 from Cython.Utils import open_new_file, replace_suffix, UtilityCode
17 from StringEncoding import EncodedString, escape_byte_string, split_docstring
18 import Options
19 import ControlFlow
20 import DebugFlags
22 from DebugFlags import debug_disposal_code
24 absolute_path_length = 0
26 def relative_position(pos):
27 """
28 We embed the relative filename in the generated C file, since we
29 don't want to have to regnerate and compile all the source code
30 whenever the Python install directory moves (which could happen,
31 e.g,. when distributing binaries.)
33 INPUT:
34 a position tuple -- (absolute filename, line number column position)
36 OUTPUT:
37 relative filename
38 line number
40 AUTHOR: William Stein
41 """
42 global absolute_path_length
43 if absolute_path_length==0:
44 absolute_path_length = len(os.path.abspath(os.getcwd()))
45 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
47 def embed_position(pos, docstring):
48 if not Options.embed_pos_in_docstring:
49 return docstring
50 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
51 if docstring is None:
52 # unicode string
53 return EncodedString(pos_line)
55 # make sure we can encode the filename in the docstring encoding
56 # otherwise make the docstring a unicode string
57 encoding = docstring.encoding
58 if encoding is not None:
59 try:
60 encoded_bytes = pos_line.encode(encoding)
61 except UnicodeEncodeError:
62 encoding = None
64 if not docstring:
65 # reuse the string encoding of the original docstring
66 doc = EncodedString(pos_line)
67 else:
68 doc = EncodedString(pos_line + u'\n' + docstring)
69 doc.encoding = encoding
70 return doc
73 from Code import CCodeWriter
74 from types import FunctionType
76 def write_func_call(func):
77 def f(*args, **kwds):
78 if len(args) > 1 and isinstance(args[1], CCodeWriter):
79 # here we annotate the code with this function call
80 # but only if new code is generated
81 node, code = args[:2]
82 marker = ' /* %s -> %s.%s %s */' % (
83 ' ' * code.call_level,
84 node.__class__.__name__,
85 func.__name__,
86 node.pos[1:])
87 pristine = code.buffer.stream.tell()
88 code.putln(marker)
89 start = code.buffer.stream.tell()
90 code.call_level += 4
91 res = func(*args, **kwds)
92 code.call_level -= 4
93 if start == code.buffer.stream.tell():
94 code.buffer.stream.seek(pristine)
95 else:
96 marker = marker.replace('->', '<-')
97 code.putln(marker)
98 return res
99 else:
100 return func(*args, **kwds)
101 return f
103 class VerboseCodeWriter(type):
104 # Set this as a metaclass to trace function calls in code.
105 # This slows down code generation and makes much larger files.
106 def __new__(cls, name, bases, attrs):
107 attrs = dict(attrs)
108 for mname, m in attrs.items():
109 if isinstance(m, FunctionType):
110 attrs[mname] = write_func_call(m)
111 return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
114 class Node(object):
115 # pos (string, int, int) Source file position
116 # is_name boolean Is a NameNode
117 # is_literal boolean Is a ConstNode
119 if DebugFlags.debug_trace_code_generation:
120 __metaclass__ = VerboseCodeWriter
122 is_name = 0
123 is_literal = 0
124 temps = None
126 # All descandants should set child_attrs to a list of the attributes
127 # containing nodes considered "children" in the tree. Each such attribute
128 # can either contain a single node or a list of nodes. See Visitor.py.
129 child_attrs = None
131 def __init__(self, pos, **kw):
132 self.pos = pos
133 self.__dict__.update(kw)
135 gil_message = "Operation"
137 def gil_check(self, env):
138 if env.nogil:
139 self.gil_error()
141 def gil_error(self):
142 error(self.pos, "%s not allowed without gil" % self.gil_message)
144 def clone_node(self):
145 """Clone the node. This is defined as a shallow copy, except for member lists
146 amongst the child attributes (from get_child_accessors) which are also
147 copied. Lists containing child nodes are thus seen as a way for the node
148 to hold multiple children directly; the list is not treated as a seperate
149 level in the tree."""
150 result = copy.copy(self)
151 for attrname in result.child_attrs:
152 value = getattr(result, attrname)
153 if isinstance(value, list):
154 setattr(result, attrname, [x for x in value])
155 return result
158 #
159 # There are 4 phases of parse tree processing, applied in order to
160 # all the statements in a given scope-block:
161 #
162 # (0) analyse_control_flow
163 # Create the control flow tree into which state can be asserted and
164 # queried.
165 #
166 # (1) analyse_declarations
167 # Make symbol table entries for all declarations at the current
168 # level, both explicit (def, cdef, etc.) and implicit (assignment
169 # to an otherwise undeclared name).
170 #
171 # (2) analyse_expressions
172 # Determine the result types of expressions and fill in the
173 # 'type' attribute of each ExprNode. Insert coercion nodes into the
174 # tree where needed to convert to and from Python objects.
175 # Allocate temporary locals for intermediate results. Fill
176 # in the 'result_code' attribute of each ExprNode with a C code
177 # fragment.
178 #
179 # (3) generate_code
180 # Emit C code for all declarations, statements and expressions.
181 # Recursively applies the 3 processing phases to the bodies of
182 # functions.
183 #
185 def analyse_control_flow(self, env):
186 pass
188 def analyse_declarations(self, env):
189 pass
191 def analyse_expressions(self, env):
192 raise InternalError("analyse_expressions not implemented for %s" % \
193 self.__class__.__name__)
195 def generate_code(self, code):
196 raise InternalError("generate_code not implemented for %s" % \
197 self.__class__.__name__)
199 def annotate(self, code):
200 # mro does the wrong thing
201 if isinstance(self, BlockNode):
202 self.body.annotate(code)
204 def end_pos(self):
205 try:
206 return self._end_pos
207 except AttributeError:
208 pos = self.pos
209 if not self.child_attrs:
210 self._end_pos = pos
211 return pos
212 for attr in self.child_attrs:
213 child = getattr(self, attr)
214 # Sometimes lists, sometimes nodes
215 if child is None:
216 pass
217 elif isinstance(child, list):
218 for c in child:
219 pos = max(pos, c.end_pos())
220 else:
221 pos = max(pos, child.end_pos())
222 self._end_pos = pos
223 return pos
225 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
226 if cutoff == 0:
227 return "<...nesting level cutoff...>"
228 if encountered is None:
229 encountered = set()
230 if id(self) in encountered:
231 return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
232 encountered.add(id(self))
234 def dump_child(x, level):
235 if isinstance(x, Node):
236 return x.dump(level, filter_out, cutoff-1, encountered)
237 elif isinstance(x, list):
238 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
239 else:
240 return repr(x)
243 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
244 if len(attrs) == 0:
245 return "<%s (%d)>" % (self.__class__.__name__, id(self))
246 else:
247 indent = " " * level
248 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
249 for key, value in attrs:
250 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
251 res += "%s>" % indent
252 return res
254 class CompilerDirectivesNode(Node):
255 """
256 Sets compiler directives for the children nodes
257 """
258 # directives {string:value} A dictionary holding the right value for
259 # *all* possible directives.
260 # body Node
261 child_attrs = ["body"]
263 def analyse_control_flow(self, env):
264 old = env.directives
265 env.directives = self.directives
266 self.body.analyse_control_flow(env)
267 env.directives = old
269 def analyse_declarations(self, env):
270 old = env.directives
271 env.directives = self.directives
272 self.body.analyse_declarations(env)
273 env.directives = old
275 def analyse_expressions(self, env):
276 old = env.directives
277 env.directives = self.directives
278 self.body.analyse_expressions(env)
279 env.directives = old
281 def generate_function_definitions(self, env, code):
282 env_old = env.directives
283 code_old = code.globalstate.directives
284 code.globalstate.directives = self.directives
285 self.body.generate_function_definitions(env, code)
286 env.directives = env_old
287 code.globalstate.directives = code_old
289 def generate_execution_code(self, code):
290 old = code.globalstate.directives
291 code.globalstate.directives = self.directives
292 self.body.generate_execution_code(code)
293 code.globalstate.directives = old
295 def annotate(self, code):
296 old = code.globalstate.directives
297 code.globalstate.directives = self.directives
298 self.body.annotate(code)
299 code.globalstate.directives = old
301 class BlockNode(object):
302 # Mixin class for nodes representing a declaration block.
304 def generate_const_definitions(self, env, code):
305 if env.const_entries:
306 for entry in env.const_entries:
307 if not entry.is_interned:
308 code.globalstate.add_const_definition(entry)
310 def generate_interned_string_decls(self, env, code):
311 entries = env.global_scope().new_interned_string_entries
312 if entries:
313 for entry in entries:
314 code.globalstate.add_interned_string_decl(entry)
315 del entries[:]
317 def generate_py_string_decls(self, env, code):
318 if env is None:
319 return # earlier error
320 entries = env.pystring_entries
321 if entries:
322 for entry in entries:
323 if not entry.is_interned:
324 code.globalstate.add_py_string_decl(entry)
326 def generate_interned_num_decls(self, env, code):
327 # Flush accumulated interned nums from the global scope
328 # and generate declarations for them.
329 genv = env.global_scope()
330 entries = genv.interned_nums
331 if entries:
332 for entry in entries:
333 code.globalstate.add_interned_num_decl(entry)
334 del entries[:]
336 def generate_cached_builtins_decls(self, env, code):
337 entries = env.global_scope().undeclared_cached_builtins
338 for entry in entries:
339 code.globalstate.add_cached_builtin_decl(entry)
340 del entries[:]
343 class StatListNode(Node):
344 # stats a list of StatNode
346 child_attrs = ["stats"]
348 def create_analysed(pos, env, *args, **kw):
349 node = StatListNode(pos, *args, **kw)
350 return node # No node-specific analysis necesarry
351 create_analysed = staticmethod(create_analysed)
353 def analyse_control_flow(self, env):
354 for stat in self.stats:
355 stat.analyse_control_flow(env)
357 def analyse_declarations(self, env):
358 #print "StatListNode.analyse_declarations" ###
359 for stat in self.stats:
360 stat.analyse_declarations(env)
362 def analyse_expressions(self, env):
363 #print "StatListNode.analyse_expressions" ###
364 for stat in self.stats:
365 stat.analyse_expressions(env)
367 def generate_function_definitions(self, env, code):
368 #print "StatListNode.generate_function_definitions" ###
369 for stat in self.stats:
370 stat.generate_function_definitions(env, code)
372 def generate_execution_code(self, code):
373 #print "StatListNode.generate_execution_code" ###
374 for stat in self.stats:
375 code.mark_pos(stat.pos)
376 stat.generate_execution_code(code)
378 def annotate(self, code):
379 for stat in self.stats:
380 stat.annotate(code)
383 class StatNode(Node):
384 #
385 # Code generation for statements is split into the following subphases:
386 #
387 # (1) generate_function_definitions
388 # Emit C code for the definitions of any structs,
389 # unions, enums and functions defined in the current
390 # scope-block.
391 #
392 # (2) generate_execution_code
393 # Emit C code for executable statements.
394 #
396 def generate_function_definitions(self, env, code):
397 pass
399 def generate_execution_code(self, code):
400 raise InternalError("generate_execution_code not implemented for %s" % \
401 self.__class__.__name__)
404 class CDefExternNode(StatNode):
405 # include_file string or None
406 # body StatNode
408 child_attrs = ["body"]
410 def analyse_declarations(self, env):
411 if self.include_file:
412 env.add_include_file(self.include_file)
413 old_cinclude_flag = env.in_cinclude
414 env.in_cinclude = 1
415 self.body.analyse_declarations(env)
416 env.in_cinclude = old_cinclude_flag
418 def analyse_expressions(self, env):
419 pass
421 def generate_execution_code(self, code):
422 pass
424 def annotate(self, code):
425 self.body.annotate(code)
428 class CDeclaratorNode(Node):
429 # Part of a C declaration.
430 #
431 # Processing during analyse_declarations phase:
432 #
433 # analyse
434 # Returns (name, type) pair where name is the
435 # CNameDeclaratorNode of the name being declared
436 # and type is the type it is being declared as.
437 #
438 # calling_convention string Calling convention of CFuncDeclaratorNode
439 # for which this is a base
441 child_attrs = []
443 calling_convention = ""
446 class CNameDeclaratorNode(CDeclaratorNode):
447 # name string The Pyrex name being declared
448 # cname string or None C name, if specified
449 # default ExprNode or None the value assigned on declaration
451 child_attrs = ['default']
453 default = None
455 def analyse(self, base_type, env, nonempty = 0):
456 if nonempty and self.name == '':
457 # May have mistaken the name for the type.
458 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
459 error(self.pos, "Missing argument name")
460 elif base_type.is_void:
461 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
462 else:
463 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
464 base_type = py_object_type
465 self.type = base_type
466 return self, base_type
468 class CPtrDeclaratorNode(CDeclaratorNode):
469 # base CDeclaratorNode
471 child_attrs = ["base"]
473 def analyse(self, base_type, env, nonempty = 0):
474 if base_type.is_pyobject:
475 error(self.pos,
476 "Pointer base type cannot be a Python object")
477 ptr_type = PyrexTypes.c_ptr_type(base_type)
478 return self.base.analyse(ptr_type, env, nonempty = nonempty)
480 class CArrayDeclaratorNode(CDeclaratorNode):
481 # base CDeclaratorNode
482 # dimension ExprNode
484 child_attrs = ["base", "dimension"]
486 def analyse(self, base_type, env, nonempty = 0):
487 if self.dimension:
488 self.dimension.analyse_const_expression(env)
489 if not self.dimension.type.is_int:
490 error(self.dimension.pos, "Array dimension not integer")
491 size = self.dimension.result()
492 try:
493 size = int(size)
494 except ValueError:
495 # runtime constant?
496 pass
497 else:
498 size = None
499 if not base_type.is_complete():
500 error(self.pos,
501 "Array element type '%s' is incomplete" % base_type)
502 if base_type.is_pyobject:
503 error(self.pos,
504 "Array element cannot be a Python object")
505 if base_type.is_cfunction:
506 error(self.pos,
507 "Array element cannot be a function")
508 array_type = PyrexTypes.c_array_type(base_type, size)
509 return self.base.analyse(array_type, env, nonempty = nonempty)
512 class CFuncDeclaratorNode(CDeclaratorNode):
513 # base CDeclaratorNode
514 # args [CArgDeclNode]
515 # has_varargs boolean
516 # exception_value ConstNode
517 # exception_check boolean True if PyErr_Occurred check needed
518 # nogil boolean Can be called without gil
519 # with_gil boolean Acquire gil around function body
521 child_attrs = ["base", "args", "exception_value"]
523 overridable = 0
524 optional_arg_count = 0
526 def analyse(self, return_type, env, nonempty = 0):
527 if nonempty:
528 nonempty -= 1
529 func_type_args = []
530 for arg_node in self.args:
531 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
532 name = name_declarator.name
533 if name_declarator.cname:
534 error(self.pos,
535 "Function argument cannot have C name specification")
536 # Turn *[] argument into **
537 if type.is_array:
538 type = PyrexTypes.c_ptr_type(type.base_type)
539 # Catch attempted C-style func(void) decl
540 if type.is_void:
541 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
542 # if type.is_pyobject and self.nogil:
543 # error(self.pos,
544 # "Function with Python argument cannot be declared nogil")
545 func_type_args.append(
546 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
547 if arg_node.default:
548 self.optional_arg_count += 1
549 elif self.optional_arg_count:
550 error(self.pos, "Non-default argument follows default argument")
552 if self.optional_arg_count:
553 scope = StructOrUnionScope()
554 scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
555 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
556 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
557 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
558 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
559 kind = 'struct',
560 scope = scope,
561 typedef_flag = 0,
562 pos = self.pos,
563 cname = struct_cname)
564 self.op_args_struct.defined_in_pxd = 1
565 self.op_args_struct.used = 1
567 exc_val = None
568 exc_check = 0
569 if return_type.is_pyobject \
570 and (self.exception_value or self.exception_check) \
571 and self.exception_check != '+':
572 error(self.pos,
573 "Exception clause not allowed for function returning Python object")
574 else:
575 if self.exception_value:
576 self.exception_value.analyse_const_expression(env)
577 if self.exception_check == '+':
578 exc_val_type = self.exception_value.type
579 if not exc_val_type.is_error and \
580 not exc_val_type.is_pyobject and \
581 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
582 error(self.exception_value.pos,
583 "Exception value must be a Python exception or cdef function with no arguments.")
584 exc_val = self.exception_value
585 else:
586 exc_val = self.exception_value.result()
587 if not return_type.assignable_from(self.exception_value.type):
588 error(self.exception_value.pos,
589 "Exception value incompatible with function return type")
590 exc_check = self.exception_check
591 if return_type.is_array:
592 error(self.pos,
593 "Function cannot return an array")
594 if return_type.is_cfunction:
595 error(self.pos,
596 "Function cannot return a function")
597 func_type = PyrexTypes.CFuncType(
598 return_type, func_type_args, self.has_varargs,
599 optional_arg_count = self.optional_arg_count,
600 exception_value = exc_val, exception_check = exc_check,
601 calling_convention = self.base.calling_convention,
602 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
603 if self.optional_arg_count:
604 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
605 return self.base.analyse(func_type, env)
608 class CArgDeclNode(Node):
609 # Item in a function declaration argument list.
610 #
611 # base_type CBaseTypeNode
612 # declarator CDeclaratorNode
613 # not_none boolean Tagged with 'not None'
614 # default ExprNode or None
615 # default_entry Symtab.Entry Entry for the variable holding the default value
616 # default_result_code string cname or code fragment for default value
617 # is_self_arg boolean Is the "self" arg of an extension type method
618 # is_kw_only boolean Is a keyword-only argument
620 child_attrs = ["base_type", "declarator", "default"]
622 is_self_arg = 0
623 is_generic = 1
624 type = None
625 name_declarator = None
627 def analyse(self, env, nonempty = 0):
628 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
629 if self.type is None:
630 # The parser may missinterpret names as types...
631 # We fix that here.
632 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
633 if nonempty:
634 self.declarator.name = self.base_type.name
635 self.base_type.name = None
636 self.base_type.is_basic_c_type = False
637 could_be_name = True
638 else:
639 could_be_name = False
640 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
641 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
642 self.declarator.name = self.base_type.arg_name
643 return self.declarator.analyse(base_type, env, nonempty = nonempty)
644 else:
645 return self.name_declarator, self.type
647 def annotate(self, code):
648 if self.default:
649 self.default.annotate(code)
652 class CBaseTypeNode(Node):
653 # Abstract base class for C base type nodes.
654 #
655 # Processing during analyse_declarations phase:
656 #
657 # analyse
658 # Returns the type.
660 pass
662 class CAnalysedBaseTypeNode(Node):
663 # type type
665 child_attrs = []
667 def analyse(self, env, could_be_name = False):
668 return self.type
670 class CSimpleBaseTypeNode(CBaseTypeNode):
671 # name string
672 # module_path [string] Qualifying name components
673 # is_basic_c_type boolean
674 # signed boolean
675 # longness integer
676 # is_self_arg boolean Is self argument of C method
678 child_attrs = []
679 arg_name = None # in case the argument name was interpreted as a type
681 def analyse(self, env, could_be_name = False):
682 # Return type descriptor.
683 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
684 type = None
685 if self.is_basic_c_type:
686 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
687 if not type:
688 error(self.pos, "Unrecognised type modifier combination")
689 elif self.name == "object" and not self.module_path:
690 type = py_object_type
691 elif self.name is None:
692 if self.is_self_arg and env.is_c_class_scope:
693 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
694 type = env.parent_type
695 else:
696 type = py_object_type
697 else:
698 if self.module_path:
699 scope = env.find_imported_module(self.module_path, self.pos)
700 else:
701 scope = env
702 if scope:
703 if scope.is_c_class_scope:
704 scope = scope.global_scope()
705 entry = scope.lookup(self.name)
706 if entry and entry.is_type:
707 type = entry.type
708 elif could_be_name:
709 if self.is_self_arg and env.is_c_class_scope:
710 type = env.parent_type
711 else:
712 type = py_object_type
713 self.arg_name = self.name
714 else:
715 error(self.pos, "'%s' is not a type identifier" % self.name)
716 if type:
717 return type
718 else:
719 return PyrexTypes.error_type
721 class CBufferAccessTypeNode(CBaseTypeNode):
722 # After parsing:
723 # positional_args [ExprNode] List of positional arguments
724 # keyword_args DictNode Keyword arguments
725 # base_type_node CBaseTypeNode
727 # After analysis:
728 # type PyrexType.BufferType ...containing the right options
731 child_attrs = ["base_type_node", "positional_args",
732 "keyword_args", "dtype_node"]
734 dtype_node = None
736 name = None
738 def analyse(self, env, could_be_name = False):
739 base_type = self.base_type_node.analyse(env)
740 if base_type.is_error: return base_type
741 import Buffer
743 options = Buffer.analyse_buffer_options(
744 self.pos,
745 env,
746 self.positional_args,
747 self.keyword_args,
748 base_type.buffer_defaults)
750 self.type = PyrexTypes.BufferType(base_type, **options)
751 return self.type
753 class CComplexBaseTypeNode(CBaseTypeNode):
754 # base_type CBaseTypeNode
755 # declarator CDeclaratorNode
757 child_attrs = ["base_type", "declarator"]
759 def analyse(self, env, could_be_name = False):
760 base = self.base_type.analyse(env, could_be_name)
761 _, type = self.declarator.analyse(base, env)
762 return type
765 class CVarDefNode(StatNode):
766 # C variable definition or forward/extern function declaration.
767 #
768 # visibility 'private' or 'public' or 'extern'
769 # base_type CBaseTypeNode
770 # declarators [CDeclaratorNode]
771 # in_pxd boolean
772 # api boolean
773 # need_properties [entry]
775 # decorators [cython.locals(...)] or None
776 # directive_locals { string : NameNode } locals defined by cython.locals(...)
778 child_attrs = ["base_type", "declarators"]
779 need_properties = ()
781 decorators = None
782 directive_locals = {}
784 def analyse_declarations(self, env, dest_scope = None):
785 if not dest_scope:
786 dest_scope = env
787 self.dest_scope = dest_scope
788 base_type = self.base_type.analyse(env)
789 if (dest_scope.is_c_class_scope
790 and self.visibility == 'public'
791 and base_type.is_pyobject
792 and (base_type.is_builtin_type or base_type.is_extension_type)):
793 self.need_properties = []
794 need_property = True
795 visibility = 'private'
796 else:
797 need_property = False
798 visibility = self.visibility
800 for declarator in self.declarators:
801 name_declarator, type = declarator.analyse(base_type, env)
802 if not type.is_complete():
803 if not (self.visibility == 'extern' and type.is_array):
804 error(declarator.pos,
805 "Variable type '%s' is incomplete" % type)
806 if self.visibility == 'extern' and type.is_pyobject:
807 error(declarator.pos,
808 "Python object cannot be declared extern")
809 name = name_declarator.name
810 cname = name_declarator.cname
811 if name == '':
812 error(declarator.pos, "Missing name in declaration.")
813 return
814 if type.is_cfunction:
815 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
816 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
817 api = self.api)
818 if entry is not None:
819 entry.directive_locals = self.directive_locals
820 else:
821 if self.directive_locals:
822 s.error("Decorators can only be followed by functions")
823 if self.in_pxd and self.visibility != 'extern':
824 error(self.pos,
825 "Only 'extern' C variable declaration allowed in .pxd file")
826 entry = dest_scope.declare_var(name, type, declarator.pos,
827 cname = cname, visibility = visibility, is_cdef = 1)
828 if need_property:
829 self.need_properties.append(entry)
830 entry.needs_property = 1
833 class CStructOrUnionDefNode(StatNode):
834 # name string
835 # cname string or None
836 # kind "struct" or "union"
837 # typedef_flag boolean
838 # visibility "public" or "private"
839 # in_pxd boolean
840 # attributes [CVarDefNode] or None
841 # entry Entry
843 child_attrs = ["attributes"]
845 def analyse_declarations(self, env):
846 scope = None
847 if self.attributes is not None:
848 scope = StructOrUnionScope(self.name)
849 self.entry = env.declare_struct_or_union(
850 self.name, self.kind, scope, self.typedef_flag, self.pos,
851 self.cname, visibility = self.visibility)
852 if self.attributes is not None:
853 if self.in_pxd and not env.in_cinclude:
854 self.entry.defined_in_pxd = 1
855 for attr in self.attributes:
856 attr.analyse_declarations(env, scope)
857 if self.visibility != 'extern':
858 need_typedef_indirection = False
859 for attr in scope.var_entries:
860 type = attr.type
861 while type.is_array:
862 type = type.base_type
863 if type == self.entry.type:
864 error(attr.pos, "Struct cannot contain itself as a member.")
865 if self.typedef_flag:
866 while type.is_ptr:
867 type = type.base_type
868 if type == self.entry.type:
869 need_typedef_indirection = True
870 if need_typedef_indirection:
871 # C can't handle typedef structs that refer to themselves.
872 struct_entry = self.entry
873 cname = env.new_const_cname()
874 self.entry = env.declare_typedef(self.name, struct_entry.type, self.pos, cname = self.cname, visibility='ignore')
875 struct_entry.type.typedef_flag = False
876 struct_entry.cname = struct_entry.type.cname = env.new_const_cname()
878 def analyse_expressions(self, env):
879 pass
881 def generate_execution_code(self, code):
882 pass
885 class CEnumDefNode(StatNode):
886 # name string or None
887 # cname string or None
888 # items [CEnumDefItemNode]
889 # typedef_flag boolean
890 # visibility "public" or "private"
891 # in_pxd boolean
892 # entry Entry
894 child_attrs = ["items"]
896 def analyse_declarations(self, env):
897 self.entry = env.declare_enum(self.name, self.pos,
898 cname = self.cname, typedef_flag = self.typedef_flag,
899 visibility = self.visibility)
900 if self.items is not None:
901 if self.in_pxd and not env.in_cinclude:
902 self.entry.defined_in_pxd = 1
903 for item in self.items:
904 item.analyse_declarations(env, self.entry)
906 def analyse_expressions(self, env):
907 if self.visibility == 'public':
908 self.temp = env.allocate_temp_pyobject()
909 env.release_temp(self.temp)
911 def generate_execution_code(self, code):
912 if self.visibility == 'public':
913 for item in self.entry.enum_values:
914 code.putln("%s = PyInt_FromLong(%s); %s" % (
915 self.temp,
916 item.cname,
917 code.error_goto_if_null(self.temp, item.pos)))
918 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
919 Naming.module_cname,
920 item.name,
921 self.temp,
922 code.error_goto(item.pos)))
923 code.putln("%s = 0;" % self.temp)
926 class CEnumDefItemNode(StatNode):
927 # name string
928 # cname string or None
929 # value ExprNode or None
931 child_attrs = ["value"]
933 def analyse_declarations(self, env, enum_entry):
934 if self.value:
935 self.value.analyse_const_expression(env)
936 if not self.value.type.is_int:
937 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
938 self.value.analyse_const_expression(env)
939 value = self.value.result()
940 else:
941 value = self.name
942 entry = env.declare_const(self.name, enum_entry.type,
943 value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
944 enum_entry.enum_values.append(entry)
947 class CTypeDefNode(StatNode):
948 # base_type CBaseTypeNode
949 # declarator CDeclaratorNode
950 # visibility "public" or "private"
951 # in_pxd boolean
953 child_attrs = ["base_type", "declarator"]
955 def analyse_declarations(self, env):
956 base = self.base_type.analyse(env)
957 name_declarator, type = self.declarator.analyse(base, env)
958 name = name_declarator.name
959 cname = name_declarator.cname
960 entry = env.declare_typedef(name, type, self.pos,
961 cname = cname, visibility = self.visibility)
962 if self.in_pxd and not env.in_cinclude:
963 entry.defined_in_pxd = 1
965 def analyse_expressions(self, env):
966 pass
967 def generate_execution_code(self, code):
968 pass
971 class FuncDefNode(StatNode, BlockNode):
972 # Base class for function definition nodes.
973 #
974 # return_type PyrexType
975 # #filename string C name of filename string const
976 # entry Symtab.Entry
977 # needs_closure boolean Whether or not this function has inner functions/classes/yield
978 # directive_locals { string : NameNode } locals defined by cython.locals(...)
980 py_func = None
981 assmt = None
982 needs_closure = False
984 def analyse_default_values(self, env):
985 genv = env.global_scope()
986 for arg in self.args:
987 if arg.default:
988 if arg.is_generic:
989 if not hasattr(arg, 'default_entry'):
990 arg.default.analyse_types(env)
991 arg.default = arg.default.coerce_to(arg.type, genv)
992 if arg.default.is_literal:
993 arg.default_entry = arg.default
994 arg.default_result_code = arg.default.calculate_result_code()
995 if arg.default.type != arg.type and not arg.type.is_int:
996 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
997 else:
998 arg.default.allocate_temps(genv)
999 arg.default_entry = genv.add_default_value(arg.type)
1000 if arg.type.is_pyobject:
1001 arg.default_entry.init = 0
1002 arg.default_entry.used = 1
1003 arg.default_result_code = arg.default_entry.cname
1004 else:
1005 error(arg.pos,
1006 "This argument cannot have a default value")
1007 arg.default = None
1009 def need_gil_acquisition(self, lenv):
1010 return 0
1012 def create_local_scope(self, env):
1013 genv = env
1014 while env.is_py_class_scope or env.is_c_class_scope:
1015 env = env.outer_scope
1016 if self.needs_closure:
1017 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
1018 else:
1019 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
1020 lenv.return_type = self.return_type
1021 type = self.entry.type
1022 if type.is_cfunction:
1023 lenv.nogil = type.nogil and not type.with_gil
1024 self.local_scope = lenv
1025 return lenv
1027 def generate_function_definitions(self, env, code):
1028 import Buffer
1030 lenv = self.local_scope
1032 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1033 self.entry.scope.is_c_class_scope)
1035 # Generate C code for header and body of function
1036 code.enter_cfunc_scope()
1037 code.return_from_error_cleanup_label = code.new_label()
1039 # ----- Top-level constants used by this function
1040 code.mark_pos(self.pos)
1041 self.generate_interned_num_decls(lenv, code)
1042 self.generate_interned_string_decls(lenv, code)
1043 self.generate_py_string_decls(lenv, code)
1044 self.generate_cached_builtins_decls(lenv, code)
1045 #code.putln("")
1046 #code.put_var_declarations(lenv.const_entries, static = 1)
1047 self.generate_const_definitions(lenv, code)
1048 # ----- Function header
1049 code.putln("")
1050 if self.py_func:
1051 self.py_func.generate_function_header(code,
1052 with_pymethdef = env.is_py_class_scope,
1053 proto_only=True)
1054 self.generate_function_header(code,
1055 with_pymethdef = env.is_py_class_scope)
1056 # ----- Local variable declarations
1057 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
1058 self.generate_argument_declarations(lenv, code)
1059 if self.needs_closure:
1060 code.putln("/* TODO: declare and create scope object */")
1061 code.put_var_declarations(lenv.var_entries)
1062 init = ""
1063 if not self.return_type.is_void:
1064 if self.return_type.is_pyobject:
1065 init = " = NULL"
1066 code.putln(
1067 "%s%s;" %
1068 (self.return_type.declaration_code(
1069 Naming.retval_cname),
1070 init))
1071 tempvardecl_code = code.insertion_point()
1072 self.generate_keyword_list(code)
1073 # ----- Extern library function declarations
1074 lenv.generate_library_function_declarations(code)
1075 # ----- GIL acquisition
1076 acquire_gil = self.need_gil_acquisition(lenv)
1077 if acquire_gil:
1078 env.use_utility_code(py23_init_threads_utility_code)
1079 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1080 # ----- Automatic lead-ins for certain special functions
1081 if not lenv.nogil:
1082 code.put_setup_refcount_context(self.entry.name)
1083 if is_getbuffer_slot:
1084 self.getbuffer_init(code)
1085 # ----- Fetch arguments
1086 self.generate_argument_parsing_code(env, code)
1087 # If an argument is assigned to in the body, we must
1088 # incref it to properly keep track of refcounts.
1089 for entry in lenv.arg_entries:
1090 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1091 code.put_var_incref(entry)
1092 # ----- Initialise local variables
1093 for entry in lenv.var_entries:
1094 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1095 code.put_init_var_to_py_none(entry)
1096 # ----- Initialise local buffer auxiliary variables
1097 for entry in lenv.var_entries + lenv.arg_entries:
1098 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1099 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1100 # ----- Check and convert arguments
1101 self.generate_argument_type_tests(code)
1102 # ----- Acquire buffer arguments
1103 for entry in lenv.arg_entries:
1104 if entry.type.is_buffer:
1105 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1106 # ----- Function body
1107 self.body.generate_execution_code(code)
1108 # ----- Default return value
1109 code.putln("")
1110 if self.return_type.is_pyobject:
1111 #if self.return_type.is_extension_type:
1112 # lhs = "(PyObject *)%s" % Naming.retval_cname
1113 #else:
1114 lhs = Naming.retval_cname
1115 code.put_init_to_py_none(lhs, self.return_type)
1116 else:
1117 val = self.return_type.default_value
1118 if val:
1119 code.putln("%s = %s;" % (Naming.retval_cname, val))
1120 # ----- Error cleanup
1121 if code.error_label in code.labels_used:
1122 code.put_goto(code.return_label)
1123 code.put_label(code.error_label)
1124 # cleanup temps the old way
1125 code.put_var_xdecrefs(lenv.temp_entries)
1126 # cleanup temps the new way
1127 for cname, type in code.funcstate.all_managed_temps():
1128 code.put_xdecref(cname, type)
1130 # Clean up buffers -- this calls a Python function
1131 # so need to save and restore error state
1132 buffers_present = len(lenv.buffer_entries) > 0
1133 if buffers_present:
1134 code.globalstate.use_utility_code(restore_exception_utility_code)
1135 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1136 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1137 for entry in lenv.buffer_entries:
1138 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1139 #code.putln("%s = 0;" % entry.cname)
1140 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1142 err_val = self.error_value()
1143 exc_check = self.caller_will_check_exceptions()
1144 if err_val is not None or exc_check:
1145 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1146 else:
1147 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1148 % self.entry.qualified_name, 0)
1149 code.putln(
1150 '__Pyx_WriteUnraisable("%s");' %
1151 self.entry.qualified_name)
1152 env.use_utility_code(unraisable_exception_utility_code)
1153 env.use_utility_code(restore_exception_utility_code)
1154 default_retval = self.return_type.default_value
1155 if err_val is None and default_retval:
1156 err_val = default_retval
1157 if err_val is not None:
1158 code.putln(
1159 "%s = %s;" % (
1160 Naming.retval_cname,
1161 err_val))
1163 if is_getbuffer_slot:
1164 self.getbuffer_error_cleanup(code)
1166 # If we are using the non-error cleanup section we should
1167 # jump past it if we have an error. The if-test below determine
1168 # whether this section is used.
1169 if buffers_present or is_getbuffer_slot:
1170 code.put_goto(code.return_from_error_cleanup_label)
1173 # ----- Non-error return cleanup
1174 # If you add anything here, remember to add a condition to the
1175 # if-test above in the error block (so that it can jump past this
1176 # block).
1177 code.put_label(code.return_label)
1178 for entry in lenv.buffer_entries:
1179 if entry.used:
1180 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1181 if is_getbuffer_slot:
1182 self.getbuffer_normal_cleanup(code)
1183 # ----- Return cleanup for both error and no-error return
1184 code.put_label(code.return_from_error_cleanup_label)
1185 if not Options.init_local_none:
1186 for entry in lenv.var_entries:
1187 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1188 entry.xdecref_cleanup = 1
1189 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1190 # Decref any increfed args
1191 for entry in lenv.arg_entries:
1192 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1193 code.put_var_decref(entry)
1195 # code.putln("/* TODO: decref scope object */")
1196 # ----- Return
1197 # This code is duplicated in ModuleNode.generate_module_init_func
1198 if not lenv.nogil:
1199 default_retval = self.return_type.default_value
1200 err_val = self.error_value()
1201 if err_val is None and default_retval:
1202 err_val = default_retval
1203 if self.return_type.is_pyobject:
1204 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1206 code.put_finish_refcount_context()
1208 if acquire_gil:
1209 code.putln("PyGILState_Release(_save);")
1211 if not self.return_type.is_void:
1212 code.putln("return %s;" % Naming.retval_cname)
1214 code.putln("}")
1215 # ----- Go back and insert temp variable declarations
1216 tempvardecl_code.put_var_declarations(lenv.temp_entries)
1217 tempvardecl_code.put_temp_declarations(code.funcstate)
1218 # ----- Python version
1219 code.exit_cfunc_scope()
1220 if self.py_func:
1221 self.py_func.generate_function_definitions(env, code)
1222 self.generate_wrapper_functions(code)
1224 def declare_argument(self, env, arg):
1225 if arg.type.is_void:
1226 error(arg.pos, "Invalid use of 'void'")
1227 elif not arg.type.is_complete() and not arg.type.is_array:
1228 error(arg.pos,
1229 "Argument type '%s' is incomplete" % arg.type)
1230 return env.declare_arg(arg.name, arg.type, arg.pos)
1232 def generate_wrapper_functions(self, code):
1233 pass
1235 def generate_execution_code(self, code):
1236 # Evaluate and store argument default values
1237 for arg in self.args:
1238 default = arg.default
1239 if default:
1240 if not default.is_literal:
1241 default.generate_evaluation_code(code)
1242 default.make_owned_reference(code)
1243 code.putln(
1244 "%s = %s;" % (
1245 arg.default_entry.cname,
1246 default.result_as(arg.default_entry.type)))
1247 if default.is_temp and default.type.is_pyobject:
1248 code.putln("%s = 0;" % default.result())
1249 default.free_temps(code)
1250 code.put_var_giveref(arg.default_entry)
1251 # For Python class methods, create and store function object
1252 if self.assmt:
1253 self.assmt.generate_execution_code(code)
1256 # Special code for the __getbuffer__ function
1258 def getbuffer_init(self, code):
1259 info = self.local_scope.arg_entries[1].cname
1260 # Python 3.0 betas have a bug in memoryview which makes it call
1261 # getbuffer with a NULL parameter. For now we work around this;
1262 # the following line should be removed when this bug is fixed.
1263 code.putln("if (%s == NULL) return 0;" % info)
1264 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1265 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1267 def getbuffer_error_cleanup(self, code):
1268 info = self.local_scope.arg_entries[1].cname
1269 code.put_gotref("%s->obj" % info)
1270 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1271 (info, info))
1273 def getbuffer_normal_cleanup(self, code):
1274 info = self.local_scope.arg_entries[1].cname
1275 code.putln("if (%s->obj == Py_None) {" % info)
1276 code.put_gotref("Py_None")
1277 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1278 code.putln("}")
1280 class CFuncDefNode(FuncDefNode):
1281 # C function definition.
1283 # modifiers ['inline']
1284 # visibility 'private' or 'public' or 'extern'
1285 # base_type CBaseTypeNode
1286 # declarator CDeclaratorNode
1287 # body StatListNode
1288 # api boolean
1289 # decorators [DecoratorNode] list of decorators
1291 # with_gil boolean Acquire GIL around body
1292 # type CFuncType
1293 # py_func wrapper for calling from Python
1294 # overridable whether or not this is a cpdef function
1295 # inline_in_pxd whether this is an inline function in a pxd file
1297 child_attrs = ["base_type", "declarator", "body", "py_func"]
1299 inline_in_pxd = False
1300 decorators = None
1301 directive_locals = {}
1303 def unqualified_name(self):
1304 return self.entry.name
1306 def analyse_declarations(self, env):
1307 if 'locals' in env.directives and env.directives['locals']:
1308 self.directive_locals = env.directives['locals']
1309 directive_locals = self.directive_locals
1310 base_type = self.base_type.analyse(env)
1311 # The 2 here is because we need both function and argument names.
1312 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1313 if not type.is_cfunction:
1314 error(self.pos,
1315 "Suite attached to non-function declaration")
1316 # Remember the actual type according to the function header
1317 # written here, because the type in the symbol table entry
1318 # may be different if we're overriding a C method inherited
1319 # from the base type of an extension type.
1320 self.type = type
1321 type.is_overridable = self.overridable
1322 declarator = self.declarator
1323 while not hasattr(declarator, 'args'):
1324 declarator = declarator.base
1325 self.args = declarator.args
1326 for formal_arg, type_arg in zip(self.args, type.args):
1327 formal_arg.type = type_arg.type
1328 formal_arg.name = type_arg.name
1329 formal_arg.cname = type_arg.cname
1330 name = name_declarator.name
1331 cname = name_declarator.cname
1332 self.entry = env.declare_cfunction(
1333 name, type, self.pos,
1334 cname = cname, visibility = self.visibility,
1335 defining = self.body is not None,
1336 api = self.api, modifiers = self.modifiers)
1337 self.entry.inline_func_in_pxd = self.inline_in_pxd
1338 self.return_type = type.return_type
1340 if self.overridable and not env.is_module_scope:
1341 if len(self.args) < 1 or not self.args[0].type.is_pyobject:
1342 # An error will be produced in the cdef function
1343 self.overridable = False
1345 if self.overridable:
1346 import ExprNodes
1347 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1348 self.py_func = DefNode(pos = self.pos,
1349 name = self.entry.name,
1350 args = self.args,
1351 star_arg = None,
1352 starstar_arg = None,
1353 doc = self.doc,
1354 body = py_func_body,
1355 is_wrapper = 1)
1356 self.py_func.is_module_scope = env.is_module_scope
1357 self.py_func.analyse_declarations(env)
1358 self.entry.as_variable = self.py_func.entry
1359 # Reset scope entry the above cfunction
1360 env.entries[name] = self.entry
1361 self.py_func.interned_attr_cname = env.intern_identifier(
1362 self.py_func.entry.name)
1363 if not env.is_module_scope or Options.lookup_module_cpdef:
1364 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1365 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1367 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1368 import ExprNodes
1369 args = self.type.args
1370 if omit_optional_args:
1371 args = args[:len(args) - self.type.optional_arg_count]
1372 arg_names = [arg.name for arg in args]
1373 if is_module_scope:
1374 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1375 else:
1376 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1377 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1378 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1379 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)
1380 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1382 def declare_arguments(self, env):
1383 for arg in self.type.args:
1384 if not arg.name:
1385 error(arg.pos, "Missing argument name")
1386 self.declare_argument(env, arg)
1388 def need_gil_acquisition(self, lenv):
1389 type = self.type
1390 with_gil = self.type.with_gil
1391 if type.nogil and not with_gil:
1392 if type.return_type.is_pyobject:
1393 error(self.pos,
1394 "Function with Python return type cannot be declared nogil")
1395 for entry in lenv.var_entries + lenv.temp_entries:
1396 if entry.type.is_pyobject:
1397 error(self.pos, "Function declared nogil has Python locals or temporaries")
1398 return with_gil
1400 def analyse_expressions(self, env):
1401 self.analyse_default_values(env)
1402 if self.py_func is not None:
1403 self.py_func.analyse_expressions(env)
1405 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1406 arg_decls = []
1407 type = self.type
1408 visibility = self.entry.visibility
1409 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1410 arg_decls.append(arg.declaration_code())
1411 if with_dispatch and self.overridable:
1412 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1413 if type.optional_arg_count and with_opt_args:
1414 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1415 if type.has_varargs:
1416 arg_decls.append("...")
1417 if not arg_decls:
1418 arg_decls = ["void"]
1419 if cname is None:
1420 cname = self.entry.func_cname
1421 entity = type.function_header_code(cname, ', '.join(arg_decls))
1422 if visibility == 'public':
1423 dll_linkage = "DL_EXPORT"
1424 else:
1425 dll_linkage = None
1426 header = self.return_type.declaration_code(entity,
1427 dll_linkage = dll_linkage)
1428 if visibility == 'extern':
1429 storage_class = "%s " % Naming.extern_c_macro
1430 elif visibility == 'public':
1431 storage_class = ""
1432 else:
1433 storage_class = "static "
1434 code.putln("%s%s %s {" % (
1435 storage_class,
1436 ' '.join(self.modifiers).upper(), # macro forms
1437 header))
1439 def generate_argument_declarations(self, env, code):
1440 for arg in self.args:
1441 if arg.default:
1442 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1444 def generate_keyword_list(self, code):
1445 pass
1447 def generate_argument_parsing_code(self, env, code):
1448 i = 0
1449 if self.type.optional_arg_count:
1450 code.putln('if (%s) {' % Naming.optional_args_cname)
1451 for arg in self.args:
1452 if arg.default:
1453 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1454 declarator = arg.declarator
1455 while not hasattr(declarator, 'name'):
1456 declarator = declarator.base
1457 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1458 i += 1
1459 for _ in range(self.type.optional_arg_count):
1460 code.putln('}')
1461 code.putln('}')
1463 def generate_argument_conversion_code(self, code):
1464 pass
1466 def generate_argument_type_tests(self, code):
1467 # Generate type tests for args whose type in a parent
1468 # class is a supertype of the declared type.
1469 for arg in self.type.args:
1470 if arg.needs_type_test:
1471 self.generate_arg_type_test(arg, code)
1473 def generate_arg_type_test(self, arg, code):
1474 # Generate type test for one argument.
1475 if arg.type.typeobj_is_available():
1476 typeptr_cname = arg.type.typeptr_cname
1477 arg_code = "((PyObject *)%s)" % arg.cname
1478 code.putln(
1479 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1480 arg_code,
1481 typeptr_cname,
1482 not arg.not_none,
1483 arg.name,
1484 type.is_builtin_type,
1485 code.error_goto(arg.pos)))
1486 else:
1487 error(arg.pos, "Cannot test type of extern C class "
1488 "without type object name specification")
1490 def error_value(self):
1491 if self.return_type.is_pyobject:
1492 return "0"
1493 else:
1494 #return None
1495 return self.entry.type.exception_value
1497 def caller_will_check_exceptions(self):
1498 return self.entry.type.exception_check
1500 def generate_wrapper_functions(self, code):
1501 # If the C signature of a function has changed, we need to generate
1502 # wrappers to put in the slots here.
1503 k = 0
1504 entry = self.entry
1505 func_type = entry.type
1506 while entry.prev_entry is not None:
1507 k += 1
1508 entry = entry.prev_entry
1509 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1510 code.putln()
1511 self.generate_function_header(code,
1512 0,
1513 with_dispatch = entry.type.is_overridable,
1514 with_opt_args = entry.type.optional_arg_count,
1515 cname = entry.func_cname)
1516 if not self.return_type.is_void:
1517 code.put('return ')
1518 args = self.type.args
1519 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1520 if entry.type.is_overridable:
1521 arglist.append(Naming.skip_dispatch_cname)
1522 elif func_type.is_overridable:
1523 arglist.append('0')
1524 if entry.type.optional_arg_count:
1525 arglist.append(Naming.optional_args_cname)
1526 elif func_type.optional_arg_count:
1527 arglist.append('NULL')
1528 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1529 code.putln('}')
1532 class PyArgDeclNode(Node):
1533 # Argument which must be a Python object (used
1534 # for * and ** arguments).
1536 # name string
1537 # entry Symtab.Entry
1538 child_attrs = []
1541 class DecoratorNode(Node):
1542 # A decorator
1544 # decorator NameNode or CallNode
1545 child_attrs = ['decorator']
1548 class DefNode(FuncDefNode):
1549 # A Python function definition.
1551 # name string the Python name of the function
1552 # decorators [DecoratorNode] list of decorators
1553 # args [CArgDeclNode] formal arguments
1554 # star_arg PyArgDeclNode or None * argument
1555 # starstar_arg PyArgDeclNode or None ** argument
1556 # doc EncodedString or None
1557 # body StatListNode
1559 # The following subnode is constructed internally
1560 # when the def statement is inside a Python class definition.
1562 # assmt AssignmentNode Function construction/assignment
1564 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1566 assmt = None
1567 num_kwonly_args = 0
1568 num_required_kw_args = 0
1569 reqd_kw_flags_cname = "0"
1570 is_wrapper = 0
1571 decorators = None
1572 entry = None
1575 def __init__(self, pos, **kwds):
1576 FuncDefNode.__init__(self, pos, **kwds)
1577 k = rk = r = 0
1578 for arg in self.args:
1579 if arg.kw_only:
1580 k += 1
1581 if not arg.default:
1582 rk += 1
1583 if not arg.default:
1584 r += 1
1585 self.num_kwonly_args = k
1586 self.num_required_kw_args = rk
1587 self.num_required_args = r
1589 def as_cfunction(self, cfunc=None, scope=None):
1590 if self.star_arg:
1591 error(self.star_arg.pos, "cdef function cannot have star argument")
1592 if self.starstar_arg:
1593 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1594 if cfunc is None:
1595 cfunc_args = []
1596 for formal_arg in self.args:
1597 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1598 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1599 cname = None,
1600 type = py_object_type,
1601 pos = formal_arg.pos))
1602 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1603 args = cfunc_args,
1604 has_varargs = False,
1605 exception_value = None,
1606 exception_check = False,
1607 nogil = False,
1608 with_gil = False,
1609 is_overridable = True)
1610 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1611 else:
1612 cfunc_type = cfunc.type
1613 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1614 error(self.pos, "wrong number of arguments")
1615 error(declarator.pos, "previous declaration here")
1616 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1617 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1618 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1619 formal_arg.type = type_arg.type
1620 formal_arg.name_declarator = name_declarator
1621 import ExprNodes
1622 if cfunc_type.exception_value is None:
1623 exception_value = None
1624 else:
1625 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1626 declarator = CFuncDeclaratorNode(self.pos,
1627 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1628 args = self.args,
1629 has_varargs = False,
1630 exception_check = cfunc_type.exception_check,
1631 exception_value = exception_value,
1632 with_gil = cfunc_type.with_gil,
1633 nogil = cfunc_type.nogil)
1634 return CFuncDefNode(self.pos,
1635 modifiers = [],
1636 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1637 declarator = declarator,
1638 body = self.body,
1639 doc = self.doc,
1640 overridable = cfunc_type.is_overridable,
1641 type = cfunc_type,
1642 with_gil = cfunc_type.with_gil,
1643 nogil = cfunc_type.nogil,
1644 visibility = 'private',
1645 api = False,
1646 directive_locals = cfunc.directive_locals)
1648 def analyse_declarations(self, env):
1649 if 'locals' in env.directives:
1650 directive_locals = env.directives['locals']
1651 else:
1652 directive_locals = {}
1653 self.directive_locals = directive_locals
1654 for arg in self.args:
1655 if hasattr(arg, 'name'):
1656 type = arg.type
1657 name_declarator = None
1658 else:
1659 base_type = arg.base_type.analyse(env)
1660 name_declarator, type = \
1661 arg.declarator.analyse(base_type, env)
1662 arg.name = name_declarator.name
1663 if arg.name in directive_locals:
1664 type_node = directive_locals[arg.name]
1665 other_type = type_node.analyse_as_type(env)
1666 if other_type is None:
1667 error(type_node.pos, "Not a type")
1668 elif (type is not PyrexTypes.py_object_type
1669 and not type.same_as(other_type)):
1670 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1671 error(type_node.pos, "Previous declaration here")
1672 else:
1673 type = other_type
1674 if name_declarator and name_declarator.cname:
1675 error(self.pos,
1676 "Python function argument cannot have C name specification")
1677 arg.type = type.as_argument_type()
1678 arg.hdr_type = None
1679 arg.needs_conversion = 0
1680 arg.needs_type_test = 0
1681 arg.is_generic = 1
1682 if arg.not_none and not arg.type.is_extension_type:
1683 error(self.pos,
1684 "Only extension type arguments can have 'not None'")
1685 self.declare_pyfunction(env)
1686 self.analyse_signature(env)
1687 self.return_type = self.entry.signature.return_type()
1689 def analyse_signature(self, env):
1690 any_type_tests_needed = 0
1691 # Use the simpler calling signature for zero- and one-argument functions.
1692 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1693 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1694 if len(self.args) == 0:
1695 self.entry.signature = TypeSlots.pyfunction_noargs
1696 elif len(self.args) == 1:
1697 if self.args[0].default is None and not self.args[0].kw_only:
1698 self.entry.signature = TypeSlots.pyfunction_onearg
1699 elif self.entry.signature is TypeSlots.pymethod_signature:
1700 if len(self.args) == 1:
1701 self.entry.signature = TypeSlots.unaryfunc
1702 elif len(self.args) == 2:
1703 if self.args[1].default is None and not self.args[1].kw_only:
1704 self.entry.signature = TypeSlots.ibinaryfunc
1705 elif self.entry.is_special:
1706 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1707 sig = self.entry.signature
1708 nfixed = sig.num_fixed_args()
1709 for i in range(nfixed):
1710 if i < len(self.args):
1711 arg = self.args[i]
1712 arg.is_generic = 0
1713 if sig.is_self_arg(i):
1714 arg.is_self_arg = 1
1715 arg.hdr_type = arg.type = env.parent_type
1716 arg.needs_conversion = 0
1717 else:
1718 arg.hdr_type = sig.fixed_arg_type(i)
1719 if not arg.type.same_as(arg.hdr_type):
1720 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1721 arg.needs_type_test = 1
1722 any_type_tests_needed = 1
1723 else:
1724 arg.needs_conversion = 1
1725 if arg.needs_conversion:
1726 arg.hdr_cname = Naming.arg_prefix + arg.name
1727 else:
1728 arg.hdr_cname = Naming.var_prefix + arg.name
1729 else:
1730 self.bad_signature()
1731 return
1732 if nfixed < len(self.args):
1733 if not sig.has_generic_args:
1734 self.bad_signature()
1735 for arg in self.args:
1736 if arg.is_generic and \
1737 (arg.type.is_extension_type or arg.type.is_builtin_type):
1738 arg.needs_type_test = 1
1739 any_type_tests_needed = 1
1740 if any_type_tests_needed:
1741 env.use_utility_code(arg_type_test_utility_code)
1743 def bad_signature(self):
1744 sig = self.entry.signature
1745 expected_str = "%d" % sig.num_fixed_args()
1746 if sig.has_generic_args:
1747 expected_str = expected_str + " or more"
1748 name = self.name
1749 if name.startswith("__") and name.endswith("__"):
1750 desc = "Special method"
1751 else:
1752 desc = "Method"
1753 error(self.pos,
1754 "%s %s has wrong number of arguments "
1755 "(%d declared, %s expected)" % (
1756 desc, self.name, len(self.args), expected_str))
1758 def signature_has_nongeneric_args(self):
1759 argcount = len(self.args)
1760 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1761 return 0
1762 return 1
1764 def signature_has_generic_args(self):
1765 return self.entry.signature.has_generic_args
1767 def declare_pyfunction(self, env):
1768 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1769 name = self.name
1770 entry = env.lookup_here(self.name)
1771 if entry and entry.type.is_cfunction and not self.is_wrapper:
1772 warning(self.pos, "Overriding cdef method with def method.", 5)
1773 entry = env.declare_pyfunction(self.name, self.pos)
1774 self.entry = entry
1775 prefix = env.scope_prefix
1776 entry.func_cname = \
1777 Naming.pyfunc_prefix + prefix + name
1778 entry.pymethdef_cname = \
1779 Naming.pymethdef_prefix + prefix + name
1780 if Options.docstrings:
1781 entry.doc = embed_position(self.pos, self.doc)
1782 entry.doc_cname = \
1783 Naming.funcdoc_prefix + prefix + name
1784 else:
1785 entry.doc = None
1787 def declare_arguments(self, env):
1788 for arg in self.args:
1789 if not arg.name:
1790 error(arg.pos, "Missing argument name")
1791 if arg.needs_conversion:
1792 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1793 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1794 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1795 if arg.type.is_pyobject:
1796 arg.entry.init = "0"
1797 arg.entry.init_to_none = 0
1798 else:
1799 arg.entry = self.declare_argument(env, arg)
1800 arg.entry.used = 1
1801 arg.entry.is_self_arg = arg.is_self_arg
1802 if not arg.is_self_arg:
1803 arg.name_entry = env.get_string_const(
1804 arg.name, identifier = True)
1805 env.add_py_string(arg.name_entry, identifier = True)
1806 if arg.hdr_type:
1807 if arg.is_self_arg or \
1808 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1809 arg.entry.is_declared_generic = 1
1810 self.declare_python_arg(env, self.star_arg)
1811 self.declare_python_arg(env, self.starstar_arg)
1813 def declare_python_arg(self, env, arg):
1814 if arg:
1815 entry = env.declare_var(arg.name,
1816 PyrexTypes.py_object_type, arg.pos)
1817 entry.used = 1
1818 entry.init = "0"
1819 entry.init_to_none = 0
1820 entry.xdecref_cleanup = 1
1821 arg.entry = entry
1822 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1824 def analyse_expressions(self, env):
1825 self.analyse_default_values(env)
1826 if env.is_py_class_scope:
1827 self.synthesize_assignment_node(env)
1829 def synthesize_assignment_node(self, env):
1830 import ExprNodes
1831 self.assmt = SingleAssignmentNode(self.pos,
1832 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1833 rhs = ExprNodes.UnboundMethodNode(self.pos,
1834 class_cname = env.class_obj_cname,
1835 function = ExprNodes.PyCFunctionNode(self.pos,
1836 pymethdef_cname = self.entry.pymethdef_cname)))
1837 self.assmt.analyse_declarations(env)
1838 self.assmt.analyse_expressions(env)
1840 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1841 arg_code_list = []
1842 sig = self.entry.signature
1843 if sig.has_dummy_arg:
1844 arg_code_list.append(
1845 "PyObject *%s" % Naming.self_cname)
1846 for arg in self.args:
1847 if not arg.is_generic:
1848 if arg.is_self_arg:
1849 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1850 else:
1851 arg_code_list.append(
1852 arg.hdr_type.declaration_code(arg.hdr_cname))
1853 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1854 arg_code_list.append("PyObject *unused")
1855 if sig.has_generic_args:
1856 arg_code_list.append(
1857 "PyObject *%s, PyObject *%s"
1858 % (Naming.args_cname, Naming.kwds_cname))
1859 arg_code = ", ".join(arg_code_list)
1860 dc = self.return_type.declaration_code(self.entry.func_cname)
1861 header = "static %s(%s)" % (dc, arg_code)
1862 code.putln("%s; /*proto*/" % header)
1863 if proto_only:
1864 return
1865 if self.entry.doc and Options.docstrings:
1866 docstr = self.entry.doc
1867 if not isinstance(docstr, str):
1868 docstr = docstr.utf8encode()
1869 code.putln(
1870 'static char %s[] = "%s";' % (
1871 self.entry.doc_cname,
1872 split_docstring(escape_byte_string(docstr))))
1873 if with_pymethdef:
1874 code.put(
1875 "static PyMethodDef %s = " %
1876 self.entry.pymethdef_cname)
1877 code.put_pymethoddef(self.entry, ";")
1878 code.putln("%s {" % header)
1880 def generate_argument_declarations(self, env, code):
1881 for arg in self.args:
1882 if arg.is_generic: # or arg.needs_conversion:
1883 if arg.needs_conversion:
1884 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1885 else:
1886 code.put_var_declaration(arg.entry)
1888 def generate_keyword_list(self, code):
1889 if self.signature_has_generic_args() and \
1890 self.signature_has_nongeneric_args():
1891 code.put(
1892 "static PyObject **%s[] = {" %
1893 Naming.pykwdlist_cname)
1894 for arg in self.args:
1895 if arg.is_generic:
1896 code.put('&%s,' % arg.name_entry.pystring_cname)
1897 code.putln("0};")
1899 def generate_argument_parsing_code(self, env, code):
1900 # Generate PyArg_ParseTuple call for generic
1901 # arguments, if any.
1902 if self.entry.signature.has_dummy_arg:
1903 # get rid of unused argument warning
1904 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1906 old_error_label = code.new_error_label()
1907 our_error_label = code.error_label
1908 end_label = code.new_label("argument_unpacking_done")
1910 has_kwonly_args = self.num_kwonly_args > 0
1911 has_star_or_kw_args = self.star_arg is not None \
1912 or self.starstar_arg is not None or has_kwonly_args
1914 if not self.signature_has_generic_args():
1915 if has_star_or_kw_args:
1916 error(self.pos, "This method cannot have * or keyword arguments")
1917 self.generate_argument_conversion_code(code)
1919 elif not self.signature_has_nongeneric_args():
1920 # func(*args) or func(**kw) or func(*args, **kw)
1921 self.generate_stararg_copy_code(code)
1923 else:
1924 positional_args = []
1925 kw_only_args = []
1926 default_seen = 0
1927 for arg in self.args:
1928 arg_entry = arg.entry
1929 if arg.is_generic:
1930 if arg.default:
1931 default_seen = 1
1932 if not arg.is_self_arg:
1933 if arg.kw_only:
1934 kw_only_args.append(arg)
1935 else:
1936 positional_args.append(arg)
1937 elif arg.kw_only:
1938 kw_only_args.append(arg)
1939 default_seen = 1
1940 elif default_seen:
1941 error(arg.pos, "Non-default argument following default argument")
1942 elif not arg.is_self_arg:
1943 positional_args.append(arg)
1945 self.generate_tuple_and_keyword_parsing_code(
1946 positional_args, kw_only_args, end_label, code)
1948 code.error_label = old_error_label
1949 if code.label_used(our_error_label):
1950 if not code.label_used(end_label):
1951 code.put_goto(end_label)
1952 code.put_label(our_error_label)
1953 if has_star_or_kw_args:
1954 self.generate_arg_decref(self.star_arg, code)
1955 if self.starstar_arg:
1956 if self.starstar_arg.entry.xdecref_cleanup:
1957 code.put_var_xdecref(self.starstar_arg.entry)
1958 else:
1959 code.put_var_decref(self.starstar_arg.entry)
1960 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1961 code.putln("return %s;" % self.error_value())
1962 if code.label_used(end_label):
1963 code.put_label(end_label)
1965 def generate_arg_assignment(self, arg, item, code):
1966 if arg.type.is_pyobject:
1967 if arg.is_generic:
1968 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1969 code.putln("%s = %s;" % (arg.entry.cname, item))
1970 else:
1971 func = arg.type.from_py_function
1972 if func:
1973 code.putln("%s = %s(%s); %s" % (
1974 arg.entry.cname,
1975 func,
1976 item,
1977 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1978 else:
1979 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1981 def generate_arg_xdecref(self, arg, code):
1982 if arg:
1983 code.put_var_xdecref(arg.entry)
1985 def generate_arg_decref(self, arg, code):
1986 if arg:
1987 code.put_var_decref(arg.entry)
1989 def generate_stararg_copy_code(self, code):
1990 if not self.star_arg:
1991 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1992 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1993 Naming.args_cname)
1994 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
1995 self.name.utf8encode(), Naming.args_cname, self.error_value()))
1996 code.putln("}")
1998 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2000 if self.starstar_arg:
2001 if self.star_arg:
2002 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2003 else:
2004 kwarg_check = "%s" % Naming.kwds_cname
2005 else:
2006 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2007 Naming.kwds_cname, Naming.kwds_cname)
2008 code.putln(
2009 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2010 kwarg_check, Naming.kwds_cname, self.name,
2011 bool(self.starstar_arg), self.error_value()))
2013 if self.starstar_arg:
2014 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2015 self.starstar_arg.entry.cname,
2016 Naming.kwds_cname,
2017 Naming.kwds_cname))
2018 code.putln("if (unlikely(!%s)) return %s;" % (
2019 self.starstar_arg.entry.cname, self.error_value()))
2020 self.starstar_arg.entry.xdecref_cleanup = 0
2021 code.put_gotref(self.starstar_arg.entry.cname)
2024 if self.star_arg:
2025 code.put_incref(Naming.args_cname, py_object_type)
2026 code.putln("%s = %s;" % (
2027 self.star_arg.entry.cname,
2028 Naming.args_cname))
2029 self.star_arg.entry.xdecref_cleanup = 0
2031 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2032 kw_only_args, success_label, code):
2033 argtuple_error_label = code.new_label("argtuple_error")
2035 min_positional_args = self.num_required_args - self.num_required_kw_args
2036 if len(self.args) > 0 and self.args[0].is_self_arg:
2037 min_positional_args -= 1
2038 max_positional_args = len(positional_args)
2039 has_fixed_positional_count = not self.star_arg and \
2040 min_positional_args == max_positional_args
2042 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2043 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2044 if self.num_required_kw_args:
2045 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2047 if self.starstar_arg or self.star_arg:
2048 self.generate_stararg_init_code(max_positional_args, code)
2050 # --- optimised code when we receive keyword arguments
2051 if self.num_required_kw_args:
2052 likely_hint = "likely"
2053 else:
2054 likely_hint = "unlikely"
2055 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2056 self.generate_keyword_unpacking_code(
2057 min_positional_args, max_positional_args,
2058 has_fixed_positional_count,
2059 positional_args, kw_only_args, argtuple_error_label, code)
2061 # --- optimised code when we do not receive any keyword arguments
2062 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2063 # Python raises arg tuple related errors first, so we must
2064 # check the length here
2065 if min_positional_args == max_positional_args and not self.star_arg:
2066 compare = '!='
2067 else:
2068 compare = '<'
2069 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2070 Naming.args_cname, compare, min_positional_args))
2071 code.put_goto(argtuple_error_label)
2073 if self.num_required_kw_args:
2074 # pure error case: keywords required but not passed
2075 if max_positional_args > min_positional_args and not self.star_arg:
2076 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2077 Naming.args_cname, max_positional_args))
2078 code.put_goto(argtuple_error_label)
2079 code.putln('} else {')
2080 for i, arg in enumerate(kw_only_args):
2081 if not arg.default:
2082 # required keyword-only argument missing
2083 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2084 self.name.utf8encode(),
2085 arg.name_entry.pystring_cname))
2086 code.putln(code.error_goto(self.pos))
2087 break
2089 elif min_positional_args == max_positional_args:
2090 # parse the exact number of positional arguments from the
2091 # args tuple
2092 code.putln('} else {')
2093 for i, arg in enumerate(positional_args):
2094 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2095 self.generate_arg_assignment(arg, item, code)
2096 self.generate_arg_default_assignments(code)
2098 else:
2099 # parse the positional arguments from the variable length
2100 # args tuple
2101 code.putln('} else {')
2102 self.generate_arg_default_assignments(code)
2103 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2104 if self.star_arg:
2105 code.putln('default:')
2106 reversed_args = list(enumerate(positional_args))[::-1]
2107 for i, arg in reversed_args:
2108 if i >= min_positional_args-1:
2109 if min_positional_args > 1:
2110 code.putln('case %2d:' % (i+1)) # pure code beautification
2111 else:
2112 code.put('case %2d: ' % (i+1))
2113 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2114 self.generate_arg_assignment(arg, item, code)
2115 if min_positional_args == 0:
2116 code.put('case 0: ')
2117 code.putln('break;')
2118 if self.star_arg:
2119 if min_positional_args:
2120 for i in range(min_positional_args-1, -1, -1):
2121 code.putln('case %2d:' % i)
2122 code.put_goto(argtuple_error_label)
2123 else:
2124 code.put('default: ')
2125 code.put_goto(argtuple_error_label)
2126 code.putln('}')
2128 code.putln('}')
2130 if code.label_used(argtuple_error_label):
2131 code.put_goto(success_label)
2132 code.put_label(argtuple_error_label)
2133 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2134 self.name.utf8encode(), has_fixed_positional_count,
2135 min_positional_args, max_positional_args,
2136 Naming.args_cname))
2137 code.putln(code.error_goto(self.pos))
2139 def generate_arg_default_assignments(self, code):
2140 for arg in self.args:
2141 if arg.is_generic and arg.default:
2142 code.putln(
2143 "%s = %s;" % (
2144 arg.entry.cname,
2145 arg.default_result_code))
2147 def generate_stararg_init_code(self, max_positional_args, code):
2148 if self.starstar_arg:
2149 self.starstar_arg.entry.xdecref_cleanup = 0
2150 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2151 self.starstar_arg.entry.cname,
2152 self.starstar_arg.entry.cname,
2153 self.error_value()))
2154 code.put_gotref(self.starstar_arg.entry.cname)
2155 if self.star_arg:
2156 self.star_arg.entry.xdecref_cleanup = 0
2157 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2158 Naming.args_cname,
2159 max_positional_args))
2160 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2161 self.star_arg.entry.cname, Naming.args_cname,
2162 max_positional_args, Naming.args_cname))
2163 code.put_gotref(self.star_arg.entry.cname)
2164 if self.starstar_arg:
2165 code.putln("")
2166 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2167 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2168 code.putln('return %s;' % self.error_value())
2169 code.putln('}')
2170 else:
2171 code.putln("if (unlikely(!%s)) return %s;" % (
2172 self.star_arg.entry.cname, self.error_value()))
2173 code.putln('} else {')
2174 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2175 code.put_incref(Naming.empty_tuple, py_object_type)
2176 code.putln('}')
2178 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2179 has_fixed_positional_count, positional_args,
2180 kw_only_args, argtuple_error_label, code):
2181 all_args = tuple(positional_args) + tuple(kw_only_args)
2182 max_args = len(all_args)
2184 default_args = []
2185 for i, arg in enumerate(all_args):
2186 if arg.default and arg.type.is_pyobject:
2187 default_value = arg.default_result_code
2188 if arg.type is not PyrexTypes.py_object_type:
2189 default_value = "(PyObject*)"+default_value
2190 default_args.append((i, default_value))
2192 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2193 Naming.kwds_cname)
2194 # it looks funny to separate the init-to-0 from setting the
2195 # default value, but C89 needs this
2196 code.putln("PyObject* values[%d] = {%s};" % (
2197 max_args, ','.join(['0']*max_args)))
2198 for i, default_value in default_args:
2199 code.putln('values[%d] = %s;' % (i, default_value))
2201 # parse the tuple and check that it's not too long
2202 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2203 if self.star_arg:
2204 code.putln('default:')
2205 for i in range(max_positional_args-1, -1, -1):
2206 code.put('case %2d: ' % (i+1))
2207 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2208 i, Naming.args_cname, i))
2209 code.putln('case 0: break;')
2210 if not self.star_arg:
2211 code.put('default: ') # more arguments than allowed
2212 code.put_goto(argtuple_error_label)
2213 code.putln('}')
2215 # now fill up the positional/required arguments with values
2216 # from the kw dict
2217 if self.num_required_args or max_positional_args > 0:
2218 last_required_arg = -1
2219 for i, arg in enumerate(all_args):
2220 if not arg.default:
2221 last_required_arg = i
2222 if last_required_arg < max_positional_args:
2223 last_required_arg = max_positional_args-1
2224 num_required_args = self.num_required_args
2225 if max_positional_args > 0:
2226 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2227 for i, arg in enumerate(all_args[:last_required_arg+1]):
2228 if max_positional_args > 0 and i <= max_positional_args:
2229 if self.star_arg and i == max_positional_args:
2230 code.putln('default:')
2231 else:
2232 code.putln('case %2d:' % i)
2233 if arg.default:
2234 if arg.kw_only:
2235 # handled separately below
2236 continue
2237 code.putln('if (kw_args > %d) {' % num_required_args)
2238 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2239 Naming.kwds_cname, arg.name_entry.pystring_cname))
2240 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2241 code.putln('}')
2242 else:
2243 num_required_args -= 1
2244 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2245 i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2246 code.putln('if (likely(values[%d])) kw_args--;' % i);
2247 if i < min_positional_args:
2248 if i == 0:
2249 # special case: we know arg 0 is missing
2250 code.put('else ')
2251 code.put_goto(argtuple_error_label)
2252 else:
2253 # print the correct number of values (args or
2254 # kwargs) that were passed into positional
2255 # arguments up to this point
2256 code.putln('else {')
2257 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2258 self.name.utf8encode(), has_fixed_positional_count,
2259 min_positional_args, max_positional_args, i))
2260 code.putln(code.error_goto(self.pos))
2261 code.putln('}')
2262 elif arg.kw_only:
2263 code.putln('else {')
2264 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2265 self.name.utf8encode(), arg.name_entry.pystring_cname))
2266 code.putln(code.error_goto(self.pos))
2267 code.putln('}')
2268 if max_positional_args > 0:
2269 code.putln('}')
2271 if kw_only_args and not self.starstar_arg:
2272 # unpack optional keyword-only arguments
2273 # checking for interned strings in a dict is faster than iterating
2274 # but it's too likely that we must iterate if we expect **kwargs
2275 optional_args = []
2276 for i, arg in enumerate(all_args[max_positional_args:]):
2277 if not arg.kw_only or not arg.default:
2278 continue
2279 optional_args.append((i+max_positional_args, arg))
2280 if optional_args:
2281 # this mimics an unrolled loop so that we can "break" out of it
2282 code.putln('while (kw_args > 0) {')
2283 code.putln('PyObject* value;')
2284 for i, arg in optional_args:
2285 code.putln(
2286 'value = PyDict_GetItem(%s, %s);' % (
2287 Naming.kwds_cname, arg.name_entry.pystring_cname))
2288 code.putln(
2289 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2290 code.putln('break;')
2291 code.putln('}')
2293 code.putln('if (unlikely(kw_args > 0)) {')
2294 # non-positional/-required kw args left in dict: default args,
2295 # kw-only args, **kwargs or error
2297 # This is sort of a catch-all: except for checking required
2298 # arguments, this will always do the right thing for unpacking
2299 # keyword arguments, so that we can concentrate on optimising
2300 # common cases above.
2301 if max_positional_args == 0:
2302 pos_arg_count = "0"
2303 elif self.star_arg:
2304 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2305 Naming.args_cname, max_positional_args,
2306 Naming.args_cname, max_positional_args))
2307 pos_arg_count = "used_pos_args"
2308 else:
2309 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2310 code.globalstate.use_utility_code(parse_keywords_utility_code)
2311 code.put(
2312 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2313 Naming.kwds_cname,
2314 Naming.pykwdlist_cname,
2315 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2316 pos_arg_count,
2317 self.name.utf8encode()))
2318 code.putln(code.error_goto(self.pos))
2319 code.putln('}')
2321 # convert arg values to their final type and assign them
2322 for i, arg in enumerate(all_args):
2323 if arg.default and not arg.type.is_pyobject:
2324 code.putln("if (values[%d]) {" % i)
2325 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2326 if arg.default and not arg.type.is_pyobject:
2327 code.putln('} else {')
2328 code.putln(
2329 "%s = %s;" % (
2330 arg.entry.cname,
2331 arg.default_result_code))
2332 code.putln('}')
2334 def generate_argument_conversion_code(self, code):
2335 # Generate code to convert arguments from
2336 # signature type to declared type, if needed.
2337 for arg in self.args:
2338 if arg.needs_conversion:
2339 self.generate_arg_conversion(arg, code)
2341 def generate_arg_conversion(self, arg, code):
2342 # Generate conversion code for one argument.
2343 old_type = arg.hdr_type
2344 new_type = arg.type
2345 if old_type.is_pyobject:
2346 if arg.default:
2347 code.putln("if (%s) {" % arg.hdr_cname)
2348 else:
2349 code.putln("assert(%s); {" % arg.hdr_cname)
2350 self.generate_arg_conversion_from_pyobject(arg, code)
2351 code.putln("}")
2352 elif new_type.is_pyobject:
2353 self.generate_arg_conversion_to_pyobject(arg, code)
2354 else:
2355 if new_type.assignable_from(old_type):
2356 code.putln(
2357 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2358 else:
2359 error(arg.pos,
2360 "Cannot convert 1 argument from '%s' to '%s'" %
2361 (old_type, new_type))
2363 def generate_arg_conversion_from_pyobject(self, arg, code):
2364 new_type = arg.type
2365 func = new_type.from_py_function
2366 # copied from CoerceFromPyTypeNode
2367 if func:
2368 code.putln("%s = %s(%s); %s" % (
2369 arg.entry.cname,
2370 func,
2371 arg.hdr_cname,
2372 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2373 else:
2374 error(arg.pos,
2375 "Cannot convert Python object argument to type '%s'"
2376 % new_type)
2378 def generate_arg_conversion_to_pyobject(self, arg, code):
2379 old_type = arg.hdr_type
2380 func = old_type.to_py_function
2381 if func:
2382 code.putln("%s = %s(%s); %s" % (
2383 arg.entry.cname,
2384 func,
2385 arg.hdr_cname,
2386 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2387 code.put_var_gotref(arg.entry)
2388 else:
2389 error(arg.pos,
2390 "Cannot convert argument of type '%s' to Python object"
2391 % old_type)
2393 def generate_argument_type_tests(self, code):
2394 # Generate type tests for args whose signature
2395 # type is PyObject * and whose declared type is
2396 # a subtype thereof.
2397 for arg in self.args:
2398 if arg.needs_type_test:
2399 self.generate_arg_type_test(arg, code)
2401 def generate_arg_type_test(self, arg, code):
2402 # Generate type test for one argument.
2403 if arg.type.typeobj_is_available():
2404 typeptr_cname = arg.type.typeptr_cname
2405 arg_code = "((PyObject *)%s)" % arg.entry.cname
2406 code.putln(
2407 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2408 arg_code,
2409 typeptr_cname,
2410 not arg.not_none,
2411 arg.name,
2412 arg.type.is_builtin_type,
2413 code.error_goto(arg.pos)))
2414 else:
2415 error(arg.pos, "Cannot test type of extern C class "
2416 "without type object name specification")
2418 def error_value(self):
2419 return self.entry.signature.error_value
2421 def caller_will_check_exceptions(self):
2422 return 1
2424 class OverrideCheckNode(StatNode):
2425 # A Node for dispatching to the def method if it
2426 # is overriden.
2428 # py_func
2430 # args
2431 # func_temp
2432 # body
2434 child_attrs = ['body']
2436 body = None
2438 def analyse_expressions(self, env):
2439 self.args = env.arg_entries
2440 if self.py_func.is_module_scope:
2441 first_arg = 0
2442 else:
2443 first_arg = 1
2444 import ExprNodes
2445 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2446 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2447 call_node = ExprNodes.SimpleCallNode(self.pos,
2448 function=self.func_node,
2449 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2450 self.body = ReturnStatNode(self.pos, value=call_node)
2451 self.body.analyse_expressions(env)
2453 def generate_execution_code(self, code):
2454 # Check to see if we are an extension type
2455 if self.py_func.is_module_scope:
2456 self_arg = "((PyObject *)%s)" % Naming.module_cname
2457 else:
2458 self_arg = "((PyObject *)%s)" % self.args[0].cname
2459 code.putln("/* Check if called by wrapper */")
2460 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2461 code.putln("/* Check if overriden in Python */")
2462 if self.py_func.is_module_scope:
2463 code.putln("else {")
2464 else:
2465 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2466 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2467 # need to get attribute manually--scope would return cdef method
2468 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2469 code.put_gotref(self.func_node.py_result())
2470 is_builtin_function_or_method = 'PyCFunction_Check(%s)' % self.func_node.result()
2471 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2472 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2473 self.body.generate_execution_code(code)
2474 code.putln('}')
2475 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2476 code.putln("}")
2478 class ClassDefNode(StatNode, BlockNode):
2479 pass
2481 class PyClassDefNode(ClassDefNode):
2482 # A Python class definition.
2484 # name EncodedString Name of the class
2485 # doc string or None
2486 # body StatNode Attribute definition code
2487 # entry Symtab.Entry
2488 # scope PyClassScope
2490 # The following subnodes are constructed internally:
2492 # dict DictNode Class dictionary
2493 # classobj ClassNode Class object
2494 # target NameNode Variable to assign class object to
2496 child_attrs = ["body", "dict", "classobj", "target"]
2498 def __init__(self, pos, name, bases, doc, body):
2499 StatNode.__init__(self, pos)
2500 self.name = name
2501 self.doc = doc
2502 self.body = body
2503 import ExprNodes
2504 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2505 if self.doc and Options.docstrings:
2506 doc = embed_position(self.pos, self.doc)
2507 doc_node = ExprNodes.StringNode(pos, value = doc)
2508 else:
2509 doc_node = None
2510 self.classobj = ExprNodes.ClassNode(pos, name = name,
2511 bases = bases, dict = self.dict, doc = doc_node)
2512 self.target = ExprNodes.NameNode(pos, name = name)
2514 def as_cclass(self):
2515 """
2516 Return this node as if it were declared as an extension class
2517 """
2518 bases = self.classobj.bases.args
2519 if len(bases) == 0:
2520 base_class_name = None
2521 base_class_module = None
2522 elif len(bases) == 1:
2523 base = bases[0]
2524 path = []
2525 from ExprNodes import AttributeNode, NameNode
2526 while isinstance(base, AttributeNode):
2527 path.insert(0, base.attribute)
2528 base = base.obj
2529 if isinstance(base, NameNode):
2530 path.insert(0, base.name)
2531 base_class_name = path[-1]
2532 if len(path) > 1:
2533 base_class_module = u'.'.join(path[:-1])
2534 else:
2535 base_class_module = None
2536 else:
2537 error(self.classobj.bases.args.pos, "Invalid base class")
2538 else:
2539 error(self.classobj.bases.args.pos, "C class may only have one base class")
2540 return None
2542 return CClassDefNode(self.pos,
2543 visibility = 'private',
2544 module_name = None,
2545 class_name = self.name,
2546 base_class_module = base_class_module,
2547 base_class_name = base_class_name,
2548 body = self.body,
2549 in_pxd = False,
2550 doc = self.doc)
2552 def create_scope(self, env):
2553 genv = env
2554 while env.is_py_class_scope or env.is_c_class_scope:
2555 env = env.outer_scope
2556 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2557 return cenv
2559 def analyse_declarations(self, env):
2560 self.target.analyse_target_declaration(env)
2561 cenv = self.create_scope(env)
2562 cenv.class_obj_cname = self.target.entry.cname
2563 self.body.analyse_declarations(cenv)
2565 def analyse_expressions(self, env):
2566 self.dict.analyse_expressions(env)
2567 self.classobj.analyse_expressions(env)
2568 genv = env.global_scope()
2569 cenv = self.scope
2570 cenv.class_dict_cname = self.dict.result()
2571 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2572 self.body.analyse_expressions(cenv)
2573 self.target.analyse_target_expression(env, self.classobj)
2574 self.dict.release_temp(env)
2575 #self.classobj.release_temp(env)
2576 #self.target.release_target_temp(env)
2578 def generate_function_definitions(self, env, code):
2579 self.generate_py_string_decls(self.scope, code)
2580 self.body.generate_function_definitions(self.scope, code)
2582 def generate_execution_code(self, code):
2583 self.dict.generate_evaluation_code(code)
2584 self.classobj.generate_evaluation_code(code)
2585 self.body.generate_execution_code(code)
2586 self.target.generate_assignment_code(self.classobj, code)
2587 self.dict.generate_disposal_code(code)
2588 self.dict.free_temps(code)
2591 class CClassDefNode(ClassDefNode):
2592 # An extension type definition.
2594 # visibility 'private' or 'public' or 'extern'
2595 # typedef_flag boolean
2596 # api boolean
2597 # module_name string or None For import of extern type objects
2598 # class_name string Unqualified name of class
2599 # as_name string or None Name to declare as in this scope
2600 # base_class_module string or None Module containing the base class
2601 # base_class_name string or None Name of the base class
2602 # objstruct_name string or None Specified C name of object struct
2603 # typeobj_name string or None Specified C name of type object
2604 # in_pxd boolean Is in a .pxd file
2605 # doc string or None
2606 # body StatNode or None
2607 # entry Symtab.Entry
2608 # base_type PyExtensionType or None
2609 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2610 # buffer_defaults_pos
2612 child_attrs = ["body"]
2613 buffer_defaults_node = None
2614 buffer_defaults_pos = None
2615 typedef_flag = False
2616 api = False
2617 objstruct_name = None
2618 typeobj_name = None
2620 def analyse_declarations(self, env):
2621 #print "CClassDefNode.analyse_declarations:", self.class_name
2622 #print "...visibility =", self.visibility
2623 #print "...module_name =", self.module_name
2625 import Buffer
2626 if self.buffer_defaults_node:
2627 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2628 env, [], self.buffer_defaults_node,
2629 need_complete=False)
2630 else:
2631 buffer_defaults = None
2633 if env.in_cinclude and not self.objstruct_name:
2634 error(self.pos, "Object struct name specification required for "
2635 "C class defined in 'extern from' block")
2636 self.base_type = None
2637 # Now that module imports are cached, we need to
2638 # import the modules for extern classes.
2639 if self.module_name:
2640 self.module = None
2641 for module in env.cimported_modules:
2642 if module.name == self.module_name:
2643 self.module = module
2644 if self.module is None:
2645 self.module = ModuleScope(self.module_name, None, env.context)
2646 self.module.has_extern_class = 1
2647 env.add_imported_module(self.module)
2649 if self.base_class_name:
2650 if self.base_class_module:
2651 base_class_scope = env.find_module(self.base_class_module, self.pos)
2652 else:
2653 base_class_scope = env
2654 if self.base_class_name == 'object':
2655 # extension classes are special and don't need to inherit from object
2656 if base_class_scope is None or base_class_scope.lookup('object') is None:
2657 self.base_class_name = None
2658 self.base_class_module = None
2659 base_class_scope = None
2660 if base_class_scope:
2661 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2662 if base_class_entry:
2663 if not base_class_entry.is_type:
2664 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2665 elif not base_class_entry.type.is_extension_type:
2666 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2667 elif not base_class_entry.type.is_complete():
2668 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2669 else:
2670 self.base_type = base_class_entry.type
2671 has_body = self.body is not None
2672 if self.module_name and self.visibility != 'extern':
2673 module_path = self.module_name.split(".")
2674 home_scope = env.find_imported_module(module_path, self.pos)
2675 if not home_scope:
2676 return
2677 else:
2678 home_scope = env
2679 self.entry = home_scope.declare_c_class(
2680 name = self.class_name,
2681 pos = self.pos,
2682 defining = has_body and self.in_pxd,
2683 implementing = has_body and not self.in_pxd,
2684 module_name = self.module_name,
2685 base_type = self.base_type,
2686 objstruct_cname = self.objstruct_name,
2687 typeobj_cname = self.typeobj_name,
2688 visibility = self.visibility,
2689 typedef_flag = self.typedef_flag,
2690 api = self.api,
2691 buffer_defaults = buffer_defaults)
2692 if home_scope is not env and self.visibility == 'extern':
2693 env.add_imported_entry(self.class_name, self.entry, pos)
2694 scope = self.entry.type.scope
2696 if self.doc and Options.docstrings:
2697 scope.doc = embed_position(self.pos, self.doc)
2699 if has_body:
2700 self.body.analyse_declarations(scope)
2701 if self.in_pxd:
2702 scope.defined = 1
2703 else:
2704 scope.implemented = 1
2705 env.allocate_vtable_names(self.entry)
2707 def analyse_expressions(self, env):
2708 if self.body:
2709 scope = self.entry.type.scope
2710 self.body.analyse_expressions(scope)
2712 def generate_function_definitions(self, env, code):
2713 self.generate_py_string_decls(self.entry.type.scope, code)
2714 if self.body:
2715 self.body.generate_function_definitions(
2716 self.entry.type.scope, code)
2718 def generate_execution_code(self, code):
2719 # This is needed to generate evaluation code for
2720 # default values of method arguments.
2721 if self.body:
2722 self.body.generate_execution_code(code)
2724 def annotate(self, code):
2725 if self.body:
2726 self.body.annotate(code)
2729 class PropertyNode(StatNode):
2730 # Definition of a property in an extension type.
2732 # name string
2733 # doc EncodedString or None Doc string
2734 # body StatListNode
2736 child_attrs = ["body"]
2738 def analyse_declarations(self, env):
2739 entry = env.declare_property(self.name, self.doc, self.pos)
2740 if entry:
2741 if self.doc and Options.docstrings:
2742 doc_entry = env.get_string_const(
2743 self.doc, identifier = False)
2744 entry.doc_cname = doc_entry.cname
2745 self.body.analyse_declarations(entry.scope)
2747 def analyse_expressions(self, env):
2748 self.body.analyse_expressions(env)
2750 def generate_function_definitions(self, env, code):
2751 self.body.generate_function_definitions(env, code)
2753 def generate_execution_code(self, code):
2754 pass
2756 def annotate(self, code):
2757 self.body.annotate(code)
2760 class GlobalNode(StatNode):
2761 # Global variable declaration.
2763 # names [string]
2765 child_attrs = []
2767 def analyse_declarations(self, env):
2768 for name in self.names:
2769 env.declare_global(name, self.pos)
2771 def analyse_expressions(self, env):
2772 pass
2774 def generate_execution_code(self, code):
2775 pass
2778 class ExprStatNode(StatNode):
2779 # Expression used as a statement.
2781 # expr ExprNode
2783 child_attrs = ["expr"]
2785 def analyse_declarations(self, env):
2786 import ExprNodes
2787 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2788 func = self.expr.function.as_cython_attribute()
2789 if func == u'declare':
2790 args, kwds = self.expr.explicit_args_kwds()
2791 if len(args):
2792 error(self.expr.pos, "Variable names must be specified.")
2793 for var, type_node in kwds.key_value_pairs:
2794 type = type_node.analyse_as_type(env)
2795 if type is None:
2796 error(type_node.pos, "Unknown type")
2797 else:
2798 env.declare_var(var.value, type, var.pos, is_cdef = True)
2799 self.__class__ = PassStatNode
2801 def analyse_expressions(self, env):
2802 self.expr.analyse_expressions(env)
2803 self.expr.release_temp(env)
2805 def generate_execution_code(self, code):
2806 self.expr.generate_evaluation_code(code)
2807 if not self.expr.is_temp and self.expr.result():
2808 code.putln("%s;" % self.expr.result())
2809 self.expr.generate_disposal_code(code)
2810 self.expr.free_temps(code)
2812 def annotate(self, code):
2813 self.expr.annotate(code)
2816 class AssignmentNode(StatNode):
2817 # Abstract base class for assignment nodes.
2819 # The analyse_expressions and generate_execution_code
2820 # phases of assignments are split into two sub-phases
2821 # each, to enable all the right hand sides of a
2822 # parallel assignment to be evaluated before assigning
2823 # to any of the left hand sides.
2825 def analyse_expressions(self, env):
2826 self.analyse_types(env)
2827 self.allocate_rhs_temps(env)
2828 self.allocate_lhs_temps(env)
2830 # def analyse_expressions(self, env):
2831 # self.analyse_expressions_1(env)
2832 # self.analyse_expressions_2(env)
2834 def generate_execution_code(self, code):
2835 self.generate_rhs_evaluation_code(code)
2836 self.generate_assignment_code(code)
2839 class SingleAssignmentNode(AssignmentNode):
2840 # The simplest case:
2842 # a = b
2844 # lhs ExprNode Left hand side
2845 # rhs ExprNode Right hand side
2846 # first bool Is this guaranteed the first assignment to lhs?
2848 child_attrs = ["lhs", "rhs"]
2849 first = False
2850 declaration_only = False
2852 def analyse_declarations(self, env):
2853 import ExprNodes
2855 # handle declarations of the form x = cython.foo()
2856 if isinstance(self.rhs, ExprNodes.CallNode):
2857 func_name = self.rhs.function.as_cython_attribute()
2858 if func_name:
2859 args, kwds = self.rhs.explicit_args_kwds()
2861 if func_name in ['declare', 'typedef']:
2862 if len(args) > 2 or kwds is not None:
2863 error(rhs.pos, "Can only declare one type at a time.")
2864 return
2865 type = args[0].analyse_as_type(env)
2866 if type is None:
2867 error(args[0].pos, "Unknown type")
2868 return
2869 lhs = self.lhs
2870 if func_name == 'declare':
2871 if isinstance(lhs, ExprNodes.NameNode):
2872 vars = [(lhs.name, lhs.pos)]
2873 elif isinstance(lhs, ExprNodes.TupleNode):
2874 vars = [(var.name, var.pos) for var in lhs.args]
2875 else:
2876 error(lhs.pos, "Invalid declaration")
2877 return
2878 for var, pos in vars:
2879 env.declare_var(var, type, pos, is_cdef = True)
2880 if len(args) == 2:
2881 # we have a value
2882 self.rhs = args[1]
2883 else:
2884 self.declaration_only = True
2885 else:
2886 self.declaration_only = True
2887 if not isinstance(lhs, ExprNodes.NameNode):
2888 error(lhs.pos, "Invalid declaration.")
2889 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2891 elif func_name in ['struct', 'union']:
2892 self.declaration_only = True
2893 if len(args) > 0 or kwds is None:
2894 error(rhs.pos, "Struct or union members must be given by name.")
2895 return
2896 members = []
2897 for member, type_node in kwds.key_value_pairs:
2898 type = type_node.analyse_as_type(env)
2899 if type is None:
2900 error(type_node.pos, "Unknown type")
2901 else:
2902 members.append((member.value, type, member.pos))
2903 if len(members) < len(kwds.key_value_pairs):
2904 return
2905 if not isinstance(self.lhs, ExprNodes.NameNode):
2906 error(self.lhs.pos, "Invalid declaration.")
2907 name = self.lhs.name
2908 scope = StructOrUnionScope(name)
2909 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2910 for member, type, pos in members:
2911 scope.declare_var(member, type, pos)
2913 if self.declaration_only:
2914 return
2915 else:
2916 self.lhs.analyse_target_declaration(env)
2918 def analyse_types(self, env, use_temp = 0):
2919 self.rhs.analyse_types(env)
2920 self.lhs.analyse_target_types(env)
2921 self.lhs.gil_assignment_check(env)
2922 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2923 if use_temp:
2924 self.rhs = self.rhs.coerce_to_temp(env)
2926 def allocate_rhs_temps(self, env):
2927 self.rhs.allocate_temps(env)
2929 def allocate_lhs_temps(self, env):
2930 self.lhs.allocate_target_temps(env, self.rhs)
2931 #self.lhs.release_target_temp(env)
2932 #self.rhs.release_temp(env)
2934 def generate_rhs_evaluation_code(self, code):
2935 self.rhs.generate_evaluation_code(code)
2937 def generate_assignment_code(self, code):
2938 self.lhs.generate_assignment_code(self.rhs, code)
2940 def annotate(self, code):
2941 self.lhs.annotate(code)
2942 self.rhs.annotate(code)
2945 class CascadedAssignmentNode(AssignmentNode):
2946 # An assignment with multiple left hand sides:
2948 # a = b = c
2950 # lhs_list [ExprNode] Left hand sides
2951 # rhs ExprNode Right hand sides
2953 # Used internally:
2955 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2957 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2958 coerced_rhs_list = None
2960 def analyse_declarations(self, env):
2961 for lhs in self.lhs_list:
2962 lhs.analyse_target_declaration(env)
2964 def analyse_types(self, env, use_temp = 0):
2965 self.rhs.analyse_types(env)
2966 if use_temp:
2967 self.rhs = self.rhs.coerce_to_temp(env)
2968 else:
2969 self.rhs = self.rhs.coerce_to_simple(env)
2970 from ExprNodes import CloneNode
2971 self.coerced_rhs_list = []
2972 for lhs in self.lhs_list:
2973 lhs.analyse_target_types(env)
2974 lhs.gil_assignment_check(env)
2975 rhs = CloneNode(self.rhs)
2976 rhs = rhs.coerce_to(lhs.type, env)
2977 self.coerced_rhs_list.append(rhs)
2979 def allocate_rhs_temps(self, env):
2980 self.rhs.allocate_temps(env)
2982 def allocate_lhs_temps(self, env):
2983 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2984 rhs.allocate_temps(env)
2985 lhs.allocate_target_temps(env, rhs)
2986 #lhs.release_target_temp(env)
2987 #rhs.release_temp(env)
2988 self.rhs.release_temp(env)
2990 def generate_rhs_evaluation_code(self, code):
2991 self.rhs.generate_evaluation_code(code)
2993 def generate_assignment_code(self, code):
2994 for i in range(len(self.lhs_list)):
2995 lhs = self.lhs_list[i]
2996 rhs = self.coerced_rhs_list[i]
2997 rhs.generate_evaluation_code(code)
2998 lhs.generate_assignment_code(rhs, code)
2999 # Assignment has disposed of the cloned RHS
3000 self.rhs.generate_disposal_code(code)
3001 self.rhs.free_temps(code)
3003 def annotate(self, code):
3004 for i in range(len(self.lhs_list)):
3005 lhs = self.lhs_list[i].annotate(code)
3006 rhs = self.coerced_rhs_list[i].annotate(code)
3007 self.rhs.annotate(code)
3010 class ParallelAssignmentNode(AssignmentNode):
3011 # A combined packing/unpacking assignment:
3013 # a, b, c = d, e, f
3015 # This has been rearranged by the parser into
3017 # a = d ; b = e ; c = f
3019 # but we must evaluate all the right hand sides
3020 # before assigning to any of the left hand sides.
3022 # stats [AssignmentNode] The constituent assignments
3024 child_attrs = ["stats"]
3026 def analyse_declarations(self, env):
3027 for stat in self.stats:
3028 stat.analyse_declarations(env)
3030 def analyse_expressions(self, env):
3031 for stat in self.stats:
3032 stat.analyse_types(env, use_temp = 1)
3033 stat.allocate_rhs_temps(env)
3034 for stat in self.stats:
3035 stat.allocate_lhs_temps(env)
3037 # def analyse_expressions(self, env):
3038 # for stat in self.stats:
3039 # stat.analyse_expressions_1(env, use_temp = 1)
3040 # for stat in self.stats:
3041 # stat.analyse_expressions_2(env)
3043 def generate_execution_code(self, code):
3044 for stat in self.stats:
3045 stat.generate_rhs_evaluation_code(code)
3046 for stat in self.stats:
3047 stat.generate_assignment_code(code)
3049 def annotate(self, code):
3050 for stat in self.stats:
3051 stat.annotate(code)
3054 class InPlaceAssignmentNode(AssignmentNode):
3055 # An in place arithmatic operand:
3057 # a += b
3058 # a -= b
3059 # ...
3061 # lhs ExprNode Left hand side
3062 # rhs ExprNode Right hand side
3063 # op char one of "+-*/%^&|"
3064 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3066 # This code is a bit tricky because in order to obey Python
3067 # semantics the sub-expressions (e.g. indices) of the lhs must
3068 # not be evaluated twice. So we must re-use the values calculated
3069 # in evaluation phase for the assignment phase as well.
3070 # Fortunately, the type of the lhs node is fairly constrained
3071 # (it must be a NameNode, AttributeNode, or IndexNode).
3073 child_attrs = ["lhs", "rhs"]
3074 dup = None
3076 def analyse_declarations(self, env):
3077 self.lhs.analyse_target_declaration(env)
3079 def analyse_types(self, env):
3080 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3081 self.rhs.analyse_types(env)
3082 self.lhs.analyse_target_types(env)
3083 if Options.incref_local_binop and self.dup.type.is_pyobject:
3084 self.dup = self.dup.coerce_to_temp(env)
3086 def allocate_rhs_temps(self, env):
3087 import ExprNodes
3088 if self.lhs.type.is_pyobject:
3089 self.rhs = self.rhs.coerce_to_pyobject(env)
3090 elif self.rhs.type.is_pyobject:
3091 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3092 if self.lhs.type.is_pyobject:
3093 self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
3094 self.result_value.allocate_temps(env)
3095 # if use_temp:
3096 # self.rhs = self.rhs.coerce_to_temp(env)
3097 self.rhs.allocate_temps(env)
3098 self.dup.allocate_subexpr_temps(env)
3099 self.dup.allocate_temp(env)
3101 def allocate_lhs_temps(self, env):
3102 self.lhs.allocate_target_temps(env, self.rhs)
3103 # self.lhs.release_target_temp(env)
3104 self.dup.release_temp(env)
3105 if self.dup.is_temp:
3106 self.dup.release_subexpr_temps(env)
3107 # self.rhs.release_temp(env)
3108 if self.lhs.type.is_pyobject:
3109 self.result_value.release_temp(env)
3111 def generate_execution_code(self, code):
3112 import ExprNodes
3113 self.rhs.generate_evaluation_code(code)
3114 self.dup.generate_subexpr_evaluation_code(code)
3115 if isinstance(self.dup, ExprNodes.NewTempExprNode):
3116 # This is because we're manually messing with subexpr nodes
3117 if self.dup.is_temp:
3118 self.dup.allocate_temp_result(code)
3119 # self.dup.generate_result_code is run only if it is not buffer access
3120 if self.operator == "**":
3121 extra = ", Py_None"
3122 else:
3123 extra = ""
3124 if self.lhs.type.is_pyobject:
3125 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3126 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3127 self.dup.generate_result_code(code)
3128 code.putln(
3129 "%s = %s(%s, %s%s); %s" % (
3130 self.result_value.result(),
3131 self.py_operation_function(),
3132 self.dup.py_result(),
3133 self.rhs.py_result(),
3134 extra,
3135 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3136 code.put_gotref(self.result_value.py_result())
3137 self.result_value.generate_evaluation_code(code) # May be a type check...
3138 self.rhs.generate_disposal_code(code)
3139 self.rhs.free_temps(code)
3140 self.dup.generate_disposal_code(code)
3141 self.dup.free_temps(code)
3142 self.lhs.generate_assignment_code(self.result_value, code)
3143 else:
3144 c_op = self.operator
3145 if c_op == "//":
3146 c_op = "/"
3147 elif c_op == "**":
3148 if self.lhs.type.is_int and self.rhs.type.is_int:
3149 error(self.pos, "** with two C int types is ambiguous")
3150 else:
3151 error(self.pos, "No C inplace power operator")
3152 # have to do assignment directly to avoid side-effects
3153 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3154 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3155 else:
3156 self.dup.generate_result_code(code)
3157 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3158 self.rhs.generate_disposal_code(code)
3159 self.rhs.free_temps(code)
3160 if self.dup.is_temp:
3161 self.dup.generate_subexpr_disposal_code(code)
3162 self.dup.free_subexpr_temps(code)
3164 def create_dup_node(self, env):
3165 import ExprNodes
3166 self.dup = self.lhs
3167 self.dup.analyse_types(env)
3168 if isinstance(self.lhs, ExprNodes.NameNode):
3169 target_lhs = ExprNodes.NameNode(self.dup.pos,
3170 name = self.dup.name,
3171 is_temp = self.dup.is_temp,
3172 entry = self.dup.entry)
3173 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3174 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3175 obj = ExprNodes.CloneNode(self.lhs.obj),
3176 attribute = self.dup.attribute,
3177 is_temp = self.dup.is_temp)
3178 elif isinstance(self.lhs, ExprNodes.IndexNode):
3179 if self.lhs.index:
3180 index = ExprNodes.CloneNode(self.lhs.index)
3181 else:
3182 index = None
3183 if self.lhs.indices:
3184 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3185 else:
3186 indices = []
3187 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3188 base = ExprNodes.CloneNode(self.dup.base),
3189 index = index,
3190 indices = indices,
3191 is_temp = self.dup.is_temp)
3192 else:
3193 assert False
3194 self.lhs = target_lhs
3195 return self.dup
3197 def py_operation_function(self):
3198 return self.py_functions[self.operator]
3200 py_functions = {
3201 "|": "PyNumber_InPlaceOr",
3202 "^": "PyNumber_InPlaceXor",
3203 "&": "PyNumber_InPlaceAnd",
3204 "+": "PyNumber_InPlaceAdd",
3205 "-": "PyNumber_InPlaceSubtract",
3206 "*": "PyNumber_InPlaceMultiply",
3207 "/": "PyNumber_InPlaceDivide",
3208 "%": "PyNumber_InPlaceRemainder",
3209 "<<": "PyNumber_InPlaceLshift",
3210 ">>": "PyNumber_InPlaceRshift",
3211 "**": "PyNumber_InPlacePower",
3212 "//": "PyNumber_InPlaceFloorDivide",
3215 def annotate(self, code):
3216 self.lhs.annotate(code)
3217 self.rhs.annotate(code)
3218 self.dup.annotate(code)
3221 class PrintStatNode(StatNode):
3222 # print statement
3224 # arg_tuple TupleNode
3225 # append_newline boolean
3227 child_attrs = ["arg_tuple"]
3229 def analyse_expressions(self, env):
3230 self.arg_tuple.analyse_expressions(env)
3231 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3232 self.arg_tuple.release_temp(env)
3233 env.use_utility_code(printing_utility_code)
3234 if len(self.arg_tuple.args) == 1 and self.append_newline:
3235 env.use_utility_code(printing_one_utility_code)
3236 self.gil_check(env)
3238 gil_message = "Python print statement"
3240 def generate_execution_code(self, code):
3241 if len(self.arg_tuple.args) == 1 and self.append_newline:
3242 arg = self.arg_tuple.args[0]
3243 arg.generate_evaluation_code(code)
3245 code.putln(
3246 "if (__Pyx_PrintOne(%s) < 0) %s" % (
3247 arg.py_result(),
3248 code.error_goto(self.pos)))
3249 arg.generate_disposal_code(code)
3250 arg.free_temps(code)
3251 else:
3252 self.arg_tuple.generate_evaluation_code(code)
3253 code.putln(
3254 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3255 self.arg_tuple.py_result(),
3256 self.append_newline,
3257 code.error_goto(self.pos)))
3258 self.arg_tuple.generate_disposal_code(code)
3259 self.arg_tuple.free_temps(code)
3261 def annotate(self, code):
3262 self.arg_tuple.annotate(code)
3265 class ExecStatNode(StatNode):
3266 # exec statement
3268 # args [ExprNode]
3270 child_attrs = ["args"]
3272 def analyse_expressions(self, env):
3273 for i, arg in enumerate(self.args):
3274 arg.analyse_expressions(env)
3275 arg = arg.coerce_to_pyobject(env)
3276 arg.release_temp(env)
3277 self.args[i] = arg
3278 self.temp_result = env.allocate_temp_pyobject()
3279 env.release_temp(self.temp_result)
3280 env.use_utility_code(Builtin.pyexec_utility_code)
3281 self.gil_check(env)
3283 gil_message = "Python exec statement"
3285 def generate_execution_code(self, code):
3286 args = []
3287 for arg in self.args:
3288 arg.generate_evaluation_code(code)
3289 args.append( arg.py_result() )
3290 args = tuple(args + ['0', '0'][:3-len(args)])
3291 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3292 (self.temp_result,) + args))
3293 for arg in self.args:
3294 arg.generate_disposal_code(code)
3295 arg.free_temps(code)
3296 code.putln(
3297 code.error_goto_if_null(self.temp_result, self.pos))
3298 code.put_gotref(self.temp_result)
3299 code.put_decref_clear(self.temp_result, py_object_type)
3301 def annotate(self, code):
3302 for arg in self.args:
3303 arg.annotate(code)
3306 class DelStatNode(StatNode):
3307 # del statement
3309 # args [ExprNode]
3311 child_attrs = ["args"]
3313 def analyse_declarations(self, env):
3314 for arg in self.args:
3315 arg.analyse_target_declaration(env)
3317 def analyse_expressions(self, env):
3318 for arg in self.args:
3319 arg.analyse_target_expression(env, None)
3320 if arg.type.is_pyobject:
3321 self.gil_check(env)
3322 else:
3323 error(arg.pos, "Deletion of non-Python object")
3324 #arg.release_target_temp(env)
3326 gil_message = "Deleting Python object"
3328 def generate_execution_code(self, code):
3329 for arg in self.args:
3330 if arg.type.is_pyobject:
3331 arg.generate_deletion_code(code)
3332 # else error reported earlier
3334 def annotate(self, code):
3335 for arg in self.args:
3336 arg.annotate(code)
3339 class PassStatNode(StatNode):
3340 # pass statement
3342 child_attrs = []
3344 def analyse_expressions(self, env):
3345 pass
3347 def generate_execution_code(self, code):
3348 pass
3351 class BreakStatNode(StatNode):
3353 child_attrs = []
3355 def analyse_expressions(self, env):
3356 pass
3358 def generate_execution_code(self, code):
3359 if not code.break_label:
3360 error(self.pos, "break statement not inside loop")
3361 else:
3362 code.put_goto(code.break_label)
3365 class ContinueStatNode(StatNode):
3367 child_attrs = []
3369 def analyse_expressions(self, env):
3370 pass
3372 def generate_execution_code(self, code):
3373 if code.funcstate.in_try_finally:
3374 error(self.pos, "continue statement inside try of try...finally")
3375 elif not code.continue_label:
3376 error(self.pos, "continue statement not inside loop")
3377 else:
3378 code.put_goto(code.continue_label)
3381 class ReturnStatNode(StatNode):
3382 # return statement
3384 # value ExprNode or None
3385 # return_type PyrexType
3386 # temps_in_use [Entry] Temps in use at time of return
3388 child_attrs = ["value"]
3390 def analyse_expressions(self, env):
3391 return_type = env.return_type
3392 self.return_type = return_type
3393 self.temps_in_use = env.temps_in_use()
3394 if not return_type:
3395 error(self.pos, "Return not inside a function body")
3396 return
3397 if self.value:
3398 self.value.analyse_types(env)
3399 if return_type.is_void or return_type.is_returncode:
3400 error(self.value.pos,
3401 "Return with value in void function")
3402 else:
3403 self.value = self.value.coerce_to(env.return_type, env)
3404 self.value.allocate_temps(env)
3405 self.value.release_temp(env)
3406 else:
3407 if (not return_type.is_void
3408 and not return_type.is_pyobject
3409 and not return_type.is_returncode):
3410 error(self.pos, "Return value required")
3411 if return_type.is_pyobject:
3412 self.gil_check(env)
3414 gil_message = "Returning Python object"
3416 def generate_execution_code(self, code):
3417 code.mark_pos(self.pos)
3418 if not self.return_type:
3419 # error reported earlier
3420 return
3421 if self.return_type.is_pyobject:
3422 code.put_xdecref(Naming.retval_cname,
3423 self.return_type)
3424 if self.value:
3425 self.value.generate_evaluation_code(code)
3426 self.value.make_owned_reference(code)
3427 code.putln(
3428 "%s = %s;" % (
3429 Naming.retval_cname,
3430 self.value.result_as(self.return_type)))
3431 self.value.generate_post_assignment_code(code)
3432 self.value.free_temps(code)
3433 else:
3434 if self.return_type.is_pyobject:
3435 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3436 elif self.return_type.is_returncode:
3437 code.putln(
3438 "%s = %s;" % (
3439 Naming.retval_cname,
3440 self.return_type.default_value))
3441 # free temps the old way
3442 for entry in self.temps_in_use:
3443 code.put_var_decref_clear(entry)
3444 # free temps the new way
3445 for cname, type in code.funcstate.temps_holding_reference():
3446 code.put_decref_clear(cname, type)
3447 #code.putln(
3448 # "goto %s;" %
3449 # code.return_label)
3450 code.put_goto(code.return_label)
3452 def annotate(self, code):
3453 if self.value:
3454 self.value.annotate(code)
3457 class RaiseStatNode(StatNode):
3458 # raise statement
3460 # exc_type ExprNode or None
3461 # exc_value ExprNode or None
3462 # exc_tb ExprNode or None
3464 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3466 def analyse_expressions(self, env):
3467 if self.exc_type:
3468 self.exc_type.analyse_types(env)
3469 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3470 self.exc_type.allocate_temps(env)
3471 if self.exc_value:
3472 self.exc_value.analyse_types(env)
3473 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3474 self.exc_value.allocate_temps(env)
3475 if self.exc_tb:
3476 self.exc_tb.analyse_types(env)
3477 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3478 self.exc_tb.allocate_temps(env)
3479 if self.exc_type:
3480 self.exc_type.release_temp(env)
3481 if self.exc_value:
3482 self.exc_value.release_temp(env)
3483 if self.exc_tb:
3484 self.exc_tb.release_temp(env)
3485 env.use_utility_code(raise_utility_code)
3486 env.use_utility_code(restore_exception_utility_code)
3487 self.gil_check(env)
3489 gil_message = "Raising exception"
3491 def generate_execution_code(self, code):
3492 if self.exc_type:
3493 self.exc_type.generate_evaluation_code(code)
3494 type_code = self.exc_type.py_result()
3495 else:
3496 type_code = "0"
3497 if self.exc_value:
3498 self.exc_value.generate_evaluation_code(code)
3499 value_code = self.exc_value.py_result()
3500 else:
3501 value_code = "0"
3502 if self.exc_tb:
3503 self.exc_tb.generate_evaluation_code(code)
3504 tb_code = self.exc_tb.py_result()
3505 else:
3506 tb_code = "0"
3507 if self.exc_type or self.exc_value or self.exc_tb:
3508 code.putln(
3509 "__Pyx_Raise(%s, %s, %s);" % (
3510 type_code,
3511 value_code,
3512 tb_code))
3513 else:
3514 code.putln(
3515 "__Pyx_ReRaise();")
3516 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3517 if obj:
3518 obj.generate_disposal_code(code)
3519 obj.free_temps(code)
3520 code.putln(
3521 code.error_goto(self.pos))
3523 def annotate(self, code):
3524 if self.exc_type:
3525 self.exc_type.annotate(code)
3526 if self.exc_value:
3527 self.exc_value.annotate(code)
3528 if self.exc_tb:
3529 self.exc_tb.annotate(code)
3532 class ReraiseStatNode(StatNode):
3534 child_attrs = []
3536 def analyse_expressions(self, env):
3537 self.gil_check(env)
3538 env.use_utility_code(raise_utility_code)
3539 env.use_utility_code(restore_exception_utility_code)
3541 gil_message = "Raising exception"
3543 def generate_execution_code(self, code):
3544 vars = code.funcstate.exc_vars
3545 if vars:
3546 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3547 code.putln(code.error_goto(self.pos))
3548 else:
3549 error(self.pos, "Reraise not inside except clause")
3552 class AssertStatNode(StatNode):
3553 # assert statement
3555 # cond ExprNode
3556 # value ExprNode or None
3558 child_attrs = ["cond", "value"]
3560 def analyse_expressions(self, env):
3561 self.cond = self.cond.analyse_boolean_expression(env)
3562 if self.value:
3563 self.value.analyse_types(env)
3564 self.value = self.value.coerce_to_pyobject(env)
3565 self.value.allocate_temps(env)
3566 self.cond.release_temp(env)
3567 if self.value:
3568 self.value.release_temp(env)
3569 self.gil_check(env)
3570 #env.recycle_pending_temps() # TEMPORARY
3572 gil_message = "Raising exception"
3574 def generate_execution_code(self, code):
3575 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3576 self.cond.generate_evaluation_code(code)
3577 code.putln(
3578 "if (unlikely(!%s)) {" %
3579 self.cond.result())
3580 if self.value:
3581 self.value.generate_evaluation_code(code)
3582 code.putln(
3583 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3584 self.value.py_result())
3585 self.value.generate_disposal_code(code)
3586 self.value.free_temps(code)
3587 else:
3588 code.putln(
3589 "PyErr_SetNone(PyExc_AssertionError);")
3590 code.putln(
3591 code.error_goto(self.pos))
3592 code.putln(
3593 "}")
3594 self.cond.generate_disposal_code(code)
3595 self.cond.free_temps(code)
3596 code.putln("#endif")
3598 def annotate(self, code):
3599 self.cond.annotate(code)
3600 if self.value:
3601 self.value.annotate(code)
3604 class IfStatNode(StatNode):
3605 # if statement
3607 # if_clauses [IfClauseNode]
3608 # else_clause StatNode or None
3610 child_attrs = ["if_clauses", "else_clause"]
3612 def analyse_control_flow(self, env):
3613 env.start_branching(self.pos)
3614 for if_clause in self.if_clauses:
3615 if_clause.analyse_control_flow(env)
3616 env.next_branch(if_clause.end_pos())
3617 if self.else_clause:
3618 self.else_clause.analyse_control_flow(env)
3619 env.finish_branching(self.end_pos())
3621 def analyse_declarations(self, env):
3622 for if_clause in self.if_clauses:
3623 if_clause.analyse_declarations(env)
3624 if self.else_clause:
3625 self.else_clause.analyse_declarations(env)
3627 def analyse_expressions(self, env):
3628 for if_clause in self.if_clauses:
3629 if_clause.analyse_expressions(env)
3630 if self.else_clause:
3631 self.else_clause.analyse_expressions(env)
3633 def generate_execution_code(self, code):
3634 code.mark_pos(self.pos)
3635 end_label = code.new_label()
3636 for if_clause in self.if_clauses:
3637 if_clause.generate_execution_code(code, end_label)
3638 if self.else_clause:
3639 code.putln("/*else*/ {")
3640 self.else_clause.generate_execution_code(code)
3641 code.putln("}")
3642 code.put_label(end_label)
3644 def annotate(self, code):
3645 for if_clause in self.if_clauses:
3646 if_clause.annotate(code)
3647 if self.else_clause:
3648 self.else_clause.annotate(code)
3651 class IfClauseNode(Node):
3652 # if or elif clause in an if statement
3654 # condition ExprNode
3655 # body StatNode
3657 child_attrs = ["condition", "body"]
3659 def analyse_control_flow(self, env):
3660 self.body.analyse_control_flow(env)
3662 def analyse_declarations(self, env):
3663 self.condition.analyse_declarations(env)
3664 self.body.analyse_declarations(env)
3666 def analyse_expressions(self, env):
3667 self.condition = \
3668 self.condition.analyse_temp_boolean_expression(env)
3669 self.condition.release_temp(env)
3670 self.body.analyse_expressions(env)
3672 def generate_execution_code(self, code, end_label):
3673 self.condition.generate_evaluation_code(code)
3674 code.putln(
3675 "if (%s) {" %
3676 self.condition.result())
3677 self.condition.generate_disposal_code(code)
3678 self.condition.free_temps(code)
3679 self.body.generate_execution_code(code)
3680 #code.putln(
3681 # "goto %s;" %
3682 # end_label)
3683 code.put_goto(end_label)
3684 code.putln("}")
3686 def annotate(self, code):
3687 self.condition.annotate(code)
3688 self.body.annotate(code)
3691 class SwitchCaseNode(StatNode):
3692 # Generated in the optimization of an if-elif-else node
3694 # conditions [ExprNode]
3695 # body StatNode
3697 child_attrs = ['conditions', 'body']
3699 def generate_execution_code(self, code):
3700 for cond in self.conditions:
3701 code.mark_pos(cond.pos)
3702 code.putln("case %s:" % cond.calculate_result_code())
3703 self.body.generate_execution_code(code)
3704 code.putln("break;")
3706 def annotate(self, code):
3707 for cond in self.conditions:
3708 cond.annotate(code)
3709 self.body.annotate(code)
3711 class SwitchStatNode(StatNode):
3712 # Generated in the optimization of an if-elif-else node
3714 # test ExprNode
3715 # cases [SwitchCaseNode]
3716 # else_clause StatNode or None
3718 child_attrs = ['test', 'cases', 'else_clause']
3720 def generate_execution_code(self, code):
3721 code.putln("switch (%s) {" % self.test.calculate_result_code())
3722 for case in self.cases:
3723 case.generate_execution_code(code)
3724 if self.else_clause is not None:
3725 code.putln("default:")
3726 self.else_clause.generate_execution_code(code)
3727 code.putln("break;")
3728 code.putln("}")
3730 def annotate(self, code):
3731 self.test.annotate(code)
3732 for case in self.cases:
3733 case.annotate(code)
3734 if self.else_clause is not None:
3735 self.else_clause.annotate(code)
3737 class LoopNode(object):
3739 def analyse_control_flow(self, env):
3740 env.start_branching(self.pos)
3741 self.body.analyse_control_flow(env)
3742 env.next_branch(self.body.end_pos())
3743 if self.else_clause:
3744 self.else_clause.analyse_control_flow(env)
3745 env.finish_branching(self.end_pos())
3748 class WhileStatNode(LoopNode, StatNode):
3749 # while statement
3751 # condition ExprNode
3752 # body StatNode
3753 # else_clause StatNode
3755 child_attrs = ["condition", "body", "else_clause"]
3757 def analyse_declarations(self, env):
3758 self.body.analyse_declarations(env)
3759 if self.else_clause:
3760 self.else_clause.analyse_declarations(env)
3762 def analyse_expressions(self, env):
3763 self.condition = \
3764 self.condition.analyse_temp_boolean_expression(env)
3765 self.condition.release_temp(env)
3766 #env.recycle_pending_temps() # TEMPORARY
3767 self.body.analyse_expressions(env)
3768 if self.else_clause:
3769 self.else_clause.analyse_expressions(env)
3771 def generate_execution_code(self, code):
3772 old_loop_labels = code.new_loop_labels()
3773 code.putln(
3774 "while (1) {")
3775 self.condition.generate_evaluation_code(code)
3776 self.condition.generate_disposal_code(code)
3777 code.putln(
3778 "if (!%s) break;" %
3779 self.condition.result())
3780 self.condition.free_temps(code)
3781 self.body.generate_execution_code(code)
3782 code.put_label(code.continue_label)
3783 code.putln("}")
3784 break_label = code.break_label
3785 code.set_loop_labels(old_loop_labels)
3786 if self.else_clause:
3787 code.putln("/*else*/ {")
3788 self.else_clause.generate_execution_code(code)
3789 code.putln("}")
3790 code.put_label(break_label)
3792 def annotate(self, code):
3793 self.condition.annotate(code)
3794 self.body.annotate(code)
3795 if self.else_clause:
3796 self.else_clause.annotate(code)
3799 def ForStatNode(pos, **kw):
3800 if 'iterator' in kw:
3801 return ForInStatNode(pos, **kw)
3802 else:
3803 return ForFromStatNode(pos, **kw)
3805 class ForInStatNode(LoopNode, StatNode):
3806 # for statement
3808 # target ExprNode
3809 # iterator IteratorNode
3810 # body StatNode
3811 # else_clause StatNode
3812 # item NextNode used internally
3814 child_attrs = ["target", "iterator", "body", "else_clause"]
3815 item = None
3817 def analyse_declarations(self, env):
3818 self.target.analyse_target_declaration(env)
3819 self.body.analyse_declarations(env)
3820 if self.else_clause:
3821 self.else_clause.analyse_declarations(env)
3823 def analyse_expressions(self, env):
3824 import ExprNodes
3825 self.target.analyse_target_types(env)
3826 self.iterator.analyse_expressions(env)
3827 self.item = ExprNodes.NextNode(self.iterator, env)
3828 self.item = self.item.coerce_to(self.target.type, env)
3829 self.item.allocate_temps(env)
3830 self.target.allocate_target_temps(env, self.item)
3831 #self.item.release_temp(env)
3832 #self.target.release_target_temp(env)
3833 self.body.analyse_expressions(env)
3834 if self.else_clause:
3835 self.else_clause.analyse_expressions(env)
3836 self.iterator.release_temp(env)
3838 def generate_execution_code(self, code):
3839 old_loop_labels = code.new_loop_labels()
3840 self.iterator.allocate_counter_temp(code)
3841 self.iterator.generate_evaluation_code(code)
3842 code.putln(
3843 "for (;;) {")
3844 self.item.generate_evaluation_code(code)
3845 self.target.generate_assignment_code(self.item, code)
3846 self.body.generate_execution_code(code)
3847 code.put_label(code.continue_label)
3848 code.putln(
3849 "}")
3850 break_label = code.break_label
3851 code.set_loop_labels(old_loop_labels)
3852 if self.else_clause:
3853 code.putln("/*else*/ {")
3854 self.else_clause.generate_execution_code(code)
3855 code.putln("}")
3856 code.put_label(break_label)
3857 self.iterator.release_counter_temp(code)
3858 self.iterator.generate_disposal_code(code)
3859 self.iterator.free_temps(code)
3861 def annotate(self, code):
3862 self.target.annotate(code)
3863 self.iterator.annotate(code)
3864 self.body.annotate(code)
3865 if self.else_clause:
3866 self.else_clause.annotate(code)
3867 self.item.annotate(code)
3870 class ForFromStatNode(LoopNode, StatNode):
3871 # for name from expr rel name rel expr
3873 # target NameNode
3874 # bound1 ExprNode
3875 # relation1 string
3876 # relation2 string
3877 # bound2 ExprNode
3878 # step ExprNode or None
3879 # body StatNode
3880 # else_clause StatNode or None
3882 # Used internally:
3884 # is_py_target bool
3885 # loopvar_node ExprNode (usually a NameNode or temp node)
3886 # py_loopvar_node PyTempNode or None
3887 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3889 is_py_target = False
3890 loopvar_node = None
3891 py_loopvar_node = None
3893 def analyse_declarations(self, env):
3894 self.target.analyse_target_declaration(env)
3895 self.body.analyse_declarations(env)
3896 if self.else_clause:
3897 self.else_clause.analyse_declarations(env)
3899 def analyse_expressions(self, env):
3900 import ExprNodes
3901 self.target.analyse_target_types(env)
3902 self.bound1.analyse_types(env)
3903 self.bound2.analyse_types(env)
3904 if self.target.type.is_numeric:
3905 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3906 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3907 else:
3908 self.bound1 = self.bound1.coerce_to_integer(env)
3909 self.bound2 = self.bound2.coerce_to_integer(env)
3910 if self.step is not None:
3911 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3912 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3913 self.step.analyse_types(env)
3914 self.step = self.step.coerce_to_integer(env)
3915 if not (self.bound2.is_name or self.bound2.is_literal):
3916 self.bound2 = self.bound2.coerce_to_temp(env)
3917 target_type = self.target.type
3918 if not (target_type.is_pyobject or target_type.is_numeric):
3919 error(self.target.pos,
3920 "Integer for-loop variable must be of type int or Python object")
3921 #if not (target_type.is_pyobject
3922 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3923 # error(self.target.pos,
3924 # "Cannot assign integer to variable of type '%s'" % target_type)
3925 if target_type.is_numeric:
3926 self.is_py_target = 0
3927 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3928 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3929 self.loopvar_node = self.target
3930 self.py_loopvar_node = None
3931 else:
3932 self.is_py_target = 1
3933 c_loopvar_node = ExprNodes.TempNode(self.pos,
3934 PyrexTypes.c_long_type, env)
3935 c_loopvar_node.allocate_temps(env)
3936 self.loopvar_node = c_loopvar_node
3937 self.py_loopvar_node = \
3938 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3939 self.bound1.allocate_temps(env)
3940 self.bound2.allocate_temps(env)
3941 if self.step is not None:
3942 self.step.allocate_temps(env)
3943 if self.is_py_target:
3944 self.py_loopvar_node.allocate_temps(env)
3945 self.target.allocate_target_temps(env, self.py_loopvar_node)
3946 #self.target.release_target_temp(env)
3947 #self.py_loopvar_node.release_temp(env)
3948 self.body.analyse_expressions(env)
3949 if self.is_py_target:
3950 c_loopvar_node.release_temp(env)
3951 if self.else_clause:
3952 self.else_clause.analyse_expressions(env)
3953 self.bound1.release_temp(env)
3954 self.bound2.release_temp(env)
3955 if self.step is not None:
3956 self.step.release_temp(env)
3958 def generate_execution_code(self, code):
3959 old_loop_labels = code.new_loop_labels()
3960 from_range = getattr(self, "from_range", False)
3961 self.bound1.generate_evaluation_code(code)
3962 self.bound2.generate_evaluation_code(code)
3963 offset, incop = self.relation_table[self.relation1]
3964 if incop == "++":
3965 decop = "--"
3966 else:
3967 decop = "++"
3968 if self.step is not None:
3969 self.step.generate_evaluation_code(code)
3970 step = self.step.result()
3971 incop = "%s=%s" % (incop[0], step)
3972 decop = "%s=%s" % (decop[0], step)
3973 loopvar_name = self.loopvar_node.result()
3974 if from_range:
3975 # Skip the loop entirely (and avoid assigning to the loopvar) if
3976 # the loop is empty:
3977 code.putln("if (%s%s %s %s) {" % (
3978 self.bound1.result(), offset, self.relation2, self.bound2.result()
3979 ))
3980 code.putln(
3981 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3982 loopvar_name,
3983 self.bound1.result(), offset,
3984 loopvar_name, self.relation2, self.bound2.result(),
3985 loopvar_name, incop))
3986 if self.py_loopvar_node:
3987 self.py_loopvar_node.generate_evaluation_code(code)
3988 self.target.generate_assignment_code(self.py_loopvar_node, code)
3989 self.body.generate_execution_code(code)
3990 code.put_label(code.continue_label)
3991 if from_range:
3992 # Undo last increment to maintain Python semantics:
3993 code.putln("} %s%s;" % (loopvar_name, decop))
3994 # End the outer if statement:
3995 code.putln("} /* end if */")
3996 else:
3997 code.putln("}")
3998 break_label = code.break_label
3999 code.set_loop_labels(old_loop_labels)
4000 if self.else_clause:
4001 code.putln("/*else*/ {")
4002 self.else_clause.generate_execution_code(code)
4003 code.putln("}")
4004 code.put_label(break_label)
4005 self.bound1.generate_disposal_code(code)
4006 self.bound1.free_temps(code)
4007 self.bound2.generate_disposal_code(code)
4008 self.bound2.free_temps(code)
4009 if self.step is not None:
4010 self.step.generate_disposal_code(code)
4011 self.step.free_temps(code)
4013 relation_table = {
4014 # {relop : (initial offset, increment op)}
4015 '<=': ("", "++"),
4016 '<' : ("+1", "++"),
4017 '>=': ("", "--"),
4018 '>' : ("-1", "--")
4021 def annotate(self, code):
4022 self.target.annotate(code)
4023 self.bound1.annotate(code)
4024 self.bound2.annotate(code)
4025 if self.step:
4026 self.bound2.annotate(code)
4027 self.body.annotate(code)
4028 if self.else_clause:
4029 self.else_clause.annotate(code)
4032 class WithStatNode(StatNode):
4033 """
4034 Represents a Python with statement.
4036 This is only used at parse tree level; and is not present in
4037 analysis or generation phases.
4038 """
4039 # manager The with statement manager object
4040 # target Node (lhs expression)
4041 # body StatNode
4042 child_attrs = ["manager", "target", "body"]
4044 class TryExceptStatNode(StatNode):
4045 # try .. except statement
4047 # body StatNode
4048 # except_clauses [ExceptClauseNode]
4049 # else_clause StatNode or None
4050 # cleanup_list [Entry] old style temps to clean up on error
4052 child_attrs = ["body", "except_clauses", "else_clause"]
4054 def analyse_control_flow(self, env):
4055 env.start_branching(self.pos)
4056 self.body.analyse_control_flow(env)
4057 successful_try = env.control_flow # grab this for later
4058 env.next_branch(self.body.end_pos())
4059 env.finish_branching(self.body.end_pos())
4061 env.start_branching(self.except_clauses[0].pos)
4062 for except_clause in self.except_clauses:
4063 except_clause.analyse_control_flow(env)
4064 env.next_branch(except_clause.end_pos())
4066 # the else cause it executed only when the try clause finishes
4067 env.control_flow.incoming = successful_try
4068 if self.else_clause:
4069 self.else_clause.analyse_control_flow(env)
4070 env.finish_branching(self.end_pos())
4072 def analyse_declarations(self, env):
4073 self.body.analyse_declarations(env)
4074 for except_clause in self.except_clauses:
4075 except_clause.analyse_declarations(env)
4076 if self.else_clause:
4077 self.else_clause.analyse_declarations(env)
4078 self.gil_check(env)
4079 env.use_utility_code(reset_exception_utility_code)
4081 def analyse_expressions(self, env):
4082 self.body.analyse_expressions(env)
4083 self.cleanup_list = env.free_temp_entries[:]
4084 default_clause_seen = 0
4085 for except_clause in self.except_clauses:
4086 except_clause.analyse_expressions(env)
4087 if default_clause_seen:
4088 error(except_clause.pos, "default 'except:' must be last")
4089 if not except_clause.pattern:
4090 default_clause_seen = 1
4091 self.has_default_clause = default_clause_seen
4092 if self.else_clause:
4093 self.else_clause.analyse_expressions(env)
4094 self.gil_check(env)
4096 gil_message = "Try-except statement"
4098 def generate_execution_code(self, code):
4099 old_return_label = code.return_label
4100 old_break_label = code.break_label
4101 old_continue_label = code.continue_label
4102 old_error_label = code.new_error_label()
4103 our_error_label = code.error_label
4104 except_end_label = code.new_label('exception_handled')
4105 except_error_label = code.new_label('except_error')
4106 except_return_label = code.new_label('except_return')
4107 try_return_label = code.new_label('try_return')
4108 try_break_label = code.new_label('try_break')
4109 try_continue_label = code.new_label('try_continue')
4110 try_end_label = code.new_label('try_end')
4112 code.putln("{")
4113 code.putln("PyObject %s;" %
4114 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4115 code.putln("__Pyx_ExceptionSave(%s);" %
4116 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4117 for var in Naming.exc_save_vars:
4118 code.put_xgotref(var)
4119 code.putln(
4120 "/*try:*/ {")
4121 code.return_label = try_return_label
4122 code.break_label = try_break_label
4123 code.continue_label = try_continue_label
4124 self.body.generate_execution_code(code)
4125 code.putln(
4126 "}")
4127 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4128 code.error_label = except_error_label
4129 code.return_label = except_return_label
4130 if self.else_clause:
4131 code.putln(
4132 "/*else:*/ {")
4133 self.else_clause.generate_execution_code(code)
4134 code.putln(
4135 "}")
4136 for var in Naming.exc_save_vars:
4137 code.put_xdecref_clear(var, py_object_type)
4138 code.put_goto(try_end_label)
4139 if code.label_used(try_return_label):
4140 code.put_label(try_return_label)
4141 for var in Naming.exc_save_vars:
4142 code.put_xdecref_clear(var, py_object_type)
4143 code.put_goto(old_return_label)
4144 code.put_label(our_error_label)
4145 code.put_var_xdecrefs_clear(self.cleanup_list)
4146 for temp_name, type in temps_to_clean_up:
4147 code.put_xdecref_clear(temp_name, type)
4148 for except_clause in self.except_clauses:
4149 except_clause.generate_handling_code(code, except_end_label)
4151 error_label_used = code.label_used(except_error_label)
4152 if error_label_used or not self.has_default_clause:
4153 if error_label_used:
4154 code.put_label(except_error_label)
4155 for var in Naming.exc_save_vars:
4156 code.put_xdecref(var, py_object_type)
4157 code.put_goto(old_error_label)
4159 if code.label_used(try_break_label):
4160 code.put_label(try_break_label)
4161 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4162 code.putln("__Pyx_ExceptionReset(%s);" %
4163 ', '.join(Naming.exc_save_vars))
4164 code.put_goto(old_break_label)
4166 if code.label_used(try_continue_label):
4167 code.put_label(try_continue_label)
4168 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4169 code.putln("__Pyx_ExceptionReset(%s);" %
4170 ', '.join(Naming.exc_save_vars))
4171 code.put_goto(old_continue_label)
4173 if code.label_used(except_return_label):
4174 code.put_label(except_return_label)
4175 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4176 code.putln("__Pyx_ExceptionReset(%s);" %
4177 ', '.join(Naming.exc_save_vars))
4178 code.put_goto(old_return_label)
4180 if code.label_used(except_end_label):
4181 code.put_label(except_end_label)
4182 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4183 code.putln("__Pyx_ExceptionReset(%s);" %
4184 ', '.join(Naming.exc_save_vars))
4185 code.put_label(try_end_label)
4186 code.putln("}")
4188 code.return_label = old_return_label
4189 code.break_label = old_break_label
4190 code.continue_label = old_continue_label
4191 code.error_label = old_error_label
4193 def annotate(self, code):
4194 self.body.annotate(code)
4195 for except_node in self.except_clauses:
4196 except_node.annotate(code)
4197 if self.else_clause:
4198 self.else_clause.annotate(code)
4201 class ExceptClauseNode(Node):
4202 # Part of try ... except statement.
4204 # pattern ExprNode
4205 # target ExprNode or None
4206 # body StatNode
4207 # excinfo_target NameNode or None optional target for exception info
4208 # match_flag string result of exception match
4209 # exc_value ExcValueNode used internally
4210 # function_name string qualified name of enclosing function
4211 # exc_vars (string * 3) local exception variables
4213 # excinfo_target is never set by the parser, but can be set by a transform
4214 # in order to extract more extensive information about the exception as a
4215 # sys.exc_info()-style tuple into a target variable
4217 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4219 exc_value = None
4220 excinfo_target = None
4222 def analyse_declarations(self, env):
4223 if self.target:
4224 self.target.analyse_target_declaration(env)
4225 if self.excinfo_target is not None:
4226 self.excinfo_target.analyse_target_declaration(env)
4227 self.body.analyse_declarations(env)
4229 def analyse_expressions(self, env):
4230 import ExprNodes
4231 genv = env.global_scope()
4232 self.function_name = env.qualified_name
4233 if self.pattern:
4234 self.pattern.analyse_expressions(env)
4235 self.pattern = self.pattern.coerce_to_pyobject(env)
4236 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
4237 self.pattern.release_temp(env)
4238 env.release_temp(self.match_flag)
4239 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
4240 if self.target:
4241 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
4242 self.exc_value.allocate_temps(env)
4243 self.target.analyse_target_expression(env, self.exc_value)
4244 if self.excinfo_target is not None:
4245 import ExprNodes
4246 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4247 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
4248 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
4249 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
4250 ])
4251 self.excinfo_tuple.analyse_expressions(env)
4252 self.excinfo_tuple.allocate_temps(env)
4253 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4255 self.body.analyse_expressions(env)
4256 for var in self.exc_vars:
4257 env.release_temp(var)
4258 env.use_utility_code(get_exception_utility_code)
4259 env.use_utility_code(restore_exception_utility_code)
4261 def generate_handling_code(self, code, end_label):
4262 code.mark_pos(self.pos)
4263 if self.pattern:
4264 self.pattern.generate_evaluation_code(code)
4265 code.putln(
4266 "%s = PyErr_ExceptionMatches(%s);" % (
4267 self.match_flag,
4268 self.pattern.py_result()))
4269 self.pattern.generate_disposal_code(code)
4270 self.pattern.free_temps(code)
4271 code.putln(
4272 "if (%s) {" %
4273 self.match_flag)
4274 else:
4275 code.putln("/*except:*/ {")
4276 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4277 # We always have to fetch the exception value even if
4278 # there is no target, because this also normalises the
4279 # exception and stores it in the thread state.
4280 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
4281 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4282 code.error_goto(self.pos)))
4283 for x in self.exc_vars:
4284 code.put_gotref(x)
4285 if self.target:
4286 self.exc_value.generate_evaluation_code(code)
4287 self.target.generate_assignment_code(self.exc_value, code)
4288 if self.excinfo_target is not None:
4289 self.excinfo_tuple.generate_evaluation_code(code)
4290 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4293 old_break_label, old_continue_label = code.break_label, code.continue_label
4294 code.break_label = code.new_label('except_break')
4295 code.continue_label = code.new_label('except_continue')
4297 old_exc_vars = code.funcstate.exc_vars
4298 code.funcstate.exc_vars = self.exc_vars
4299 self.body.generate_execution_code(code)
4300 code.funcstate.exc_vars = old_exc_vars
4301 for var in self.exc_vars:
4302 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4303 code.put_goto(end_label)
4305 if code.label_used(code.break_label):
4306 code.put_label(code.break_label)
4307 for var in self.exc_vars:
4308 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4309 code.put_goto(old_break_label)
4310 code.break_label = old_break_label
4312 if code.label_used(code.continue_label):
4313 code.put_label(code.continue_label)
4314 for var in self.exc_vars:
4315 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4316 code.put_goto(old_continue_label)
4317 code.continue_label = old_continue_label
4319 code.putln(
4320 "}")
4322 def annotate(self, code):
4323 if self.pattern:
4324 self.pattern.annotate(code)
4325 if self.target:
4326 self.target.annotate(code)
4327 self.body.annotate(code)
4330 class TryFinallyStatNode(StatNode):
4331 # try ... finally statement
4333 # body StatNode
4334 # finally_clause StatNode
4336 # cleanup_list [Entry] old_style temps to clean up on error
4338 # The plan is that we funnel all continue, break
4339 # return and error gotos into the beginning of the
4340 # finally block, setting a variable to remember which
4341 # one we're doing. At the end of the finally block, we
4342 # switch on the variable to figure out where to go.
4343 # In addition, if we're doing an error, we save the
4344 # exception on entry to the finally block and restore
4345 # it on exit.
4347 child_attrs = ["body", "finally_clause"]
4349 preserve_exception = 1
4351 disallow_continue_in_try_finally = 0
4352 # There doesn't seem to be any point in disallowing
4353 # continue in the try block, since we have no problem
4354 # handling it.
4356 def create_analysed(pos, env, body, finally_clause):
4357 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4358 node.cleanup_list = []
4359 return node
4360 create_analysed = staticmethod(create_analysed)
4362 def analyse_control_flow(self, env):
4363 env.start_branching(self.pos)
4364 self.body.analyse_control_flow(env)
4365 env.next_branch(self.body.end_pos())
4366 env.finish_branching(self.body.end_pos())
4367 self.finally_clause.analyse_control_flow(env)
4369 def analyse_declarations(self, env):
4370 self.body.analyse_declarations(env)
4371 self.finally_clause.analyse_declarations(env)
4373 def analyse_expressions(self, env):
4374 self.body.analyse_expressions(env)
4375 self.cleanup_list = env.free_temp_entries[:]
4376 self.finally_clause.analyse_expressions(env)
4377 self.gil_check(env)
4379 gil_message = "Try-finally statement"
4381 def generate_execution_code(self, code):
4382 old_error_label = code.error_label
4383 old_labels = code.all_new_labels()
4384 new_labels = code.get_all_labels()
4385 new_error_label = code.error_label
4386 catch_label = code.new_label()
4387 code.putln(
4388 "/*try:*/ {")
4389 if self.disallow_continue_in_try_finally:
4390 was_in_try_finally = code.funcstate.in_try_finally
4391 code.funcstate.in_try_finally = 1
4392 self.body.generate_execution_code(code)
4393 if self.disallow_continue_in_try_finally:
4394 code.funcstate.in_try_finally = was_in_try_finally
4395 code.putln(
4396 "}")
4397 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4398 code.putln(
4399 "/*finally:*/ {")
4400 cases_used = []
4401 error_label_used = 0
4402 for i, new_label in enumerate(new_labels):
4403 if new_label in code.labels_used:
4404 cases_used.append(i)
4405 if new_label == new_error_label:
4406 error_label_used = 1
4407 error_label_case = i
4408 if cases_used:
4409 code.putln(
4410 "int __pyx_why;")
4411 if error_label_used and self.preserve_exception:
4412 code.putln(
4413 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4414 code.putln(
4415 "int %s;" % Naming.exc_lineno_name)
4416 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4417 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4418 code.putln(exc_var_init_zero)
4419 else:
4420 exc_var_init_zero = None
4421 code.use_label(catch_label)
4422 code.putln(
4423 "__pyx_why = 0; goto %s;" % catch_label)
4424 for i in cases_used:
4425 new_label = new_labels[i]
4426 #if new_label and new_label != "<try>":
4427 if new_label == new_error_label and self.preserve_exception:
4428 self.put_error_catcher(code,
4429 new_error_label, i+1, catch_label, temps_to_clean_up)
4430 else:
4431 code.put('%s: ' % new_label)
4432 if exc_var_init_zero:
4433 code.putln(exc_var_init_zero)
4434 code.putln("__pyx_why = %s; goto %s;" % (
4435 i+1,
4436 catch_label))
4437 code.put_label(catch_label)
4438 code.set_all_labels(old_labels)
4439 if error_label_used:
4440 code.new_error_label()
4441 finally_error_label = code.error_label
4442 self.finally_clause.generate_execution_code(code)
4443 if error_label_used:
4444 if finally_error_label in code.labels_used and self.preserve_exception:
4445 over_label = code.new_label()
4446 code.put_goto(over_label);
4447 code.put_label(finally_error_label)
4448 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4449 for var in Naming.exc_vars:
4450 code.putln("Py_XDECREF(%s);" % var)
4451 code.putln("}")
4452 code.put_goto(old_error_label)
4453 code.put_label(over_label)
4454 code.error_label = old_error_label
4455 if cases_used:
4456 code.putln(
4457 "switch (__pyx_why) {")
4458 for i in cases_used:
4459 old_label = old_labels[i]
4460 if old_label == old_error_label and self.preserve_exception:
4461 self.put_error_uncatcher(code, i+1, old_error_label)
4462 else:
4463 code.use_label(old_label)
4464 code.putln(
4465 "case %s: goto %s;" % (
4466 i+1,
4467 old_label))
4468 code.putln(
4469 "}")
4470 code.putln(
4471 "}")
4473 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4474 code.globalstate.use_utility_code(restore_exception_utility_code)
4475 code.putln(
4476 "%s: {" %
4477 error_label)
4478 code.putln(
4479 "__pyx_why = %s;" %
4480 i)
4481 code.put_var_xdecrefs_clear(self.cleanup_list)
4482 for temp_name, type in temps_to_clean_up:
4483 code.put_xdecref_clear(temp_name, type)
4484 code.putln(
4485 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4486 Naming.exc_vars)
4487 code.putln(
4488 "%s = %s;" % (
4489 Naming.exc_lineno_name, Naming.lineno_cname))
4490 #code.putln(
4491 # "goto %s;" %
4492 # catch_label)
4493 code.put_goto(catch_label)
4494 code.putln(
4495 "}")
4497 def put_error_uncatcher(self, code, i, error_label):
4498 code.globalstate.use_utility_code(restore_exception_utility_code)
4499 code.putln(
4500 "case %s: {" %
4501 i)
4502 code.putln(
4503 "__Pyx_ErrRestore(%s, %s, %s);" %
4504 Naming.exc_vars)
4505 code.putln(
4506 "%s = %s;" % (
4507 Naming.lineno_cname, Naming.exc_lineno_name))
4508 for var in Naming.exc_vars:
4509 code.putln(
4510 "%s = 0;" %
4511 var)
4512 code.put_goto(error_label)
4513 code.putln(
4514 "}")
4516 def annotate(self, code):
4517 self.body.annotate(code)
4518 self.finally_clause.annotate(code)
4521 class GILStatNode(TryFinallyStatNode):
4522 # 'with gil' or 'with nogil' statement
4524 # state string 'gil' or 'nogil'
4526 child_attrs = []
4528 preserve_exception = 0
4530 def __init__(self, pos, state, body):
4531 self.state = state
4532 TryFinallyStatNode.__init__(self, pos,
4533 body = body,
4534 finally_clause = GILExitNode(pos, state = state))
4536 def analyse_expressions(self, env):
4537 env.use_utility_code(py23_init_threads_utility_code)
4538 was_nogil = env.nogil
4539 env.nogil = 1
4540 TryFinallyStatNode.analyse_expressions(self, env)
4541 env.nogil = was_nogil
4543 def gil_check(self, env):
4544 pass
4546 def generate_execution_code(self, code):
4547 code.putln("/*with %s:*/ {" % self.state)
4548 if self.state == 'gil':
4549 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
4550 else:
4551 code.putln("PyThreadState *_save;")
4552 code.putln("Py_UNBLOCK_THREADS")
4553 TryFinallyStatNode.generate_execution_code(self, code)
4554 code.putln("}")
4557 class GILExitNode(StatNode):
4558 # Used as the 'finally' block in a GILStatNode
4560 # state string 'gil' or 'nogil'
4562 child_attrs = []
4564 def analyse_expressions(self, env):
4565 pass
4567 def generate_execution_code(self, code):
4568 if self.state == 'gil':
4569 code.putln("PyGILState_Release();")
4570 else:
4571 code.putln("Py_BLOCK_THREADS")
4574 class CImportStatNode(StatNode):
4575 # cimport statement
4577 # module_name string Qualified name of module being imported
4578 # as_name string or None Name specified in "as" clause, if any
4580 child_attrs = []
4582 def analyse_declarations(self, env):
4583 if not env.is_module_scope:
4584 error(self.pos, "cimport only allowed at module level")
4585 return
4586 module_scope = env.find_module(self.module_name, self.pos)
4587 if "." in self.module_name:
4588 names = [EncodedString(name) for name in self.module_name.split(".")]
4589 top_name = names[0]
4590 top_module_scope = env.context.find_submodule(top_name)
4591 module_scope = top_module_scope
4592 for name in names[1:]:
4593 submodule_scope = module_scope.find_submodule(name)
4594 module_scope.declare_module(name, submodule_scope, self.pos)
4595 module_scope = submodule_scope
4596 if self.as_name:
4597 env.declare_module(self.as_name, module_scope, self.pos)
4598 else:
4599 env.declare_module(top_name, top_module_scope, self.pos)
4600 else:
4601 name = self.as_name or self.module_name
4602 env.declare_module(name, module_scope, self.pos)
4604 def analyse_expressions(self, env):
4605 pass
4607 def generate_execution_code(self, code):
4608 pass
4611 class FromCImportStatNode(StatNode):
4612 # from ... cimport statement
4614 # module_name string Qualified name of module
4615 # imported_names [(pos, name, as_name, kind)] Names to be imported
4617 child_attrs = []
4619 def analyse_declarations(self, env):
4620 if not env.is_module_scope:
4621 error(self.pos, "cimport only allowed at module level")
4622 return
4623 module_scope = env.find_module(self.module_name, self.pos)
4624 env.add_imported_module(module_scope)
4625 for pos, name, as_name, kind in self.imported_names:
4626 if name == "*":
4627 for local_name, entry in module_scope.entries.items():
4628 env.add_imported_entry(local_name, entry, pos)
4629 else:
4630 entry = module_scope.lookup(name)
4631 if entry:
4632 if kind and not self.declaration_matches(entry, kind):
4633 entry.redeclared(pos)
4634 else:
4635 if kind == 'struct' or kind == 'union':
4636 entry = module_scope.declare_struct_or_union(name,
4637 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4638 elif kind == 'class':
4639 entry = module_scope.declare_c_class(name, pos = pos,
4640 module_name = self.module_name)
4641 else:
4642 error(pos, "Name '%s' not declared in module '%s'"
4643 % (name, self.module_name))
4645 if entry:
4646 local_name = as_name or name
4647 env.add_imported_entry(local_name, entry, pos)
4649 def declaration_matches(self, entry, kind):
4650 if not entry.is_type:
4651 return 0
4652 type = entry.type
4653 if kind == 'class':
4654 if not type.is_extension_type:
4655 return 0
4656 else:
4657 if not type.is_struct_or_union:
4658 return 0
4659 if kind != type.kind:
4660 return 0
4661 return 1
4663 def analyse_expressions(self, env):
4664 pass
4666 def generate_execution_code(self, code):
4667 pass
4670 class FromImportStatNode(StatNode):
4671 # from ... import statement
4673 # module ImportNode
4674 # items [(string, NameNode)]
4675 # interned_items [(string, NameNode, ExprNode)]
4676 # item PyTempNode used internally
4677 # import_star boolean used internally
4679 child_attrs = ["module"]
4680 import_star = 0
4682 def analyse_declarations(self, env):
4683 for name, target in self.items:
4684 if name == "*":
4685 if not env.is_module_scope:
4686 error(self.pos, "import * only allowed at module level")
4687 return
4688 env.has_import_star = 1
4689 self.import_star = 1
4690 else:
4691 target.analyse_target_declaration(env)
4693 def analyse_expressions(self, env):
4694 import ExprNodes
4695 self.module.analyse_expressions(env)
4696 self.item = ExprNodes.PyTempNode(self.pos, env)
4697 self.item.allocate_temp(env)
4698 self.interned_items = []
4699 for name, target in self.items:
4700 if name == '*':
4701 for _, entry in env.entries.items():
4702 if not entry.is_type and entry.type.is_extension_type:
4703 env.use_utility_code(ExprNodes.type_test_utility_code)
4704 break
4705 else:
4706 entry = env.lookup(target.name)
4707 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4708 continue # already cimported
4709 target.analyse_target_expression(env, None)
4710 if target.type is py_object_type:
4711 coerced_item = None
4712 else:
4713 coerced_item = self.item.coerce_to(target.type, env)
4714 self.interned_items.append(
4715 (env.intern_identifier(name), target, coerced_item))
4716 #target.release_target_temp(env) # was release_temp ?!?
4717 self.module.release_temp(env)
4718 self.item.release_temp(env)
4720 def generate_execution_code(self, code):
4721 self.module.generate_evaluation_code(code)
4722 if self.import_star:
4723 code.putln(
4724 'if (%s(%s) < 0) %s;' % (
4725 Naming.import_star,
4726 self.module.py_result(),
4727 code.error_goto(self.pos)))
4728 for cname, target, coerced_item in self.interned_items:
4729 code.putln(
4730 '%s = PyObject_GetAttr(%s, %s); %s' % (
4731 self.item.result(),
4732 self.module.py_result(),
4733 cname,
4734 code.error_goto_if_null(self.item.result(), self.pos)))
4735 code.put_gotref(self.item.py_result())
4736 if coerced_item is None:
4737 target.generate_assignment_code(self.item, code)
4738 else:
4739 coerced_item.allocate_temp_result(code)
4740 coerced_item.generate_result_code(code)
4741 target.generate_assignment_code(coerced_item, code)
4742 if self.item.result() != coerced_item.result():
4743 code.put_decref_clear(self.item.result(), self.item.type)
4744 self.module.generate_disposal_code(code)
4745 self.module.free_temps(code)
4749 #------------------------------------------------------------------------------------
4751 # Runtime support code
4753 #------------------------------------------------------------------------------------
4755 utility_function_predeclarations = \
4756 """
4757 #ifdef __GNUC__
4758 #define INLINE __inline__
4759 #elif _WIN32
4760 #define INLINE __inline
4761 #else
4762 #define INLINE
4763 #endif
4765 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4767 """ + """
4769 static int %(skip_dispatch_cname)s = 0;
4771 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4773 if Options.gcc_branch_hints:
4774 branch_prediction_macros = \
4775 """
4776 #ifdef __GNUC__
4777 /* Test for GCC > 2.95 */
4778 #if __GNUC__ > 2 || \
4779 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4780 #define likely(x) __builtin_expect(!!(x), 1)
4781 #define unlikely(x) __builtin_expect(!!(x), 0)
4782 #else /* __GNUC__ > 2 ... */
4783 #define likely(x) (x)
4784 #define unlikely(x) (x)
4785 #endif /* __GNUC__ > 2 ... */
4786 #else /* __GNUC__ */
4787 #define likely(x) (x)
4788 #define unlikely(x) (x)
4789 #endif /* __GNUC__ */
4790 """
4791 else:
4792 branch_prediction_macros = \
4793 """
4794 #define likely(x) (x)
4795 #define unlikely(x) (x)
4796 """
4798 #get_name_predeclaration = \
4799 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4801 #get_name_interned_predeclaration = \
4802 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4804 #------------------------------------------------------------------------------------
4806 printing_utility_code = UtilityCode(
4807 proto = """
4808 static int __Pyx_Print(PyObject *, int); /*proto*/
4809 #if PY_MAJOR_VERSION >= 3
4810 static PyObject* %s = 0;
4811 static PyObject* %s = 0;
4812 #endif
4813 """ % (Naming.print_function, Naming.print_function_kwargs),
4814 impl = r"""
4815 #if PY_MAJOR_VERSION < 3
4816 static PyObject *__Pyx_GetStdout(void) {
4817 PyObject *f = PySys_GetObject((char *)"stdout");
4818 if (!f) {
4819 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4821 return f;
4824 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4825 PyObject *f;
4826 PyObject* v;
4827 int i;
4829 if (!(f = __Pyx_GetStdout()))
4830 return -1;
4831 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4832 if (PyFile_SoftSpace(f, 1)) {
4833 if (PyFile_WriteString(" ", f) < 0)
4834 return -1;
4836 v = PyTuple_GET_ITEM(arg_tuple, i);
4837 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4838 return -1;
4839 if (PyString_Check(v)) {
4840 char *s = PyString_AsString(v);
4841 Py_ssize_t len = PyString_Size(v);
4842 if (len > 0 &&
4843 isspace(Py_CHARMASK(s[len-1])) &&
4844 s[len-1] != ' ')
4845 PyFile_SoftSpace(f, 0);
4848 if (newline) {
4849 if (PyFile_WriteString("\n", f) < 0)
4850 return -1;
4851 PyFile_SoftSpace(f, 0);
4853 return 0;
4856 #else /* Python 3 has a print function */
4858 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4859 PyObject* kwargs = 0;
4860 PyObject* result = 0;
4861 PyObject* end_string;
4862 if (!%(PRINT_FUNCTION)s) {
4863 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4864 if (!%(PRINT_FUNCTION)s)
4865 return -1;
4867 if (!newline) {
4868 if (!%(PRINT_KWARGS)s) {
4869 %(PRINT_KWARGS)s = PyDict_New();
4870 if (!%(PRINT_KWARGS)s)
4871 return -1;
4872 end_string = PyUnicode_FromStringAndSize(" ", 1);
4873 if (!end_string)
4874 return -1;
4875 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4876 Py_DECREF(end_string);
4877 return -1;
4879 Py_DECREF(end_string);
4881 kwargs = %(PRINT_KWARGS)s;
4883 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4884 if (!result)
4885 return -1;
4886 Py_DECREF(result);
4887 return 0;
4890 #endif
4891 """ % {'BUILTINS' : Naming.builtins_cname,
4892 'PRINT_FUNCTION' : Naming.print_function,
4893 'PRINT_KWARGS' : Naming.print_function_kwargs}
4897 printing_one_utility_code = UtilityCode(
4898 proto = """
4899 static int __Pyx_PrintOne(PyObject *o); /*proto*/
4900 """,
4901 impl = r"""
4902 #if PY_MAJOR_VERSION < 3
4904 static int __Pyx_PrintOne(PyObject *o) {
4905 PyObject *f;
4906 if (!(f = __Pyx_GetStdout()))
4907 return -1;
4908 if (PyFile_SoftSpace(f, 0)) {
4909 if (PyFile_WriteString(" ", f) < 0)
4910 return -1;
4912 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
4913 return -1;
4914 if (PyFile_WriteString("\n", f) < 0)
4915 return -1;
4916 return 0;
4917 /* the line below is just to avoid compiler
4918 * compiler warnings about unused functions */
4919 return __Pyx_Print(NULL, 0);
4922 #else /* Python 3 has a print function */
4924 static int __Pyx_PrintOne(PyObject *o) {
4925 int res;
4926 PyObject* arg_tuple = PyTuple_New(1);
4927 if (unlikely(!arg_tuple))
4928 return -1;
4929 Py_INCREF(o);
4930 PyTuple_SET_ITEM(arg_tuple, 0, o);
4931 res = __Pyx_Print(arg_tuple, 1);
4932 Py_DECREF(arg_tuple);
4933 return res;
4936 #endif
4937 """)
4941 #------------------------------------------------------------------------------------
4943 # The following function is based on do_raise() from ceval.c.
4945 raise_utility_code = UtilityCode(
4946 proto = """
4947 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4948 """,
4949 impl = """
4950 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4951 Py_XINCREF(type);
4952 Py_XINCREF(value);
4953 Py_XINCREF(tb);
4954 /* First, check the traceback argument, replacing None with NULL. */
4955 if (tb == Py_None) {
4956 Py_DECREF(tb);
4957 tb = 0;
4959 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4960 PyErr_SetString(PyExc_TypeError,
4961 "raise: arg 3 must be a traceback or None");
4962 goto raise_error;
4964 /* Next, replace a missing value with None */
4965 if (value == NULL) {
4966 value = Py_None;
4967 Py_INCREF(value);
4969 #if PY_VERSION_HEX < 0x02050000
4970 if (!PyClass_Check(type))
4971 #else
4972 if (!PyType_Check(type))
4973 #endif
4975 /* Raising an instance. The value should be a dummy. */
4976 if (value != Py_None) {
4977 PyErr_SetString(PyExc_TypeError,
4978 "instance exception may not have a separate value");
4979 goto raise_error;
4981 /* Normalize to raise <class>, <instance> */
4982 Py_DECREF(value);
4983 value = type;
4984 #if PY_VERSION_HEX < 0x02050000
4985 if (PyInstance_Check(type)) {
4986 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4987 Py_INCREF(type);
4989 else {
4990 type = 0;
4991 PyErr_SetString(PyExc_TypeError,
4992 "raise: exception must be an old-style class or instance");
4993 goto raise_error;
4995 #else
4996 type = (PyObject*) Py_TYPE(type);
4997 Py_INCREF(type);
4998 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4999 PyErr_SetString(PyExc_TypeError,
5000 "raise: exception class must be a subclass of BaseException");
5001 goto raise_error;
5003 #endif
5005 __Pyx_ErrRestore(type, value, tb);
5006 return;
5007 raise_error:
5008 Py_XDECREF(value);
5009 Py_XDECREF(type);
5010 Py_XDECREF(tb);
5011 return;
5013 """)
5015 #------------------------------------------------------------------------------------
5017 reraise_utility_code = UtilityCode(
5018 proto = """
5019 static void __Pyx_ReRaise(void); /*proto*/
5020 """,
5021 impl = """
5022 static void __Pyx_ReRaise(void) {
5023 PyThreadState *tstate = PyThreadState_GET();
5024 PyObject* tmp_type = tstate->curexc_type;
5025 PyObject* tmp_value = tstate->curexc_value;
5026 PyObject* tmp_tb = tstate->curexc_traceback;
5027 tstate->curexc_type = tstate->exc_type;
5028 tstate->curexc_value = tstate->exc_value;
5029 tstate->curexc_traceback = tstate->exc_traceback;
5030 tstate->exc_type = 0;
5031 tstate->exc_value = 0;
5032 tstate->exc_traceback = 0;
5033 Py_XDECREF(tmp_type);
5034 Py_XDECREF(tmp_value);
5035 Py_XDECREF(tmp_tb);
5037 """)
5039 #------------------------------------------------------------------------------------
5041 arg_type_test_utility_code = UtilityCode(
5042 proto = """
5043 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5044 const char *name, int exact); /*proto*/
5045 """,
5046 impl = """
5047 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5048 const char *name, int exact)
5050 if (!type) {
5051 PyErr_Format(PyExc_SystemError, "Missing type object");
5052 return 0;
5054 if (none_allowed && obj == Py_None) return 1;
5055 else if (exact) {
5056 if (Py_TYPE(obj) == type) return 1;
5058 else {
5059 if (PyObject_TypeCheck(obj, type)) return 1;
5061 PyErr_Format(PyExc_TypeError,
5062 "Argument '%s' has incorrect type (expected %s, got %s)",
5063 name, type->tp_name, Py_TYPE(obj)->tp_name);
5064 return 0;
5066 """)
5068 #------------------------------------------------------------------------------------
5070 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5071 # many or too few positional arguments were found. This handles
5072 # Py_ssize_t formatting correctly.
5074 raise_argtuple_invalid_utility_code = UtilityCode(
5075 proto = """
5076 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5077 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5078 """,
5079 impl = """
5080 static void __Pyx_RaiseArgtupleInvalid(
5081 const char* func_name,
5082 int exact,
5083 Py_ssize_t num_min,
5084 Py_ssize_t num_max,
5085 Py_ssize_t num_found)
5087 Py_ssize_t num_expected;
5088 const char *number, *more_or_less;
5090 if (num_found < num_min) {
5091 num_expected = num_min;
5092 more_or_less = "at least";
5093 } else {
5094 num_expected = num_max;
5095 more_or_less = "at most";
5097 if (exact) {
5098 more_or_less = "exactly";
5100 number = (num_expected == 1) ? "" : "s";
5101 PyErr_Format(PyExc_TypeError,
5102 #if PY_VERSION_HEX < 0x02050000
5103 "%s() takes %s %d positional argument%s (%d given)",
5104 #else
5105 "%s() takes %s %zd positional argument%s (%zd given)",
5106 #endif
5107 func_name, more_or_less, num_expected, number, num_found);
5109 """)
5111 raise_keyword_required_utility_code = UtilityCode(
5112 proto = """
5113 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5114 """,
5115 impl = """
5116 static INLINE void __Pyx_RaiseKeywordRequired(
5117 const char* func_name,
5118 PyObject* kw_name)
5120 PyErr_Format(PyExc_TypeError,
5121 #if PY_MAJOR_VERSION >= 3
5122 "%s() needs keyword-only argument %U", func_name, kw_name);
5123 #else
5124 "%s() needs keyword-only argument %s", func_name,
5125 PyString_AS_STRING(kw_name));
5126 #endif
5128 """)
5130 raise_double_keywords_utility_code = UtilityCode(
5131 proto = """
5132 static void __Pyx_RaiseDoubleKeywordsError(
5133 const char* func_name, PyObject* kw_name); /*proto*/
5134 """,
5135 impl = """
5136 static void __Pyx_RaiseDoubleKeywordsError(
5137 const char* func_name,
5138 PyObject* kw_name)
5140 PyErr_Format(PyExc_TypeError,
5141 #if PY_MAJOR_VERSION >= 3
5142 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5143 #else
5144 "%s() got multiple values for keyword argument '%s'", func_name,
5145 PyString_AS_STRING(kw_name));
5146 #endif
5148 """)
5150 #------------------------------------------------------------------------------------
5152 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5153 # were passed to a function, or if any keywords were passed to a
5154 # function that does not accept them.
5156 keyword_string_check_utility_code = UtilityCode(
5157 proto = """
5158 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5159 const char* function_name, int kw_allowed); /*proto*/
5160 """,
5161 impl = """
5162 static INLINE int __Pyx_CheckKeywordStrings(
5163 PyObject *kwdict,
5164 const char* function_name,
5165 int kw_allowed)
5167 PyObject* key = 0;
5168 Py_ssize_t pos = 0;
5169 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5170 #if PY_MAJOR_VERSION < 3
5171 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5172 #else
5173 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5174 #endif
5175 goto invalid_keyword_type;
5177 if ((!kw_allowed) && unlikely(key))
5178 goto invalid_keyword;
5179 return 1;
5180 invalid_keyword_type:
5181 PyErr_Format(PyExc_TypeError,
5182 "%s() keywords must be strings", function_name);
5183 return 0;
5184 invalid_keyword:
5185 PyErr_Format(PyExc_TypeError,
5186 #if PY_MAJOR_VERSION < 3
5187 "%s() got an unexpected keyword argument '%s'",
5188 function_name, PyString_AsString(key));
5189 #else
5190 "%s() got an unexpected keyword argument '%U'",
5191 function_name, key);
5192 #endif
5193 return 0;
5195 """)
5197 #------------------------------------------------------------------------------------
5199 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5200 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5201 # keywords will raise an invalid keyword error.
5203 # Three kinds of errors are checked: 1) non-string keywords, 2)
5204 # unexpected keywords and 3) overlap with positional arguments.
5206 # If num_posargs is greater 0, it denotes the number of positional
5207 # arguments that were passed and that must therefore not appear
5208 # amongst the keywords as well.
5210 # This method does not check for required keyword arguments.
5213 parse_keywords_utility_code = UtilityCode(
5214 proto = """
5215 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5216 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5217 const char* function_name); /*proto*/
5218 """,
5219 impl = """
5220 static int __Pyx_ParseOptionalKeywords(
5221 PyObject *kwds,
5222 PyObject **argnames[],
5223 PyObject *kwds2,
5224 PyObject *values[],
5225 Py_ssize_t num_pos_args,
5226 const char* function_name)
5228 PyObject *key = 0, *value = 0;
5229 Py_ssize_t pos = 0;
5230 PyObject*** name;
5231 PyObject*** first_kw_arg = argnames + num_pos_args;
5233 while (PyDict_Next(kwds, &pos, &key, &value)) {
5234 name = first_kw_arg;
5235 while (*name && (**name != key)) name++;
5236 if (*name) {
5237 values[name-argnames] = value;
5238 } else {
5239 #if PY_MAJOR_VERSION < 3
5240 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5241 #else
5242 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5243 #endif
5244 goto invalid_keyword_type;
5245 } else {
5246 for (name = first_kw_arg; *name; name++) {
5247 #if PY_MAJOR_VERSION >= 3
5248 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5249 PyUnicode_Compare(**name, key) == 0) break;
5250 #else
5251 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5252 _PyString_Eq(**name, key)) break;
5253 #endif
5255 if (*name) {
5256 values[name-argnames] = value;
5257 } else {
5258 /* unexpected keyword found */
5259 for (name=argnames; name != first_kw_arg; name++) {
5260 if (**name == key) goto arg_passed_twice;
5261 #if PY_MAJOR_VERSION >= 3
5262 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5263 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5264 #else
5265 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5266 _PyString_Eq(**name, key)) goto arg_passed_twice;
5267 #endif
5269 if (kwds2) {
5270 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5271 } else {
5272 goto invalid_keyword;
5278 return 0;
5279 arg_passed_twice:
5280 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5281 goto bad;
5282 invalid_keyword_type:
5283 PyErr_Format(PyExc_TypeError,
5284 "%s() keywords must be strings", function_name);
5285 goto bad;
5286 invalid_keyword:
5287 PyErr_Format(PyExc_TypeError,
5288 #if PY_MAJOR_VERSION < 3
5289 "%s() got an unexpected keyword argument '%s'",
5290 function_name, PyString_AsString(key));
5291 #else
5292 "%s() got an unexpected keyword argument '%U'",
5293 function_name, key);
5294 #endif
5295 bad:
5296 return -1;
5298 """)
5300 #------------------------------------------------------------------------------------
5302 unraisable_exception_utility_code = UtilityCode(
5303 proto = """
5304 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5305 """,
5306 impl = """
5307 static void __Pyx_WriteUnraisable(const char *name) {
5308 PyObject *old_exc, *old_val, *old_tb;
5309 PyObject *ctx;
5310 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5311 #if PY_MAJOR_VERSION < 3
5312 ctx = PyString_FromString(name);
5313 #else
5314 ctx = PyUnicode_FromString(name);
5315 #endif
5316 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5317 if (!ctx) {
5318 PyErr_WriteUnraisable(Py_None);
5319 } else {
5320 PyErr_WriteUnraisable(ctx);
5321 Py_DECREF(ctx);
5324 """)
5326 #------------------------------------------------------------------------------------
5328 traceback_utility_code = UtilityCode(
5329 proto = """
5330 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5331 """,
5332 impl = """
5333 #include "compile.h"
5334 #include "frameobject.h"
5335 #include "traceback.h"
5337 static void __Pyx_AddTraceback(const char *funcname) {
5338 PyObject *py_srcfile = 0;
5339 PyObject *py_funcname = 0;
5340 PyObject *py_globals = 0;
5341 PyObject *empty_string = 0;
5342 PyCodeObject *py_code = 0;
5343 PyFrameObject *py_frame = 0;
5345 #if PY_MAJOR_VERSION < 3
5346 py_srcfile = PyString_FromString(%(FILENAME)s);
5347 #else
5348 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5349 #endif
5350 if (!py_srcfile) goto bad;
5351 if (%(CLINENO)s) {
5352 #if PY_MAJOR_VERSION < 3
5353 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5354 #else
5355 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5356 #endif
5358 else {
5359 #if PY_MAJOR_VERSION < 3
5360 py_funcname = PyString_FromString(funcname);
5361 #else
5362 py_funcname = PyUnicode_FromString(funcname);
5363 #endif
5365 if (!py_funcname) goto bad;
5366 py_globals = PyModule_GetDict(%(GLOBALS)s);
5367 if (!py_globals) goto bad;
5368 #if PY_MAJOR_VERSION < 3
5369 empty_string = PyString_FromStringAndSize("", 0);
5370 #else
5371 empty_string = PyBytes_FromStringAndSize("", 0);
5372 #endif
5373 if (!empty_string) goto bad;
5374 py_code = PyCode_New(
5375 0, /*int argcount,*/
5376 #if PY_MAJOR_VERSION >= 3
5377 0, /*int kwonlyargcount,*/
5378 #endif
5379 0, /*int nlocals,*/
5380 0, /*int stacksize,*/
5381 0, /*int flags,*/
5382 empty_string, /*PyObject *code,*/
5383 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5384 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5385 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5386 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5387 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5388 py_srcfile, /*PyObject *filename,*/
5389 py_funcname, /*PyObject *name,*/
5390 %(LINENO)s, /*int firstlineno,*/
5391 empty_string /*PyObject *lnotab*/
5392 );
5393 if (!py_code) goto bad;
5394 py_frame = PyFrame_New(
5395 PyThreadState_GET(), /*PyThreadState *tstate,*/
5396 py_code, /*PyCodeObject *code,*/
5397 py_globals, /*PyObject *globals,*/
5398 0 /*PyObject *locals*/
5399 );
5400 if (!py_frame) goto bad;
5401 py_frame->f_lineno = %(LINENO)s;
5402 PyTraceBack_Here(py_frame);
5403 bad:
5404 Py_XDECREF(py_srcfile);
5405 Py_XDECREF(py_funcname);
5406 Py_XDECREF(empty_string);
5407 Py_XDECREF(py_code);
5408 Py_XDECREF(py_frame);
5410 """ % {
5411 'FILENAME': Naming.filename_cname,
5412 'LINENO': Naming.lineno_cname,
5413 'CFILENAME': Naming.cfilenm_cname,
5414 'CLINENO': Naming.clineno_cname,
5415 'GLOBALS': Naming.module_cname,
5416 'EMPTY_TUPLE' : Naming.empty_tuple,
5417 })
5419 restore_exception_utility_code = UtilityCode(
5420 proto = """
5421 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5422 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5423 """,
5424 impl = """
5425 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5426 PyObject *tmp_type, *tmp_value, *tmp_tb;
5427 PyThreadState *tstate = PyThreadState_GET();
5429 #if PY_MAJOR_VERSION >= 3
5430 /* Note: this is a temporary work-around to prevent crashes in Python 3.0 */
5431 if ((tstate->exc_type != NULL) & (tstate->exc_type != Py_None)) {
5432 tmp_type = tstate->exc_type;
5433 tmp_value = tstate->exc_value;
5434 tmp_tb = tstate->exc_traceback;
5435 PyErr_NormalizeException(&type, &value, &tb);
5436 PyErr_NormalizeException(&tmp_type, &tmp_value, &tmp_tb);
5437 tstate->exc_type = 0;
5438 tstate->exc_value = 0;
5439 tstate->exc_traceback = 0;
5440 PyException_SetContext(value, tmp_value);
5441 Py_DECREF(tmp_type);
5442 Py_XDECREF(tmp_tb);
5444 #endif
5446 tmp_type = tstate->curexc_type;
5447 tmp_value = tstate->curexc_value;
5448 tmp_tb = tstate->curexc_traceback;
5449 tstate->curexc_type = type;
5450 tstate->curexc_value = value;
5451 tstate->curexc_traceback = tb;
5452 Py_XDECREF(tmp_type);
5453 Py_XDECREF(tmp_value);
5454 Py_XDECREF(tmp_tb);
5457 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5458 PyThreadState *tstate = PyThreadState_GET();
5459 *type = tstate->curexc_type;
5460 *value = tstate->curexc_value;
5461 *tb = tstate->curexc_traceback;
5463 tstate->curexc_type = 0;
5464 tstate->curexc_value = 0;
5465 tstate->curexc_traceback = 0;
5468 """)
5470 #------------------------------------------------------------------------------------
5472 set_vtable_utility_code = UtilityCode(
5473 proto = """
5474 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5475 """,
5476 impl = """
5477 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5478 PyObject *pycobj = 0;
5479 int result;
5481 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5482 if (!pycobj)
5483 goto bad;
5484 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5485 goto bad;
5486 result = 0;
5487 goto done;
5489 bad:
5490 result = -1;
5491 done:
5492 Py_XDECREF(pycobj);
5493 return result;
5495 """)
5497 #------------------------------------------------------------------------------------
5499 get_vtable_utility_code = UtilityCode(
5500 proto = """
5501 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5502 """,
5503 impl = r"""
5504 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5505 int result;
5506 PyObject *pycobj;
5508 pycobj = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5509 if (!pycobj)
5510 goto bad;
5511 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5512 if (!*(void **)vtabptr)
5513 goto bad;
5514 result = 0;
5515 goto done;
5517 bad:
5518 result = -1;
5519 done:
5520 Py_XDECREF(pycobj);
5521 return result;
5523 """)
5525 #------------------------------------------------------------------------------------
5527 init_string_tab_utility_code = UtilityCode(
5528 proto = """
5529 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5530 """,
5531 impl = """
5532 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5533 while (t->p) {
5534 #if PY_MAJOR_VERSION < 3
5535 if (t->is_unicode && (!t->is_identifier)) {
5536 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5537 } else if (t->intern) {
5538 *t->p = PyString_InternFromString(t->s);
5539 } else {
5540 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5542 #else /* Python 3+ has unicode identifiers */
5543 if (t->is_identifier || (t->is_unicode && t->intern)) {
5544 *t->p = PyUnicode_InternFromString(t->s);
5545 } else if (t->is_unicode) {
5546 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5547 } else {
5548 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5550 #endif
5551 if (!*t->p)
5552 return -1;
5553 ++t;
5555 return 0;
5557 """)
5559 #------------------------------------------------------------------------------------
5561 get_exception_utility_code = UtilityCode(
5562 proto = """
5563 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5564 """,
5565 impl = """
5566 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5567 PyObject *tmp_type, *tmp_value, *tmp_tb;
5568 PyThreadState *tstate = PyThreadState_GET();
5569 __Pyx_ErrFetch(type, value, tb);
5570 PyErr_NormalizeException(type, value, tb);
5571 if (PyErr_Occurred())
5572 goto bad;
5573 Py_INCREF(*type);
5574 Py_INCREF(*value);
5575 Py_INCREF(*tb);
5576 tmp_type = tstate->exc_type;
5577 tmp_value = tstate->exc_value;
5578 tmp_tb = tstate->exc_traceback;
5579 tstate->exc_type = *type;
5580 tstate->exc_value = *value;
5581 tstate->exc_traceback = *tb;
5582 /* Make sure tstate is in a consistent state when we XDECREF
5583 these objects (XDECREF may run arbitrary code). */
5584 Py_XDECREF(tmp_type);
5585 Py_XDECREF(tmp_value);
5586 Py_XDECREF(tmp_tb);
5587 return 0;
5588 bad:
5589 Py_XDECREF(*type);
5590 Py_XDECREF(*value);
5591 Py_XDECREF(*tb);
5592 return -1;
5595 """)
5597 #------------------------------------------------------------------------------------
5599 reset_exception_utility_code = UtilityCode(
5600 proto = """
5601 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5602 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5603 """,
5604 impl = """
5605 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5606 PyThreadState *tstate = PyThreadState_GET();
5607 *type = tstate->exc_type;
5608 *value = tstate->exc_value;
5609 *tb = tstate->exc_traceback;
5610 Py_XINCREF(*type);
5611 Py_XINCREF(*value);
5612 Py_XINCREF(*tb);
5615 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5616 PyObject *tmp_type, *tmp_value, *tmp_tb;
5617 PyThreadState *tstate = PyThreadState_GET();
5618 tmp_type = tstate->exc_type;
5619 tmp_value = tstate->exc_value;
5620 tmp_tb = tstate->exc_traceback;
5621 tstate->exc_type = type;
5622 tstate->exc_value = value;
5623 tstate->exc_traceback = tb;
5624 Py_XDECREF(tmp_type);
5625 Py_XDECREF(tmp_value);
5626 Py_XDECREF(tmp_tb);
5628 """)
5630 #------------------------------------------------------------------------------------
5632 py23_init_threads_utility_code = UtilityCode(
5633 proto="""
5634 #ifndef __PYX_FORCE_INIT_THREADS
5635 #if PY_VERSION_HEX < 0x02040200
5636 #define __PYX_FORCE_INIT_THREADS 1
5637 #else
5638 #define __PYX_FORCE_INIT_THREADS 0
5639 #endif
5640 #endif
5641 """)
5643 #------------------------------------------------------------------------------------