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