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