Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 1946:49523eb3abb5

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