Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 2158:50307880f9c1

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