Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 1875:9a1f6f7c260a

thread initialisation when using with gil/nogil (by Lisandro)
author Stefan Behnel <scoder@users.berlios.de>
date Thu Mar 19 10:50:40 2009 +0100 (3 years ago)
parents b1bdbb05d78c
children 0bd3bfd487a5
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 len(self.args) > 0:
1341 import ExprNodes
1342 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1343 self.py_func = DefNode(pos = self.pos,
1344 name = self.entry.name,
1345 args = self.args,
1346 star_arg = None,
1347 starstar_arg = None,
1348 doc = self.doc,
1349 body = py_func_body,
1350 is_wrapper = 1)
1351 self.py_func.is_module_scope = env.is_module_scope
1352 self.py_func.analyse_declarations(env)
1353 self.entry.as_variable = self.py_func.entry
1354 # Reset scope entry the above cfunction
1355 env.entries[name] = self.entry
1356 self.py_func.interned_attr_cname = env.intern_identifier(
1357 self.py_func.entry.name)
1358 if not env.is_module_scope or Options.lookup_module_cpdef:
1359 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1360 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1362 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1363 import ExprNodes
1364 args = self.type.args
1365 if omit_optional_args:
1366 args = args[:len(args) - self.type.optional_arg_count]
1367 arg_names = [arg.name for arg in args]
1368 if is_module_scope:
1369 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1370 else:
1371 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1372 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1373 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1374 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)
1375 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1377 def declare_arguments(self, env):
1378 for arg in self.type.args:
1379 if not arg.name:
1380 error(arg.pos, "Missing argument name")
1381 self.declare_argument(env, arg)
1383 def need_gil_acquisition(self, lenv):
1384 type = self.type
1385 with_gil = self.type.with_gil
1386 if type.nogil and not with_gil:
1387 if type.return_type.is_pyobject:
1388 error(self.pos,
1389 "Function with Python return type cannot be declared nogil")
1390 for entry in lenv.var_entries + lenv.temp_entries:
1391 if entry.type.is_pyobject:
1392 error(self.pos, "Function declared nogil has Python locals or temporaries")
1393 return with_gil
1395 def analyse_expressions(self, env):
1396 self.analyse_default_values(env)
1397 if self.py_func is not None:
1398 self.py_func.analyse_expressions(env)
1400 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1401 arg_decls = []
1402 type = self.type
1403 visibility = self.entry.visibility
1404 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1405 arg_decls.append(arg.declaration_code())
1406 if with_dispatch and self.overridable:
1407 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1408 if type.optional_arg_count and with_opt_args:
1409 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1410 if type.has_varargs:
1411 arg_decls.append("...")
1412 if not arg_decls:
1413 arg_decls = ["void"]
1414 if cname is None:
1415 cname = self.entry.func_cname
1416 entity = type.function_header_code(cname, ', '.join(arg_decls))
1417 if visibility == 'public':
1418 dll_linkage = "DL_EXPORT"
1419 else:
1420 dll_linkage = None
1421 header = self.return_type.declaration_code(entity,
1422 dll_linkage = dll_linkage)
1423 if visibility == 'extern':
1424 storage_class = "%s " % Naming.extern_c_macro
1425 elif visibility == 'public':
1426 storage_class = ""
1427 else:
1428 storage_class = "static "
1429 code.putln("%s%s %s {" % (
1430 storage_class,
1431 ' '.join(self.modifiers).upper(), # macro forms
1432 header))
1434 def generate_argument_declarations(self, env, code):
1435 for arg in self.args:
1436 if arg.default:
1437 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1439 def generate_keyword_list(self, code):
1440 pass
1442 def generate_argument_parsing_code(self, env, code):
1443 i = 0
1444 if self.type.optional_arg_count:
1445 code.putln('if (%s) {' % Naming.optional_args_cname)
1446 for arg in self.args:
1447 if arg.default:
1448 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1449 declarator = arg.declarator
1450 while not hasattr(declarator, 'name'):
1451 declarator = declarator.base
1452 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1453 i += 1
1454 for _ in range(self.type.optional_arg_count):
1455 code.putln('}')
1456 code.putln('}')
1458 def generate_argument_conversion_code(self, code):
1459 pass
1461 def generate_argument_type_tests(self, code):
1462 # Generate type tests for args whose type in a parent
1463 # class is a supertype of the declared type.
1464 for arg in self.type.args:
1465 if arg.needs_type_test:
1466 self.generate_arg_type_test(arg, code)
1468 def generate_arg_type_test(self, arg, code):
1469 # Generate type test for one argument.
1470 if arg.type.typeobj_is_available():
1471 typeptr_cname = arg.type.typeptr_cname
1472 arg_code = "((PyObject *)%s)" % arg.cname
1473 code.putln(
1474 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1475 arg_code,
1476 typeptr_cname,
1477 not arg.not_none,
1478 arg.name,
1479 type.is_builtin_type,
1480 code.error_goto(arg.pos)))
1481 else:
1482 error(arg.pos, "Cannot test type of extern C class "
1483 "without type object name specification")
1485 def error_value(self):
1486 if self.return_type.is_pyobject:
1487 return "0"
1488 else:
1489 #return None
1490 return self.entry.type.exception_value
1492 def caller_will_check_exceptions(self):
1493 return self.entry.type.exception_check
1495 def generate_wrapper_functions(self, code):
1496 # If the C signature of a function has changed, we need to generate
1497 # wrappers to put in the slots here.
1498 k = 0
1499 entry = self.entry
1500 func_type = entry.type
1501 while entry.prev_entry is not None:
1502 k += 1
1503 entry = entry.prev_entry
1504 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1505 code.putln()
1506 self.generate_function_header(code,
1507 0,
1508 with_dispatch = entry.type.is_overridable,
1509 with_opt_args = entry.type.optional_arg_count,
1510 cname = entry.func_cname)
1511 if not self.return_type.is_void:
1512 code.put('return ')
1513 args = self.type.args
1514 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1515 if entry.type.is_overridable:
1516 arglist.append(Naming.skip_dispatch_cname)
1517 elif func_type.is_overridable:
1518 arglist.append('0')
1519 if entry.type.optional_arg_count:
1520 arglist.append(Naming.optional_args_cname)
1521 elif func_type.optional_arg_count:
1522 arglist.append('NULL')
1523 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1524 code.putln('}')
1527 class PyArgDeclNode(Node):
1528 # Argument which must be a Python object (used
1529 # for * and ** arguments).
1531 # name string
1532 # entry Symtab.Entry
1533 child_attrs = []
1536 class DecoratorNode(Node):
1537 # A decorator
1539 # decorator NameNode or CallNode
1540 child_attrs = ['decorator']
1543 class DefNode(FuncDefNode):
1544 # A Python function definition.
1546 # name string the Python name of the function
1547 # decorators [DecoratorNode] list of decorators
1548 # args [CArgDeclNode] formal arguments
1549 # star_arg PyArgDeclNode or None * argument
1550 # starstar_arg PyArgDeclNode or None ** argument
1551 # doc EncodedString or None
1552 # body StatListNode
1554 # The following subnode is constructed internally
1555 # when the def statement is inside a Python class definition.
1557 # assmt AssignmentNode Function construction/assignment
1559 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1561 assmt = None
1562 num_kwonly_args = 0
1563 num_required_kw_args = 0
1564 reqd_kw_flags_cname = "0"
1565 is_wrapper = 0
1566 decorators = None
1567 entry = None
1570 def __init__(self, pos, **kwds):
1571 FuncDefNode.__init__(self, pos, **kwds)
1572 k = rk = r = 0
1573 for arg in self.args:
1574 if arg.kw_only:
1575 k += 1
1576 if not arg.default:
1577 rk += 1
1578 if not arg.default:
1579 r += 1
1580 self.num_kwonly_args = k
1581 self.num_required_kw_args = rk
1582 self.num_required_args = r
1584 def as_cfunction(self, cfunc=None, scope=None):
1585 if self.star_arg:
1586 error(self.star_arg.pos, "cdef function cannot have star argument")
1587 if self.starstar_arg:
1588 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1589 if cfunc is None:
1590 cfunc_args = []
1591 for formal_arg in self.args:
1592 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1593 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1594 cname = None,
1595 type = py_object_type,
1596 pos = formal_arg.pos))
1597 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1598 args = cfunc_args,
1599 has_varargs = False,
1600 exception_value = None,
1601 exception_check = False,
1602 nogil = False,
1603 with_gil = False,
1604 is_overridable = True)
1605 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1606 else:
1607 cfunc_type = cfunc.type
1608 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1609 error(self.pos, "wrong number of arguments")
1610 error(declarator.pos, "previous declaration here")
1611 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1612 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1613 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1614 formal_arg.type = type_arg.type
1615 formal_arg.name_declarator = name_declarator
1616 import ExprNodes
1617 if cfunc_type.exception_value is None:
1618 exception_value = None
1619 else:
1620 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1621 declarator = CFuncDeclaratorNode(self.pos,
1622 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1623 args = self.args,
1624 has_varargs = False,
1625 exception_check = cfunc_type.exception_check,
1626 exception_value = exception_value,
1627 with_gil = cfunc_type.with_gil,
1628 nogil = cfunc_type.nogil)
1629 return CFuncDefNode(self.pos,
1630 modifiers = [],
1631 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1632 declarator = declarator,
1633 body = self.body,
1634 doc = self.doc,
1635 overridable = cfunc_type.is_overridable,
1636 type = cfunc_type,
1637 with_gil = cfunc_type.with_gil,
1638 nogil = cfunc_type.nogil,
1639 visibility = 'private',
1640 api = False,
1641 directive_locals = cfunc.directive_locals)
1643 def analyse_declarations(self, env):
1644 if 'locals' in env.directives:
1645 directive_locals = env.directives['locals']
1646 else:
1647 directive_locals = {}
1648 self.directive_locals = directive_locals
1649 for arg in self.args:
1650 if hasattr(arg, 'name'):
1651 type = arg.type
1652 name_declarator = None
1653 else:
1654 base_type = arg.base_type.analyse(env)
1655 name_declarator, type = \
1656 arg.declarator.analyse(base_type, env)
1657 arg.name = name_declarator.name
1658 if arg.name in directive_locals:
1659 type_node = directive_locals[arg.name]
1660 other_type = type_node.analyse_as_type(env)
1661 if other_type is None:
1662 error(type_node.pos, "Not a type")
1663 elif (type is not PyrexTypes.py_object_type
1664 and not type.same_as(other_type)):
1665 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1666 error(type_node.pos, "Previous declaration here")
1667 else:
1668 type = other_type
1669 if name_declarator and name_declarator.cname:
1670 error(self.pos,
1671 "Python function argument cannot have C name specification")
1672 arg.type = type.as_argument_type()
1673 arg.hdr_type = None
1674 arg.needs_conversion = 0
1675 arg.needs_type_test = 0
1676 arg.is_generic = 1
1677 if arg.not_none and not arg.type.is_extension_type:
1678 error(self.pos,
1679 "Only extension type arguments can have 'not None'")
1680 self.declare_pyfunction(env)
1681 self.analyse_signature(env)
1682 self.return_type = self.entry.signature.return_type()
1684 def analyse_signature(self, env):
1685 any_type_tests_needed = 0
1686 # Use the simpler calling signature for zero- and one-argument functions.
1687 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1688 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1689 if len(self.args) == 0:
1690 self.entry.signature = TypeSlots.pyfunction_noargs
1691 elif len(self.args) == 1:
1692 if self.args[0].default is None and not self.args[0].kw_only:
1693 self.entry.signature = TypeSlots.pyfunction_onearg
1694 elif self.entry.signature is TypeSlots.pymethod_signature:
1695 if len(self.args) == 1:
1696 self.entry.signature = TypeSlots.unaryfunc
1697 elif len(self.args) == 2:
1698 if self.args[1].default is None and not self.args[1].kw_only:
1699 self.entry.signature = TypeSlots.ibinaryfunc
1700 elif self.entry.is_special:
1701 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1702 sig = self.entry.signature
1703 nfixed = sig.num_fixed_args()
1704 for i in range(nfixed):
1705 if i < len(self.args):
1706 arg = self.args[i]
1707 arg.is_generic = 0
1708 if sig.is_self_arg(i):
1709 arg.is_self_arg = 1
1710 arg.hdr_type = arg.type = env.parent_type
1711 arg.needs_conversion = 0
1712 else:
1713 arg.hdr_type = sig.fixed_arg_type(i)
1714 if not arg.type.same_as(arg.hdr_type):
1715 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1716 arg.needs_type_test = 1
1717 any_type_tests_needed = 1
1718 else:
1719 arg.needs_conversion = 1
1720 if arg.needs_conversion:
1721 arg.hdr_cname = Naming.arg_prefix + arg.name
1722 else:
1723 arg.hdr_cname = Naming.var_prefix + arg.name
1724 else:
1725 self.bad_signature()
1726 return
1727 if nfixed < len(self.args):
1728 if not sig.has_generic_args:
1729 self.bad_signature()
1730 for arg in self.args:
1731 if arg.is_generic and \
1732 (arg.type.is_extension_type or arg.type.is_builtin_type):
1733 arg.needs_type_test = 1
1734 any_type_tests_needed = 1
1735 if any_type_tests_needed:
1736 env.use_utility_code(arg_type_test_utility_code)
1738 def bad_signature(self):
1739 sig = self.entry.signature
1740 expected_str = "%d" % sig.num_fixed_args()
1741 if sig.has_generic_args:
1742 expected_str = expected_str + " or more"
1743 name = self.name
1744 if name.startswith("__") and name.endswith("__"):
1745 desc = "Special method"
1746 else:
1747 desc = "Method"
1748 error(self.pos,
1749 "%s %s has wrong number of arguments "
1750 "(%d declared, %s expected)" % (
1751 desc, self.name, len(self.args), expected_str))
1753 def signature_has_nongeneric_args(self):
1754 argcount = len(self.args)
1755 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1756 return 0
1757 return 1
1759 def signature_has_generic_args(self):
1760 return self.entry.signature.has_generic_args
1762 def declare_pyfunction(self, env):
1763 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1764 name = self.name
1765 entry = env.lookup_here(self.name)
1766 if entry and entry.type.is_cfunction and not self.is_wrapper:
1767 warning(self.pos, "Overriding cdef method with def method.", 5)
1768 entry = env.declare_pyfunction(self.name, self.pos)
1769 self.entry = entry
1770 prefix = env.scope_prefix
1771 entry.func_cname = \
1772 Naming.pyfunc_prefix + prefix + name
1773 entry.pymethdef_cname = \
1774 Naming.pymethdef_prefix + prefix + name
1775 if Options.docstrings:
1776 entry.doc = embed_position(self.pos, self.doc)
1777 entry.doc_cname = \
1778 Naming.funcdoc_prefix + prefix + name
1779 else:
1780 entry.doc = None
1782 def declare_arguments(self, env):
1783 for arg in self.args:
1784 if not arg.name:
1785 error(arg.pos, "Missing argument name")
1786 if arg.needs_conversion:
1787 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1788 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1789 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1790 if arg.type.is_pyobject:
1791 arg.entry.init = "0"
1792 arg.entry.init_to_none = 0
1793 else:
1794 arg.entry = self.declare_argument(env, arg)
1795 arg.entry.used = 1
1796 arg.entry.is_self_arg = arg.is_self_arg
1797 if not arg.is_self_arg:
1798 arg.name_entry = env.get_string_const(
1799 arg.name, identifier = True)
1800 env.add_py_string(arg.name_entry, identifier = True)
1801 if arg.hdr_type:
1802 if arg.is_self_arg or \
1803 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1804 arg.entry.is_declared_generic = 1
1805 self.declare_python_arg(env, self.star_arg)
1806 self.declare_python_arg(env, self.starstar_arg)
1808 def declare_python_arg(self, env, arg):
1809 if arg:
1810 entry = env.declare_var(arg.name,
1811 PyrexTypes.py_object_type, arg.pos)
1812 entry.used = 1
1813 entry.init = "0"
1814 entry.init_to_none = 0
1815 entry.xdecref_cleanup = 1
1816 arg.entry = entry
1817 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1819 def analyse_expressions(self, env):
1820 self.analyse_default_values(env)
1821 if env.is_py_class_scope:
1822 self.synthesize_assignment_node(env)
1824 def synthesize_assignment_node(self, env):
1825 import ExprNodes
1826 self.assmt = SingleAssignmentNode(self.pos,
1827 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1828 rhs = ExprNodes.UnboundMethodNode(self.pos,
1829 class_cname = env.class_obj_cname,
1830 function = ExprNodes.PyCFunctionNode(self.pos,
1831 pymethdef_cname = self.entry.pymethdef_cname)))
1832 self.assmt.analyse_declarations(env)
1833 self.assmt.analyse_expressions(env)
1835 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1836 arg_code_list = []
1837 sig = self.entry.signature
1838 if sig.has_dummy_arg:
1839 arg_code_list.append(
1840 "PyObject *%s" % Naming.self_cname)
1841 for arg in self.args:
1842 if not arg.is_generic:
1843 if arg.is_self_arg:
1844 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1845 else:
1846 arg_code_list.append(
1847 arg.hdr_type.declaration_code(arg.hdr_cname))
1848 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1849 arg_code_list.append("PyObject *unused")
1850 if sig.has_generic_args:
1851 arg_code_list.append(
1852 "PyObject *%s, PyObject *%s"
1853 % (Naming.args_cname, Naming.kwds_cname))
1854 arg_code = ", ".join(arg_code_list)
1855 dc = self.return_type.declaration_code(self.entry.func_cname)
1856 header = "static %s(%s)" % (dc, arg_code)
1857 code.putln("%s; /*proto*/" % header)
1858 if proto_only:
1859 return
1860 if self.entry.doc and Options.docstrings:
1861 docstr = self.entry.doc
1862 if not isinstance(docstr, str):
1863 docstr = docstr.utf8encode()
1864 code.putln(
1865 'static char %s[] = "%s";' % (
1866 self.entry.doc_cname,
1867 split_docstring(escape_byte_string(docstr))))
1868 if with_pymethdef:
1869 code.put(
1870 "static PyMethodDef %s = " %
1871 self.entry.pymethdef_cname)
1872 code.put_pymethoddef(self.entry, ";")
1873 code.putln("%s {" % header)
1875 def generate_argument_declarations(self, env, code):
1876 for arg in self.args:
1877 if arg.is_generic: # or arg.needs_conversion:
1878 if arg.needs_conversion:
1879 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1880 else:
1881 code.put_var_declaration(arg.entry)
1883 def generate_keyword_list(self, code):
1884 if self.signature_has_generic_args() and \
1885 self.signature_has_nongeneric_args():
1886 code.put(
1887 "static PyObject **%s[] = {" %
1888 Naming.pykwdlist_cname)
1889 for arg in self.args:
1890 if arg.is_generic:
1891 code.put('&%s,' % arg.name_entry.pystring_cname)
1892 code.putln("0};")
1894 def generate_argument_parsing_code(self, env, code):
1895 # Generate PyArg_ParseTuple call for generic
1896 # arguments, if any.
1897 if self.entry.signature.has_dummy_arg:
1898 # get rid of unused argument warning
1899 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1901 old_error_label = code.new_error_label()
1902 our_error_label = code.error_label
1903 end_label = code.new_label("argument_unpacking_done")
1905 has_kwonly_args = self.num_kwonly_args > 0
1906 has_star_or_kw_args = self.star_arg is not None \
1907 or self.starstar_arg is not None or has_kwonly_args
1909 if not self.signature_has_generic_args():
1910 if has_star_or_kw_args:
1911 error(self.pos, "This method cannot have * or keyword arguments")
1912 self.generate_argument_conversion_code(code)
1914 elif not self.signature_has_nongeneric_args():
1915 # func(*args) or func(**kw) or func(*args, **kw)
1916 self.generate_stararg_copy_code(code)
1918 else:
1919 positional_args = []
1920 kw_only_args = []
1921 default_seen = 0
1922 for arg in self.args:
1923 arg_entry = arg.entry
1924 if arg.is_generic:
1925 if arg.default:
1926 default_seen = 1
1927 if not arg.is_self_arg:
1928 if arg.kw_only:
1929 kw_only_args.append(arg)
1930 else:
1931 positional_args.append(arg)
1932 elif arg.kw_only:
1933 kw_only_args.append(arg)
1934 default_seen = 1
1935 elif default_seen:
1936 error(arg.pos, "Non-default argument following default argument")
1937 elif not arg.is_self_arg:
1938 positional_args.append(arg)
1940 self.generate_tuple_and_keyword_parsing_code(
1941 positional_args, kw_only_args, end_label, code)
1943 code.error_label = old_error_label
1944 if code.label_used(our_error_label):
1945 if not code.label_used(end_label):
1946 code.put_goto(end_label)
1947 code.put_label(our_error_label)
1948 if has_star_or_kw_args:
1949 self.generate_arg_decref(self.star_arg, code)
1950 if self.starstar_arg:
1951 if self.starstar_arg.entry.xdecref_cleanup:
1952 code.put_var_xdecref(self.starstar_arg.entry)
1953 else:
1954 code.put_var_decref(self.starstar_arg.entry)
1955 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1956 code.putln("return %s;" % self.error_value())
1957 if code.label_used(end_label):
1958 code.put_label(end_label)
1960 def generate_arg_assignment(self, arg, item, code):
1961 if arg.type.is_pyobject:
1962 if arg.is_generic:
1963 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1964 code.putln("%s = %s;" % (arg.entry.cname, item))
1965 else:
1966 func = arg.type.from_py_function
1967 if func:
1968 code.putln("%s = %s(%s); %s" % (
1969 arg.entry.cname,
1970 func,
1971 item,
1972 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1973 else:
1974 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1976 def generate_arg_xdecref(self, arg, code):
1977 if arg:
1978 code.put_var_xdecref(arg.entry)
1980 def generate_arg_decref(self, arg, code):
1981 if arg:
1982 code.put_var_decref(arg.entry)
1984 def generate_stararg_copy_code(self, code):
1985 if not self.star_arg:
1986 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1987 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1988 Naming.args_cname)
1989 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
1990 self.name.utf8encode(), Naming.args_cname, self.error_value()))
1991 code.putln("}")
1993 code.globalstate.use_utility_code(keyword_string_check_utility_code)
1995 if self.starstar_arg:
1996 if self.star_arg:
1997 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
1998 else:
1999 kwarg_check = "%s" % Naming.kwds_cname
2000 else:
2001 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2002 Naming.kwds_cname, Naming.kwds_cname)
2003 code.putln(
2004 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2005 kwarg_check, Naming.kwds_cname, self.name,
2006 bool(self.starstar_arg), self.error_value()))
2008 if self.starstar_arg:
2009 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2010 self.starstar_arg.entry.cname,
2011 Naming.kwds_cname,
2012 Naming.kwds_cname))
2013 code.putln("if (unlikely(!%s)) return %s;" % (
2014 self.starstar_arg.entry.cname, self.error_value()))
2015 self.starstar_arg.entry.xdecref_cleanup = 0
2016 code.put_gotref(self.starstar_arg.entry.cname)
2019 if self.star_arg:
2020 code.put_incref(Naming.args_cname, py_object_type)
2021 code.putln("%s = %s;" % (
2022 self.star_arg.entry.cname,
2023 Naming.args_cname))
2024 self.star_arg.entry.xdecref_cleanup = 0
2026 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2027 kw_only_args, success_label, code):
2028 argtuple_error_label = code.new_label("argtuple_error")
2030 min_positional_args = self.num_required_args - self.num_required_kw_args
2031 if len(self.args) > 0 and self.args[0].is_self_arg:
2032 min_positional_args -= 1
2033 max_positional_args = len(positional_args)
2034 has_fixed_positional_count = not self.star_arg and \
2035 min_positional_args == max_positional_args
2037 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2038 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2039 if self.num_required_kw_args:
2040 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2042 if self.starstar_arg or self.star_arg:
2043 self.generate_stararg_init_code(max_positional_args, code)
2045 # --- optimised code when we receive keyword arguments
2046 if self.num_required_kw_args:
2047 likely_hint = "likely"
2048 else:
2049 likely_hint = "unlikely"
2050 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2051 self.generate_keyword_unpacking_code(
2052 min_positional_args, max_positional_args,
2053 has_fixed_positional_count,
2054 positional_args, kw_only_args, argtuple_error_label, code)
2056 # --- optimised code when we do not receive any keyword arguments
2057 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2058 # Python raises arg tuple related errors first, so we must
2059 # check the length here
2060 if min_positional_args == max_positional_args and not self.star_arg:
2061 compare = '!='
2062 else:
2063 compare = '<'
2064 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2065 Naming.args_cname, compare, min_positional_args))
2066 code.put_goto(argtuple_error_label)
2068 if self.num_required_kw_args:
2069 # pure error case: keywords required but not passed
2070 if max_positional_args > min_positional_args and not self.star_arg:
2071 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2072 Naming.args_cname, max_positional_args))
2073 code.put_goto(argtuple_error_label)
2074 code.putln('} else {')
2075 for i, arg in enumerate(kw_only_args):
2076 if not arg.default:
2077 # required keyword-only argument missing
2078 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2079 self.name.utf8encode(),
2080 arg.name_entry.pystring_cname))
2081 code.putln(code.error_goto(self.pos))
2082 break
2084 elif min_positional_args == max_positional_args:
2085 # parse the exact number of positional arguments from the
2086 # args tuple
2087 code.putln('} else {')
2088 for i, arg in enumerate(positional_args):
2089 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2090 self.generate_arg_assignment(arg, item, code)
2091 self.generate_arg_default_assignments(code)
2093 else:
2094 # parse the positional arguments from the variable length
2095 # args tuple
2096 code.putln('} else {')
2097 self.generate_arg_default_assignments(code)
2098 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2099 if self.star_arg:
2100 code.putln('default:')
2101 reversed_args = list(enumerate(positional_args))[::-1]
2102 for i, arg in reversed_args:
2103 if i >= min_positional_args-1:
2104 if min_positional_args > 1:
2105 code.putln('case %2d:' % (i+1)) # pure code beautification
2106 else:
2107 code.put('case %2d: ' % (i+1))
2108 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2109 self.generate_arg_assignment(arg, item, code)
2110 if min_positional_args == 0:
2111 code.put('case 0: ')
2112 code.putln('break;')
2113 if self.star_arg:
2114 if min_positional_args:
2115 for i in range(min_positional_args-1, -1, -1):
2116 code.putln('case %2d:' % i)
2117 code.put_goto(argtuple_error_label)
2118 else:
2119 code.put('default: ')
2120 code.put_goto(argtuple_error_label)
2121 code.putln('}')
2123 code.putln('}')
2125 if code.label_used(argtuple_error_label):
2126 code.put_goto(success_label)
2127 code.put_label(argtuple_error_label)
2128 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2129 self.name.utf8encode(), has_fixed_positional_count,
2130 min_positional_args, max_positional_args,
2131 Naming.args_cname))
2132 code.putln(code.error_goto(self.pos))
2134 def generate_arg_default_assignments(self, code):
2135 for arg in self.args:
2136 if arg.is_generic and arg.default:
2137 code.putln(
2138 "%s = %s;" % (
2139 arg.entry.cname,
2140 arg.default_result_code))
2142 def generate_stararg_init_code(self, max_positional_args, code):
2143 if self.starstar_arg:
2144 self.starstar_arg.entry.xdecref_cleanup = 0
2145 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2146 self.starstar_arg.entry.cname,
2147 self.starstar_arg.entry.cname,
2148 self.error_value()))
2149 code.put_gotref(self.starstar_arg.entry.cname)
2150 if self.star_arg:
2151 self.star_arg.entry.xdecref_cleanup = 0
2152 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2153 Naming.args_cname,
2154 max_positional_args))
2155 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2156 self.star_arg.entry.cname, Naming.args_cname,
2157 max_positional_args, Naming.args_cname))
2158 code.put_gotref(self.star_arg.entry.cname)
2159 if self.starstar_arg:
2160 code.putln("")
2161 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2162 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2163 code.putln('return %s;' % self.error_value())
2164 code.putln('}')
2165 else:
2166 code.putln("if (unlikely(!%s)) return %s;" % (
2167 self.star_arg.entry.cname, self.error_value()))
2168 code.putln('} else {')
2169 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2170 code.put_incref(Naming.empty_tuple, py_object_type)
2171 code.putln('}')
2173 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2174 has_fixed_positional_count, positional_args,
2175 kw_only_args, argtuple_error_label, code):
2176 all_args = tuple(positional_args) + tuple(kw_only_args)
2177 max_args = len(all_args)
2179 default_args = []
2180 for i, arg in enumerate(all_args):
2181 if arg.default and arg.type.is_pyobject:
2182 default_value = arg.default_result_code
2183 if arg.type is not PyrexTypes.py_object_type:
2184 default_value = "(PyObject*)"+default_value
2185 default_args.append((i, default_value))
2187 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2188 Naming.kwds_cname)
2189 # it looks funny to separate the init-to-0 from setting the
2190 # default value, but C89 needs this
2191 code.putln("PyObject* values[%d] = {%s};" % (
2192 max_args, ','.join(['0']*max_args)))
2193 for i, default_value in default_args:
2194 code.putln('values[%d] = %s;' % (i, default_value))
2196 # parse the tuple and check that it's not too long
2197 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2198 if self.star_arg:
2199 code.putln('default:')
2200 for i in range(max_positional_args-1, -1, -1):
2201 code.put('case %2d: ' % (i+1))
2202 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2203 i, Naming.args_cname, i))
2204 code.putln('case 0: break;')
2205 if not self.star_arg:
2206 code.put('default: ') # more arguments than allowed
2207 code.put_goto(argtuple_error_label)
2208 code.putln('}')
2210 # now fill up the positional/required arguments with values
2211 # from the kw dict
2212 if self.num_required_args or max_positional_args > 0:
2213 last_required_arg = -1
2214 for i, arg in enumerate(all_args):
2215 if not arg.default:
2216 last_required_arg = i
2217 if last_required_arg < max_positional_args:
2218 last_required_arg = max_positional_args-1
2219 num_required_args = self.num_required_args
2220 if max_positional_args > 0:
2221 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2222 for i, arg in enumerate(all_args[:last_required_arg+1]):
2223 if max_positional_args > 0 and i <= max_positional_args:
2224 if self.star_arg and i == max_positional_args:
2225 code.putln('default:')
2226 else:
2227 code.putln('case %2d:' % i)
2228 if arg.default:
2229 if arg.kw_only:
2230 # handled separately below
2231 continue
2232 code.putln('if (kw_args > %d) {' % num_required_args)
2233 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2234 Naming.kwds_cname, arg.name_entry.pystring_cname))
2235 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2236 code.putln('}')
2237 else:
2238 num_required_args -= 1
2239 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2240 i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2241 code.putln('if (likely(values[%d])) kw_args--;' % i);
2242 if i < min_positional_args:
2243 if i == 0:
2244 # special case: we know arg 0 is missing
2245 code.put('else ')
2246 code.put_goto(argtuple_error_label)
2247 else:
2248 # print the correct number of values (args or
2249 # kwargs) that were passed into positional
2250 # arguments up to this point
2251 code.putln('else {')
2252 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2253 self.name.utf8encode(), has_fixed_positional_count,
2254 min_positional_args, max_positional_args, i))
2255 code.putln(code.error_goto(self.pos))
2256 code.putln('}')
2257 elif arg.kw_only:
2258 code.putln('else {')
2259 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2260 self.name.utf8encode(), arg.name_entry.pystring_cname))
2261 code.putln(code.error_goto(self.pos))
2262 code.putln('}')
2263 if max_positional_args > 0:
2264 code.putln('}')
2266 if kw_only_args and not self.starstar_arg:
2267 # unpack optional keyword-only arguments
2268 # checking for interned strings in a dict is faster than iterating
2269 # but it's too likely that we must iterate if we expect **kwargs
2270 optional_args = []
2271 for i, arg in enumerate(all_args[max_positional_args:]):
2272 if not arg.kw_only or not arg.default:
2273 continue
2274 optional_args.append((i+max_positional_args, arg))
2275 if optional_args:
2276 # this mimics an unrolled loop so that we can "break" out of it
2277 code.putln('while (kw_args > 0) {')
2278 code.putln('PyObject* value;')
2279 for i, arg in optional_args:
2280 code.putln(
2281 'value = PyDict_GetItem(%s, %s);' % (
2282 Naming.kwds_cname, arg.name_entry.pystring_cname))
2283 code.putln(
2284 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2285 code.putln('break;')
2286 code.putln('}')
2288 code.putln('if (unlikely(kw_args > 0)) {')
2289 # non-positional/-required kw args left in dict: default args,
2290 # kw-only args, **kwargs or error
2292 # This is sort of a catch-all: except for checking required
2293 # arguments, this will always do the right thing for unpacking
2294 # keyword arguments, so that we can concentrate on optimising
2295 # common cases above.
2296 if max_positional_args == 0:
2297 pos_arg_count = "0"
2298 elif self.star_arg:
2299 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2300 Naming.args_cname, max_positional_args,
2301 Naming.args_cname, max_positional_args))
2302 pos_arg_count = "used_pos_args"
2303 else:
2304 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2305 code.globalstate.use_utility_code(parse_keywords_utility_code)
2306 code.put(
2307 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2308 Naming.kwds_cname,
2309 Naming.pykwdlist_cname,
2310 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2311 pos_arg_count,
2312 self.name.utf8encode()))
2313 code.putln(code.error_goto(self.pos))
2314 code.putln('}')
2316 # convert arg values to their final type and assign them
2317 for i, arg in enumerate(all_args):
2318 if arg.default and not arg.type.is_pyobject:
2319 code.putln("if (values[%d]) {" % i)
2320 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2321 if arg.default and not arg.type.is_pyobject:
2322 code.putln('} else {')
2323 code.putln(
2324 "%s = %s;" % (
2325 arg.entry.cname,
2326 arg.default_result_code))
2327 code.putln('}')
2329 def generate_argument_conversion_code(self, code):
2330 # Generate code to convert arguments from
2331 # signature type to declared type, if needed.
2332 for arg in self.args:
2333 if arg.needs_conversion:
2334 self.generate_arg_conversion(arg, code)
2336 def generate_arg_conversion(self, arg, code):
2337 # Generate conversion code for one argument.
2338 old_type = arg.hdr_type
2339 new_type = arg.type
2340 if old_type.is_pyobject:
2341 if arg.default:
2342 code.putln("if (%s) {" % arg.hdr_cname)
2343 else:
2344 code.putln("assert(%s); {" % arg.hdr_cname)
2345 self.generate_arg_conversion_from_pyobject(arg, code)
2346 code.putln("}")
2347 elif new_type.is_pyobject:
2348 self.generate_arg_conversion_to_pyobject(arg, code)
2349 else:
2350 if new_type.assignable_from(old_type):
2351 code.putln(
2352 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2353 else:
2354 error(arg.pos,
2355 "Cannot convert 1 argument from '%s' to '%s'" %
2356 (old_type, new_type))
2358 def generate_arg_conversion_from_pyobject(self, arg, code):
2359 new_type = arg.type
2360 func = new_type.from_py_function
2361 # copied from CoerceFromPyTypeNode
2362 if func:
2363 code.putln("%s = %s(%s); %s" % (
2364 arg.entry.cname,
2365 func,
2366 arg.hdr_cname,
2367 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2368 else:
2369 error(arg.pos,
2370 "Cannot convert Python object argument to type '%s'"
2371 % new_type)
2373 def generate_arg_conversion_to_pyobject(self, arg, code):
2374 old_type = arg.hdr_type
2375 func = old_type.to_py_function
2376 if func:
2377 code.putln("%s = %s(%s); %s" % (
2378 arg.entry.cname,
2379 func,
2380 arg.hdr_cname,
2381 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2382 code.put_var_gotref(arg.entry)
2383 else:
2384 error(arg.pos,
2385 "Cannot convert argument of type '%s' to Python object"
2386 % old_type)
2388 def generate_argument_type_tests(self, code):
2389 # Generate type tests for args whose signature
2390 # type is PyObject * and whose declared type is
2391 # a subtype thereof.
2392 for arg in self.args:
2393 if arg.needs_type_test:
2394 self.generate_arg_type_test(arg, code)
2396 def generate_arg_type_test(self, arg, code):
2397 # Generate type test for one argument.
2398 if arg.type.typeobj_is_available():
2399 typeptr_cname = arg.type.typeptr_cname
2400 arg_code = "((PyObject *)%s)" % arg.entry.cname
2401 code.putln(
2402 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2403 arg_code,
2404 typeptr_cname,
2405 not arg.not_none,
2406 arg.name,
2407 arg.type.is_builtin_type,
2408 code.error_goto(arg.pos)))
2409 else:
2410 error(arg.pos, "Cannot test type of extern C class "
2411 "without type object name specification")
2413 def error_value(self):
2414 return self.entry.signature.error_value
2416 def caller_will_check_exceptions(self):
2417 return 1
2419 class OverrideCheckNode(StatNode):
2420 # A Node for dispatching to the def method if it
2421 # is overriden.
2423 # py_func
2425 # args
2426 # func_temp
2427 # body
2429 child_attrs = ['body']
2431 body = None
2433 def analyse_expressions(self, env):
2434 self.args = env.arg_entries
2435 if self.py_func.is_module_scope:
2436 first_arg = 0
2437 else:
2438 first_arg = 1
2439 import ExprNodes
2440 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2441 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2442 call_node = ExprNodes.SimpleCallNode(self.pos,
2443 function=self.func_node,
2444 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2445 self.body = ReturnStatNode(self.pos, value=call_node)
2446 self.body.analyse_expressions(env)
2448 def generate_execution_code(self, code):
2449 # Check to see if we are an extension type
2450 if self.py_func.is_module_scope:
2451 self_arg = "((PyObject *)%s)" % Naming.module_cname
2452 else:
2453 self_arg = "((PyObject *)%s)" % self.args[0].cname
2454 code.putln("/* Check if called by wrapper */")
2455 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2456 code.putln("/* Check if overriden in Python */")
2457 if self.py_func.is_module_scope:
2458 code.putln("else {")
2459 else:
2460 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2461 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2462 # need to get attribute manually--scope would return cdef method
2463 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2464 code.put_gotref(self.func_node.py_result())
2465 is_builtin_function_or_method = 'PyCFunction_Check(%s)' % self.func_node.result()
2466 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2467 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2468 self.body.generate_execution_code(code)
2469 code.putln('}')
2470 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2471 code.putln("}")
2473 class ClassDefNode(StatNode, BlockNode):
2474 pass
2476 class PyClassDefNode(ClassDefNode):
2477 # A Python class definition.
2479 # name EncodedString Name of the class
2480 # doc string or None
2481 # body StatNode Attribute definition code
2482 # entry Symtab.Entry
2483 # scope PyClassScope
2485 # The following subnodes are constructed internally:
2487 # dict DictNode Class dictionary
2488 # classobj ClassNode Class object
2489 # target NameNode Variable to assign class object to
2491 child_attrs = ["body", "dict", "classobj", "target"]
2493 def __init__(self, pos, name, bases, doc, body):
2494 StatNode.__init__(self, pos)
2495 self.name = name
2496 self.doc = doc
2497 self.body = body
2498 import ExprNodes
2499 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2500 if self.doc and Options.docstrings:
2501 doc = embed_position(self.pos, self.doc)
2502 doc_node = ExprNodes.StringNode(pos, value = doc)
2503 else:
2504 doc_node = None
2505 self.classobj = ExprNodes.ClassNode(pos, name = name,
2506 bases = bases, dict = self.dict, doc = doc_node)
2507 self.target = ExprNodes.NameNode(pos, name = name)
2509 def as_cclass(self):
2510 """
2511 Return this node as if it were declared as an extension class
2512 """
2513 bases = self.classobj.bases.args
2514 if len(bases) == 0:
2515 base_class_name = None
2516 base_class_module = None
2517 elif len(bases) == 1:
2518 base = bases[0]
2519 path = []
2520 from ExprNodes import AttributeNode, NameNode
2521 while isinstance(base, AttributeNode):
2522 path.insert(0, base.attribute)
2523 base = base.obj
2524 if isinstance(base, NameNode):
2525 path.insert(0, base.name)
2526 base_class_name = path[-1]
2527 if len(path) > 1:
2528 base_class_module = u'.'.join(path[:-1])
2529 else:
2530 base_class_module = None
2531 else:
2532 error(self.classobj.bases.args.pos, "Invalid base class")
2533 else:
2534 error(self.classobj.bases.args.pos, "C class may only have one base class")
2535 return None
2537 return CClassDefNode(self.pos,
2538 visibility = 'private',
2539 module_name = None,
2540 class_name = self.name,
2541 base_class_module = base_class_module,
2542 base_class_name = base_class_name,
2543 body = self.body,
2544 in_pxd = False,
2545 doc = self.doc)
2547 def create_scope(self, env):
2548 genv = env
2549 while env.is_py_class_scope or env.is_c_class_scope:
2550 env = env.outer_scope
2551 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2552 return cenv
2554 def analyse_declarations(self, env):
2555 self.target.analyse_target_declaration(env)
2556 cenv = self.create_scope(env)
2557 cenv.class_obj_cname = self.target.entry.cname
2558 self.body.analyse_declarations(cenv)
2560 def analyse_expressions(self, env):
2561 self.dict.analyse_expressions(env)
2562 self.classobj.analyse_expressions(env)
2563 genv = env.global_scope()
2564 cenv = self.scope
2565 cenv.class_dict_cname = self.dict.result()
2566 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2567 self.body.analyse_expressions(cenv)
2568 self.target.analyse_target_expression(env, self.classobj)
2569 self.dict.release_temp(env)
2570 #self.classobj.release_temp(env)
2571 #self.target.release_target_temp(env)
2573 def generate_function_definitions(self, env, code):
2574 self.generate_py_string_decls(self.scope, code)
2575 self.body.generate_function_definitions(self.scope, code)
2577 def generate_execution_code(self, code):
2578 self.dict.generate_evaluation_code(code)
2579 self.classobj.generate_evaluation_code(code)
2580 self.body.generate_execution_code(code)
2581 self.target.generate_assignment_code(self.classobj, code)
2582 self.dict.generate_disposal_code(code)
2583 self.dict.free_temps(code)
2586 class CClassDefNode(ClassDefNode):
2587 # An extension type definition.
2589 # visibility 'private' or 'public' or 'extern'
2590 # typedef_flag boolean
2591 # api boolean
2592 # module_name string or None For import of extern type objects
2593 # class_name string Unqualified name of class
2594 # as_name string or None Name to declare as in this scope
2595 # base_class_module string or None Module containing the base class
2596 # base_class_name string or None Name of the base class
2597 # objstruct_name string or None Specified C name of object struct
2598 # typeobj_name string or None Specified C name of type object
2599 # in_pxd boolean Is in a .pxd file
2600 # doc string or None
2601 # body StatNode or None
2602 # entry Symtab.Entry
2603 # base_type PyExtensionType or None
2604 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2605 # buffer_defaults_pos
2607 child_attrs = ["body"]
2608 buffer_defaults_node = None
2609 buffer_defaults_pos = None
2610 typedef_flag = False
2611 api = False
2612 objstruct_name = None
2613 typeobj_name = None
2615 def analyse_declarations(self, env):
2616 #print "CClassDefNode.analyse_declarations:", self.class_name
2617 #print "...visibility =", self.visibility
2618 #print "...module_name =", self.module_name
2620 import Buffer
2621 if self.buffer_defaults_node:
2622 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2623 env, [], self.buffer_defaults_node,
2624 need_complete=False)
2625 else:
2626 buffer_defaults = None
2628 if env.in_cinclude and not self.objstruct_name:
2629 error(self.pos, "Object struct name specification required for "
2630 "C class defined in 'extern from' block")
2631 self.base_type = None
2632 # Now that module imports are cached, we need to
2633 # import the modules for extern classes.
2634 if self.module_name:
2635 self.module = None
2636 for module in env.cimported_modules:
2637 if module.name == self.module_name:
2638 self.module = module
2639 if self.module is None:
2640 self.module = ModuleScope(self.module_name, None, env.context)
2641 self.module.has_extern_class = 1
2642 env.add_imported_module(self.module)
2644 if self.base_class_name:
2645 if self.base_class_module:
2646 base_class_scope = env.find_module(self.base_class_module, self.pos)
2647 else:
2648 base_class_scope = env
2649 if self.base_class_name == 'object':
2650 # extension classes are special and don't need to inherit from object
2651 if base_class_scope is None or base_class_scope.lookup('object') is None:
2652 self.base_class_name = None
2653 self.base_class_module = None
2654 base_class_scope = None
2655 if base_class_scope:
2656 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2657 if base_class_entry:
2658 if not base_class_entry.is_type:
2659 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2660 elif not base_class_entry.type.is_extension_type:
2661 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2662 elif not base_class_entry.type.is_complete():
2663 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2664 else:
2665 self.base_type = base_class_entry.type
2666 has_body = self.body is not None
2667 if self.module_name and self.visibility != 'extern':
2668 module_path = self.module_name.split(".")
2669 home_scope = env.find_imported_module(module_path, self.pos)
2670 if not home_scope:
2671 return
2672 else:
2673 home_scope = env
2674 self.entry = home_scope.declare_c_class(
2675 name = self.class_name,
2676 pos = self.pos,
2677 defining = has_body and self.in_pxd,
2678 implementing = has_body and not self.in_pxd,
2679 module_name = self.module_name,
2680 base_type = self.base_type,
2681 objstruct_cname = self.objstruct_name,
2682 typeobj_cname = self.typeobj_name,
2683 visibility = self.visibility,
2684 typedef_flag = self.typedef_flag,
2685 api = self.api,
2686 buffer_defaults = buffer_defaults)
2687 if home_scope is not env and self.visibility == 'extern':
2688 env.add_imported_entry(self.class_name, self.entry, pos)
2689 scope = self.entry.type.scope
2691 if self.doc and Options.docstrings:
2692 scope.doc = embed_position(self.pos, self.doc)
2694 if has_body:
2695 self.body.analyse_declarations(scope)
2696 if self.in_pxd:
2697 scope.defined = 1
2698 else:
2699 scope.implemented = 1
2700 env.allocate_vtable_names(self.entry)
2702 def analyse_expressions(self, env):
2703 if self.body:
2704 scope = self.entry.type.scope
2705 self.body.analyse_expressions(scope)
2707 def generate_function_definitions(self, env, code):
2708 self.generate_py_string_decls(self.entry.type.scope, code)
2709 if self.body:
2710 self.body.generate_function_definitions(
2711 self.entry.type.scope, code)
2713 def generate_execution_code(self, code):
2714 # This is needed to generate evaluation code for
2715 # default values of method arguments.
2716 if self.body:
2717 self.body.generate_execution_code(code)
2719 def annotate(self, code):
2720 if self.body:
2721 self.body.annotate(code)
2724 class PropertyNode(StatNode):
2725 # Definition of a property in an extension type.
2727 # name string
2728 # doc EncodedString or None Doc string
2729 # body StatListNode
2731 child_attrs = ["body"]
2733 def analyse_declarations(self, env):
2734 entry = env.declare_property(self.name, self.doc, self.pos)
2735 if entry:
2736 if self.doc and Options.docstrings:
2737 doc_entry = env.get_string_const(
2738 self.doc, identifier = False)
2739 entry.doc_cname = doc_entry.cname
2740 self.body.analyse_declarations(entry.scope)
2742 def analyse_expressions(self, env):
2743 self.body.analyse_expressions(env)
2745 def generate_function_definitions(self, env, code):
2746 self.body.generate_function_definitions(env, code)
2748 def generate_execution_code(self, code):
2749 pass
2751 def annotate(self, code):
2752 self.body.annotate(code)
2755 class GlobalNode(StatNode):
2756 # Global variable declaration.
2758 # names [string]
2760 child_attrs = []
2762 def analyse_declarations(self, env):
2763 for name in self.names:
2764 env.declare_global(name, self.pos)
2766 def analyse_expressions(self, env):
2767 pass
2769 def generate_execution_code(self, code):
2770 pass
2773 class ExprStatNode(StatNode):
2774 # Expression used as a statement.
2776 # expr ExprNode
2778 child_attrs = ["expr"]
2780 def analyse_declarations(self, env):
2781 import ExprNodes
2782 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2783 func = self.expr.function.as_cython_attribute()
2784 if func == u'declare':
2785 args, kwds = self.expr.explicit_args_kwds()
2786 if len(args):
2787 error(self.expr.pos, "Variable names must be specified.")
2788 for var, type_node in kwds.key_value_pairs:
2789 type = type_node.analyse_as_type(env)
2790 if type is None:
2791 error(type_node.pos, "Unknown type")
2792 else:
2793 env.declare_var(var.value, type, var.pos, is_cdef = True)
2794 self.__class__ = PassStatNode
2796 def analyse_expressions(self, env):
2797 self.expr.analyse_expressions(env)
2798 self.expr.release_temp(env)
2800 def generate_execution_code(self, code):
2801 self.expr.generate_evaluation_code(code)
2802 if not self.expr.is_temp and self.expr.result():
2803 code.putln("%s;" % self.expr.result())
2804 self.expr.generate_disposal_code(code)
2805 self.expr.free_temps(code)
2807 def annotate(self, code):
2808 self.expr.annotate(code)
2811 class AssignmentNode(StatNode):
2812 # Abstract base class for assignment nodes.
2814 # The analyse_expressions and generate_execution_code
2815 # phases of assignments are split into two sub-phases
2816 # each, to enable all the right hand sides of a
2817 # parallel assignment to be evaluated before assigning
2818 # to any of the left hand sides.
2820 def analyse_expressions(self, env):
2821 self.analyse_types(env)
2822 self.allocate_rhs_temps(env)
2823 self.allocate_lhs_temps(env)
2825 # def analyse_expressions(self, env):
2826 # self.analyse_expressions_1(env)
2827 # self.analyse_expressions_2(env)
2829 def generate_execution_code(self, code):
2830 self.generate_rhs_evaluation_code(code)
2831 self.generate_assignment_code(code)
2834 class SingleAssignmentNode(AssignmentNode):
2835 # The simplest case:
2837 # a = b
2839 # lhs ExprNode Left hand side
2840 # rhs ExprNode Right hand side
2841 # first bool Is this guaranteed the first assignment to lhs?
2843 child_attrs = ["lhs", "rhs"]
2844 first = False
2845 declaration_only = False
2847 def analyse_declarations(self, env):
2848 import ExprNodes
2850 # handle declarations of the form x = cython.foo()
2851 if isinstance(self.rhs, ExprNodes.CallNode):
2852 func_name = self.rhs.function.as_cython_attribute()
2853 if func_name:
2854 args, kwds = self.rhs.explicit_args_kwds()
2856 if func_name in ['declare', 'typedef']:
2857 if len(args) > 2 or kwds is not None:
2858 error(rhs.pos, "Can only declare one type at a time.")
2859 return
2860 type = args[0].analyse_as_type(env)
2861 if type is None:
2862 error(args[0].pos, "Unknown type")
2863 return
2864 lhs = self.lhs
2865 if func_name == 'declare':
2866 if isinstance(lhs, ExprNodes.NameNode):
2867 vars = [(lhs.name, lhs.pos)]
2868 elif isinstance(lhs, ExprNodes.TupleNode):
2869 vars = [(var.name, var.pos) for var in lhs.args]
2870 else:
2871 error(lhs.pos, "Invalid declaration")
2872 return
2873 for var, pos in vars:
2874 env.declare_var(var, type, pos, is_cdef = True)
2875 if len(args) == 2:
2876 # we have a value
2877 self.rhs = args[1]
2878 else:
2879 self.declaration_only = True
2880 else:
2881 self.declaration_only = True
2882 if not isinstance(lhs, ExprNodes.NameNode):
2883 error(lhs.pos, "Invalid declaration.")
2884 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2886 elif func_name in ['struct', 'union']:
2887 self.declaration_only = True
2888 if len(args) > 0 or kwds is None:
2889 error(rhs.pos, "Struct or union members must be given by name.")
2890 return
2891 members = []
2892 for member, type_node in kwds.key_value_pairs:
2893 type = type_node.analyse_as_type(env)
2894 if type is None:
2895 error(type_node.pos, "Unknown type")
2896 else:
2897 members.append((member.value, type, member.pos))
2898 if len(members) < len(kwds.key_value_pairs):
2899 return
2900 if not isinstance(self.lhs, ExprNodes.NameNode):
2901 error(self.lhs.pos, "Invalid declaration.")
2902 name = self.lhs.name
2903 scope = StructOrUnionScope(name)
2904 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2905 for member, type, pos in members:
2906 scope.declare_var(member, type, pos)
2908 if self.declaration_only:
2909 return
2910 else:
2911 self.lhs.analyse_target_declaration(env)
2913 def analyse_types(self, env, use_temp = 0):
2914 self.rhs.analyse_types(env)
2915 self.lhs.analyse_target_types(env)
2916 self.lhs.gil_assignment_check(env)
2917 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2918 if use_temp:
2919 self.rhs = self.rhs.coerce_to_temp(env)
2921 def allocate_rhs_temps(self, env):
2922 self.rhs.allocate_temps(env)
2924 def allocate_lhs_temps(self, env):
2925 self.lhs.allocate_target_temps(env, self.rhs)
2926 #self.lhs.release_target_temp(env)
2927 #self.rhs.release_temp(env)
2929 def generate_rhs_evaluation_code(self, code):
2930 self.rhs.generate_evaluation_code(code)
2932 def generate_assignment_code(self, code):
2933 self.lhs.generate_assignment_code(self.rhs, code)
2935 def annotate(self, code):
2936 self.lhs.annotate(code)
2937 self.rhs.annotate(code)
2940 class CascadedAssignmentNode(AssignmentNode):
2941 # An assignment with multiple left hand sides:
2943 # a = b = c
2945 # lhs_list [ExprNode] Left hand sides
2946 # rhs ExprNode Right hand sides
2948 # Used internally:
2950 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2952 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2953 coerced_rhs_list = None
2955 def analyse_declarations(self, env):
2956 for lhs in self.lhs_list:
2957 lhs.analyse_target_declaration(env)
2959 def analyse_types(self, env, use_temp = 0):
2960 self.rhs.analyse_types(env)
2961 if use_temp:
2962 self.rhs = self.rhs.coerce_to_temp(env)
2963 else:
2964 self.rhs = self.rhs.coerce_to_simple(env)
2965 from ExprNodes import CloneNode
2966 self.coerced_rhs_list = []
2967 for lhs in self.lhs_list:
2968 lhs.analyse_target_types(env)
2969 lhs.gil_assignment_check(env)
2970 rhs = CloneNode(self.rhs)
2971 rhs = rhs.coerce_to(lhs.type, env)
2972 self.coerced_rhs_list.append(rhs)
2974 def allocate_rhs_temps(self, env):
2975 self.rhs.allocate_temps(env)
2977 def allocate_lhs_temps(self, env):
2978 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2979 rhs.allocate_temps(env)
2980 lhs.allocate_target_temps(env, rhs)
2981 #lhs.release_target_temp(env)
2982 #rhs.release_temp(env)
2983 self.rhs.release_temp(env)
2985 def generate_rhs_evaluation_code(self, code):
2986 self.rhs.generate_evaluation_code(code)
2988 def generate_assignment_code(self, code):
2989 for i in range(len(self.lhs_list)):
2990 lhs = self.lhs_list[i]
2991 rhs = self.coerced_rhs_list[i]
2992 rhs.generate_evaluation_code(code)
2993 lhs.generate_assignment_code(rhs, code)
2994 # Assignment has disposed of the cloned RHS
2995 self.rhs.generate_disposal_code(code)
2996 self.rhs.free_temps(code)
2998 def annotate(self, code):
2999 for i in range(len(self.lhs_list)):
3000 lhs = self.lhs_list[i].annotate(code)
3001 rhs = self.coerced_rhs_list[i].annotate(code)
3002 self.rhs.annotate(code)
3005 class ParallelAssignmentNode(AssignmentNode):
3006 # A combined packing/unpacking assignment:
3008 # a, b, c = d, e, f
3010 # This has been rearranged by the parser into
3012 # a = d ; b = e ; c = f
3014 # but we must evaluate all the right hand sides
3015 # before assigning to any of the left hand sides.
3017 # stats [AssignmentNode] The constituent assignments
3019 child_attrs = ["stats"]
3021 def analyse_declarations(self, env):
3022 for stat in self.stats:
3023 stat.analyse_declarations(env)
3025 def analyse_expressions(self, env):
3026 for stat in self.stats:
3027 stat.analyse_types(env, use_temp = 1)
3028 stat.allocate_rhs_temps(env)
3029 for stat in self.stats:
3030 stat.allocate_lhs_temps(env)
3032 # def analyse_expressions(self, env):
3033 # for stat in self.stats:
3034 # stat.analyse_expressions_1(env, use_temp = 1)
3035 # for stat in self.stats:
3036 # stat.analyse_expressions_2(env)
3038 def generate_execution_code(self, code):
3039 for stat in self.stats:
3040 stat.generate_rhs_evaluation_code(code)
3041 for stat in self.stats:
3042 stat.generate_assignment_code(code)
3044 def annotate(self, code):
3045 for stat in self.stats:
3046 stat.annotate(code)
3049 class InPlaceAssignmentNode(AssignmentNode):
3050 # An in place arithmatic operand:
3052 # a += b
3053 # a -= b
3054 # ...
3056 # lhs ExprNode Left hand side
3057 # rhs ExprNode Right hand side
3058 # op char one of "+-*/%^&|"
3059 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3061 # This code is a bit tricky because in order to obey Python
3062 # semantics the sub-expressions (e.g. indices) of the lhs must
3063 # not be evaluated twice. So we must re-use the values calculated
3064 # in evaluation phase for the assignment phase as well.
3065 # Fortunately, the type of the lhs node is fairly constrained
3066 # (it must be a NameNode, AttributeNode, or IndexNode).
3068 child_attrs = ["lhs", "rhs"]
3069 dup = None
3071 def analyse_declarations(self, env):
3072 self.lhs.analyse_target_declaration(env)
3074 def analyse_types(self, env):
3075 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3076 self.rhs.analyse_types(env)
3077 self.lhs.analyse_target_types(env)
3078 if Options.incref_local_binop and self.dup.type.is_pyobject:
3079 self.dup = self.dup.coerce_to_temp(env)
3081 def allocate_rhs_temps(self, env):
3082 import ExprNodes
3083 if self.lhs.type.is_pyobject:
3084 self.rhs = self.rhs.coerce_to_pyobject(env)
3085 elif self.rhs.type.is_pyobject:
3086 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3087 if self.lhs.type.is_pyobject:
3088 self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
3089 self.result_value.allocate_temps(env)
3090 # if use_temp:
3091 # self.rhs = self.rhs.coerce_to_temp(env)
3092 self.rhs.allocate_temps(env)
3093 self.dup.allocate_subexpr_temps(env)
3094 self.dup.allocate_temp(env)
3096 def allocate_lhs_temps(self, env):
3097 self.lhs.allocate_target_temps(env, self.rhs)
3098 # self.lhs.release_target_temp(env)
3099 self.dup.release_temp(env)
3100 if self.dup.is_temp:
3101 self.dup.release_subexpr_temps(env)
3102 # self.rhs.release_temp(env)
3103 if self.lhs.type.is_pyobject:
3104 self.result_value.release_temp(env)
3106 def generate_execution_code(self, code):
3107 import ExprNodes
3108 self.rhs.generate_evaluation_code(code)
3109 self.dup.generate_subexpr_evaluation_code(code)
3110 if isinstance(self.dup, ExprNodes.NewTempExprNode):
3111 # This is because we're manually messing with subexpr nodes
3112 if self.dup.is_temp:
3113 self.dup.allocate_temp_result(code)
3114 # self.dup.generate_result_code is run only if it is not buffer access
3115 if self.operator == "**":
3116 extra = ", Py_None"
3117 else:
3118 extra = ""
3119 if self.lhs.type.is_pyobject:
3120 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3121 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3122 self.dup.generate_result_code(code)
3123 code.putln(
3124 "%s = %s(%s, %s%s); %s" % (
3125 self.result_value.result(),
3126 self.py_operation_function(),
3127 self.dup.py_result(),
3128 self.rhs.py_result(),
3129 extra,
3130 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3131 code.put_gotref(self.result_value.py_result())
3132 self.result_value.generate_evaluation_code(code) # May be a type check...
3133 self.rhs.generate_disposal_code(code)
3134 self.rhs.free_temps(code)
3135 self.dup.generate_disposal_code(code)
3136 self.dup.free_temps(code)
3137 self.lhs.generate_assignment_code(self.result_value, code)
3138 else:
3139 c_op = self.operator
3140 if c_op == "//":
3141 c_op = "/"
3142 elif c_op == "**":
3143 if self.lhs.type.is_int and self.rhs.type.is_int:
3144 error(self.pos, "** with two C int types is ambiguous")
3145 else:
3146 error(self.pos, "No C inplace power operator")
3147 # have to do assignment directly to avoid side-effects
3148 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3149 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3150 else:
3151 self.dup.generate_result_code(code)
3152 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3153 self.rhs.generate_disposal_code(code)
3154 self.rhs.free_temps(code)
3155 if self.dup.is_temp:
3156 self.dup.generate_subexpr_disposal_code(code)
3157 self.dup.free_subexpr_temps(code)
3159 def create_dup_node(self, env):
3160 import ExprNodes
3161 self.dup = self.lhs
3162 self.dup.analyse_types(env)
3163 if isinstance(self.lhs, ExprNodes.NameNode):
3164 target_lhs = ExprNodes.NameNode(self.dup.pos,
3165 name = self.dup.name,
3166 is_temp = self.dup.is_temp,
3167 entry = self.dup.entry)
3168 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3169 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3170 obj = ExprNodes.CloneNode(self.lhs.obj),
3171 attribute = self.dup.attribute,
3172 is_temp = self.dup.is_temp)
3173 elif isinstance(self.lhs, ExprNodes.IndexNode):
3174 if self.lhs.index:
3175 index = ExprNodes.CloneNode(self.lhs.index)
3176 else:
3177 index = None
3178 if self.lhs.indices:
3179 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3180 else:
3181 indices = []
3182 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3183 base = ExprNodes.CloneNode(self.dup.base),
3184 index = index,
3185 indices = indices,
3186 is_temp = self.dup.is_temp)
3187 else:
3188 assert False
3189 self.lhs = target_lhs
3190 return self.dup
3192 def py_operation_function(self):
3193 return self.py_functions[self.operator]
3195 py_functions = {
3196 "|": "PyNumber_InPlaceOr",
3197 "^": "PyNumber_InPlaceXor",
3198 "&": "PyNumber_InPlaceAnd",
3199 "+": "PyNumber_InPlaceAdd",
3200 "-": "PyNumber_InPlaceSubtract",
3201 "*": "PyNumber_InPlaceMultiply",
3202 "/": "PyNumber_InPlaceDivide",
3203 "%": "PyNumber_InPlaceRemainder",
3204 "<<": "PyNumber_InPlaceLshift",
3205 ">>": "PyNumber_InPlaceRshift",
3206 "**": "PyNumber_InPlacePower",
3207 "//": "PyNumber_InPlaceFloorDivide",
3210 def annotate(self, code):
3211 self.lhs.annotate(code)
3212 self.rhs.annotate(code)
3213 self.dup.annotate(code)
3216 class PrintStatNode(StatNode):
3217 # print statement
3219 # arg_tuple TupleNode
3220 # append_newline boolean
3222 child_attrs = ["arg_tuple"]
3224 def analyse_expressions(self, env):
3225 self.arg_tuple.analyse_expressions(env)
3226 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3227 self.arg_tuple.release_temp(env)
3228 env.use_utility_code(printing_utility_code)
3229 if len(self.arg_tuple.args) == 1 and self.append_newline:
3230 env.use_utility_code(printing_one_utility_code)
3231 self.gil_check(env)
3233 gil_message = "Python print statement"
3235 def generate_execution_code(self, code):
3236 if len(self.arg_tuple.args) == 1 and self.append_newline:
3237 arg = self.arg_tuple.args[0]
3238 arg.generate_evaluation_code(code)
3240 code.putln(
3241 "if (__Pyx_PrintOne(%s) < 0) %s" % (
3242 arg.py_result(),
3243 code.error_goto(self.pos)))
3244 arg.generate_disposal_code(code)
3245 arg.free_temps(code)
3246 else:
3247 self.arg_tuple.generate_evaluation_code(code)
3248 code.putln(
3249 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3250 self.arg_tuple.py_result(),
3251 self.append_newline,
3252 code.error_goto(self.pos)))
3253 self.arg_tuple.generate_disposal_code(code)
3254 self.arg_tuple.free_temps(code)
3256 def annotate(self, code):
3257 self.arg_tuple.annotate(code)
3260 class ExecStatNode(StatNode):
3261 # exec statement
3263 # args [ExprNode]
3265 child_attrs = ["args"]
3267 def analyse_expressions(self, env):
3268 for i, arg in enumerate(self.args):
3269 arg.analyse_expressions(env)
3270 arg = arg.coerce_to_pyobject(env)
3271 arg.release_temp(env)
3272 self.args[i] = arg
3273 self.temp_result = env.allocate_temp_pyobject()
3274 env.release_temp(self.temp_result)
3275 env.use_utility_code(Builtin.pyexec_utility_code)
3276 self.gil_check(env)
3278 gil_message = "Python exec statement"
3280 def generate_execution_code(self, code):
3281 args = []
3282 for arg in self.args:
3283 arg.generate_evaluation_code(code)
3284 args.append( arg.py_result() )
3285 args = tuple(args + ['0', '0'][:3-len(args)])
3286 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3287 (self.temp_result,) + args))
3288 for arg in self.args:
3289 arg.generate_disposal_code(code)
3290 arg.free_temps(code)
3291 code.putln(
3292 code.error_goto_if_null(self.temp_result, self.pos))
3293 code.put_gotref(self.temp_result)
3294 code.put_decref_clear(self.temp_result, py_object_type)
3296 def annotate(self, code):
3297 for arg in self.args:
3298 arg.annotate(code)
3301 class DelStatNode(StatNode):
3302 # del statement
3304 # args [ExprNode]
3306 child_attrs = ["args"]
3308 def analyse_declarations(self, env):
3309 for arg in self.args:
3310 arg.analyse_target_declaration(env)
3312 def analyse_expressions(self, env):
3313 for arg in self.args:
3314 arg.analyse_target_expression(env, None)
3315 if arg.type.is_pyobject:
3316 self.gil_check(env)
3317 else:
3318 error(arg.pos, "Deletion of non-Python object")
3319 #arg.release_target_temp(env)
3321 gil_message = "Deleting Python object"
3323 def generate_execution_code(self, code):
3324 for arg in self.args:
3325 if arg.type.is_pyobject:
3326 arg.generate_deletion_code(code)
3327 # else error reported earlier
3329 def annotate(self, code):
3330 for arg in self.args:
3331 arg.annotate(code)
3334 class PassStatNode(StatNode):
3335 # pass statement
3337 child_attrs = []
3339 def analyse_expressions(self, env):
3340 pass
3342 def generate_execution_code(self, code):
3343 pass
3346 class BreakStatNode(StatNode):
3348 child_attrs = []
3350 def analyse_expressions(self, env):
3351 pass
3353 def generate_execution_code(self, code):
3354 if not code.break_label:
3355 error(self.pos, "break statement not inside loop")
3356 else:
3357 code.put_goto(code.break_label)
3360 class ContinueStatNode(StatNode):
3362 child_attrs = []
3364 def analyse_expressions(self, env):
3365 pass
3367 def generate_execution_code(self, code):
3368 if code.funcstate.in_try_finally:
3369 error(self.pos, "continue statement inside try of try...finally")
3370 elif not code.continue_label:
3371 error(self.pos, "continue statement not inside loop")
3372 else:
3373 code.put_goto(code.continue_label)
3376 class ReturnStatNode(StatNode):
3377 # return statement
3379 # value ExprNode or None
3380 # return_type PyrexType
3381 # temps_in_use [Entry] Temps in use at time of return
3383 child_attrs = ["value"]
3385 def analyse_expressions(self, env):
3386 return_type = env.return_type
3387 self.return_type = return_type
3388 self.temps_in_use = env.temps_in_use()
3389 if not return_type:
3390 error(self.pos, "Return not inside a function body")
3391 return
3392 if self.value:
3393 self.value.analyse_types(env)
3394 if return_type.is_void or return_type.is_returncode:
3395 error(self.value.pos,
3396 "Return with value in void function")
3397 else:
3398 self.value = self.value.coerce_to(env.return_type, env)
3399 self.value.allocate_temps(env)
3400 self.value.release_temp(env)
3401 else:
3402 if (not return_type.is_void
3403 and not return_type.is_pyobject
3404 and not return_type.is_returncode):
3405 error(self.pos, "Return value required")
3406 if return_type.is_pyobject:
3407 self.gil_check(env)
3409 gil_message = "Returning Python object"
3411 def generate_execution_code(self, code):
3412 code.mark_pos(self.pos)
3413 if not self.return_type:
3414 # error reported earlier
3415 return
3416 if self.return_type.is_pyobject:
3417 code.put_xdecref(Naming.retval_cname,
3418 self.return_type)
3419 if self.value:
3420 self.value.generate_evaluation_code(code)
3421 self.value.make_owned_reference(code)
3422 code.putln(
3423 "%s = %s;" % (
3424 Naming.retval_cname,
3425 self.value.result_as(self.return_type)))
3426 self.value.generate_post_assignment_code(code)
3427 self.value.free_temps(code)
3428 else:
3429 if self.return_type.is_pyobject:
3430 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3431 elif self.return_type.is_returncode:
3432 code.putln(
3433 "%s = %s;" % (
3434 Naming.retval_cname,
3435 self.return_type.default_value))
3436 # free temps the old way
3437 for entry in self.temps_in_use:
3438 code.put_var_decref_clear(entry)
3439 # free temps the new way
3440 for cname, type in code.funcstate.temps_holding_reference():
3441 code.put_decref_clear(cname, type)
3442 #code.putln(
3443 # "goto %s;" %
3444 # code.return_label)
3445 code.put_goto(code.return_label)
3447 def annotate(self, code):
3448 if self.value:
3449 self.value.annotate(code)
3452 class RaiseStatNode(StatNode):
3453 # raise statement
3455 # exc_type ExprNode or None
3456 # exc_value ExprNode or None
3457 # exc_tb ExprNode or None
3459 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3461 def analyse_expressions(self, env):
3462 if self.exc_type:
3463 self.exc_type.analyse_types(env)
3464 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3465 self.exc_type.allocate_temps(env)
3466 if self.exc_value:
3467 self.exc_value.analyse_types(env)
3468 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3469 self.exc_value.allocate_temps(env)
3470 if self.exc_tb:
3471 self.exc_tb.analyse_types(env)
3472 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3473 self.exc_tb.allocate_temps(env)
3474 if self.exc_type:
3475 self.exc_type.release_temp(env)
3476 if self.exc_value:
3477 self.exc_value.release_temp(env)
3478 if self.exc_tb:
3479 self.exc_tb.release_temp(env)
3480 env.use_utility_code(raise_utility_code)
3481 env.use_utility_code(restore_exception_utility_code)
3482 self.gil_check(env)
3484 gil_message = "Raising exception"
3486 def generate_execution_code(self, code):
3487 if self.exc_type:
3488 self.exc_type.generate_evaluation_code(code)
3489 type_code = self.exc_type.py_result()
3490 else:
3491 type_code = "0"
3492 if self.exc_value:
3493 self.exc_value.generate_evaluation_code(code)
3494 value_code = self.exc_value.py_result()
3495 else:
3496 value_code = "0"
3497 if self.exc_tb:
3498 self.exc_tb.generate_evaluation_code(code)
3499 tb_code = self.exc_tb.py_result()
3500 else:
3501 tb_code = "0"
3502 if self.exc_type or self.exc_value or self.exc_tb:
3503 code.putln(
3504 "__Pyx_Raise(%s, %s, %s);" % (
3505 type_code,
3506 value_code,
3507 tb_code))
3508 else:
3509 code.putln(
3510 "__Pyx_ReRaise();")
3511 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3512 if obj:
3513 obj.generate_disposal_code(code)
3514 obj.free_temps(code)
3515 code.putln(
3516 code.error_goto(self.pos))
3518 def annotate(self, code):
3519 if self.exc_type:
3520 self.exc_type.annotate(code)
3521 if self.exc_value:
3522 self.exc_value.annotate(code)
3523 if self.exc_tb:
3524 self.exc_tb.annotate(code)
3527 class ReraiseStatNode(StatNode):
3529 child_attrs = []
3531 def analyse_expressions(self, env):
3532 self.gil_check(env)
3533 env.use_utility_code(raise_utility_code)
3534 env.use_utility_code(restore_exception_utility_code)
3536 gil_message = "Raising exception"
3538 def generate_execution_code(self, code):
3539 vars = code.funcstate.exc_vars
3540 if vars:
3541 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3542 code.putln(code.error_goto(self.pos))
3543 else:
3544 error(self.pos, "Reraise not inside except clause")
3547 class AssertStatNode(StatNode):
3548 # assert statement
3550 # cond ExprNode
3551 # value ExprNode or None
3553 child_attrs = ["cond", "value"]
3555 def analyse_expressions(self, env):
3556 self.cond = self.cond.analyse_boolean_expression(env)
3557 if self.value:
3558 self.value.analyse_types(env)
3559 self.value = self.value.coerce_to_pyobject(env)
3560 self.value.allocate_temps(env)
3561 self.cond.release_temp(env)
3562 if self.value:
3563 self.value.release_temp(env)
3564 self.gil_check(env)
3565 #env.recycle_pending_temps() # TEMPORARY
3567 gil_message = "Raising exception"
3569 def generate_execution_code(self, code):
3570 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3571 self.cond.generate_evaluation_code(code)
3572 code.putln(
3573 "if (unlikely(!%s)) {" %
3574 self.cond.result())
3575 if self.value:
3576 self.value.generate_evaluation_code(code)
3577 code.putln(
3578 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3579 self.value.py_result())
3580 self.value.generate_disposal_code(code)
3581 self.value.free_temps(code)
3582 else:
3583 code.putln(
3584 "PyErr_SetNone(PyExc_AssertionError);")
3585 code.putln(
3586 code.error_goto(self.pos))
3587 code.putln(
3588 "}")
3589 self.cond.generate_disposal_code(code)
3590 self.cond.free_temps(code)
3591 code.putln("#endif")
3593 def annotate(self, code):
3594 self.cond.annotate(code)
3595 if self.value:
3596 self.value.annotate(code)
3599 class IfStatNode(StatNode):
3600 # if statement
3602 # if_clauses [IfClauseNode]
3603 # else_clause StatNode or None
3605 child_attrs = ["if_clauses", "else_clause"]
3607 def analyse_control_flow(self, env):
3608 env.start_branching(self.pos)
3609 for if_clause in self.if_clauses:
3610 if_clause.analyse_control_flow(env)
3611 env.next_branch(if_clause.end_pos())
3612 if self.else_clause:
3613 self.else_clause.analyse_control_flow(env)
3614 env.finish_branching(self.end_pos())
3616 def analyse_declarations(self, env):
3617 for if_clause in self.if_clauses:
3618 if_clause.analyse_declarations(env)
3619 if self.else_clause:
3620 self.else_clause.analyse_declarations(env)
3622 def analyse_expressions(self, env):
3623 for if_clause in self.if_clauses:
3624 if_clause.analyse_expressions(env)
3625 if self.else_clause:
3626 self.else_clause.analyse_expressions(env)
3628 def generate_execution_code(self, code):
3629 code.mark_pos(self.pos)
3630 end_label = code.new_label()
3631 for if_clause in self.if_clauses:
3632 if_clause.generate_execution_code(code, end_label)
3633 if self.else_clause:
3634 code.putln("/*else*/ {")
3635 self.else_clause.generate_execution_code(code)
3636 code.putln("}")
3637 code.put_label(end_label)
3639 def annotate(self, code):
3640 for if_clause in self.if_clauses:
3641 if_clause.annotate(code)
3642 if self.else_clause:
3643 self.else_clause.annotate(code)
3646 class IfClauseNode(Node):
3647 # if or elif clause in an if statement
3649 # condition ExprNode
3650 # body StatNode
3652 child_attrs = ["condition", "body"]
3654 def analyse_control_flow(self, env):
3655 self.body.analyse_control_flow(env)
3657 def analyse_declarations(self, env):
3658 self.condition.analyse_declarations(env)
3659 self.body.analyse_declarations(env)
3661 def analyse_expressions(self, env):
3662 self.condition = \
3663 self.condition.analyse_temp_boolean_expression(env)
3664 self.condition.release_temp(env)
3665 self.body.analyse_expressions(env)
3667 def generate_execution_code(self, code, end_label):
3668 self.condition.generate_evaluation_code(code)
3669 code.putln(
3670 "if (%s) {" %
3671 self.condition.result())
3672 self.condition.generate_disposal_code(code)
3673 self.condition.free_temps(code)
3674 self.body.generate_execution_code(code)
3675 #code.putln(
3676 # "goto %s;" %
3677 # end_label)
3678 code.put_goto(end_label)
3679 code.putln("}")
3681 def annotate(self, code):
3682 self.condition.annotate(code)
3683 self.body.annotate(code)
3686 class SwitchCaseNode(StatNode):
3687 # Generated in the optimization of an if-elif-else node
3689 # conditions [ExprNode]
3690 # body StatNode
3692 child_attrs = ['conditions', 'body']
3694 def generate_execution_code(self, code):
3695 for cond in self.conditions:
3696 code.mark_pos(cond.pos)
3697 code.putln("case %s:" % cond.calculate_result_code())
3698 self.body.generate_execution_code(code)
3699 code.putln("break;")
3701 def annotate(self, code):
3702 for cond in self.conditions:
3703 cond.annotate(code)
3704 self.body.annotate(code)
3706 class SwitchStatNode(StatNode):
3707 # Generated in the optimization of an if-elif-else node
3709 # test ExprNode
3710 # cases [SwitchCaseNode]
3711 # else_clause StatNode or None
3713 child_attrs = ['test', 'cases', 'else_clause']
3715 def generate_execution_code(self, code):
3716 code.putln("switch (%s) {" % self.test.calculate_result_code())
3717 for case in self.cases:
3718 case.generate_execution_code(code)
3719 if self.else_clause is not None:
3720 code.putln("default:")
3721 self.else_clause.generate_execution_code(code)
3722 code.putln("break;")
3723 code.putln("}")
3725 def annotate(self, code):
3726 self.test.annotate(code)
3727 for case in self.cases:
3728 case.annotate(code)
3729 if self.else_clause is not None:
3730 self.else_clause.annotate(code)
3732 class LoopNode(object):
3734 def analyse_control_flow(self, env):
3735 env.start_branching(self.pos)
3736 self.body.analyse_control_flow(env)
3737 env.next_branch(self.body.end_pos())
3738 if self.else_clause:
3739 self.else_clause.analyse_control_flow(env)
3740 env.finish_branching(self.end_pos())
3743 class WhileStatNode(LoopNode, StatNode):
3744 # while statement
3746 # condition ExprNode
3747 # body StatNode
3748 # else_clause StatNode
3750 child_attrs = ["condition", "body", "else_clause"]
3752 def analyse_declarations(self, env):
3753 self.body.analyse_declarations(env)
3754 if self.else_clause:
3755 self.else_clause.analyse_declarations(env)
3757 def analyse_expressions(self, env):
3758 self.condition = \
3759 self.condition.analyse_temp_boolean_expression(env)
3760 self.condition.release_temp(env)
3761 #env.recycle_pending_temps() # TEMPORARY
3762 self.body.analyse_expressions(env)
3763 if self.else_clause:
3764 self.else_clause.analyse_expressions(env)
3766 def generate_execution_code(self, code):
3767 old_loop_labels = code.new_loop_labels()
3768 code.putln(
3769 "while (1) {")
3770 self.condition.generate_evaluation_code(code)
3771 self.condition.generate_disposal_code(code)
3772 code.putln(
3773 "if (!%s) break;" %
3774 self.condition.result())
3775 self.condition.free_temps(code)
3776 self.body.generate_execution_code(code)
3777 code.put_label(code.continue_label)
3778 code.putln("}")
3779 break_label = code.break_label
3780 code.set_loop_labels(old_loop_labels)
3781 if self.else_clause:
3782 code.putln("/*else*/ {")
3783 self.else_clause.generate_execution_code(code)
3784 code.putln("}")
3785 code.put_label(break_label)
3787 def annotate(self, code):
3788 self.condition.annotate(code)
3789 self.body.annotate(code)
3790 if self.else_clause:
3791 self.else_clause.annotate(code)
3794 def ForStatNode(pos, **kw):
3795 if 'iterator' in kw:
3796 return ForInStatNode(pos, **kw)
3797 else:
3798 return ForFromStatNode(pos, **kw)
3800 class ForInStatNode(LoopNode, StatNode):
3801 # for statement
3803 # target ExprNode
3804 # iterator IteratorNode
3805 # body StatNode
3806 # else_clause StatNode
3807 # item NextNode used internally
3809 child_attrs = ["target", "iterator", "body", "else_clause"]
3810 item = None
3812 def analyse_declarations(self, env):
3813 self.target.analyse_target_declaration(env)
3814 self.body.analyse_declarations(env)
3815 if self.else_clause:
3816 self.else_clause.analyse_declarations(env)
3818 def analyse_expressions(self, env):
3819 import ExprNodes
3820 self.target.analyse_target_types(env)
3821 self.iterator.analyse_expressions(env)
3822 self.item = ExprNodes.NextNode(self.iterator, env)
3823 self.item = self.item.coerce_to(self.target.type, env)
3824 self.item.allocate_temps(env)
3825 self.target.allocate_target_temps(env, self.item)
3826 #self.item.release_temp(env)
3827 #self.target.release_target_temp(env)
3828 self.body.analyse_expressions(env)
3829 if self.else_clause:
3830 self.else_clause.analyse_expressions(env)
3831 self.iterator.release_temp(env)
3833 def generate_execution_code(self, code):
3834 old_loop_labels = code.new_loop_labels()
3835 self.iterator.allocate_counter_temp(code)
3836 self.iterator.generate_evaluation_code(code)
3837 code.putln(
3838 "for (;;) {")
3839 self.item.generate_evaluation_code(code)
3840 self.target.generate_assignment_code(self.item, code)
3841 self.body.generate_execution_code(code)
3842 code.put_label(code.continue_label)
3843 code.putln(
3844 "}")
3845 break_label = code.break_label
3846 code.set_loop_labels(old_loop_labels)
3847 if self.else_clause:
3848 code.putln("/*else*/ {")
3849 self.else_clause.generate_execution_code(code)
3850 code.putln("}")
3851 code.put_label(break_label)
3852 self.iterator.release_counter_temp(code)
3853 self.iterator.generate_disposal_code(code)
3854 self.iterator.free_temps(code)
3856 def annotate(self, code):
3857 self.target.annotate(code)
3858 self.iterator.annotate(code)
3859 self.body.annotate(code)
3860 if self.else_clause:
3861 self.else_clause.annotate(code)
3862 self.item.annotate(code)
3865 class ForFromStatNode(LoopNode, StatNode):
3866 # for name from expr rel name rel expr
3868 # target NameNode
3869 # bound1 ExprNode
3870 # relation1 string
3871 # relation2 string
3872 # bound2 ExprNode
3873 # step ExprNode or None
3874 # body StatNode
3875 # else_clause StatNode or None
3877 # Used internally:
3879 # is_py_target bool
3880 # loopvar_node ExprNode (usually a NameNode or temp node)
3881 # py_loopvar_node PyTempNode or None
3882 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3884 is_py_target = False
3885 loopvar_node = None
3886 py_loopvar_node = None
3888 def analyse_declarations(self, env):
3889 self.target.analyse_target_declaration(env)
3890 self.body.analyse_declarations(env)
3891 if self.else_clause:
3892 self.else_clause.analyse_declarations(env)
3894 def analyse_expressions(self, env):
3895 import ExprNodes
3896 self.target.analyse_target_types(env)
3897 self.bound1.analyse_types(env)
3898 self.bound2.analyse_types(env)
3899 if self.target.type.is_numeric:
3900 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3901 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3902 else:
3903 self.bound1 = self.bound1.coerce_to_integer(env)
3904 self.bound2 = self.bound2.coerce_to_integer(env)
3905 if self.step is not None:
3906 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3907 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3908 self.step.analyse_types(env)
3909 self.step = self.step.coerce_to_integer(env)
3910 if not (self.bound2.is_name or self.bound2.is_literal):
3911 self.bound2 = self.bound2.coerce_to_temp(env)
3912 target_type = self.target.type
3913 if not (target_type.is_pyobject or target_type.is_numeric):
3914 error(self.target.pos,
3915 "Integer for-loop variable must be of type int or Python object")
3916 #if not (target_type.is_pyobject
3917 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3918 # error(self.target.pos,
3919 # "Cannot assign integer to variable of type '%s'" % target_type)
3920 if target_type.is_numeric:
3921 self.is_py_target = 0
3922 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3923 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3924 self.loopvar_node = self.target
3925 self.py_loopvar_node = None
3926 else:
3927 self.is_py_target = 1
3928 c_loopvar_node = ExprNodes.TempNode(self.pos,
3929 PyrexTypes.c_long_type, env)
3930 c_loopvar_node.allocate_temps(env)
3931 self.loopvar_node = c_loopvar_node
3932 self.py_loopvar_node = \
3933 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3934 self.bound1.allocate_temps(env)
3935 self.bound2.allocate_temps(env)
3936 if self.step is not None:
3937 self.step.allocate_temps(env)
3938 if self.is_py_target:
3939 self.py_loopvar_node.allocate_temps(env)
3940 self.target.allocate_target_temps(env, self.py_loopvar_node)
3941 #self.target.release_target_temp(env)
3942 #self.py_loopvar_node.release_temp(env)
3943 self.body.analyse_expressions(env)
3944 if self.is_py_target:
3945 c_loopvar_node.release_temp(env)
3946 if self.else_clause:
3947 self.else_clause.analyse_expressions(env)
3948 self.bound1.release_temp(env)
3949 self.bound2.release_temp(env)
3950 if self.step is not None:
3951 self.step.release_temp(env)
3953 def generate_execution_code(self, code):
3954 old_loop_labels = code.new_loop_labels()
3955 from_range = getattr(self, "from_range", False)
3956 self.bound1.generate_evaluation_code(code)
3957 self.bound2.generate_evaluation_code(code)
3958 offset, incop = self.relation_table[self.relation1]
3959 if incop == "++":
3960 decop = "--"
3961 else:
3962 decop = "++"
3963 if self.step is not None:
3964 self.step.generate_evaluation_code(code)
3965 step = self.step.result()
3966 incop = "%s=%s" % (incop[0], step)
3967 decop = "%s=%s" % (decop[0], step)
3968 loopvar_name = self.loopvar_node.result()
3969 if from_range:
3970 # Skip the loop entirely (and avoid assigning to the loopvar) if
3971 # the loop is empty:
3972 code.putln("if (%s%s %s %s) {" % (
3973 self.bound1.result(), offset, self.relation2, self.bound2.result()
3974 ))
3975 code.putln(
3976 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3977 loopvar_name,
3978 self.bound1.result(), offset,
3979 loopvar_name, self.relation2, self.bound2.result(),
3980 loopvar_name, incop))
3981 if self.py_loopvar_node:
3982 self.py_loopvar_node.generate_evaluation_code(code)
3983 self.target.generate_assignment_code(self.py_loopvar_node, code)
3984 self.body.generate_execution_code(code)
3985 code.put_label(code.continue_label)
3986 if from_range:
3987 # Undo last increment to maintain Python semantics:
3988 code.putln("} %s%s;" % (loopvar_name, decop))
3989 # End the outer if statement:
3990 code.putln("} /* end if */")
3991 else:
3992 code.putln("}")
3993 break_label = code.break_label
3994 code.set_loop_labels(old_loop_labels)
3995 if self.else_clause:
3996 code.putln("/*else*/ {")
3997 self.else_clause.generate_execution_code(code)
3998 code.putln("}")
3999 code.put_label(break_label)
4000 self.bound1.generate_disposal_code(code)
4001 self.bound1.free_temps(code)
4002 self.bound2.generate_disposal_code(code)
4003 self.bound2.free_temps(code)
4004 if self.step is not None:
4005 self.step.generate_disposal_code(code)
4006 self.step.free_temps(code)
4008 relation_table = {
4009 # {relop : (initial offset, increment op)}
4010 '<=': ("", "++"),
4011 '<' : ("+1", "++"),
4012 '>=': ("", "--"),
4013 '>' : ("-1", "--")
4016 def annotate(self, code):
4017 self.target.annotate(code)
4018 self.bound1.annotate(code)
4019 self.bound2.annotate(code)
4020 if self.step:
4021 self.bound2.annotate(code)
4022 self.body.annotate(code)
4023 if self.else_clause:
4024 self.else_clause.annotate(code)
4027 class WithStatNode(StatNode):
4028 """
4029 Represents a Python with statement.
4031 This is only used at parse tree level; and is not present in
4032 analysis or generation phases.
4033 """
4034 # manager The with statement manager object
4035 # target Node (lhs expression)
4036 # body StatNode
4037 child_attrs = ["manager", "target", "body"]
4039 class TryExceptStatNode(StatNode):
4040 # try .. except statement
4042 # body StatNode
4043 # except_clauses [ExceptClauseNode]
4044 # else_clause StatNode or None
4045 # cleanup_list [Entry] old style temps to clean up on error
4047 child_attrs = ["body", "except_clauses", "else_clause"]
4049 def analyse_control_flow(self, env):
4050 env.start_branching(self.pos)
4051 self.body.analyse_control_flow(env)
4052 successful_try = env.control_flow # grab this for later
4053 env.next_branch(self.body.end_pos())
4054 env.finish_branching(self.body.end_pos())
4056 env.start_branching(self.except_clauses[0].pos)
4057 for except_clause in self.except_clauses:
4058 except_clause.analyse_control_flow(env)
4059 env.next_branch(except_clause.end_pos())
4061 # the else cause it executed only when the try clause finishes
4062 env.control_flow.incoming = successful_try
4063 if self.else_clause:
4064 self.else_clause.analyse_control_flow(env)
4065 env.finish_branching(self.end_pos())
4067 def analyse_declarations(self, env):
4068 self.body.analyse_declarations(env)
4069 for except_clause in self.except_clauses:
4070 except_clause.analyse_declarations(env)
4071 if self.else_clause:
4072 self.else_clause.analyse_declarations(env)
4073 self.gil_check(env)
4074 env.use_utility_code(reset_exception_utility_code)
4076 def analyse_expressions(self, env):
4077 self.body.analyse_expressions(env)
4078 self.cleanup_list = env.free_temp_entries[:]
4079 default_clause_seen = 0
4080 for except_clause in self.except_clauses:
4081 except_clause.analyse_expressions(env)
4082 if default_clause_seen:
4083 error(except_clause.pos, "default 'except:' must be last")
4084 if not except_clause.pattern:
4085 default_clause_seen = 1
4086 self.has_default_clause = default_clause_seen
4087 if self.else_clause:
4088 self.else_clause.analyse_expressions(env)
4089 self.gil_check(env)
4091 gil_message = "Try-except statement"
4093 def generate_execution_code(self, code):
4094 old_return_label = code.return_label
4095 old_break_label = code.break_label
4096 old_continue_label = code.continue_label
4097 old_error_label = code.new_error_label()
4098 our_error_label = code.error_label
4099 except_end_label = code.new_label('exception_handled')
4100 except_error_label = code.new_label('except_error')
4101 except_return_label = code.new_label('except_return')
4102 try_return_label = code.new_label('try_return')
4103 try_break_label = code.new_label('try_break')
4104 try_continue_label = code.new_label('try_continue')
4105 try_end_label = code.new_label('try_end')
4107 code.putln("{")
4108 code.putln("PyObject %s;" %
4109 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4110 code.putln("__Pyx_ExceptionSave(%s);" %
4111 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4112 for var in Naming.exc_save_vars:
4113 code.put_xgotref(var)
4114 code.putln(
4115 "/*try:*/ {")
4116 code.return_label = try_return_label
4117 code.break_label = try_break_label
4118 code.continue_label = try_continue_label
4119 self.body.generate_execution_code(code)
4120 code.putln(
4121 "}")
4122 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4123 code.error_label = except_error_label
4124 code.return_label = except_return_label
4125 if self.else_clause:
4126 code.putln(
4127 "/*else:*/ {")
4128 self.else_clause.generate_execution_code(code)
4129 code.putln(
4130 "}")
4131 for var in Naming.exc_save_vars:
4132 code.put_xdecref_clear(var, py_object_type)
4133 code.put_goto(try_end_label)
4134 if code.label_used(try_return_label):
4135 code.put_label(try_return_label)
4136 for var in Naming.exc_save_vars:
4137 code.put_xdecref_clear(var, py_object_type)
4138 code.put_goto(old_return_label)
4139 code.put_label(our_error_label)
4140 code.put_var_xdecrefs_clear(self.cleanup_list)
4141 for temp_name, type in temps_to_clean_up:
4142 code.put_xdecref_clear(temp_name, type)
4143 for except_clause in self.except_clauses:
4144 except_clause.generate_handling_code(code, except_end_label)
4146 error_label_used = code.label_used(except_error_label)
4147 if error_label_used or not self.has_default_clause:
4148 if error_label_used:
4149 code.put_label(except_error_label)
4150 for var in Naming.exc_save_vars:
4151 code.put_xdecref(var, py_object_type)
4152 code.put_goto(old_error_label)
4154 if code.label_used(try_break_label):
4155 code.put_label(try_break_label)
4156 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4157 code.putln("__Pyx_ExceptionReset(%s);" %
4158 ', '.join(Naming.exc_save_vars))
4159 code.put_goto(old_break_label)
4161 if code.label_used(try_continue_label):
4162 code.put_label(try_continue_label)
4163 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4164 code.putln("__Pyx_ExceptionReset(%s);" %
4165 ', '.join(Naming.exc_save_vars))
4166 code.put_goto(old_continue_label)
4168 if code.label_used(except_return_label):
4169 code.put_label(except_return_label)
4170 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4171 code.putln("__Pyx_ExceptionReset(%s);" %
4172 ', '.join(Naming.exc_save_vars))
4173 code.put_goto(old_return_label)
4175 if code.label_used(except_end_label):
4176 code.put_label(except_end_label)
4177 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4178 code.putln("__Pyx_ExceptionReset(%s);" %
4179 ', '.join(Naming.exc_save_vars))
4180 code.put_label(try_end_label)
4181 code.putln("}")
4183 code.return_label = old_return_label
4184 code.break_label = old_break_label
4185 code.continue_label = old_continue_label
4186 code.error_label = old_error_label
4188 def annotate(self, code):
4189 self.body.annotate(code)
4190 for except_node in self.except_clauses:
4191 except_node.annotate(code)
4192 if self.else_clause:
4193 self.else_clause.annotate(code)
4196 class ExceptClauseNode(Node):
4197 # Part of try ... except statement.
4199 # pattern ExprNode
4200 # target ExprNode or None
4201 # body StatNode
4202 # excinfo_target NameNode or None optional target for exception info
4203 # match_flag string result of exception match
4204 # exc_value ExcValueNode used internally
4205 # function_name string qualified name of enclosing function
4206 # exc_vars (string * 3) local exception variables
4208 # excinfo_target is never set by the parser, but can be set by a transform
4209 # in order to extract more extensive information about the exception as a
4210 # sys.exc_info()-style tuple into a target variable
4212 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4214 exc_value = None
4215 excinfo_target = None
4217 def analyse_declarations(self, env):
4218 if self.target:
4219 self.target.analyse_target_declaration(env)
4220 if self.excinfo_target is not None:
4221 self.excinfo_target.analyse_target_declaration(env)
4222 self.body.analyse_declarations(env)
4224 def analyse_expressions(self, env):
4225 import ExprNodes
4226 genv = env.global_scope()
4227 self.function_name = env.qualified_name
4228 if self.pattern:
4229 self.pattern.analyse_expressions(env)
4230 self.pattern = self.pattern.coerce_to_pyobject(env)
4231 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
4232 self.pattern.release_temp(env)
4233 env.release_temp(self.match_flag)
4234 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
4235 if self.target:
4236 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
4237 self.exc_value.allocate_temps(env)
4238 self.target.analyse_target_expression(env, self.exc_value)
4239 if self.excinfo_target is not None:
4240 import ExprNodes
4241 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4242 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
4243 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
4244 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
4245 ])
4246 self.excinfo_tuple.analyse_expressions(env)
4247 self.excinfo_tuple.allocate_temps(env)
4248 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4250 self.body.analyse_expressions(env)
4251 for var in self.exc_vars:
4252 env.release_temp(var)
4253 env.use_utility_code(get_exception_utility_code)
4254 env.use_utility_code(restore_exception_utility_code)
4256 def generate_handling_code(self, code, end_label):
4257 code.mark_pos(self.pos)
4258 if self.pattern:
4259 self.pattern.generate_evaluation_code(code)
4260 code.putln(
4261 "%s = PyErr_ExceptionMatches(%s);" % (
4262 self.match_flag,
4263 self.pattern.py_result()))
4264 self.pattern.generate_disposal_code(code)
4265 self.pattern.free_temps(code)
4266 code.putln(
4267 "if (%s) {" %
4268 self.match_flag)
4269 else:
4270 code.putln("/*except:*/ {")
4271 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4272 # We always have to fetch the exception value even if
4273 # there is no target, because this also normalises the
4274 # exception and stores it in the thread state.
4275 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
4276 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4277 code.error_goto(self.pos)))
4278 for x in self.exc_vars:
4279 code.put_gotref(x)
4280 if self.target:
4281 self.exc_value.generate_evaluation_code(code)
4282 self.target.generate_assignment_code(self.exc_value, code)
4283 if self.excinfo_target is not None:
4284 self.excinfo_tuple.generate_evaluation_code(code)
4285 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4288 old_break_label, old_continue_label = code.break_label, code.continue_label
4289 code.break_label = code.new_label('except_break')
4290 code.continue_label = code.new_label('except_continue')
4292 old_exc_vars = code.funcstate.exc_vars
4293 code.funcstate.exc_vars = self.exc_vars
4294 self.body.generate_execution_code(code)
4295 code.funcstate.exc_vars = old_exc_vars
4296 for var in self.exc_vars:
4297 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4298 code.put_goto(end_label)
4300 if code.label_used(code.break_label):
4301 code.put_label(code.break_label)
4302 for var in self.exc_vars:
4303 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4304 code.put_goto(old_break_label)
4305 code.break_label = old_break_label
4307 if code.label_used(code.continue_label):
4308 code.put_label(code.continue_label)
4309 for var in self.exc_vars:
4310 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4311 code.put_goto(old_continue_label)
4312 code.continue_label = old_continue_label
4314 code.putln(
4315 "}")
4317 def annotate(self, code):
4318 if self.pattern:
4319 self.pattern.annotate(code)
4320 if self.target:
4321 self.target.annotate(code)
4322 self.body.annotate(code)
4325 class TryFinallyStatNode(StatNode):
4326 # try ... finally statement
4328 # body StatNode
4329 # finally_clause StatNode
4331 # cleanup_list [Entry] old_style temps to clean up on error
4333 # The plan is that we funnel all continue, break
4334 # return and error gotos into the beginning of the
4335 # finally block, setting a variable to remember which
4336 # one we're doing. At the end of the finally block, we
4337 # switch on the variable to figure out where to go.
4338 # In addition, if we're doing an error, we save the
4339 # exception on entry to the finally block and restore
4340 # it on exit.
4342 child_attrs = ["body", "finally_clause"]
4344 preserve_exception = 1
4346 disallow_continue_in_try_finally = 0
4347 # There doesn't seem to be any point in disallowing
4348 # continue in the try block, since we have no problem
4349 # handling it.
4351 def create_analysed(pos, env, body, finally_clause):
4352 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4353 node.cleanup_list = []
4354 return node
4355 create_analysed = staticmethod(create_analysed)
4357 def analyse_control_flow(self, env):
4358 env.start_branching(self.pos)
4359 self.body.analyse_control_flow(env)
4360 env.next_branch(self.body.end_pos())
4361 env.finish_branching(self.body.end_pos())
4362 self.finally_clause.analyse_control_flow(env)
4364 def analyse_declarations(self, env):
4365 self.body.analyse_declarations(env)
4366 self.finally_clause.analyse_declarations(env)
4368 def analyse_expressions(self, env):
4369 self.body.analyse_expressions(env)
4370 self.cleanup_list = env.free_temp_entries[:]
4371 self.finally_clause.analyse_expressions(env)
4372 self.gil_check(env)
4374 gil_message = "Try-finally statement"
4376 def generate_execution_code(self, code):
4377 old_error_label = code.error_label
4378 old_labels = code.all_new_labels()
4379 new_labels = code.get_all_labels()
4380 new_error_label = code.error_label
4381 catch_label = code.new_label()
4382 code.putln(
4383 "/*try:*/ {")
4384 if self.disallow_continue_in_try_finally:
4385 was_in_try_finally = code.funcstate.in_try_finally
4386 code.funcstate.in_try_finally = 1
4387 self.body.generate_execution_code(code)
4388 if self.disallow_continue_in_try_finally:
4389 code.funcstate.in_try_finally = was_in_try_finally
4390 code.putln(
4391 "}")
4392 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4393 code.putln(
4394 "/*finally:*/ {")
4395 cases_used = []
4396 error_label_used = 0
4397 for i, new_label in enumerate(new_labels):
4398 if new_label in code.labels_used:
4399 cases_used.append(i)
4400 if new_label == new_error_label:
4401 error_label_used = 1
4402 error_label_case = i
4403 if cases_used:
4404 code.putln(
4405 "int __pyx_why;")
4406 if error_label_used and self.preserve_exception:
4407 code.putln(
4408 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4409 code.putln(
4410 "int %s;" % Naming.exc_lineno_name)
4411 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4412 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4413 code.putln(exc_var_init_zero)
4414 else:
4415 exc_var_init_zero = None
4416 code.use_label(catch_label)
4417 code.putln(
4418 "__pyx_why = 0; goto %s;" % catch_label)
4419 for i in cases_used:
4420 new_label = new_labels[i]
4421 #if new_label and new_label != "<try>":
4422 if new_label == new_error_label and self.preserve_exception:
4423 self.put_error_catcher(code,
4424 new_error_label, i+1, catch_label, temps_to_clean_up)
4425 else:
4426 code.put('%s: ' % new_label)
4427 if exc_var_init_zero:
4428 code.putln(exc_var_init_zero)
4429 code.putln("__pyx_why = %s; goto %s;" % (
4430 i+1,
4431 catch_label))
4432 code.put_label(catch_label)
4433 code.set_all_labels(old_labels)
4434 if error_label_used:
4435 code.new_error_label()
4436 finally_error_label = code.error_label
4437 self.finally_clause.generate_execution_code(code)
4438 if error_label_used:
4439 if finally_error_label in code.labels_used and self.preserve_exception:
4440 over_label = code.new_label()
4441 code.put_goto(over_label);
4442 code.put_label(finally_error_label)
4443 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4444 for var in Naming.exc_vars:
4445 code.putln("Py_XDECREF(%s);" % var)
4446 code.putln("}")
4447 code.put_goto(old_error_label)
4448 code.put_label(over_label)
4449 code.error_label = old_error_label
4450 if cases_used:
4451 code.putln(
4452 "switch (__pyx_why) {")
4453 for i in cases_used:
4454 old_label = old_labels[i]
4455 if old_label == old_error_label and self.preserve_exception:
4456 self.put_error_uncatcher(code, i+1, old_error_label)
4457 else:
4458 code.use_label(old_label)
4459 code.putln(
4460 "case %s: goto %s;" % (
4461 i+1,
4462 old_label))
4463 code.putln(
4464 "}")
4465 code.putln(
4466 "}")
4468 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4469 code.globalstate.use_utility_code(restore_exception_utility_code)
4470 code.putln(
4471 "%s: {" %
4472 error_label)
4473 code.putln(
4474 "__pyx_why = %s;" %
4475 i)
4476 code.put_var_xdecrefs_clear(self.cleanup_list)
4477 for temp_name, type in temps_to_clean_up:
4478 code.put_xdecref_clear(temp_name, type)
4479 code.putln(
4480 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4481 Naming.exc_vars)
4482 code.putln(
4483 "%s = %s;" % (
4484 Naming.exc_lineno_name, Naming.lineno_cname))
4485 #code.putln(
4486 # "goto %s;" %
4487 # catch_label)
4488 code.put_goto(catch_label)
4489 code.putln(
4490 "}")
4492 def put_error_uncatcher(self, code, i, error_label):
4493 code.globalstate.use_utility_code(restore_exception_utility_code)
4494 code.putln(
4495 "case %s: {" %
4496 i)
4497 code.putln(
4498 "__Pyx_ErrRestore(%s, %s, %s);" %
4499 Naming.exc_vars)
4500 code.putln(
4501 "%s = %s;" % (
4502 Naming.lineno_cname, Naming.exc_lineno_name))
4503 for var in Naming.exc_vars:
4504 code.putln(
4505 "%s = 0;" %
4506 var)
4507 code.put_goto(error_label)
4508 code.putln(
4509 "}")
4511 def annotate(self, code):
4512 self.body.annotate(code)
4513 self.finally_clause.annotate(code)
4516 class GILStatNode(TryFinallyStatNode):
4517 # 'with gil' or 'with nogil' statement
4519 # state string 'gil' or 'nogil'
4521 child_attrs = []
4523 preserve_exception = 0
4525 def __init__(self, pos, state, body):
4526 self.state = state
4527 TryFinallyStatNode.__init__(self, pos,
4528 body = body,
4529 finally_clause = GILExitNode(pos, state = state))
4531 def analyse_expressions(self, env):
4532 env.use_utility_code(py23_init_threads_utility_code)
4533 was_nogil = env.nogil
4534 env.nogil = 1
4535 TryFinallyStatNode.analyse_expressions(self, env)
4536 env.nogil = was_nogil
4538 def gil_check(self, env):
4539 pass
4541 def generate_execution_code(self, code):
4542 code.putln("/*with %s:*/ {" % self.state)
4543 if self.state == 'gil':
4544 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
4545 else:
4546 code.putln("PyThreadState *_save;")
4547 code.putln("Py_UNBLOCK_THREADS")
4548 TryFinallyStatNode.generate_execution_code(self, code)
4549 code.putln("}")
4552 class GILExitNode(StatNode):
4553 # Used as the 'finally' block in a GILStatNode
4555 # state string 'gil' or 'nogil'
4557 child_attrs = []
4559 def analyse_expressions(self, env):
4560 pass
4562 def generate_execution_code(self, code):
4563 if self.state == 'gil':
4564 code.putln("PyGILState_Release();")
4565 else:
4566 code.putln("Py_BLOCK_THREADS")
4569 class CImportStatNode(StatNode):
4570 # cimport statement
4572 # module_name string Qualified name of module being imported
4573 # as_name string or None Name specified in "as" clause, if any
4575 child_attrs = []
4577 def analyse_declarations(self, env):
4578 if not env.is_module_scope:
4579 error(self.pos, "cimport only allowed at module level")
4580 return
4581 module_scope = env.find_module(self.module_name, self.pos)
4582 if "." in self.module_name:
4583 names = [EncodedString(name) for name in self.module_name.split(".")]
4584 top_name = names[0]
4585 top_module_scope = env.context.find_submodule(top_name)
4586 module_scope = top_module_scope
4587 for name in names[1:]:
4588 submodule_scope = module_scope.find_submodule(name)
4589 module_scope.declare_module(name, submodule_scope, self.pos)
4590 module_scope = submodule_scope
4591 if self.as_name:
4592 env.declare_module(self.as_name, module_scope, self.pos)
4593 else:
4594 env.declare_module(top_name, top_module_scope, self.pos)
4595 else:
4596 name = self.as_name or self.module_name
4597 env.declare_module(name, module_scope, self.pos)
4599 def analyse_expressions(self, env):
4600 pass
4602 def generate_execution_code(self, code):
4603 pass
4606 class FromCImportStatNode(StatNode):
4607 # from ... cimport statement
4609 # module_name string Qualified name of module
4610 # imported_names [(pos, name, as_name, kind)] Names to be imported
4612 child_attrs = []
4614 def analyse_declarations(self, env):
4615 if not env.is_module_scope:
4616 error(self.pos, "cimport only allowed at module level")
4617 return
4618 module_scope = env.find_module(self.module_name, self.pos)
4619 env.add_imported_module(module_scope)
4620 for pos, name, as_name, kind in self.imported_names:
4621 if name == "*":
4622 for local_name, entry in module_scope.entries.items():
4623 env.add_imported_entry(local_name, entry, pos)
4624 else:
4625 entry = module_scope.lookup(name)
4626 if entry:
4627 if kind and not self.declaration_matches(entry, kind):
4628 entry.redeclared(pos)
4629 else:
4630 if kind == 'struct' or kind == 'union':
4631 entry = module_scope.declare_struct_or_union(name,
4632 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4633 elif kind == 'class':
4634 entry = module_scope.declare_c_class(name, pos = pos,
4635 module_name = self.module_name)
4636 else:
4637 error(pos, "Name '%s' not declared in module '%s'"
4638 % (name, self.module_name))
4640 if entry:
4641 local_name = as_name or name
4642 env.add_imported_entry(local_name, entry, pos)
4644 def declaration_matches(self, entry, kind):
4645 if not entry.is_type:
4646 return 0
4647 type = entry.type
4648 if kind == 'class':
4649 if not type.is_extension_type:
4650 return 0
4651 else:
4652 if not type.is_struct_or_union:
4653 return 0
4654 if kind != type.kind:
4655 return 0
4656 return 1
4658 def analyse_expressions(self, env):
4659 pass
4661 def generate_execution_code(self, code):
4662 pass
4665 class FromImportStatNode(StatNode):
4666 # from ... import statement
4668 # module ImportNode
4669 # items [(string, NameNode)]
4670 # interned_items [(string, NameNode, ExprNode)]
4671 # item PyTempNode used internally
4672 # import_star boolean used internally
4674 child_attrs = ["module"]
4675 import_star = 0
4677 def analyse_declarations(self, env):
4678 for name, target in self.items:
4679 if name == "*":
4680 if not env.is_module_scope:
4681 error(self.pos, "import * only allowed at module level")
4682 return
4683 env.has_import_star = 1
4684 self.import_star = 1
4685 else:
4686 target.analyse_target_declaration(env)
4688 def analyse_expressions(self, env):
4689 import ExprNodes
4690 self.module.analyse_expressions(env)
4691 self.item = ExprNodes.PyTempNode(self.pos, env)
4692 self.item.allocate_temp(env)
4693 self.interned_items = []
4694 for name, target in self.items:
4695 if name == '*':
4696 for _, entry in env.entries.items():
4697 if not entry.is_type and entry.type.is_extension_type:
4698 env.use_utility_code(ExprNodes.type_test_utility_code)
4699 break
4700 else:
4701 entry = env.lookup(target.name)
4702 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4703 continue # already cimported
4704 target.analyse_target_expression(env, None)
4705 if target.type is py_object_type:
4706 coerced_item = None
4707 else:
4708 coerced_item = self.item.coerce_to(target.type, env)
4709 self.interned_items.append(
4710 (env.intern_identifier(name), target, coerced_item))
4711 #target.release_target_temp(env) # was release_temp ?!?
4712 self.module.release_temp(env)
4713 self.item.release_temp(env)
4715 def generate_execution_code(self, code):
4716 self.module.generate_evaluation_code(code)
4717 if self.import_star:
4718 code.putln(
4719 'if (%s(%s) < 0) %s;' % (
4720 Naming.import_star,
4721 self.module.py_result(),
4722 code.error_goto(self.pos)))
4723 for cname, target, coerced_item in self.interned_items:
4724 code.putln(
4725 '%s = PyObject_GetAttr(%s, %s); %s' % (
4726 self.item.result(),
4727 self.module.py_result(),
4728 cname,
4729 code.error_goto_if_null(self.item.result(), self.pos)))
4730 code.put_gotref(self.item.py_result())
4731 if coerced_item is None:
4732 target.generate_assignment_code(self.item, code)
4733 else:
4734 coerced_item.allocate_temp_result(code)
4735 coerced_item.generate_result_code(code)
4736 target.generate_assignment_code(coerced_item, code)
4737 if self.item.result() != coerced_item.result():
4738 code.put_decref_clear(self.item.result(), self.item.type)
4739 self.module.generate_disposal_code(code)
4740 self.module.free_temps(code)
4744 #------------------------------------------------------------------------------------
4746 # Runtime support code
4748 #------------------------------------------------------------------------------------
4750 utility_function_predeclarations = \
4751 """
4752 #ifdef __GNUC__
4753 #define INLINE __inline__
4754 #elif _WIN32
4755 #define INLINE __inline
4756 #else
4757 #define INLINE
4758 #endif
4760 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4762 """ + """
4764 static int %(skip_dispatch_cname)s = 0;
4766 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4768 if Options.gcc_branch_hints:
4769 branch_prediction_macros = \
4770 """
4771 #ifdef __GNUC__
4772 /* Test for GCC > 2.95 */
4773 #if __GNUC__ > 2 || \
4774 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4775 #define likely(x) __builtin_expect(!!(x), 1)
4776 #define unlikely(x) __builtin_expect(!!(x), 0)
4777 #else /* __GNUC__ > 2 ... */
4778 #define likely(x) (x)
4779 #define unlikely(x) (x)
4780 #endif /* __GNUC__ > 2 ... */
4781 #else /* __GNUC__ */
4782 #define likely(x) (x)
4783 #define unlikely(x) (x)
4784 #endif /* __GNUC__ */
4785 """
4786 else:
4787 branch_prediction_macros = \
4788 """
4789 #define likely(x) (x)
4790 #define unlikely(x) (x)
4791 """
4793 #get_name_predeclaration = \
4794 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4796 #get_name_interned_predeclaration = \
4797 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4799 #------------------------------------------------------------------------------------
4801 printing_utility_code = UtilityCode(
4802 proto = """
4803 static int __Pyx_Print(PyObject *, int); /*proto*/
4804 #if PY_MAJOR_VERSION >= 3
4805 static PyObject* %s = 0;
4806 static PyObject* %s = 0;
4807 #endif
4808 """ % (Naming.print_function, Naming.print_function_kwargs),
4809 impl = r"""
4810 #if PY_MAJOR_VERSION < 3
4811 static PyObject *__Pyx_GetStdout(void) {
4812 PyObject *f = PySys_GetObject((char *)"stdout");
4813 if (!f) {
4814 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4816 return f;
4819 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4820 PyObject *f;
4821 PyObject* v;
4822 int i;
4824 if (!(f = __Pyx_GetStdout()))
4825 return -1;
4826 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4827 if (PyFile_SoftSpace(f, 1)) {
4828 if (PyFile_WriteString(" ", f) < 0)
4829 return -1;
4831 v = PyTuple_GET_ITEM(arg_tuple, i);
4832 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4833 return -1;
4834 if (PyString_Check(v)) {
4835 char *s = PyString_AsString(v);
4836 Py_ssize_t len = PyString_Size(v);
4837 if (len > 0 &&
4838 isspace(Py_CHARMASK(s[len-1])) &&
4839 s[len-1] != ' ')
4840 PyFile_SoftSpace(f, 0);
4843 if (newline) {
4844 if (PyFile_WriteString("\n", f) < 0)
4845 return -1;
4846 PyFile_SoftSpace(f, 0);
4848 return 0;
4851 #else /* Python 3 has a print function */
4853 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4854 PyObject* kwargs = 0;
4855 PyObject* result = 0;
4856 PyObject* end_string;
4857 if (!%(PRINT_FUNCTION)s) {
4858 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4859 if (!%(PRINT_FUNCTION)s)
4860 return -1;
4862 if (!newline) {
4863 if (!%(PRINT_KWARGS)s) {
4864 %(PRINT_KWARGS)s = PyDict_New();
4865 if (!%(PRINT_KWARGS)s)
4866 return -1;
4867 end_string = PyUnicode_FromStringAndSize(" ", 1);
4868 if (!end_string)
4869 return -1;
4870 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4871 Py_DECREF(end_string);
4872 return -1;
4874 Py_DECREF(end_string);
4876 kwargs = %(PRINT_KWARGS)s;
4878 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4879 if (!result)
4880 return -1;
4881 Py_DECREF(result);
4882 return 0;
4885 #endif
4886 """ % {'BUILTINS' : Naming.builtins_cname,
4887 'PRINT_FUNCTION' : Naming.print_function,
4888 'PRINT_KWARGS' : Naming.print_function_kwargs}
4892 printing_one_utility_code = UtilityCode(
4893 proto = """
4894 static int __Pyx_PrintOne(PyObject *o); /*proto*/
4895 """,
4896 impl = r"""
4897 #if PY_MAJOR_VERSION < 3
4899 static int __Pyx_PrintOne(PyObject *o) {
4900 PyObject *f;
4901 if (!(f = __Pyx_GetStdout()))
4902 return -1;
4903 if (PyFile_SoftSpace(f, 0)) {
4904 if (PyFile_WriteString(" ", f) < 0)
4905 return -1;
4907 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
4908 return -1;
4909 if (PyFile_WriteString("\n", f) < 0)
4910 return -1;
4911 return 0;
4912 /* the line below is just to avoid compiler
4913 * compiler warnings about unused functions */
4914 return __Pyx_Print(NULL, 0);
4917 #else /* Python 3 has a print function */
4919 static int __Pyx_PrintOne(PyObject *o) {
4920 int res;
4921 PyObject* arg_tuple = PyTuple_New(1);
4922 if (unlikely(!arg_tuple))
4923 return -1;
4924 Py_INCREF(o);
4925 PyTuple_SET_ITEM(arg_tuple, 0, o);
4926 res = __Pyx_Print(arg_tuple, 1);
4927 Py_DECREF(arg_tuple);
4928 return res;
4931 #endif
4932 """)
4936 #------------------------------------------------------------------------------------
4938 # The following function is based on do_raise() from ceval.c.
4940 raise_utility_code = UtilityCode(
4941 proto = """
4942 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4943 """,
4944 impl = """
4945 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4946 Py_XINCREF(type);
4947 Py_XINCREF(value);
4948 Py_XINCREF(tb);
4949 /* First, check the traceback argument, replacing None with NULL. */
4950 if (tb == Py_None) {
4951 Py_DECREF(tb);
4952 tb = 0;
4954 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4955 PyErr_SetString(PyExc_TypeError,
4956 "raise: arg 3 must be a traceback or None");
4957 goto raise_error;
4959 /* Next, replace a missing value with None */
4960 if (value == NULL) {
4961 value = Py_None;
4962 Py_INCREF(value);
4964 #if PY_VERSION_HEX < 0x02050000
4965 if (!PyClass_Check(type))
4966 #else
4967 if (!PyType_Check(type))
4968 #endif
4970 /* Raising an instance. The value should be a dummy. */
4971 if (value != Py_None) {
4972 PyErr_SetString(PyExc_TypeError,
4973 "instance exception may not have a separate value");
4974 goto raise_error;
4976 /* Normalize to raise <class>, <instance> */
4977 Py_DECREF(value);
4978 value = type;
4979 #if PY_VERSION_HEX < 0x02050000
4980 if (PyInstance_Check(type)) {
4981 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4982 Py_INCREF(type);
4984 else {
4985 type = 0;
4986 PyErr_SetString(PyExc_TypeError,
4987 "raise: exception must be an old-style class or instance");
4988 goto raise_error;
4990 #else
4991 type = (PyObject*) Py_TYPE(type);
4992 Py_INCREF(type);
4993 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4994 PyErr_SetString(PyExc_TypeError,
4995 "raise: exception class must be a subclass of BaseException");
4996 goto raise_error;
4998 #endif
5000 __Pyx_ErrRestore(type, value, tb);
5001 return;
5002 raise_error:
5003 Py_XDECREF(value);
5004 Py_XDECREF(type);
5005 Py_XDECREF(tb);
5006 return;
5008 """)
5010 #------------------------------------------------------------------------------------
5012 reraise_utility_code = UtilityCode(
5013 proto = """
5014 static void __Pyx_ReRaise(void); /*proto*/
5015 """,
5016 impl = """
5017 static void __Pyx_ReRaise(void) {
5018 PyThreadState *tstate = PyThreadState_GET();
5019 PyObject* tmp_type = tstate->curexc_type;
5020 PyObject* tmp_value = tstate->curexc_value;
5021 PyObject* tmp_tb = tstate->curexc_traceback;
5022 tstate->curexc_type = tstate->exc_type;
5023 tstate->curexc_value = tstate->exc_value;
5024 tstate->curexc_traceback = tstate->exc_traceback;
5025 tstate->exc_type = 0;
5026 tstate->exc_value = 0;
5027 tstate->exc_traceback = 0;
5028 Py_XDECREF(tmp_type);
5029 Py_XDECREF(tmp_value);
5030 Py_XDECREF(tmp_tb);
5032 """)
5034 #------------------------------------------------------------------------------------
5036 arg_type_test_utility_code = UtilityCode(
5037 proto = """
5038 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5039 const char *name, int exact); /*proto*/
5040 """,
5041 impl = """
5042 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5043 const char *name, int exact)
5045 if (!type) {
5046 PyErr_Format(PyExc_SystemError, "Missing type object");
5047 return 0;
5049 if (none_allowed && obj == Py_None) return 1;
5050 else if (exact) {
5051 if (Py_TYPE(obj) == type) return 1;
5053 else {
5054 if (PyObject_TypeCheck(obj, type)) return 1;
5056 PyErr_Format(PyExc_TypeError,
5057 "Argument '%s' has incorrect type (expected %s, got %s)",
5058 name, type->tp_name, Py_TYPE(obj)->tp_name);
5059 return 0;
5061 """)
5063 #------------------------------------------------------------------------------------
5065 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5066 # many or too few positional arguments were found. This handles
5067 # Py_ssize_t formatting correctly.
5069 raise_argtuple_invalid_utility_code = UtilityCode(
5070 proto = """
5071 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5072 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5073 """,
5074 impl = """
5075 static void __Pyx_RaiseArgtupleInvalid(
5076 const char* func_name,
5077 int exact,
5078 Py_ssize_t num_min,
5079 Py_ssize_t num_max,
5080 Py_ssize_t num_found)
5082 Py_ssize_t num_expected;
5083 const char *number, *more_or_less;
5085 if (num_found < num_min) {
5086 num_expected = num_min;
5087 more_or_less = "at least";
5088 } else {
5089 num_expected = num_max;
5090 more_or_less = "at most";
5092 if (exact) {
5093 more_or_less = "exactly";
5095 number = (num_expected == 1) ? "" : "s";
5096 PyErr_Format(PyExc_TypeError,
5097 #if PY_VERSION_HEX < 0x02050000
5098 "%s() takes %s %d positional argument%s (%d given)",
5099 #else
5100 "%s() takes %s %zd positional argument%s (%zd given)",
5101 #endif
5102 func_name, more_or_less, num_expected, number, num_found);
5104 """)
5106 raise_keyword_required_utility_code = UtilityCode(
5107 proto = """
5108 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5109 """,
5110 impl = """
5111 static INLINE void __Pyx_RaiseKeywordRequired(
5112 const char* func_name,
5113 PyObject* kw_name)
5115 PyErr_Format(PyExc_TypeError,
5116 #if PY_MAJOR_VERSION >= 3
5117 "%s() needs keyword-only argument %U", func_name, kw_name);
5118 #else
5119 "%s() needs keyword-only argument %s", func_name,
5120 PyString_AS_STRING(kw_name));
5121 #endif
5123 """)
5125 raise_double_keywords_utility_code = UtilityCode(
5126 proto = """
5127 static void __Pyx_RaiseDoubleKeywordsError(
5128 const char* func_name, PyObject* kw_name); /*proto*/
5129 """,
5130 impl = """
5131 static void __Pyx_RaiseDoubleKeywordsError(
5132 const char* func_name,
5133 PyObject* kw_name)
5135 PyErr_Format(PyExc_TypeError,
5136 #if PY_MAJOR_VERSION >= 3
5137 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5138 #else
5139 "%s() got multiple values for keyword argument '%s'", func_name,
5140 PyString_AS_STRING(kw_name));
5141 #endif
5143 """)
5145 #------------------------------------------------------------------------------------
5147 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5148 # were passed to a function, or if any keywords were passed to a
5149 # function that does not accept them.
5151 keyword_string_check_utility_code = UtilityCode(
5152 proto = """
5153 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5154 const char* function_name, int kw_allowed); /*proto*/
5155 """,
5156 impl = """
5157 static INLINE int __Pyx_CheckKeywordStrings(
5158 PyObject *kwdict,
5159 const char* function_name,
5160 int kw_allowed)
5162 PyObject* key = 0;
5163 Py_ssize_t pos = 0;
5164 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5165 #if PY_MAJOR_VERSION < 3
5166 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5167 #else
5168 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5169 #endif
5170 goto invalid_keyword_type;
5172 if ((!kw_allowed) && unlikely(key))
5173 goto invalid_keyword;
5174 return 1;
5175 invalid_keyword_type:
5176 PyErr_Format(PyExc_TypeError,
5177 "%s() keywords must be strings", function_name);
5178 return 0;
5179 invalid_keyword:
5180 PyErr_Format(PyExc_TypeError,
5181 #if PY_MAJOR_VERSION < 3
5182 "%s() got an unexpected keyword argument '%s'",
5183 function_name, PyString_AsString(key));
5184 #else
5185 "%s() got an unexpected keyword argument '%U'",
5186 function_name, key);
5187 #endif
5188 return 0;
5190 """)
5192 #------------------------------------------------------------------------------------
5194 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5195 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5196 # keywords will raise an invalid keyword error.
5198 # Three kinds of errors are checked: 1) non-string keywords, 2)
5199 # unexpected keywords and 3) overlap with positional arguments.
5201 # If num_posargs is greater 0, it denotes the number of positional
5202 # arguments that were passed and that must therefore not appear
5203 # amongst the keywords as well.
5205 # This method does not check for required keyword arguments.
5208 parse_keywords_utility_code = UtilityCode(
5209 proto = """
5210 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5211 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5212 const char* function_name); /*proto*/
5213 """,
5214 impl = """
5215 static int __Pyx_ParseOptionalKeywords(
5216 PyObject *kwds,
5217 PyObject **argnames[],
5218 PyObject *kwds2,
5219 PyObject *values[],
5220 Py_ssize_t num_pos_args,
5221 const char* function_name)
5223 PyObject *key = 0, *value = 0;
5224 Py_ssize_t pos = 0;
5225 PyObject*** name;
5226 PyObject*** first_kw_arg = argnames + num_pos_args;
5228 while (PyDict_Next(kwds, &pos, &key, &value)) {
5229 name = first_kw_arg;
5230 while (*name && (**name != key)) name++;
5231 if (*name) {
5232 values[name-argnames] = value;
5233 } else {
5234 #if PY_MAJOR_VERSION < 3
5235 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5236 #else
5237 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5238 #endif
5239 goto invalid_keyword_type;
5240 } else {
5241 for (name = first_kw_arg; *name; name++) {
5242 #if PY_MAJOR_VERSION >= 3
5243 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5244 PyUnicode_Compare(**name, key) == 0) break;
5245 #else
5246 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5247 _PyString_Eq(**name, key)) break;
5248 #endif
5250 if (*name) {
5251 values[name-argnames] = value;
5252 } else {
5253 /* unexpected keyword found */
5254 for (name=argnames; name != first_kw_arg; name++) {
5255 if (**name == key) goto arg_passed_twice;
5256 #if PY_MAJOR_VERSION >= 3
5257 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5258 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5259 #else
5260 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5261 _PyString_Eq(**name, key)) goto arg_passed_twice;
5262 #endif
5264 if (kwds2) {
5265 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5266 } else {
5267 goto invalid_keyword;
5273 return 0;
5274 arg_passed_twice:
5275 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5276 goto bad;
5277 invalid_keyword_type:
5278 PyErr_Format(PyExc_TypeError,
5279 "%s() keywords must be strings", function_name);
5280 goto bad;
5281 invalid_keyword:
5282 PyErr_Format(PyExc_TypeError,
5283 #if PY_MAJOR_VERSION < 3
5284 "%s() got an unexpected keyword argument '%s'",
5285 function_name, PyString_AsString(key));
5286 #else
5287 "%s() got an unexpected keyword argument '%U'",
5288 function_name, key);
5289 #endif
5290 bad:
5291 return -1;
5293 """)
5295 #------------------------------------------------------------------------------------
5297 unraisable_exception_utility_code = UtilityCode(
5298 proto = """
5299 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5300 """,
5301 impl = """
5302 static void __Pyx_WriteUnraisable(const char *name) {
5303 PyObject *old_exc, *old_val, *old_tb;
5304 PyObject *ctx;
5305 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5306 #if PY_MAJOR_VERSION < 3
5307 ctx = PyString_FromString(name);
5308 #else
5309 ctx = PyUnicode_FromString(name);
5310 #endif
5311 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5312 if (!ctx) {
5313 PyErr_WriteUnraisable(Py_None);
5314 } else {
5315 PyErr_WriteUnraisable(ctx);
5316 Py_DECREF(ctx);
5319 """)
5321 #------------------------------------------------------------------------------------
5323 traceback_utility_code = UtilityCode(
5324 proto = """
5325 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5326 """,
5327 impl = """
5328 #include "compile.h"
5329 #include "frameobject.h"
5330 #include "traceback.h"
5332 static void __Pyx_AddTraceback(const char *funcname) {
5333 PyObject *py_srcfile = 0;
5334 PyObject *py_funcname = 0;
5335 PyObject *py_globals = 0;
5336 PyObject *empty_string = 0;
5337 PyCodeObject *py_code = 0;
5338 PyFrameObject *py_frame = 0;
5340 #if PY_MAJOR_VERSION < 3
5341 py_srcfile = PyString_FromString(%(FILENAME)s);
5342 #else
5343 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5344 #endif
5345 if (!py_srcfile) goto bad;
5346 if (%(CLINENO)s) {
5347 #if PY_MAJOR_VERSION < 3
5348 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5349 #else
5350 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5351 #endif
5353 else {
5354 #if PY_MAJOR_VERSION < 3
5355 py_funcname = PyString_FromString(funcname);
5356 #else
5357 py_funcname = PyUnicode_FromString(funcname);
5358 #endif
5360 if (!py_funcname) goto bad;
5361 py_globals = PyModule_GetDict(%(GLOBALS)s);
5362 if (!py_globals) goto bad;
5363 #if PY_MAJOR_VERSION < 3
5364 empty_string = PyString_FromStringAndSize("", 0);
5365 #else
5366 empty_string = PyBytes_FromStringAndSize("", 0);
5367 #endif
5368 if (!empty_string) goto bad;
5369 py_code = PyCode_New(
5370 0, /*int argcount,*/
5371 #if PY_MAJOR_VERSION >= 3
5372 0, /*int kwonlyargcount,*/
5373 #endif
5374 0, /*int nlocals,*/
5375 0, /*int stacksize,*/
5376 0, /*int flags,*/
5377 empty_string, /*PyObject *code,*/
5378 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5379 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5380 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5381 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5382 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5383 py_srcfile, /*PyObject *filename,*/
5384 py_funcname, /*PyObject *name,*/
5385 %(LINENO)s, /*int firstlineno,*/
5386 empty_string /*PyObject *lnotab*/
5387 );
5388 if (!py_code) goto bad;
5389 py_frame = PyFrame_New(
5390 PyThreadState_GET(), /*PyThreadState *tstate,*/
5391 py_code, /*PyCodeObject *code,*/
5392 py_globals, /*PyObject *globals,*/
5393 0 /*PyObject *locals*/
5394 );
5395 if (!py_frame) goto bad;
5396 py_frame->f_lineno = %(LINENO)s;
5397 PyTraceBack_Here(py_frame);
5398 bad:
5399 Py_XDECREF(py_srcfile);
5400 Py_XDECREF(py_funcname);
5401 Py_XDECREF(empty_string);
5402 Py_XDECREF(py_code);
5403 Py_XDECREF(py_frame);
5405 """ % {
5406 'FILENAME': Naming.filename_cname,
5407 'LINENO': Naming.lineno_cname,
5408 'CFILENAME': Naming.cfilenm_cname,
5409 'CLINENO': Naming.clineno_cname,
5410 'GLOBALS': Naming.module_cname,
5411 'EMPTY_TUPLE' : Naming.empty_tuple,
5412 })
5414 restore_exception_utility_code = UtilityCode(
5415 proto = """
5416 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5417 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5418 """,
5419 impl = """
5420 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5421 PyObject *tmp_type, *tmp_value, *tmp_tb;
5422 PyThreadState *tstate = PyThreadState_GET();
5424 #if PY_MAJOR_VERSION >= 3
5425 /* Note: this is a temporary work-around to prevent crashes in Python 3.0 */
5426 if ((tstate->exc_type != NULL) & (tstate->exc_type != Py_None)) {
5427 tmp_type = tstate->exc_type;
5428 tmp_value = tstate->exc_value;
5429 tmp_tb = tstate->exc_traceback;
5430 PyErr_NormalizeException(&type, &value, &tb);
5431 PyErr_NormalizeException(&tmp_type, &tmp_value, &tmp_tb);
5432 tstate->exc_type = 0;
5433 tstate->exc_value = 0;
5434 tstate->exc_traceback = 0;
5435 PyException_SetContext(value, tmp_value);
5436 Py_DECREF(tmp_type);
5437 Py_XDECREF(tmp_tb);
5439 #endif
5441 tmp_type = tstate->curexc_type;
5442 tmp_value = tstate->curexc_value;
5443 tmp_tb = tstate->curexc_traceback;
5444 tstate->curexc_type = type;
5445 tstate->curexc_value = value;
5446 tstate->curexc_traceback = tb;
5447 Py_XDECREF(tmp_type);
5448 Py_XDECREF(tmp_value);
5449 Py_XDECREF(tmp_tb);
5452 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5453 PyThreadState *tstate = PyThreadState_GET();
5454 *type = tstate->curexc_type;
5455 *value = tstate->curexc_value;
5456 *tb = tstate->curexc_traceback;
5458 tstate->curexc_type = 0;
5459 tstate->curexc_value = 0;
5460 tstate->curexc_traceback = 0;
5463 """)
5465 #------------------------------------------------------------------------------------
5467 set_vtable_utility_code = UtilityCode(
5468 proto = """
5469 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5470 """,
5471 impl = """
5472 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5473 PyObject *pycobj = 0;
5474 int result;
5476 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5477 if (!pycobj)
5478 goto bad;
5479 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5480 goto bad;
5481 result = 0;
5482 goto done;
5484 bad:
5485 result = -1;
5486 done:
5487 Py_XDECREF(pycobj);
5488 return result;
5490 """)
5492 #------------------------------------------------------------------------------------
5494 get_vtable_utility_code = UtilityCode(
5495 proto = """
5496 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5497 """,
5498 impl = r"""
5499 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5500 int result;
5501 PyObject *pycobj;
5503 pycobj = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5504 if (!pycobj)
5505 goto bad;
5506 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5507 if (!*(void **)vtabptr)
5508 goto bad;
5509 result = 0;
5510 goto done;
5512 bad:
5513 result = -1;
5514 done:
5515 Py_XDECREF(pycobj);
5516 return result;
5518 """)
5520 #------------------------------------------------------------------------------------
5522 init_string_tab_utility_code = UtilityCode(
5523 proto = """
5524 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5525 """,
5526 impl = """
5527 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5528 while (t->p) {
5529 #if PY_MAJOR_VERSION < 3
5530 if (t->is_unicode && (!t->is_identifier)) {
5531 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5532 } else if (t->intern) {
5533 *t->p = PyString_InternFromString(t->s);
5534 } else {
5535 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5537 #else /* Python 3+ has unicode identifiers */
5538 if (t->is_identifier || (t->is_unicode && t->intern)) {
5539 *t->p = PyUnicode_InternFromString(t->s);
5540 } else if (t->is_unicode) {
5541 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5542 } else {
5543 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5545 #endif
5546 if (!*t->p)
5547 return -1;
5548 ++t;
5550 return 0;
5552 """)
5554 #------------------------------------------------------------------------------------
5556 get_exception_utility_code = UtilityCode(
5557 proto = """
5558 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5559 """,
5560 impl = """
5561 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5562 PyObject *tmp_type, *tmp_value, *tmp_tb;
5563 PyThreadState *tstate = PyThreadState_GET();
5564 __Pyx_ErrFetch(type, value, tb);
5565 PyErr_NormalizeException(type, value, tb);
5566 if (PyErr_Occurred())
5567 goto bad;
5568 Py_INCREF(*type);
5569 Py_INCREF(*value);
5570 Py_INCREF(*tb);
5571 tmp_type = tstate->exc_type;
5572 tmp_value = tstate->exc_value;
5573 tmp_tb = tstate->exc_traceback;
5574 tstate->exc_type = *type;
5575 tstate->exc_value = *value;
5576 tstate->exc_traceback = *tb;
5577 /* Make sure tstate is in a consistent state when we XDECREF
5578 these objects (XDECREF may run arbitrary code). */
5579 Py_XDECREF(tmp_type);
5580 Py_XDECREF(tmp_value);
5581 Py_XDECREF(tmp_tb);
5582 return 0;
5583 bad:
5584 Py_XDECREF(*type);
5585 Py_XDECREF(*value);
5586 Py_XDECREF(*tb);
5587 return -1;
5590 """)
5592 #------------------------------------------------------------------------------------
5594 reset_exception_utility_code = UtilityCode(
5595 proto = """
5596 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5597 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5598 """,
5599 impl = """
5600 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5601 PyThreadState *tstate = PyThreadState_GET();
5602 *type = tstate->exc_type;
5603 *value = tstate->exc_value;
5604 *tb = tstate->exc_traceback;
5605 Py_XINCREF(*type);
5606 Py_XINCREF(*value);
5607 Py_XINCREF(*tb);
5610 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5611 PyObject *tmp_type, *tmp_value, *tmp_tb;
5612 PyThreadState *tstate = PyThreadState_GET();
5613 tmp_type = tstate->exc_type;
5614 tmp_value = tstate->exc_value;
5615 tmp_tb = tstate->exc_traceback;
5616 tstate->exc_type = type;
5617 tstate->exc_value = value;
5618 tstate->exc_traceback = tb;
5619 Py_XDECREF(tmp_type);
5620 Py_XDECREF(tmp_value);
5621 Py_XDECREF(tmp_tb);
5623 """)
5625 #------------------------------------------------------------------------------------
5627 py23_init_threads_utility_code = UtilityCode(
5628 proto="""
5629 #ifndef __PYX_FORCE_INIT_THREADS
5630 #define __PYX_FORCE_INIT_THREADS 0
5631 #if PY_VERSION_HEX < 0x02040000
5632 #undef __PYX_FORCE_INIT_THREADS
5633 #define __PYX_FORCE_INIT_THREADS 1
5634 #endif
5635 #endif
5636 """)
5638 #------------------------------------------------------------------------------------