Cython has moved to github.
cython-devel
view Cython/Compiler/Nodes.py @ 2792:9918bc676467
protect definition of INLINE and fix for MSVC (thanks to Julien Danjou)
| author | Lisandro Dalcin <dalcinl@gmail.com> |
|---|---|
| date | Thu Dec 17 21:46:03 2009 -0300 (2 years ago) |
| parents | c4e5058caa27 |
| children | 14e8990f41a7 |
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, 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 if self.exception_check == '+':
550 self.exception_value.analyse_types(env)
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 exc_val = self.exception_value
558 else:
559 if self.exception_value.analyse_const_expression(env):
560 exc_val = self.exception_value.get_constant_c_result_code()
561 if exc_val is None:
562 raise InternalError("get_constant_c_result_code not implemented for %s" %
563 self.exception_value.__class__.__name__)
564 if not return_type.assignable_from(self.exception_value.type):
565 error(self.exception_value.pos,
566 "Exception value incompatible with function return type")
567 exc_check = self.exception_check
568 if return_type.is_array:
569 error(self.pos,
570 "Function cannot return an array")
571 if return_type.is_cfunction:
572 error(self.pos,
573 "Function cannot return a function")
574 func_type = PyrexTypes.CFuncType(
575 return_type, func_type_args, self.has_varargs,
576 optional_arg_count = self.optional_arg_count,
577 exception_value = exc_val, exception_check = exc_check,
578 calling_convention = self.base.calling_convention,
579 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
580 if self.optional_arg_count:
581 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
582 callspec = env.directives['callspec']
583 if callspec:
584 current = func_type.calling_convention
585 if current and current != callspec:
586 error(self.pos, "cannot have both '%s' and '%s' "
587 "calling conventions" % (current, callspec))
588 func_type.calling_convention = callspec
589 return self.base.analyse(func_type, env)
592 class CArgDeclNode(Node):
593 # Item in a function declaration argument list.
594 #
595 # base_type CBaseTypeNode
596 # declarator CDeclaratorNode
597 # not_none boolean Tagged with 'not None'
598 # default ExprNode or None
599 # default_value PyObjectConst constant for default value
600 # is_self_arg boolean Is the "self" arg of an extension type method
601 # is_type_arg boolean Is the "class" arg of an extension type classmethod
602 # is_kw_only boolean Is a keyword-only argument
604 child_attrs = ["base_type", "declarator", "default"]
606 is_self_arg = 0
607 is_type_arg = 0
608 is_generic = 1
609 type = None
610 name_declarator = None
611 default_value = None
613 def analyse(self, env, nonempty = 0):
614 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
615 if self.type is None:
616 # The parser may missinterpret names as types...
617 # We fix that here.
618 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
619 if nonempty:
620 self.declarator.name = self.base_type.name
621 self.base_type.name = None
622 self.base_type.is_basic_c_type = False
623 could_be_name = True
624 else:
625 could_be_name = False
626 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
627 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
628 self.declarator.name = self.base_type.arg_name
629 return self.declarator.analyse(base_type, env, nonempty = nonempty)
630 else:
631 return self.name_declarator, self.type
633 def calculate_default_value_code(self, code):
634 if self.default_value is None:
635 if self.default:
636 if self.default.is_literal:
637 # will not output any code, just assign the result_code
638 self.default.generate_evaluation_code(code)
639 return self.type.cast_code(self.default.result())
640 self.default_value = code.get_argument_default_const(self.type)
641 return self.default_value
643 def annotate(self, code):
644 if self.default:
645 self.default.annotate(code)
648 class CBaseTypeNode(Node):
649 # Abstract base class for C base type nodes.
650 #
651 # Processing during analyse_declarations phase:
652 #
653 # analyse
654 # Returns the type.
656 pass
658 class CAnalysedBaseTypeNode(Node):
659 # type type
661 child_attrs = []
663 def analyse(self, env, could_be_name = False):
664 return self.type
666 class CSimpleBaseTypeNode(CBaseTypeNode):
667 # name string
668 # module_path [string] Qualifying name components
669 # is_basic_c_type boolean
670 # signed boolean
671 # longness integer
672 # complex boolean
673 # is_self_arg boolean Is self argument of C method
674 # ##is_type_arg boolean Is type argument of class method
676 child_attrs = []
677 arg_name = None # in case the argument name was interpreted as a type
679 def analyse(self, env, could_be_name = False):
680 # Return type descriptor.
681 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
682 type = None
683 if self.is_basic_c_type:
684 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
685 if not type:
686 error(self.pos, "Unrecognised type modifier combination")
687 elif self.name == "object" and not self.module_path:
688 type = py_object_type
689 elif self.name is None:
690 if self.is_self_arg and env.is_c_class_scope:
691 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
692 type = env.parent_type
693 ## elif self.is_type_arg and env.is_c_class_scope:
694 ## type = Builtin.type_type
695 else:
696 type = py_object_type
697 else:
698 if self.module_path:
699 scope = env.find_imported_module(self.module_path, self.pos)
700 else:
701 scope = env
702 if scope:
703 if scope.is_c_class_scope:
704 scope = scope.global_scope()
705 entry = scope.lookup(self.name)
706 if entry and entry.is_type:
707 type = entry.type
708 elif could_be_name:
709 if self.is_self_arg and env.is_c_class_scope:
710 type = env.parent_type
711 ## elif self.is_type_arg and env.is_c_class_scope:
712 ## type = Builtin.type_type
713 else:
714 type = py_object_type
715 self.arg_name = self.name
716 else:
717 error(self.pos, "'%s' is not a type identifier" % self.name)
718 if self.complex:
719 if not type.is_numeric or type.is_complex:
720 error(self.pos, "can only complexify c numeric types")
721 type = PyrexTypes.CComplexType(type)
722 type.create_declaration_utility_code(env)
723 if type:
724 return type
725 else:
726 return PyrexTypes.error_type
728 class CBufferAccessTypeNode(CBaseTypeNode):
729 # After parsing:
730 # positional_args [ExprNode] List of positional arguments
731 # keyword_args DictNode Keyword arguments
732 # base_type_node CBaseTypeNode
734 # After analysis:
735 # type PyrexType.BufferType ...containing the right options
738 child_attrs = ["base_type_node", "positional_args",
739 "keyword_args", "dtype_node"]
741 dtype_node = None
743 name = None
745 def analyse(self, env, could_be_name = False):
746 base_type = self.base_type_node.analyse(env)
747 if base_type.is_error: return base_type
748 import Buffer
750 options = Buffer.analyse_buffer_options(
751 self.pos,
752 env,
753 self.positional_args,
754 self.keyword_args,
755 base_type.buffer_defaults)
757 if sys.version_info[0] < 3:
758 # Py 2.x enforces byte strings as keyword arguments ...
759 options = dict([ (name.encode('ASCII'), value)
760 for name, value in options.iteritems() ])
762 self.type = PyrexTypes.BufferType(base_type, **options)
763 return self.type
765 class CComplexBaseTypeNode(CBaseTypeNode):
766 # base_type CBaseTypeNode
767 # declarator CDeclaratorNode
769 child_attrs = ["base_type", "declarator"]
771 def analyse(self, env, could_be_name = False):
772 base = self.base_type.analyse(env, could_be_name)
773 _, type = self.declarator.analyse(base, env)
774 return type
777 class CVarDefNode(StatNode):
778 # C variable definition or forward/extern function declaration.
779 #
780 # visibility 'private' or 'public' or 'extern'
781 # base_type CBaseTypeNode
782 # declarators [CDeclaratorNode]
783 # in_pxd boolean
784 # api boolean
785 # need_properties [entry]
787 # decorators [cython.locals(...)] or None
788 # directive_locals { string : NameNode } locals defined by cython.locals(...)
790 child_attrs = ["base_type", "declarators"]
791 need_properties = ()
793 decorators = None
794 directive_locals = {}
796 def analyse_declarations(self, env, dest_scope = None):
797 if not dest_scope:
798 dest_scope = env
799 self.dest_scope = dest_scope
800 base_type = self.base_type.analyse(env)
802 # If the field is an external typedef, we cannot be sure about the type,
803 # so do conversion ourself rather than rely on the CPython mechanism (through
804 # a property; made in AnalyseDeclarationsTransform).
805 if (dest_scope.is_c_class_scope
806 and self.visibility == 'public'
807 and base_type.is_pyobject
808 and (base_type.is_builtin_type or base_type.is_extension_type)):
809 self.need_properties = []
810 need_property = True
811 visibility = 'private'
812 else:
813 need_property = False
814 visibility = self.visibility
816 for declarator in self.declarators:
817 name_declarator, type = declarator.analyse(base_type, env)
818 if not type.is_complete():
819 if not (self.visibility == 'extern' and type.is_array):
820 error(declarator.pos,
821 "Variable type '%s' is incomplete" % type)
822 if self.visibility == 'extern' and type.is_pyobject:
823 error(declarator.pos,
824 "Python object cannot be declared extern")
825 name = name_declarator.name
826 cname = name_declarator.cname
827 if name == '':
828 error(declarator.pos, "Missing name in declaration.")
829 return
830 if type.is_cfunction:
831 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
832 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
833 api = self.api)
834 if entry is not None:
835 entry.directive_locals = self.directive_locals
836 else:
837 if self.directive_locals:
838 s.error("Decorators can only be followed by functions")
839 if self.in_pxd and self.visibility != 'extern':
840 error(self.pos,
841 "Only 'extern' C variable declaration allowed in .pxd file")
842 entry = dest_scope.declare_var(name, type, declarator.pos,
843 cname = cname, visibility = visibility, is_cdef = 1)
844 if need_property:
845 self.need_properties.append(entry)
846 entry.needs_property = 1
849 class CStructOrUnionDefNode(StatNode):
850 # name string
851 # cname string or None
852 # kind "struct" or "union"
853 # typedef_flag boolean
854 # visibility "public" or "private"
855 # in_pxd boolean
856 # attributes [CVarDefNode] or None
857 # entry Entry
858 # packed boolean
860 child_attrs = ["attributes"]
862 def analyse_declarations(self, env):
863 scope = None
864 if self.visibility == 'extern' and self.packed:
865 error(self.pos, "Cannot declare extern struct as 'packed'")
866 if self.attributes is not None:
867 scope = StructOrUnionScope(self.name)
868 self.entry = env.declare_struct_or_union(
869 self.name, self.kind, scope, self.typedef_flag, self.pos,
870 self.cname, visibility = self.visibility, packed = self.packed)
871 if self.attributes is not None:
872 if self.in_pxd and not env.in_cinclude:
873 self.entry.defined_in_pxd = 1
874 for attr in self.attributes:
875 attr.analyse_declarations(env, scope)
876 if self.visibility != 'extern':
877 need_typedef_indirection = False
878 for attr in scope.var_entries:
879 type = attr.type
880 while type.is_array:
881 type = type.base_type
882 if type == self.entry.type:
883 error(attr.pos, "Struct cannot contain itself as a member.")
884 if self.typedef_flag:
885 while type.is_ptr:
886 type = type.base_type
887 if type == self.entry.type:
888 need_typedef_indirection = True
889 if need_typedef_indirection:
890 # C can't handle typedef structs that refer to themselves.
891 struct_entry = self.entry
892 self.entry = env.declare_typedef(
893 self.name, struct_entry.type, self.pos,
894 cname = self.cname, visibility='ignore')
895 struct_entry.type.typedef_flag = False
896 # FIXME: this might be considered a hack ;-)
897 struct_entry.cname = struct_entry.type.cname = \
898 '_' + self.entry.type.typedef_cname
900 def analyse_expressions(self, env):
901 pass
903 def generate_execution_code(self, code):
904 pass
907 class CEnumDefNode(StatNode):
908 # name string or None
909 # cname string or None
910 # items [CEnumDefItemNode]
911 # typedef_flag boolean
912 # visibility "public" or "private"
913 # in_pxd boolean
914 # entry Entry
916 child_attrs = ["items"]
918 def analyse_declarations(self, env):
919 self.entry = env.declare_enum(self.name, self.pos,
920 cname = self.cname, typedef_flag = self.typedef_flag,
921 visibility = self.visibility)
922 if self.items is not None:
923 if self.in_pxd and not env.in_cinclude:
924 self.entry.defined_in_pxd = 1
925 for item in self.items:
926 item.analyse_declarations(env, self.entry)
928 def analyse_expressions(self, env):
929 pass
931 def generate_execution_code(self, code):
932 if self.visibility == 'public':
933 temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
934 for item in self.entry.enum_values:
935 code.putln("%s = PyInt_FromLong(%s); %s" % (
936 temp,
937 item.cname,
938 code.error_goto_if_null(temp, item.pos)))
939 code.put_gotref(temp)
940 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
941 Naming.module_cname,
942 item.name,
943 temp,
944 code.error_goto(item.pos)))
945 code.put_decref_clear(temp, PyrexTypes.py_object_type)
946 code.funcstate.release_temp(temp)
949 class CEnumDefItemNode(StatNode):
950 # name string
951 # cname string or None
952 # value ExprNode or None
954 child_attrs = ["value"]
956 def analyse_declarations(self, env, enum_entry):
957 if self.value:
958 self.value.analyse_const_expression(env)
959 if not self.value.type.is_int:
960 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
961 self.value.analyse_const_expression(env)
962 entry = env.declare_const(self.name, enum_entry.type,
963 self.value, self.pos, cname = self.cname,
964 visibility = enum_entry.visibility)
965 enum_entry.enum_values.append(entry)
968 class CTypeDefNode(StatNode):
969 # base_type CBaseTypeNode
970 # declarator CDeclaratorNode
971 # visibility "public" or "private"
972 # in_pxd boolean
974 child_attrs = ["base_type", "declarator"]
976 def analyse_declarations(self, env):
977 base = self.base_type.analyse(env)
978 name_declarator, type = self.declarator.analyse(base, env)
979 name = name_declarator.name
980 cname = name_declarator.cname
981 entry = env.declare_typedef(name, type, self.pos,
982 cname = cname, visibility = self.visibility)
983 if self.in_pxd and not env.in_cinclude:
984 entry.defined_in_pxd = 1
986 def analyse_expressions(self, env):
987 pass
988 def generate_execution_code(self, code):
989 pass
992 class FuncDefNode(StatNode, BlockNode):
993 # Base class for function definition nodes.
994 #
995 # return_type PyrexType
996 # #filename string C name of filename string const
997 # entry Symtab.Entry
998 # needs_closure boolean Whether or not this function has inner functions/classes/yield
999 # directive_locals { string : NameNode } locals defined by cython.locals(...)
1001 py_func = None
1002 assmt = None
1003 needs_closure = False
1004 modifiers = []
1006 def analyse_default_values(self, env):
1007 genv = env.global_scope()
1008 default_seen = 0
1009 for arg in self.args:
1010 if arg.default:
1011 default_seen = 1
1012 if arg.is_generic:
1013 arg.default.analyse_types(env)
1014 arg.default = arg.default.coerce_to(arg.type, genv)
1015 else:
1016 error(arg.pos,
1017 "This argument cannot have a default value")
1018 arg.default = None
1019 elif arg.kw_only:
1020 default_seen = 1
1021 elif default_seen:
1022 error(arg.pos, "Non-default argument following default argument")
1024 def need_gil_acquisition(self, lenv):
1025 return 0
1027 def create_local_scope(self, env):
1028 genv = env
1029 while genv.is_py_class_scope or genv.is_c_class_scope:
1030 genv = env.outer_scope
1031 if self.needs_closure:
1032 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
1033 else:
1034 lenv = LocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
1035 lenv.return_type = self.return_type
1036 type = self.entry.type
1037 if type.is_cfunction:
1038 lenv.nogil = type.nogil and not type.with_gil
1039 self.local_scope = lenv
1040 lenv.directives = env.directives
1041 return lenv
1043 def generate_function_definitions(self, env, code):
1044 import Buffer
1046 lenv = self.local_scope
1048 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1049 self.entry.scope.is_c_class_scope)
1051 profile = code.globalstate.directives['profile']
1052 if profile:
1053 if lenv.nogil:
1054 error(self.pos, "Cannot profile nogil function.")
1055 code.globalstate.use_utility_code(profile_utility_code)
1057 # Generate C code for header and body of function
1058 code.enter_cfunc_scope()
1059 code.return_from_error_cleanup_label = code.new_label()
1061 # ----- Top-level constants used by this function
1062 code.mark_pos(self.pos)
1063 self.generate_cached_builtins_decls(lenv, code)
1064 # ----- Function header
1065 code.putln("")
1066 if self.py_func:
1067 self.py_func.generate_function_header(code,
1068 with_pymethdef = env.is_py_class_scope,
1069 proto_only=True)
1070 self.generate_function_header(code,
1071 with_pymethdef = env.is_py_class_scope)
1072 # ----- Local variable declarations
1073 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
1074 self.generate_argument_declarations(lenv, code)
1075 if self.needs_closure:
1076 code.putln("/* TODO: declare and create scope object */")
1077 code.put_var_declarations(lenv.var_entries)
1078 init = ""
1079 if not self.return_type.is_void:
1080 if self.return_type.is_pyobject:
1081 init = " = NULL"
1082 code.putln(
1083 "%s%s;" %
1084 (self.return_type.declaration_code(
1085 Naming.retval_cname),
1086 init))
1087 tempvardecl_code = code.insertion_point()
1088 self.generate_keyword_list(code)
1089 # ----- Extern library function declarations
1090 lenv.generate_library_function_declarations(code)
1091 # ----- GIL acquisition
1092 acquire_gil = self.acquire_gil
1093 if acquire_gil:
1094 env.use_utility_code(force_init_threads_utility_code)
1095 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1096 # ----- Automatic lead-ins for certain special functions
1097 if not lenv.nogil:
1098 code.put_setup_refcount_context(self.entry.name)
1099 if profile:
1100 code.put_trace_call(self.entry.name, self.pos)
1101 if is_getbuffer_slot:
1102 self.getbuffer_init(code)
1103 # ----- Fetch arguments
1104 self.generate_argument_parsing_code(env, code)
1105 # If an argument is assigned to in the body, we must
1106 # incref it to properly keep track of refcounts.
1107 for entry in lenv.arg_entries:
1108 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1109 code.put_var_incref(entry)
1110 # ----- Initialise local variables
1111 for entry in lenv.var_entries:
1112 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1113 code.put_init_var_to_py_none(entry)
1114 # ----- Initialise local buffer auxiliary variables
1115 for entry in lenv.var_entries + lenv.arg_entries:
1116 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1117 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1118 # ----- Check and convert arguments
1119 self.generate_argument_type_tests(code)
1120 # ----- Acquire buffer arguments
1121 for entry in lenv.arg_entries:
1122 if entry.type.is_buffer:
1123 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1124 # ----- Function body
1125 self.body.generate_execution_code(code)
1126 # ----- Default return value
1127 code.putln("")
1128 if self.return_type.is_pyobject:
1129 #if self.return_type.is_extension_type:
1130 # lhs = "(PyObject *)%s" % Naming.retval_cname
1131 #else:
1132 lhs = Naming.retval_cname
1133 code.put_init_to_py_none(lhs, self.return_type)
1134 else:
1135 val = self.return_type.default_value
1136 if val:
1137 code.putln("%s = %s;" % (Naming.retval_cname, val))
1138 # ----- Error cleanup
1139 if code.error_label in code.labels_used:
1140 code.put_goto(code.return_label)
1141 code.put_label(code.error_label)
1142 for cname, type in code.funcstate.all_managed_temps():
1143 code.put_xdecref(cname, type)
1145 # Clean up buffers -- this calls a Python function
1146 # so need to save and restore error state
1147 buffers_present = len(lenv.buffer_entries) > 0
1148 if buffers_present:
1149 code.globalstate.use_utility_code(restore_exception_utility_code)
1150 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1151 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1152 for entry in lenv.buffer_entries:
1153 Buffer.put_release_buffer_code(code, entry)
1154 #code.putln("%s = 0;" % entry.cname)
1155 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1157 err_val = self.error_value()
1158 exc_check = self.caller_will_check_exceptions()
1159 if err_val is not None or exc_check:
1160 # TODO: Fix exception tracing (though currently unused by cProfile).
1161 # code.globalstate.use_utility_code(get_exception_tuple_utility_code)
1162 # code.put_trace_exception()
1163 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1164 else:
1165 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1166 % self.entry.qualified_name, 0)
1167 code.putln(
1168 '__Pyx_WriteUnraisable("%s");' %
1169 self.entry.qualified_name)
1170 env.use_utility_code(unraisable_exception_utility_code)
1171 env.use_utility_code(restore_exception_utility_code)
1172 default_retval = self.return_type.default_value
1173 if err_val is None and default_retval:
1174 err_val = default_retval
1175 if err_val is not None:
1176 code.putln(
1177 "%s = %s;" % (
1178 Naming.retval_cname,
1179 err_val))
1181 if is_getbuffer_slot:
1182 self.getbuffer_error_cleanup(code)
1184 # If we are using the non-error cleanup section we should
1185 # jump past it if we have an error. The if-test below determine
1186 # whether this section is used.
1187 if buffers_present or is_getbuffer_slot:
1188 code.put_goto(code.return_from_error_cleanup_label)
1191 # ----- Non-error return cleanup
1192 code.put_label(code.return_label)
1193 for entry in lenv.buffer_entries:
1194 if entry.used:
1195 Buffer.put_release_buffer_code(code, entry)
1196 if is_getbuffer_slot:
1197 self.getbuffer_normal_cleanup(code)
1198 # ----- Return cleanup for both error and no-error return
1199 code.put_label(code.return_from_error_cleanup_label)
1200 if not Options.init_local_none:
1201 for entry in lenv.var_entries:
1202 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1203 entry.xdecref_cleanup = 1
1204 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1205 # Decref any increfed args
1206 for entry in lenv.arg_entries:
1207 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1208 code.put_var_decref(entry)
1210 # code.putln("/* TODO: decref scope object */")
1211 # ----- Return
1212 # This code is duplicated in ModuleNode.generate_module_init_func
1213 if not lenv.nogil:
1214 default_retval = self.return_type.default_value
1215 err_val = self.error_value()
1216 if err_val is None and default_retval:
1217 err_val = default_retval
1218 if self.return_type.is_pyobject:
1219 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1221 if self.entry.is_special and self.entry.name == "__hash__":
1222 # Returning -1 for __hash__ is supposed to signal an error
1223 # We do as Python instances and coerce -1 into -2.
1224 code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (
1225 Naming.retval_cname, Naming.retval_cname))
1227 if profile:
1228 if self.return_type.is_pyobject:
1229 code.put_trace_return(Naming.retval_cname)
1230 else:
1231 code.put_trace_return("Py_None")
1232 if not lenv.nogil:
1233 code.put_finish_refcount_context()
1235 if acquire_gil:
1236 code.putln("PyGILState_Release(_save);")
1238 if not self.return_type.is_void:
1239 code.putln("return %s;" % Naming.retval_cname)
1241 code.putln("}")
1242 # ----- Go back and insert temp variable declarations
1243 tempvardecl_code.put_temp_declarations(code.funcstate)
1244 # ----- Python version
1245 code.exit_cfunc_scope()
1246 if self.py_func:
1247 self.py_func.generate_function_definitions(env, code)
1248 self.generate_wrapper_functions(code)
1250 def declare_argument(self, env, arg):
1251 if arg.type.is_void:
1252 error(arg.pos, "Invalid use of 'void'")
1253 elif not arg.type.is_complete() and not arg.type.is_array:
1254 error(arg.pos,
1255 "Argument type '%s' is incomplete" % arg.type)
1256 return env.declare_arg(arg.name, arg.type, arg.pos)
1258 def generate_wrapper_functions(self, code):
1259 pass
1261 def generate_execution_code(self, code):
1262 # Evaluate and store argument default values
1263 for arg in self.args:
1264 default = arg.default
1265 if default:
1266 if not default.is_literal:
1267 default.generate_evaluation_code(code)
1268 default.make_owned_reference(code)
1269 result = default.result_as(arg.type)
1270 code.putln(
1271 "%s = %s;" % (
1272 arg.calculate_default_value_code(code),
1273 result))
1274 if arg.type.is_pyobject:
1275 code.put_giveref(default.result())
1276 default.generate_post_assignment_code(code)
1277 default.free_temps(code)
1278 # For Python class methods, create and store function object
1279 if self.assmt:
1280 self.assmt.generate_execution_code(code)
1282 #
1283 # Special code for the __getbuffer__ function
1284 #
1285 def getbuffer_init(self, code):
1286 info = self.local_scope.arg_entries[1].cname
1287 # Python 3.0 betas have a bug in memoryview which makes it call
1288 # getbuffer with a NULL parameter. For now we work around this;
1289 # the following line should be removed when this bug is fixed.
1290 code.putln("if (%s == NULL) return 0;" % info)
1291 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1292 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1294 def getbuffer_error_cleanup(self, code):
1295 info = self.local_scope.arg_entries[1].cname
1296 code.put_gotref("%s->obj" % info)
1297 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1298 (info, info))
1300 def getbuffer_normal_cleanup(self, code):
1301 info = self.local_scope.arg_entries[1].cname
1302 code.putln("if (%s->obj == Py_None) {" % info)
1303 code.put_gotref("Py_None")
1304 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1305 code.putln("}")
1307 class CFuncDefNode(FuncDefNode):
1308 # C function definition.
1309 #
1310 # modifiers ['inline']
1311 # visibility 'private' or 'public' or 'extern'
1312 # base_type CBaseTypeNode
1313 # declarator CDeclaratorNode
1314 # body StatListNode
1315 # api boolean
1316 # decorators [DecoratorNode] list of decorators
1317 #
1318 # with_gil boolean Acquire GIL around body
1319 # type CFuncType
1320 # py_func wrapper for calling from Python
1321 # overridable whether or not this is a cpdef function
1322 # inline_in_pxd whether this is an inline function in a pxd file
1324 child_attrs = ["base_type", "declarator", "body", "py_func"]
1326 inline_in_pxd = False
1327 decorators = None
1328 directive_locals = {}
1330 def unqualified_name(self):
1331 return self.entry.name
1333 def analyse_declarations(self, env):
1334 self.directive_locals.update(env.directives['locals'])
1335 base_type = self.base_type.analyse(env)
1336 # The 2 here is because we need both function and argument names.
1337 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1338 if not type.is_cfunction:
1339 error(self.pos,
1340 "Suite attached to non-function declaration")
1341 # Remember the actual type according to the function header
1342 # written here, because the type in the symbol table entry
1343 # may be different if we're overriding a C method inherited
1344 # from the base type of an extension type.
1345 self.type = type
1346 type.is_overridable = self.overridable
1347 declarator = self.declarator
1348 while not hasattr(declarator, 'args'):
1349 declarator = declarator.base
1350 self.args = declarator.args
1351 for formal_arg, type_arg in zip(self.args, type.args):
1352 formal_arg.type = type_arg.type
1353 formal_arg.name = type_arg.name
1354 formal_arg.cname = type_arg.cname
1355 name = name_declarator.name
1356 cname = name_declarator.cname
1357 self.entry = env.declare_cfunction(
1358 name, type, self.pos,
1359 cname = cname, visibility = self.visibility,
1360 defining = self.body is not None,
1361 api = self.api, modifiers = self.modifiers)
1362 self.entry.inline_func_in_pxd = self.inline_in_pxd
1363 self.return_type = type.return_type
1365 if self.overridable and not env.is_module_scope:
1366 if len(self.args) < 1 or not self.args[0].type.is_pyobject:
1367 # An error will be produced in the cdef function
1368 self.overridable = False
1370 if self.overridable:
1371 import ExprNodes
1372 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1373 self.py_func = DefNode(pos = self.pos,
1374 name = self.entry.name,
1375 args = self.args,
1376 star_arg = None,
1377 starstar_arg = None,
1378 doc = self.doc,
1379 body = py_func_body,
1380 is_wrapper = 1)
1381 self.py_func.is_module_scope = env.is_module_scope
1382 self.py_func.analyse_declarations(env)
1383 self.entry.as_variable = self.py_func.entry
1384 # Reset scope entry the above cfunction
1385 env.entries[name] = self.entry
1386 if not env.is_module_scope or Options.lookup_module_cpdef:
1387 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1388 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1389 self.create_local_scope(env)
1391 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1392 import ExprNodes
1393 args = self.type.args
1394 if omit_optional_args:
1395 args = args[:len(args) - self.type.optional_arg_count]
1396 arg_names = [arg.name for arg in args]
1397 if is_module_scope:
1398 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1399 else:
1400 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1401 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1402 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1403 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)
1404 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1406 def declare_arguments(self, env):
1407 for arg in self.type.args:
1408 if not arg.name:
1409 error(arg.pos, "Missing argument name")
1410 self.declare_argument(env, arg)
1412 def need_gil_acquisition(self, lenv):
1413 return self.type.with_gil
1415 def nogil_check(self, env):
1416 type = self.type
1417 with_gil = type.with_gil
1418 if type.nogil and not with_gil:
1419 if type.return_type.is_pyobject:
1420 error(self.pos,
1421 "Function with Python return type cannot be declared nogil")
1422 for entry in self.local_scope.var_entries:
1423 if entry.type.is_pyobject:
1424 error(self.pos, "Function declared nogil has Python locals or temporaries")
1426 def analyse_expressions(self, env):
1427 self.local_scope.directives = env.directives
1428 if self.py_func is not None:
1429 # this will also analyse the default values
1430 self.py_func.analyse_expressions(env)
1431 else:
1432 self.analyse_default_values(env)
1433 self.acquire_gil = self.need_gil_acquisition(self.local_scope)
1435 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1436 arg_decls = []
1437 type = self.type
1438 visibility = self.entry.visibility
1439 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1440 arg_decls.append(arg.declaration_code())
1441 if with_dispatch and self.overridable:
1442 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1443 if type.optional_arg_count and with_opt_args:
1444 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1445 if type.has_varargs:
1446 arg_decls.append("...")
1447 if not arg_decls:
1448 arg_decls = ["void"]
1449 if cname is None:
1450 cname = self.entry.func_cname
1451 entity = type.function_header_code(cname, ', '.join(arg_decls))
1452 if visibility == 'public':
1453 dll_linkage = "DL_EXPORT"
1454 else:
1455 dll_linkage = None
1456 header = self.return_type.declaration_code(entity,
1457 dll_linkage = dll_linkage)
1458 if visibility == 'extern':
1459 storage_class = "%s " % Naming.extern_c_macro
1460 elif visibility == 'public':
1461 storage_class = ""
1462 else:
1463 storage_class = "static "
1464 code.putln("%s%s %s {" % (
1465 storage_class,
1466 ' '.join(self.modifiers).upper(), # macro forms
1467 header))
1469 def generate_argument_declarations(self, env, code):
1470 for arg in self.args:
1471 if arg.default:
1472 result = arg.calculate_default_value_code(code)
1473 code.putln('%s = %s;' % (
1474 arg.type.declaration_code(arg.cname), result))
1476 def generate_keyword_list(self, code):
1477 pass
1479 def generate_argument_parsing_code(self, env, code):
1480 i = 0
1481 if self.type.optional_arg_count:
1482 code.putln('if (%s) {' % Naming.optional_args_cname)
1483 for arg in self.args:
1484 if arg.default:
1485 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1486 declarator = arg.declarator
1487 while not hasattr(declarator, 'name'):
1488 declarator = declarator.base
1489 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, self.type.opt_arg_cname(declarator.name)))
1490 i += 1
1491 for _ in range(self.type.optional_arg_count):
1492 code.putln('}')
1493 code.putln('}')
1495 def generate_argument_conversion_code(self, code):
1496 pass
1498 def generate_argument_type_tests(self, code):
1499 # Generate type tests for args whose type in a parent
1500 # class is a supertype of the declared type.
1501 for arg in self.type.args:
1502 if arg.needs_type_test:
1503 self.generate_arg_type_test(arg, code)
1505 def generate_arg_type_test(self, arg, code):
1506 # Generate type test for one argument.
1507 if arg.type.typeobj_is_available():
1508 typeptr_cname = arg.type.typeptr_cname
1509 arg_code = "((PyObject *)%s)" % arg.cname
1510 code.putln(
1511 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1512 arg_code,
1513 typeptr_cname,
1514 not arg.not_none,
1515 arg.name,
1516 type.is_builtin_type,
1517 code.error_goto(arg.pos)))
1518 else:
1519 error(arg.pos, "Cannot test type of extern C class "
1520 "without type object name specification")
1522 def error_value(self):
1523 if self.return_type.is_pyobject:
1524 return "0"
1525 else:
1526 #return None
1527 return self.entry.type.exception_value
1529 def caller_will_check_exceptions(self):
1530 return self.entry.type.exception_check
1532 def generate_wrapper_functions(self, code):
1533 # If the C signature of a function has changed, we need to generate
1534 # wrappers to put in the slots here.
1535 k = 0
1536 entry = self.entry
1537 func_type = entry.type
1538 while entry.prev_entry is not None:
1539 k += 1
1540 entry = entry.prev_entry
1541 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1542 code.putln()
1543 self.generate_function_header(code,
1544 0,
1545 with_dispatch = entry.type.is_overridable,
1546 with_opt_args = entry.type.optional_arg_count,
1547 cname = entry.func_cname)
1548 if not self.return_type.is_void:
1549 code.put('return ')
1550 args = self.type.args
1551 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1552 if entry.type.is_overridable:
1553 arglist.append(Naming.skip_dispatch_cname)
1554 elif func_type.is_overridable:
1555 arglist.append('0')
1556 if entry.type.optional_arg_count:
1557 arglist.append(Naming.optional_args_cname)
1558 elif func_type.optional_arg_count:
1559 arglist.append('NULL')
1560 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1561 code.putln('}')
1564 class PyArgDeclNode(Node):
1565 # Argument which must be a Python object (used
1566 # for * and ** arguments).
1567 #
1568 # name string
1569 # entry Symtab.Entry
1570 child_attrs = []
1573 class DecoratorNode(Node):
1574 # A decorator
1575 #
1576 # decorator NameNode or CallNode
1577 child_attrs = ['decorator']
1580 class DefNode(FuncDefNode):
1581 # A Python function definition.
1582 #
1583 # name string the Python name of the function
1584 # decorators [DecoratorNode] list of decorators
1585 # args [CArgDeclNode] formal arguments
1586 # star_arg PyArgDeclNode or None * argument
1587 # starstar_arg PyArgDeclNode or None ** argument
1588 # doc EncodedString or None
1589 # body StatListNode
1590 #
1591 # The following subnode is constructed internally
1592 # when the def statement is inside a Python class definition.
1593 #
1594 # assmt AssignmentNode Function construction/assignment
1596 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1598 assmt = None
1599 num_kwonly_args = 0
1600 num_required_kw_args = 0
1601 reqd_kw_flags_cname = "0"
1602 is_wrapper = 0
1603 decorators = None
1604 entry = None
1605 acquire_gil = 0
1606 self_in_stararg = 0
1608 def __init__(self, pos, **kwds):
1609 FuncDefNode.__init__(self, pos, **kwds)
1610 k = rk = r = 0
1611 for arg in self.args:
1612 if arg.kw_only:
1613 k += 1
1614 if not arg.default:
1615 rk += 1
1616 if not arg.default:
1617 r += 1
1618 self.num_kwonly_args = k
1619 self.num_required_kw_args = rk
1620 self.num_required_args = r
1622 def as_cfunction(self, cfunc=None, scope=None):
1623 if self.star_arg:
1624 error(self.star_arg.pos, "cdef function cannot have star argument")
1625 if self.starstar_arg:
1626 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1627 if cfunc is None:
1628 cfunc_args = []
1629 for formal_arg in self.args:
1630 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1631 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1632 cname = None,
1633 type = py_object_type,
1634 pos = formal_arg.pos))
1635 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1636 args = cfunc_args,
1637 has_varargs = False,
1638 exception_value = None,
1639 exception_check = False,
1640 nogil = False,
1641 with_gil = False,
1642 is_overridable = True)
1643 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1644 else:
1645 cfunc_type = cfunc.type
1646 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1647 error(self.pos, "wrong number of arguments")
1648 error(declarator.pos, "previous declaration here")
1649 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1650 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1651 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1652 formal_arg.type = type_arg.type
1653 formal_arg.name_declarator = name_declarator
1654 import ExprNodes
1655 if cfunc_type.exception_value is None:
1656 exception_value = None
1657 else:
1658 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1659 declarator = CFuncDeclaratorNode(self.pos,
1660 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1661 args = self.args,
1662 has_varargs = False,
1663 exception_check = cfunc_type.exception_check,
1664 exception_value = exception_value,
1665 with_gil = cfunc_type.with_gil,
1666 nogil = cfunc_type.nogil)
1667 return CFuncDefNode(self.pos,
1668 modifiers = [],
1669 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1670 declarator = declarator,
1671 body = self.body,
1672 doc = self.doc,
1673 overridable = cfunc_type.is_overridable,
1674 type = cfunc_type,
1675 with_gil = cfunc_type.with_gil,
1676 nogil = cfunc_type.nogil,
1677 visibility = 'private',
1678 api = False,
1679 directive_locals = getattr(cfunc, 'directive_locals', {}))
1681 def analyse_declarations(self, env):
1682 self.is_classmethod = self.is_staticmethod = False
1683 if self.decorators:
1684 for decorator in self.decorators:
1685 func = decorator.decorator
1686 if func.is_name:
1687 self.is_classmethod |= func.name == 'classmethod'
1688 self.is_staticmethod |= func.name == 'staticmethod'
1690 if self.is_classmethod and env.lookup_here('classmethod'):
1691 # classmethod() was overridden - not much we can do here ...
1692 self.is_classmethod = False
1693 if self.is_staticmethod and env.lookup_here('staticmethod'):
1694 # staticmethod() was overridden - not much we can do here ...
1695 self.is_staticmethod = False
1697 self.analyse_argument_types(env)
1698 self.declare_pyfunction(env)
1699 self.analyse_signature(env)
1700 self.return_type = self.entry.signature.return_type()
1701 self.create_local_scope(env)
1703 def analyse_argument_types(self, env):
1704 directive_locals = self.directive_locals = env.directives['locals']
1705 for arg in self.args:
1706 if hasattr(arg, 'name'):
1707 type = arg.type
1708 name_declarator = None
1709 else:
1710 base_type = arg.base_type.analyse(env)
1711 name_declarator, type = \
1712 arg.declarator.analyse(base_type, env)
1713 arg.name = name_declarator.name
1714 if arg.name in directive_locals:
1715 type_node = directive_locals[arg.name]
1716 other_type = type_node.analyse_as_type(env)
1717 if other_type is None:
1718 error(type_node.pos, "Not a type")
1719 elif (type is not PyrexTypes.py_object_type
1720 and not type.same_as(other_type)):
1721 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1722 error(type_node.pos, "Previous declaration here")
1723 else:
1724 type = other_type
1725 if name_declarator and name_declarator.cname:
1726 error(self.pos,
1727 "Python function argument cannot have C name specification")
1728 arg.type = type.as_argument_type()
1729 arg.hdr_type = None
1730 arg.needs_conversion = 0
1731 arg.needs_type_test = 0
1732 arg.is_generic = 1
1733 if arg.not_none and not arg.type.is_extension_type:
1734 error(self.pos,
1735 "Only extension type arguments can have 'not None'")
1737 def analyse_signature(self, env):
1738 any_type_tests_needed = 0
1739 if self.entry.is_special:
1740 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1741 elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
1742 # Use the simpler calling signature for zero- and one-argument functions.
1743 if self.entry.signature is TypeSlots.pyfunction_signature:
1744 if len(self.args) == 0:
1745 self.entry.signature = TypeSlots.pyfunction_noargs
1746 elif len(self.args) == 1:
1747 if self.args[0].default is None and not self.args[0].kw_only:
1748 self.entry.signature = TypeSlots.pyfunction_onearg
1749 elif self.entry.signature is TypeSlots.pymethod_signature:
1750 if len(self.args) == 1:
1751 self.entry.signature = TypeSlots.unaryfunc
1752 elif len(self.args) == 2:
1753 if self.args[1].default is None and not self.args[1].kw_only:
1754 self.entry.signature = TypeSlots.ibinaryfunc
1756 sig = self.entry.signature
1757 nfixed = sig.num_fixed_args()
1758 if sig is TypeSlots.pymethod_signature and nfixed == 1 \
1759 and len(self.args) == 0 and self.star_arg:
1760 # this is the only case where a diverging number of
1761 # arguments is not an error - when we have no explicit
1762 # 'self' parameter as in method(*args)
1763 sig = self.entry.signature = TypeSlots.pyfunction_signature # self is not 'really' used
1764 self.self_in_stararg = 1
1765 nfixed = 0
1767 for i in range(min(nfixed, len(self.args))):
1768 arg = self.args[i]
1769 arg.is_generic = 0
1770 if sig.is_self_arg(i) and not self.is_staticmethod:
1771 if self.is_classmethod:
1772 arg.is_type_arg = 1
1773 arg.hdr_type = arg.type = Builtin.type_type
1774 else:
1775 arg.is_self_arg = 1
1776 arg.hdr_type = arg.type = env.parent_type
1777 arg.needs_conversion = 0
1778 else:
1779 arg.hdr_type = sig.fixed_arg_type(i)
1780 if not arg.type.same_as(arg.hdr_type):
1781 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1782 arg.needs_type_test = 1
1783 any_type_tests_needed = 1
1784 else:
1785 arg.needs_conversion = 1
1786 if arg.needs_conversion:
1787 arg.hdr_cname = Naming.arg_prefix + arg.name
1788 else:
1789 arg.hdr_cname = Naming.var_prefix + arg.name
1791 if nfixed > len(self.args):
1792 self.bad_signature()
1793 return
1794 elif nfixed < len(self.args):
1795 if not sig.has_generic_args:
1796 self.bad_signature()
1797 for arg in self.args:
1798 if arg.is_generic and \
1799 (arg.type.is_extension_type or arg.type.is_builtin_type):
1800 arg.needs_type_test = 1
1801 any_type_tests_needed = 1
1802 if any_type_tests_needed:
1803 env.use_utility_code(arg_type_test_utility_code)
1805 def bad_signature(self):
1806 sig = self.entry.signature
1807 expected_str = "%d" % sig.num_fixed_args()
1808 if sig.has_generic_args:
1809 expected_str = expected_str + " or more"
1810 name = self.name
1811 if name.startswith("__") and name.endswith("__"):
1812 desc = "Special method"
1813 else:
1814 desc = "Method"
1815 error(self.pos,
1816 "%s %s has wrong number of arguments "
1817 "(%d declared, %s expected)" % (
1818 desc, self.name, len(self.args), expected_str))
1820 def signature_has_nongeneric_args(self):
1821 argcount = len(self.args)
1822 if argcount == 0 or (
1823 argcount == 1 and (self.args[0].is_self_arg or
1824 self.args[0].is_type_arg)):
1825 return 0
1826 return 1
1828 def signature_has_generic_args(self):
1829 return self.entry.signature.has_generic_args
1831 def declare_pyfunction(self, env):
1832 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1833 name = self.name
1834 entry = env.lookup_here(self.name)
1835 if entry and entry.type.is_cfunction and not self.is_wrapper:
1836 warning(self.pos, "Overriding cdef method with def method.", 5)
1837 entry = env.declare_pyfunction(self.name, self.pos)
1838 self.entry = entry
1839 prefix = env.scope_prefix
1840 entry.func_cname = \
1841 Naming.pyfunc_prefix + prefix + name
1842 entry.pymethdef_cname = \
1843 Naming.pymethdef_prefix + prefix + name
1844 if Options.docstrings:
1845 entry.doc = embed_position(self.pos, self.doc)
1846 entry.doc_cname = \
1847 Naming.funcdoc_prefix + prefix + name
1848 else:
1849 entry.doc = None
1851 def declare_arguments(self, env):
1852 for arg in self.args:
1853 if not arg.name:
1854 error(arg.pos, "Missing argument name")
1855 if arg.needs_conversion:
1856 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1857 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1858 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1859 if arg.type.is_pyobject:
1860 arg.entry.init = "0"
1861 arg.entry.init_to_none = 0
1862 else:
1863 arg.entry = self.declare_argument(env, arg)
1864 arg.entry.used = 1
1865 arg.entry.is_self_arg = arg.is_self_arg
1866 if arg.hdr_type:
1867 if arg.is_self_arg or arg.is_type_arg or \
1868 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1869 arg.entry.is_declared_generic = 1
1870 self.declare_python_arg(env, self.star_arg)
1871 self.declare_python_arg(env, self.starstar_arg)
1873 def declare_python_arg(self, env, arg):
1874 if arg:
1875 if env.directives['infer_types'] != 'none':
1876 type = PyrexTypes.unspecified_type
1877 else:
1878 type = py_object_type
1879 entry = env.declare_var(arg.name, type, arg.pos)
1880 entry.used = 1
1881 entry.init = "0"
1882 entry.init_to_none = 0
1883 entry.xdecref_cleanup = 1
1884 arg.entry = entry
1885 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1887 def analyse_expressions(self, env):
1888 self.local_scope.directives = env.directives
1889 self.analyse_default_values(env)
1890 if env.is_py_class_scope:
1891 self.synthesize_assignment_node(env)
1893 def synthesize_assignment_node(self, env):
1894 import ExprNodes
1895 self.assmt = SingleAssignmentNode(self.pos,
1896 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1897 rhs = ExprNodes.UnboundMethodNode(self.pos,
1898 function = ExprNodes.PyCFunctionNode(self.pos,
1899 pymethdef_cname = self.entry.pymethdef_cname)))
1900 self.assmt.analyse_declarations(env)
1901 self.assmt.analyse_expressions(env)
1903 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1904 arg_code_list = []
1905 sig = self.entry.signature
1906 if sig.has_dummy_arg or self.self_in_stararg:
1907 arg_code_list.append(
1908 "PyObject *%s" % Naming.self_cname)
1909 for arg in self.args:
1910 if not arg.is_generic:
1911 if arg.is_self_arg or arg.is_type_arg:
1912 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1913 else:
1914 arg_code_list.append(
1915 arg.hdr_type.declaration_code(arg.hdr_cname))
1916 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1917 arg_code_list.append("PyObject *unused")
1918 if sig.has_generic_args:
1919 arg_code_list.append(
1920 "PyObject *%s, PyObject *%s"
1921 % (Naming.args_cname, Naming.kwds_cname))
1922 arg_code = ", ".join(arg_code_list)
1923 dc = self.return_type.declaration_code(self.entry.func_cname)
1924 header = "static %s(%s)" % (dc, arg_code)
1925 code.putln("%s; /*proto*/" % header)
1926 if proto_only:
1927 return
1928 if self.entry.doc and Options.docstrings:
1929 docstr = self.entry.doc
1930 if docstr.is_unicode:
1931 docstr = docstr.utf8encode()
1932 code.putln(
1933 'static char %s[] = "%s";' % (
1934 self.entry.doc_cname,
1935 split_docstring(escape_byte_string(docstr))))
1936 if with_pymethdef:
1937 code.put(
1938 "static PyMethodDef %s = " %
1939 self.entry.pymethdef_cname)
1940 code.put_pymethoddef(self.entry, ";")
1941 code.putln("%s {" % header)
1943 def generate_argument_declarations(self, env, code):
1944 for arg in self.args:
1945 if arg.is_generic: # or arg.needs_conversion:
1946 if arg.needs_conversion:
1947 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1948 else:
1949 code.put_var_declaration(arg.entry)
1951 def generate_keyword_list(self, code):
1952 if self.signature_has_generic_args() and \
1953 self.signature_has_nongeneric_args():
1954 code.put(
1955 "static PyObject **%s[] = {" %
1956 Naming.pykwdlist_cname)
1957 for arg in self.args:
1958 if arg.is_generic:
1959 pystring_cname = code.intern_identifier(arg.name)
1960 code.put('&%s,' % pystring_cname)
1961 code.putln("0};")
1963 def generate_argument_parsing_code(self, env, code):
1964 # Generate PyArg_ParseTuple call for generic
1965 # arguments, if any.
1966 if self.entry.signature.has_dummy_arg and not self.self_in_stararg:
1967 # get rid of unused argument warning
1968 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1970 old_error_label = code.new_error_label()
1971 our_error_label = code.error_label
1972 end_label = code.new_label("argument_unpacking_done")
1974 has_kwonly_args = self.num_kwonly_args > 0
1975 has_star_or_kw_args = self.star_arg is not None \
1976 or self.starstar_arg is not None or has_kwonly_args
1978 for arg in self.args:
1979 if not arg.type.is_pyobject:
1980 done = arg.type.create_from_py_utility_code(env)
1981 if not done: pass # will fail later
1983 if not self.signature_has_generic_args():
1984 if has_star_or_kw_args:
1985 error(self.pos, "This method cannot have * or keyword arguments")
1986 self.generate_argument_conversion_code(code)
1988 elif not self.signature_has_nongeneric_args():
1989 # func(*args) or func(**kw) or func(*args, **kw)
1990 self.generate_stararg_copy_code(code)
1992 else:
1993 positional_args = []
1994 kw_only_args = []
1995 for arg in self.args:
1996 arg_entry = arg.entry
1997 if arg.is_generic:
1998 if arg.default:
1999 if not arg.is_self_arg and not arg.is_type_arg:
2000 if arg.kw_only:
2001 kw_only_args.append(arg)
2002 else:
2003 positional_args.append(arg)
2004 elif arg.kw_only:
2005 kw_only_args.append(arg)
2006 elif not arg.is_self_arg and not arg.is_type_arg:
2007 positional_args.append(arg)
2009 self.generate_tuple_and_keyword_parsing_code(
2010 positional_args, kw_only_args, end_label, code)
2012 code.error_label = old_error_label
2013 if code.label_used(our_error_label):
2014 if not code.label_used(end_label):
2015 code.put_goto(end_label)
2016 code.put_label(our_error_label)
2017 if has_star_or_kw_args:
2018 self.generate_arg_decref(self.star_arg, code)
2019 if self.starstar_arg:
2020 if self.starstar_arg.entry.xdecref_cleanup:
2021 code.put_var_xdecref(self.starstar_arg.entry)
2022 else:
2023 code.put_var_decref(self.starstar_arg.entry)
2024 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
2025 code.putln("return %s;" % self.error_value())
2026 if code.label_used(end_label):
2027 code.put_label(end_label)
2029 def generate_arg_assignment(self, arg, item, code):
2030 if arg.type.is_pyobject:
2031 if arg.is_generic:
2032 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
2033 code.putln("%s = %s;" % (arg.entry.cname, item))
2034 else:
2035 func = arg.type.from_py_function
2036 if func:
2037 code.putln("%s = %s(%s); %s" % (
2038 arg.entry.cname,
2039 func,
2040 item,
2041 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
2042 else:
2043 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
2045 def generate_arg_xdecref(self, arg, code):
2046 if arg:
2047 code.put_var_xdecref(arg.entry)
2049 def generate_arg_decref(self, arg, code):
2050 if arg:
2051 code.put_var_decref(arg.entry)
2053 def generate_stararg_copy_code(self, code):
2054 if not self.star_arg:
2055 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2056 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
2057 Naming.args_cname)
2058 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2059 self.name, Naming.args_cname, self.error_value()))
2060 code.putln("}")
2062 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2064 if self.starstar_arg:
2065 if self.star_arg:
2066 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2067 else:
2068 kwarg_check = "%s" % Naming.kwds_cname
2069 else:
2070 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2071 Naming.kwds_cname, Naming.kwds_cname)
2072 code.putln(
2073 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2074 kwarg_check, Naming.kwds_cname, self.name,
2075 bool(self.starstar_arg), self.error_value()))
2077 if self.starstar_arg:
2078 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2079 self.starstar_arg.entry.cname,
2080 Naming.kwds_cname,
2081 Naming.kwds_cname))
2082 code.putln("if (unlikely(!%s)) return %s;" % (
2083 self.starstar_arg.entry.cname, self.error_value()))
2084 self.starstar_arg.entry.xdecref_cleanup = 0
2085 code.put_gotref(self.starstar_arg.entry.cname)
2087 if self.self_in_stararg:
2088 # need to create a new tuple with 'self' inserted as first item
2089 code.put("%s = PyTuple_New(PyTuple_GET_SIZE(%s)+1); if (unlikely(!%s)) " % (
2090 self.star_arg.entry.cname,
2091 Naming.args_cname,
2092 self.star_arg.entry.cname))
2093 if self.starstar_arg:
2094 code.putln("{")
2095 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2096 code.putln("return %s;" % self.error_value())
2097 code.putln("}")
2098 else:
2099 code.putln("return %s;" % self.error_value())
2100 code.put_gotref(self.star_arg.entry.cname)
2101 code.put_incref(Naming.self_cname, py_object_type)
2102 code.put_giveref(Naming.self_cname)
2103 code.putln("PyTuple_SET_ITEM(%s, 0, %s);" % (
2104 self.star_arg.entry.cname, Naming.self_cname))
2105 temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False)
2106 code.putln("for (%s=0; %s < PyTuple_GET_SIZE(%s); %s++) {" % (
2107 temp, temp, Naming.args_cname, temp))
2108 code.putln("PyObject* item = PyTuple_GET_ITEM(%s, %s);" % (
2109 Naming.args_cname, temp))
2110 code.put_incref("item", py_object_type)
2111 code.put_giveref("item")
2112 code.putln("PyTuple_SET_ITEM(%s, %s+1, item);" % (
2113 self.star_arg.entry.cname, temp))
2114 code.putln("}")
2115 code.funcstate.release_temp(temp)
2116 self.star_arg.entry.xdecref_cleanup = 0
2117 elif self.star_arg:
2118 code.put_incref(Naming.args_cname, py_object_type)
2119 code.putln("%s = %s;" % (
2120 self.star_arg.entry.cname,
2121 Naming.args_cname))
2122 self.star_arg.entry.xdecref_cleanup = 0
2124 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2125 kw_only_args, success_label, code):
2126 argtuple_error_label = code.new_label("argtuple_error")
2128 min_positional_args = self.num_required_args - self.num_required_kw_args
2129 if len(self.args) > 0 and (self.args[0].is_self_arg or self.args[0].is_type_arg):
2130 min_positional_args -= 1
2131 max_positional_args = len(positional_args)
2132 has_fixed_positional_count = not self.star_arg and \
2133 min_positional_args == max_positional_args
2135 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2136 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2137 if self.num_required_kw_args:
2138 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2140 if self.starstar_arg or self.star_arg:
2141 self.generate_stararg_init_code(max_positional_args, code)
2143 # --- optimised code when we receive keyword arguments
2144 if self.num_required_kw_args:
2145 likely_hint = "likely"
2146 else:
2147 likely_hint = "unlikely"
2148 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2149 self.generate_keyword_unpacking_code(
2150 min_positional_args, max_positional_args,
2151 has_fixed_positional_count,
2152 positional_args, kw_only_args, argtuple_error_label, code)
2154 # --- optimised code when we do not receive any keyword arguments
2155 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2156 # Python raises arg tuple related errors first, so we must
2157 # check the length here
2158 if min_positional_args == max_positional_args and not self.star_arg:
2159 compare = '!='
2160 else:
2161 compare = '<'
2162 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2163 Naming.args_cname, compare, min_positional_args))
2164 code.put_goto(argtuple_error_label)
2166 if self.num_required_kw_args:
2167 # pure error case: keywords required but not passed
2168 if max_positional_args > min_positional_args and not self.star_arg:
2169 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2170 Naming.args_cname, max_positional_args))
2171 code.put_goto(argtuple_error_label)
2172 code.putln('} else {')
2173 for i, arg in enumerate(kw_only_args):
2174 if not arg.default:
2175 pystring_cname = code.intern_identifier(arg.name)
2176 # required keyword-only argument missing
2177 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2178 self.name,
2179 pystring_cname))
2180 code.putln(code.error_goto(self.pos))
2181 break
2183 elif min_positional_args == max_positional_args:
2184 # parse the exact number of positional arguments from the
2185 # args tuple
2186 code.putln('} else {')
2187 for i, arg in enumerate(positional_args):
2188 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2189 self.generate_arg_assignment(arg, item, code)
2190 self.generate_arg_default_assignments(code)
2192 else:
2193 # parse the positional arguments from the variable length
2194 # args tuple
2195 code.putln('} else {')
2196 self.generate_arg_default_assignments(code)
2197 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2198 if self.star_arg:
2199 code.putln('default:')
2200 reversed_args = list(enumerate(positional_args))[::-1]
2201 for i, arg in reversed_args:
2202 if i >= min_positional_args-1:
2203 if min_positional_args > 1:
2204 code.putln('case %2d:' % (i+1)) # pure code beautification
2205 else:
2206 code.put('case %2d: ' % (i+1))
2207 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2208 self.generate_arg_assignment(arg, item, code)
2209 if min_positional_args == 0:
2210 code.put('case 0: ')
2211 code.putln('break;')
2212 if self.star_arg:
2213 if min_positional_args:
2214 for i in range(min_positional_args-1, -1, -1):
2215 code.putln('case %2d:' % i)
2216 code.put_goto(argtuple_error_label)
2217 else:
2218 code.put('default: ')
2219 code.put_goto(argtuple_error_label)
2220 code.putln('}')
2222 code.putln('}')
2224 if code.label_used(argtuple_error_label):
2225 code.put_goto(success_label)
2226 code.put_label(argtuple_error_label)
2227 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2228 self.name, has_fixed_positional_count,
2229 min_positional_args, max_positional_args,
2230 Naming.args_cname))
2231 code.putln(code.error_goto(self.pos))
2233 def generate_arg_default_assignments(self, code):
2234 for arg in self.args:
2235 if arg.is_generic and arg.default:
2236 code.putln(
2237 "%s = %s;" % (
2238 arg.entry.cname,
2239 arg.calculate_default_value_code(code)))
2241 def generate_stararg_init_code(self, max_positional_args, code):
2242 if self.starstar_arg:
2243 self.starstar_arg.entry.xdecref_cleanup = 0
2244 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2245 self.starstar_arg.entry.cname,
2246 self.starstar_arg.entry.cname,
2247 self.error_value()))
2248 code.put_gotref(self.starstar_arg.entry.cname)
2249 if self.star_arg:
2250 self.star_arg.entry.xdecref_cleanup = 0
2251 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2252 Naming.args_cname,
2253 max_positional_args))
2254 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2255 self.star_arg.entry.cname, Naming.args_cname,
2256 max_positional_args, Naming.args_cname))
2257 code.put_gotref(self.star_arg.entry.cname)
2258 if self.starstar_arg:
2259 code.putln("")
2260 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2261 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2262 code.putln('return %s;' % self.error_value())
2263 code.putln('}')
2264 else:
2265 code.putln("if (unlikely(!%s)) return %s;" % (
2266 self.star_arg.entry.cname, self.error_value()))
2267 code.putln('} else {')
2268 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2269 code.put_incref(Naming.empty_tuple, py_object_type)
2270 code.putln('}')
2272 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2273 has_fixed_positional_count, positional_args,
2274 kw_only_args, argtuple_error_label, code):
2275 all_args = tuple(positional_args) + tuple(kw_only_args)
2276 max_args = len(all_args)
2278 default_args = []
2279 for i, arg in enumerate(all_args):
2280 if arg.default and arg.type.is_pyobject:
2281 default_value = arg.calculate_default_value_code(code)
2282 if arg.type is not PyrexTypes.py_object_type:
2283 default_value = "(PyObject*)"+default_value
2284 default_args.append((i, default_value))
2286 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2287 Naming.kwds_cname)
2288 # it looks funny to separate the init-to-0 from setting the
2289 # default value, but C89 needs this
2290 code.putln("PyObject* values[%d] = {%s};" % (
2291 max_args, ','.join(['0']*max_args)))
2292 for i, default_value in default_args:
2293 code.putln('values[%d] = %s;' % (i, default_value))
2295 # parse the tuple and check that it's not too long
2296 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2297 if self.star_arg:
2298 code.putln('default:')
2299 for i in range(max_positional_args-1, -1, -1):
2300 code.put('case %2d: ' % (i+1))
2301 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2302 i, Naming.args_cname, i))
2303 code.putln('case 0: break;')
2304 if not self.star_arg:
2305 code.put('default: ') # more arguments than allowed
2306 code.put_goto(argtuple_error_label)
2307 code.putln('}')
2309 # now fill up the positional/required arguments with values
2310 # from the kw dict
2311 if self.num_required_args or max_positional_args > 0:
2312 last_required_arg = -1
2313 for i, arg in enumerate(all_args):
2314 if not arg.default:
2315 last_required_arg = i
2316 if last_required_arg < max_positional_args:
2317 last_required_arg = max_positional_args-1
2318 num_required_args = self.num_required_args
2319 if max_positional_args > 0:
2320 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2321 for i, arg in enumerate(all_args[:last_required_arg+1]):
2322 if max_positional_args > 0 and i <= max_positional_args:
2323 if self.star_arg and i == max_positional_args:
2324 code.putln('default:')
2325 else:
2326 code.putln('case %2d:' % i)
2327 pystring_cname = code.intern_identifier(arg.name)
2328 if arg.default:
2329 if arg.kw_only:
2330 # handled separately below
2331 continue
2332 code.putln('if (kw_args > %d) {' % num_required_args)
2333 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2334 Naming.kwds_cname, pystring_cname))
2335 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2336 code.putln('}')
2337 else:
2338 num_required_args -= 1
2339 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2340 i, Naming.kwds_cname, pystring_cname))
2341 code.putln('if (likely(values[%d])) kw_args--;' % i);
2342 if i < min_positional_args:
2343 if i == 0:
2344 # special case: we know arg 0 is missing
2345 code.put('else ')
2346 code.put_goto(argtuple_error_label)
2347 else:
2348 # print the correct number of values (args or
2349 # kwargs) that were passed into positional
2350 # arguments up to this point
2351 code.putln('else {')
2352 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2353 self.name, has_fixed_positional_count,
2354 min_positional_args, max_positional_args, i))
2355 code.putln(code.error_goto(self.pos))
2356 code.putln('}')
2357 elif arg.kw_only:
2358 code.putln('else {')
2359 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2360 self.name, pystring_cname))
2361 code.putln(code.error_goto(self.pos))
2362 code.putln('}')
2363 if max_positional_args > 0:
2364 code.putln('}')
2366 if kw_only_args and not self.starstar_arg:
2367 # unpack optional keyword-only arguments
2368 # checking for interned strings in a dict is faster than iterating
2369 # but it's too likely that we must iterate if we expect **kwargs
2370 optional_args = []
2371 for i, arg in enumerate(all_args[max_positional_args:]):
2372 if not arg.kw_only or not arg.default:
2373 continue
2374 optional_args.append((i+max_positional_args, arg))
2375 if optional_args:
2376 # this mimics an unrolled loop so that we can "break" out of it
2377 code.putln('while (kw_args > 0) {')
2378 code.putln('PyObject* value;')
2379 for i, arg in optional_args:
2380 pystring_cname = code.intern_identifier(arg.name)
2381 code.putln(
2382 'value = PyDict_GetItem(%s, %s);' % (
2383 Naming.kwds_cname, pystring_cname))
2384 code.putln(
2385 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2386 code.putln('break;')
2387 code.putln('}')
2389 code.putln('if (unlikely(kw_args > 0)) {')
2390 # non-positional/-required kw args left in dict: default args,
2391 # kw-only args, **kwargs or error
2392 #
2393 # This is sort of a catch-all: except for checking required
2394 # arguments, this will always do the right thing for unpacking
2395 # keyword arguments, so that we can concentrate on optimising
2396 # common cases above.
2397 if max_positional_args == 0:
2398 pos_arg_count = "0"
2399 elif self.star_arg:
2400 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2401 Naming.args_cname, max_positional_args,
2402 Naming.args_cname, max_positional_args))
2403 pos_arg_count = "used_pos_args"
2404 else:
2405 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2406 code.globalstate.use_utility_code(parse_keywords_utility_code)
2407 code.put(
2408 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2409 Naming.kwds_cname,
2410 Naming.pykwdlist_cname,
2411 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2412 pos_arg_count,
2413 self.name))
2414 code.putln(code.error_goto(self.pos))
2415 code.putln('}')
2417 # convert arg values to their final type and assign them
2418 for i, arg in enumerate(all_args):
2419 if arg.default and not arg.type.is_pyobject:
2420 code.putln("if (values[%d]) {" % i)
2421 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2422 if arg.default and not arg.type.is_pyobject:
2423 code.putln('} else {')
2424 code.putln(
2425 "%s = %s;" % (
2426 arg.entry.cname,
2427 arg.calculate_default_value_code(code)))
2428 code.putln('}')
2430 def generate_argument_conversion_code(self, code):
2431 # Generate code to convert arguments from
2432 # signature type to declared type, if needed.
2433 for arg in self.args:
2434 if arg.needs_conversion:
2435 self.generate_arg_conversion(arg, code)
2437 def generate_arg_conversion(self, arg, code):
2438 # Generate conversion code for one argument.
2439 old_type = arg.hdr_type
2440 new_type = arg.type
2441 if old_type.is_pyobject:
2442 if arg.default:
2443 code.putln("if (%s) {" % arg.hdr_cname)
2444 else:
2445 code.putln("assert(%s); {" % arg.hdr_cname)
2446 self.generate_arg_conversion_from_pyobject(arg, code)
2447 code.putln("}")
2448 elif new_type.is_pyobject:
2449 self.generate_arg_conversion_to_pyobject(arg, code)
2450 else:
2451 if new_type.assignable_from(old_type):
2452 code.putln(
2453 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2454 else:
2455 error(arg.pos,
2456 "Cannot convert 1 argument from '%s' to '%s'" %
2457 (old_type, new_type))
2459 def generate_arg_conversion_from_pyobject(self, arg, code):
2460 new_type = arg.type
2461 func = new_type.from_py_function
2462 # copied from CoerceFromPyTypeNode
2463 if func:
2464 code.putln("%s = %s(%s); %s" % (
2465 arg.entry.cname,
2466 func,
2467 arg.hdr_cname,
2468 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2469 else:
2470 error(arg.pos,
2471 "Cannot convert Python object argument to type '%s'"
2472 % new_type)
2474 def generate_arg_conversion_to_pyobject(self, arg, code):
2475 old_type = arg.hdr_type
2476 func = old_type.to_py_function
2477 if func:
2478 code.putln("%s = %s(%s); %s" % (
2479 arg.entry.cname,
2480 func,
2481 arg.hdr_cname,
2482 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2483 code.put_var_gotref(arg.entry)
2484 else:
2485 error(arg.pos,
2486 "Cannot convert argument of type '%s' to Python object"
2487 % old_type)
2489 def generate_argument_type_tests(self, code):
2490 # Generate type tests for args whose signature
2491 # type is PyObject * and whose declared type is
2492 # a subtype thereof.
2493 for arg in self.args:
2494 if arg.needs_type_test:
2495 self.generate_arg_type_test(arg, code)
2497 def generate_arg_type_test(self, arg, code):
2498 # Generate type test for one argument.
2499 if arg.type.typeobj_is_available():
2500 typeptr_cname = arg.type.typeptr_cname
2501 arg_code = "((PyObject *)%s)" % arg.entry.cname
2502 code.putln(
2503 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2504 arg_code,
2505 typeptr_cname,
2506 not arg.not_none,
2507 arg.name,
2508 arg.type.is_builtin_type,
2509 code.error_goto(arg.pos)))
2510 else:
2511 error(arg.pos, "Cannot test type of extern C class "
2512 "without type object name specification")
2514 def error_value(self):
2515 return self.entry.signature.error_value
2517 def caller_will_check_exceptions(self):
2518 return 1
2520 class OverrideCheckNode(StatNode):
2521 # A Node for dispatching to the def method if it
2522 # is overriden.
2523 #
2524 # py_func
2525 #
2526 # args
2527 # func_temp
2528 # body
2530 child_attrs = ['body']
2532 body = None
2534 def analyse_expressions(self, env):
2535 self.args = env.arg_entries
2536 if self.py_func.is_module_scope:
2537 first_arg = 0
2538 else:
2539 first_arg = 1
2540 import ExprNodes
2541 self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
2542 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2543 call_node = ExprNodes.SimpleCallNode(self.pos,
2544 function=self.func_node,
2545 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2546 self.body = ReturnStatNode(self.pos, value=call_node)
2547 self.body.analyse_expressions(env)
2549 def generate_execution_code(self, code):
2550 interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
2551 # Check to see if we are an extension type
2552 if self.py_func.is_module_scope:
2553 self_arg = "((PyObject *)%s)" % Naming.module_cname
2554 else:
2555 self_arg = "((PyObject *)%s)" % self.args[0].cname
2556 code.putln("/* Check if called by wrapper */")
2557 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2558 code.putln("/* Check if overriden in Python */")
2559 if self.py_func.is_module_scope:
2560 code.putln("else {")
2561 else:
2562 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2563 func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
2564 self.func_node.set_cname(func_node_temp)
2565 # need to get attribute manually--scope would return cdef method
2566 err = code.error_goto_if_null(func_node_temp, self.pos)
2567 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
2568 func_node_temp, self_arg, interned_attr_cname, err))
2569 code.put_gotref(func_node_temp)
2570 is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
2571 is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)" % (
2572 func_node_temp, self.py_func.entry.func_cname)
2573 code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
2574 self.body.generate_execution_code(code)
2575 code.putln("}")
2576 code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
2577 code.funcstate.release_temp(func_node_temp)
2578 code.putln("}")
2580 class ClassDefNode(StatNode, BlockNode):
2581 pass
2583 class PyClassDefNode(ClassDefNode):
2584 # A Python class definition.
2585 #
2586 # name EncodedString Name of the class
2587 # doc string or None
2588 # body StatNode Attribute definition code
2589 # entry Symtab.Entry
2590 # scope PyClassScope
2591 # decorators [DecoratorNode] list of decorators or None
2592 #
2593 # The following subnodes are constructed internally:
2594 #
2595 # dict DictNode Class dictionary
2596 # classobj ClassNode Class object
2597 # target NameNode Variable to assign class object to
2599 child_attrs = ["body", "dict", "classobj", "target"]
2600 decorators = None
2602 def __init__(self, pos, name, bases, doc, body, decorators = None):
2603 StatNode.__init__(self, pos)
2604 self.name = name
2605 self.doc = doc
2606 self.body = body
2607 self.decorators = decorators
2608 import ExprNodes
2609 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2610 if self.doc and Options.docstrings:
2611 doc = embed_position(self.pos, self.doc)
2612 # FIXME: correct string node?
2613 doc_node = ExprNodes.StringNode(pos, value = doc)
2614 else:
2615 doc_node = None
2616 self.classobj = ExprNodes.ClassNode(pos, name = name,
2617 bases = bases, dict = self.dict, doc = doc_node)
2618 self.target = ExprNodes.NameNode(pos, name = name)
2620 def as_cclass(self):
2621 """
2622 Return this node as if it were declared as an extension class
2623 """
2624 bases = self.classobj.bases.args
2625 if len(bases) == 0:
2626 base_class_name = None
2627 base_class_module = None
2628 elif len(bases) == 1:
2629 base = bases[0]
2630 path = []
2631 from ExprNodes import AttributeNode, NameNode
2632 while isinstance(base, AttributeNode):
2633 path.insert(0, base.attribute)
2634 base = base.obj
2635 if isinstance(base, NameNode):
2636 path.insert(0, base.name)
2637 base_class_name = path[-1]
2638 if len(path) > 1:
2639 base_class_module = u'.'.join(path[:-1])
2640 else:
2641 base_class_module = None
2642 else:
2643 error(self.classobj.bases.args.pos, "Invalid base class")
2644 else:
2645 error(self.classobj.bases.args.pos, "C class may only have one base class")
2646 return None
2648 return CClassDefNode(self.pos,
2649 visibility = 'private',
2650 module_name = None,
2651 class_name = self.name,
2652 base_class_module = base_class_module,
2653 base_class_name = base_class_name,
2654 decorators = self.decorators,
2655 body = self.body,
2656 in_pxd = False,
2657 doc = self.doc)
2659 def create_scope(self, env):
2660 genv = env
2661 while env.is_py_class_scope or env.is_c_class_scope:
2662 env = env.outer_scope
2663 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2664 return cenv
2666 def analyse_declarations(self, env):
2667 self.target.analyse_target_declaration(env)
2668 cenv = self.create_scope(env)
2669 cenv.directives = env.directives
2670 cenv.class_obj_cname = self.target.entry.cname
2671 self.body.analyse_declarations(cenv)
2673 def analyse_expressions(self, env):
2674 self.dict.analyse_expressions(env)
2675 self.classobj.analyse_expressions(env)
2676 genv = env.global_scope()
2677 cenv = self.scope
2678 self.body.analyse_expressions(cenv)
2679 self.target.analyse_target_expression(env, self.classobj)
2681 def generate_function_definitions(self, env, code):
2682 self.body.generate_function_definitions(self.scope, code)
2684 def generate_execution_code(self, code):
2685 code.pyclass_stack.append(self)
2686 cenv = self.scope
2687 self.dict.generate_evaluation_code(code)
2688 self.classobj.generate_evaluation_code(code)
2689 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2690 self.body.generate_execution_code(code)
2691 self.target.generate_assignment_code(self.classobj, code)
2692 self.dict.generate_disposal_code(code)
2693 self.dict.free_temps(code)
2694 code.pyclass_stack.pop()
2697 class CClassDefNode(ClassDefNode):
2698 # An extension type definition.
2699 #
2700 # visibility 'private' or 'public' or 'extern'
2701 # typedef_flag boolean
2702 # api boolean
2703 # module_name string or None For import of extern type objects
2704 # class_name string Unqualified name of class
2705 # as_name string or None Name to declare as in this scope
2706 # base_class_module string or None Module containing the base class
2707 # base_class_name string or None Name of the base class
2708 # objstruct_name string or None Specified C name of object struct
2709 # typeobj_name string or None Specified C name of type object
2710 # in_pxd boolean Is in a .pxd file
2711 # decorators [DecoratorNode] list of decorators or None
2712 # doc string or None
2713 # body StatNode or None
2714 # entry Symtab.Entry
2715 # base_type PyExtensionType or None
2716 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2717 # buffer_defaults_pos
2719 child_attrs = ["body"]
2720 buffer_defaults_node = None
2721 buffer_defaults_pos = None
2722 typedef_flag = False
2723 api = False
2724 objstruct_name = None
2725 typeobj_name = None
2726 decorators = None
2728 def analyse_declarations(self, env):
2729 #print "CClassDefNode.analyse_declarations:", self.class_name
2730 #print "...visibility =", self.visibility
2731 #print "...module_name =", self.module_name
2733 import Buffer
2734 if self.buffer_defaults_node:
2735 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2736 env, [], self.buffer_defaults_node,
2737 need_complete=False)
2738 else:
2739 buffer_defaults = None
2741 if env.in_cinclude and not self.objstruct_name:
2742 error(self.pos, "Object struct name specification required for "
2743 "C class defined in 'extern from' block")
2744 self.base_type = None
2745 # Now that module imports are cached, we need to
2746 # import the modules for extern classes.
2747 if self.module_name:
2748 self.module = None
2749 for module in env.cimported_modules:
2750 if module.name == self.module_name:
2751 self.module = module
2752 if self.module is None:
2753 self.module = ModuleScope(self.module_name, None, env.context)
2754 self.module.has_extern_class = 1
2755 env.add_imported_module(self.module)
2757 if self.base_class_name:
2758 if self.base_class_module:
2759 base_class_scope = env.find_module(self.base_class_module, self.pos)
2760 else:
2761 base_class_scope = env
2762 if self.base_class_name == 'object':
2763 # extension classes are special and don't need to inherit from object
2764 if base_class_scope is None or base_class_scope.lookup('object') is None:
2765 self.base_class_name = None
2766 self.base_class_module = None
2767 base_class_scope = None
2768 if base_class_scope:
2769 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2770 if base_class_entry:
2771 if not base_class_entry.is_type:
2772 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2773 elif not base_class_entry.type.is_extension_type:
2774 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2775 elif not base_class_entry.type.is_complete():
2776 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2777 else:
2778 self.base_type = base_class_entry.type
2779 has_body = self.body is not None
2780 if self.module_name and self.visibility != 'extern':
2781 module_path = self.module_name.split(".")
2782 home_scope = env.find_imported_module(module_path, self.pos)
2783 if not home_scope:
2784 return
2785 else:
2786 home_scope = env
2788 if self.visibility == 'extern':
2789 if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
2790 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
2792 self.entry = home_scope.declare_c_class(
2793 name = self.class_name,
2794 pos = self.pos,
2795 defining = has_body and self.in_pxd,
2796 implementing = has_body and not self.in_pxd,
2797 module_name = self.module_name,
2798 base_type = self.base_type,
2799 objstruct_cname = self.objstruct_name,
2800 typeobj_cname = self.typeobj_name,
2801 visibility = self.visibility,
2802 typedef_flag = self.typedef_flag,
2803 api = self.api,
2804 buffer_defaults = buffer_defaults)
2805 if home_scope is not env and self.visibility == 'extern':
2806 env.add_imported_entry(self.class_name, self.entry, pos)
2807 self.scope = scope = self.entry.type.scope
2808 if scope is not None:
2809 scope.directives = env.directives
2811 if self.doc and Options.docstrings:
2812 scope.doc = embed_position(self.pos, self.doc)
2814 if has_body:
2815 self.body.analyse_declarations(scope)
2816 if self.in_pxd:
2817 scope.defined = 1
2818 else:
2819 scope.implemented = 1
2820 env.allocate_vtable_names(self.entry)
2822 def analyse_expressions(self, env):
2823 if self.body:
2824 scope = self.entry.type.scope
2825 self.body.analyse_expressions(scope)
2827 def generate_function_definitions(self, env, code):
2828 if self.body:
2829 self.body.generate_function_definitions(
2830 self.entry.type.scope, code)
2832 def generate_execution_code(self, code):
2833 # This is needed to generate evaluation code for
2834 # default values of method arguments.
2835 if self.body:
2836 self.body.generate_execution_code(code)
2838 def annotate(self, code):
2839 if self.body:
2840 self.body.annotate(code)
2843 class PropertyNode(StatNode):
2844 # Definition of a property in an extension type.
2845 #
2846 # name string
2847 # doc EncodedString or None Doc string
2848 # body StatListNode
2850 child_attrs = ["body"]
2852 def analyse_declarations(self, env):
2853 entry = env.declare_property(self.name, self.doc, self.pos)
2854 if entry:
2855 entry.scope.directives = env.directives
2856 self.body.analyse_declarations(entry.scope)
2858 def analyse_expressions(self, env):
2859 self.body.analyse_expressions(env)
2861 def generate_function_definitions(self, env, code):
2862 self.body.generate_function_definitions(env, code)
2864 def generate_execution_code(self, code):
2865 pass
2867 def annotate(self, code):
2868 self.body.annotate(code)
2871 class GlobalNode(StatNode):
2872 # Global variable declaration.
2873 #
2874 # names [string]
2876 child_attrs = []
2878 def analyse_declarations(self, env):
2879 for name in self.names:
2880 env.declare_global(name, self.pos)
2882 def analyse_expressions(self, env):
2883 pass
2885 def generate_execution_code(self, code):
2886 pass
2889 class ExprStatNode(StatNode):
2890 # Expression used as a statement.
2891 #
2892 # expr ExprNode
2894 child_attrs = ["expr"]
2896 def analyse_declarations(self, env):
2897 import ExprNodes
2898 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2899 func = self.expr.function.as_cython_attribute()
2900 if func == u'declare':
2901 args, kwds = self.expr.explicit_args_kwds()
2902 if len(args):
2903 error(self.expr.pos, "Variable names must be specified.")
2904 for var, type_node in kwds.key_value_pairs:
2905 type = type_node.analyse_as_type(env)
2906 if type is None:
2907 error(type_node.pos, "Unknown type")
2908 else:
2909 env.declare_var(var.value, type, var.pos, is_cdef = True)
2910 self.__class__ = PassStatNode
2912 def analyse_expressions(self, env):
2913 self.expr.analyse_expressions(env)
2915 def generate_execution_code(self, code):
2916 self.expr.generate_evaluation_code(code)
2917 if not self.expr.is_temp and self.expr.result():
2918 code.putln("%s;" % self.expr.result())
2919 self.expr.generate_disposal_code(code)
2920 self.expr.free_temps(code)
2922 def annotate(self, code):
2923 self.expr.annotate(code)
2926 class AssignmentNode(StatNode):
2927 # Abstract base class for assignment nodes.
2928 #
2929 # The analyse_expressions and generate_execution_code
2930 # phases of assignments are split into two sub-phases
2931 # each, to enable all the right hand sides of a
2932 # parallel assignment to be evaluated before assigning
2933 # to any of the left hand sides.
2935 def analyse_expressions(self, env):
2936 self.analyse_types(env)
2938 # def analyse_expressions(self, env):
2939 # self.analyse_expressions_1(env)
2940 # self.analyse_expressions_2(env)
2942 def generate_execution_code(self, code):
2943 self.generate_rhs_evaluation_code(code)
2944 self.generate_assignment_code(code)
2947 class SingleAssignmentNode(AssignmentNode):
2948 # The simplest case:
2949 #
2950 # a = b
2951 #
2952 # lhs ExprNode Left hand side
2953 # rhs ExprNode Right hand side
2954 # first bool Is this guaranteed the first assignment to lhs?
2956 child_attrs = ["lhs", "rhs"]
2957 first = False
2958 declaration_only = False
2960 def analyse_declarations(self, env):
2961 import ExprNodes
2963 # handle declarations of the form x = cython.foo()
2964 if isinstance(self.rhs, ExprNodes.CallNode):
2965 func_name = self.rhs.function.as_cython_attribute()
2966 if func_name:
2967 args, kwds = self.rhs.explicit_args_kwds()
2969 if func_name in ['declare', 'typedef']:
2970 if len(args) > 2 or kwds is not None:
2971 error(rhs.pos, "Can only declare one type at a time.")
2972 return
2973 type = args[0].analyse_as_type(env)
2974 if type is None:
2975 error(args[0].pos, "Unknown type")
2976 return
2977 lhs = self.lhs
2978 if func_name == 'declare':
2979 if isinstance(lhs, ExprNodes.NameNode):
2980 vars = [(lhs.name, lhs.pos)]
2981 elif isinstance(lhs, ExprNodes.TupleNode):
2982 vars = [(var.name, var.pos) for var in lhs.args]
2983 else:
2984 error(lhs.pos, "Invalid declaration")
2985 return
2986 for var, pos in vars:
2987 env.declare_var(var, type, pos, is_cdef = True)
2988 if len(args) == 2:
2989 # we have a value
2990 self.rhs = args[1]
2991 else:
2992 self.declaration_only = True
2993 else:
2994 self.declaration_only = True
2995 if not isinstance(lhs, ExprNodes.NameNode):
2996 error(lhs.pos, "Invalid declaration.")
2997 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2999 elif func_name in ['struct', 'union']:
3000 self.declaration_only = True
3001 if len(args) > 0 or kwds is None:
3002 error(rhs.pos, "Struct or union members must be given by name.")
3003 return
3004 members = []
3005 for member, type_node in kwds.key_value_pairs:
3006 type = type_node.analyse_as_type(env)
3007 if type is None:
3008 error(type_node.pos, "Unknown type")
3009 else:
3010 members.append((member.value, type, member.pos))
3011 if len(members) < len(kwds.key_value_pairs):
3012 return
3013 if not isinstance(self.lhs, ExprNodes.NameNode):
3014 error(self.lhs.pos, "Invalid declaration.")
3015 name = self.lhs.name
3016 scope = StructOrUnionScope(name)
3017 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
3018 for member, type, pos in members:
3019 scope.declare_var(member, type, pos)
3021 if self.declaration_only:
3022 return
3023 else:
3024 self.lhs.analyse_target_declaration(env)
3026 def analyse_types(self, env, use_temp = 0):
3027 self.rhs.analyse_types(env)
3028 self.lhs.analyse_target_types(env)
3029 self.lhs.gil_assignment_check(env)
3030 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3031 if use_temp:
3032 self.rhs = self.rhs.coerce_to_temp(env)
3034 def generate_rhs_evaluation_code(self, code):
3035 self.rhs.generate_evaluation_code(code)
3037 def generate_assignment_code(self, code):
3038 self.lhs.generate_assignment_code(self.rhs, code)
3040 def annotate(self, code):
3041 self.lhs.annotate(code)
3042 self.rhs.annotate(code)
3045 class CascadedAssignmentNode(AssignmentNode):
3046 # An assignment with multiple left hand sides:
3047 #
3048 # a = b = c
3049 #
3050 # lhs_list [ExprNode] Left hand sides
3051 # rhs ExprNode Right hand sides
3052 #
3053 # Used internally:
3054 #
3055 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
3057 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
3058 coerced_rhs_list = None
3060 def analyse_declarations(self, env):
3061 for lhs in self.lhs_list:
3062 lhs.analyse_target_declaration(env)
3064 def analyse_types(self, env, use_temp = 0):
3065 self.rhs.analyse_types(env)
3066 if not self.rhs.is_simple():
3067 if use_temp:
3068 self.rhs = self.rhs.coerce_to_temp(env)
3069 else:
3070 self.rhs = self.rhs.coerce_to_simple(env)
3071 from ExprNodes import CloneNode
3072 self.coerced_rhs_list = []
3073 for lhs in self.lhs_list:
3074 lhs.analyse_target_types(env)
3075 lhs.gil_assignment_check(env)
3076 rhs = CloneNode(self.rhs)
3077 rhs = rhs.coerce_to(lhs.type, env)
3078 self.coerced_rhs_list.append(rhs)
3080 def generate_rhs_evaluation_code(self, code):
3081 self.rhs.generate_evaluation_code(code)
3083 def generate_assignment_code(self, code):
3084 for i in range(len(self.lhs_list)):
3085 lhs = self.lhs_list[i]
3086 rhs = self.coerced_rhs_list[i]
3087 rhs.generate_evaluation_code(code)
3088 lhs.generate_assignment_code(rhs, code)
3089 # Assignment has disposed of the cloned RHS
3090 self.rhs.generate_disposal_code(code)
3091 self.rhs.free_temps(code)
3093 def annotate(self, code):
3094 for i in range(len(self.lhs_list)):
3095 lhs = self.lhs_list[i].annotate(code)
3096 rhs = self.coerced_rhs_list[i].annotate(code)
3097 self.rhs.annotate(code)
3100 class ParallelAssignmentNode(AssignmentNode):
3101 # A combined packing/unpacking assignment:
3102 #
3103 # a, b, c = d, e, f
3104 #
3105 # This has been rearranged by the parser into
3106 #
3107 # a = d ; b = e ; c = f
3108 #
3109 # but we must evaluate all the right hand sides
3110 # before assigning to any of the left hand sides.
3111 #
3112 # stats [AssignmentNode] The constituent assignments
3114 child_attrs = ["stats"]
3116 def analyse_declarations(self, env):
3117 for stat in self.stats:
3118 stat.analyse_declarations(env)
3120 def analyse_expressions(self, env):
3121 for stat in self.stats:
3122 stat.analyse_types(env, use_temp = 1)
3124 # def analyse_expressions(self, env):
3125 # for stat in self.stats:
3126 # stat.analyse_expressions_1(env, use_temp = 1)
3127 # for stat in self.stats:
3128 # stat.analyse_expressions_2(env)
3130 def generate_execution_code(self, code):
3131 for stat in self.stats:
3132 stat.generate_rhs_evaluation_code(code)
3133 for stat in self.stats:
3134 stat.generate_assignment_code(code)
3136 def annotate(self, code):
3137 for stat in self.stats:
3138 stat.annotate(code)
3141 class InPlaceAssignmentNode(AssignmentNode):
3142 # An in place arithmatic operand:
3143 #
3144 # a += b
3145 # a -= b
3146 # ...
3147 #
3148 # lhs ExprNode Left hand side
3149 # rhs ExprNode Right hand side
3150 # op char one of "+-*/%^&|"
3151 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3152 #
3153 # This code is a bit tricky because in order to obey Python
3154 # semantics the sub-expressions (e.g. indices) of the lhs must
3155 # not be evaluated twice. So we must re-use the values calculated
3156 # in evaluation phase for the assignment phase as well.
3157 # Fortunately, the type of the lhs node is fairly constrained
3158 # (it must be a NameNode, AttributeNode, or IndexNode).
3160 child_attrs = ["lhs", "rhs"]
3161 dup = None
3163 def analyse_declarations(self, env):
3164 self.lhs.analyse_target_declaration(env)
3166 def analyse_types(self, env):
3167 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3168 self.rhs.analyse_types(env)
3169 self.lhs.analyse_target_types(env)
3170 import ExprNodes
3171 if self.lhs.type.is_pyobject:
3172 self.rhs = self.rhs.coerce_to_pyobject(env)
3173 elif self.rhs.type.is_pyobject:
3174 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3175 if self.lhs.type.is_pyobject:
3176 self.result_value_temp = ExprNodes.PyTempNode(self.pos, env)
3177 self.result_value = self.result_value_temp.coerce_to(self.lhs.type, env)
3179 def generate_execution_code(self, code):
3180 import ExprNodes
3181 self.rhs.generate_evaluation_code(code)
3182 self.dup.generate_subexpr_evaluation_code(code)
3183 if self.dup.is_temp:
3184 self.dup.allocate_temp_result(code)
3185 # self.dup.generate_result_code is run only if it is not buffer access
3186 if self.operator == "**":
3187 extra = ", Py_None"
3188 else:
3189 extra = ""
3190 if self.lhs.type.is_pyobject:
3191 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3192 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3193 self.dup.generate_result_code(code)
3194 self.result_value_temp.allocate(code)
3195 code.putln(
3196 "%s = %s(%s, %s%s); %s" % (
3197 self.result_value.result(),
3198 self.py_operation_function(),
3199 self.dup.py_result(),
3200 self.rhs.py_result(),
3201 extra,
3202 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3203 code.put_gotref(self.result_value.py_result())
3204 self.result_value.generate_evaluation_code(code) # May be a type check...
3205 self.rhs.generate_disposal_code(code)
3206 self.rhs.free_temps(code)
3207 self.dup.generate_disposal_code(code)
3208 self.dup.free_temps(code)
3209 self.lhs.generate_assignment_code(self.result_value, code)
3210 self.result_value_temp.release(code)
3211 else:
3212 c_op = self.operator
3213 if c_op == "//":
3214 c_op = "/"
3215 elif c_op == "**":
3216 error(self.pos, "No C inplace power operator")
3217 elif self.lhs.type.is_complex:
3218 error(self.pos, "Inplace operators not implemented for complex types.")
3220 # have to do assignment directly to avoid side-effects
3221 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3222 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3223 else:
3224 self.dup.generate_result_code(code)
3225 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3226 self.rhs.generate_disposal_code(code)
3227 self.rhs.free_temps(code)
3228 if self.dup.is_temp:
3229 self.dup.generate_subexpr_disposal_code(code)
3230 self.dup.free_subexpr_temps(code)
3232 def create_dup_node(self, env):
3233 import ExprNodes
3234 self.dup = self.lhs
3235 self.dup.analyse_types(env)
3236 if isinstance(self.lhs, ExprNodes.NameNode):
3237 target_lhs = ExprNodes.NameNode(self.dup.pos,
3238 name = self.dup.name,
3239 is_temp = self.dup.is_temp,
3240 entry = self.dup.entry)
3241 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3242 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3243 obj = ExprNodes.CloneNode(self.lhs.obj),
3244 attribute = self.dup.attribute,
3245 is_temp = self.dup.is_temp)
3246 elif isinstance(self.lhs, ExprNodes.IndexNode):
3247 if self.lhs.index:
3248 index = ExprNodes.CloneNode(self.lhs.index)
3249 else:
3250 index = None
3251 if self.lhs.indices:
3252 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3253 else:
3254 indices = []
3255 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3256 base = ExprNodes.CloneNode(self.dup.base),
3257 index = index,
3258 indices = indices,
3259 is_temp = self.dup.is_temp)
3260 else:
3261 assert False
3262 self.lhs = target_lhs
3263 return self.dup
3265 def py_operation_function(self):
3266 return self.py_functions[self.operator]
3268 py_functions = {
3269 "|": "PyNumber_InPlaceOr",
3270 "^": "PyNumber_InPlaceXor",
3271 "&": "PyNumber_InPlaceAnd",
3272 "+": "PyNumber_InPlaceAdd",
3273 "-": "PyNumber_InPlaceSubtract",
3274 "*": "PyNumber_InPlaceMultiply",
3275 "/": "__Pyx_PyNumber_InPlaceDivide",
3276 "%": "PyNumber_InPlaceRemainder",
3277 "<<": "PyNumber_InPlaceLshift",
3278 ">>": "PyNumber_InPlaceRshift",
3279 "**": "PyNumber_InPlacePower",
3280 "//": "PyNumber_InPlaceFloorDivide",
3281 }
3283 def annotate(self, code):
3284 self.lhs.annotate(code)
3285 self.rhs.annotate(code)
3286 self.dup.annotate(code)
3288 def create_binop_node(self):
3289 import ExprNodes
3290 return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
3293 class PrintStatNode(StatNode):
3294 # print statement
3295 #
3296 # arg_tuple TupleNode
3297 # append_newline boolean
3299 child_attrs = ["arg_tuple"]
3301 def analyse_expressions(self, env):
3302 self.arg_tuple.analyse_expressions(env)
3303 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3304 env.use_utility_code(printing_utility_code)
3305 if len(self.arg_tuple.args) == 1 and self.append_newline:
3306 env.use_utility_code(printing_one_utility_code)
3308 nogil_check = Node.gil_error
3309 gil_message = "Python print statement"
3311 def generate_execution_code(self, code):
3312 if len(self.arg_tuple.args) == 1 and self.append_newline:
3313 arg = self.arg_tuple.args[0]
3314 arg.generate_evaluation_code(code)
3316 code.putln(
3317 "if (__Pyx_PrintOne(%s) < 0) %s" % (
3318 arg.py_result(),
3319 code.error_goto(self.pos)))
3320 arg.generate_disposal_code(code)
3321 arg.free_temps(code)
3322 else:
3323 self.arg_tuple.generate_evaluation_code(code)
3324 code.putln(
3325 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3326 self.arg_tuple.py_result(),
3327 self.append_newline,
3328 code.error_goto(self.pos)))
3329 self.arg_tuple.generate_disposal_code(code)
3330 self.arg_tuple.free_temps(code)
3332 def annotate(self, code):
3333 self.arg_tuple.annotate(code)
3336 class ExecStatNode(StatNode):
3337 # exec statement
3338 #
3339 # args [ExprNode]
3341 child_attrs = ["args"]
3343 def analyse_expressions(self, env):
3344 for i, arg in enumerate(self.args):
3345 arg.analyse_expressions(env)
3346 arg = arg.coerce_to_pyobject(env)
3347 self.args[i] = arg
3348 env.use_utility_code(Builtin.pyexec_utility_code)
3350 nogil_check = Node.gil_error
3351 gil_message = "Python exec statement"
3353 def generate_execution_code(self, code):
3354 args = []
3355 for arg in self.args:
3356 arg.generate_evaluation_code(code)
3357 args.append( arg.py_result() )
3358 args = tuple(args + ['0', '0'][:3-len(args)])
3359 temp_result = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
3360 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3361 (temp_result,) + args))
3362 for arg in self.args:
3363 arg.generate_disposal_code(code)
3364 arg.free_temps(code)
3365 code.putln(
3366 code.error_goto_if_null(temp_result, self.pos))
3367 code.put_gotref(temp_result)
3368 code.put_decref_clear(temp_result, py_object_type)
3369 code.funcstate.release_temp(temp_result)
3371 def annotate(self, code):
3372 for arg in self.args:
3373 arg.annotate(code)
3376 class DelStatNode(StatNode):
3377 # del statement
3378 #
3379 # args [ExprNode]
3381 child_attrs = ["args"]
3383 def analyse_declarations(self, env):
3384 for arg in self.args:
3385 arg.analyse_target_declaration(env)
3387 def analyse_expressions(self, env):
3388 for arg in self.args:
3389 arg.analyse_target_expression(env, None)
3390 if not arg.type.is_pyobject:
3391 error(arg.pos, "Deletion of non-Python object")
3392 #arg.release_target_temp(env)
3394 def nogil_check(self, env):
3395 for arg in self.args:
3396 if arg.type.is_pyobject:
3397 self.gil_error()
3399 gil_message = "Deleting Python object"
3401 def generate_execution_code(self, code):
3402 for arg in self.args:
3403 if arg.type.is_pyobject:
3404 arg.generate_deletion_code(code)
3405 # else error reported earlier
3407 def annotate(self, code):
3408 for arg in self.args:
3409 arg.annotate(code)
3412 class PassStatNode(StatNode):
3413 # pass statement
3415 child_attrs = []
3417 def analyse_expressions(self, env):
3418 pass
3420 def generate_execution_code(self, code):
3421 pass
3424 class BreakStatNode(StatNode):
3426 child_attrs = []
3428 def analyse_expressions(self, env):
3429 pass
3431 def generate_execution_code(self, code):
3432 if not code.break_label:
3433 error(self.pos, "break statement not inside loop")
3434 else:
3435 code.put_goto(code.break_label)
3438 class ContinueStatNode(StatNode):
3440 child_attrs = []
3442 def analyse_expressions(self, env):
3443 pass
3445 def generate_execution_code(self, code):
3446 if code.funcstate.in_try_finally:
3447 error(self.pos, "continue statement inside try of try...finally")
3448 elif not code.continue_label:
3449 error(self.pos, "continue statement not inside loop")
3450 else:
3451 code.put_goto(code.continue_label)
3454 class ReturnStatNode(StatNode):
3455 # return statement
3456 #
3457 # value ExprNode or None
3458 # return_type PyrexType
3460 child_attrs = ["value"]
3462 def analyse_expressions(self, env):
3463 return_type = env.return_type
3464 self.return_type = return_type
3465 if not return_type:
3466 error(self.pos, "Return not inside a function body")
3467 return
3468 if self.value:
3469 self.value.analyse_types(env)
3470 if return_type.is_void or return_type.is_returncode:
3471 error(self.value.pos,
3472 "Return with value in void function")
3473 else:
3474 self.value = self.value.coerce_to(env.return_type, env)
3475 else:
3476 if (not return_type.is_void
3477 and not return_type.is_pyobject
3478 and not return_type.is_returncode):
3479 error(self.pos, "Return value required")
3481 def nogil_check(self, env):
3482 if self.return_type.is_pyobject:
3483 self.gil_error()
3485 gil_message = "Returning Python object"
3487 def generate_execution_code(self, code):
3488 code.mark_pos(self.pos)
3489 if not self.return_type:
3490 # error reported earlier
3491 return
3492 if self.return_type.is_pyobject:
3493 code.put_xdecref(Naming.retval_cname,
3494 self.return_type)
3495 if self.value:
3496 self.value.generate_evaluation_code(code)
3497 self.value.make_owned_reference(code)
3498 code.putln(
3499 "%s = %s;" % (
3500 Naming.retval_cname,
3501 self.value.result_as(self.return_type)))
3502 self.value.generate_post_assignment_code(code)
3503 self.value.free_temps(code)
3504 else:
3505 if self.return_type.is_pyobject:
3506 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3507 elif self.return_type.is_returncode:
3508 code.putln(
3509 "%s = %s;" % (
3510 Naming.retval_cname,
3511 self.return_type.default_value))
3512 for cname, type in code.funcstate.temps_holding_reference():
3513 code.put_decref_clear(cname, type)
3514 code.put_goto(code.return_label)
3516 def annotate(self, code):
3517 if self.value:
3518 self.value.annotate(code)
3521 class RaiseStatNode(StatNode):
3522 # raise statement
3523 #
3524 # exc_type ExprNode or None
3525 # exc_value ExprNode or None
3526 # exc_tb ExprNode or None
3528 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3530 def analyse_expressions(self, env):
3531 if self.exc_type:
3532 self.exc_type.analyse_types(env)
3533 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3534 if self.exc_value:
3535 self.exc_value.analyse_types(env)
3536 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3537 if self.exc_tb:
3538 self.exc_tb.analyse_types(env)
3539 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3540 env.use_utility_code(raise_utility_code)
3542 nogil_check = Node.gil_error
3543 gil_message = "Raising exception"
3545 def generate_execution_code(self, code):
3546 if self.exc_type:
3547 self.exc_type.generate_evaluation_code(code)
3548 type_code = self.exc_type.py_result()
3549 else:
3550 type_code = "0"
3551 if self.exc_value:
3552 self.exc_value.generate_evaluation_code(code)
3553 value_code = self.exc_value.py_result()
3554 else:
3555 value_code = "0"
3556 if self.exc_tb:
3557 self.exc_tb.generate_evaluation_code(code)
3558 tb_code = self.exc_tb.py_result()
3559 else:
3560 tb_code = "0"
3561 code.putln(
3562 "__Pyx_Raise(%s, %s, %s);" % (
3563 type_code,
3564 value_code,
3565 tb_code))
3566 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3567 if obj:
3568 obj.generate_disposal_code(code)
3569 obj.free_temps(code)
3570 code.putln(
3571 code.error_goto(self.pos))
3573 def annotate(self, code):
3574 if self.exc_type:
3575 self.exc_type.annotate(code)
3576 if self.exc_value:
3577 self.exc_value.annotate(code)
3578 if self.exc_tb:
3579 self.exc_tb.annotate(code)
3582 class ReraiseStatNode(StatNode):
3584 child_attrs = []
3586 def analyse_expressions(self, env):
3587 env.use_utility_code(restore_exception_utility_code)
3589 nogil_check = Node.gil_error
3590 gil_message = "Raising exception"
3592 def generate_execution_code(self, code):
3593 vars = code.funcstate.exc_vars
3594 if vars:
3595 for varname in vars:
3596 code.put_giveref(varname)
3597 code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars))
3598 for varname in vars:
3599 code.put("%s = 0; " % varname)
3600 code.putln()
3601 code.putln(code.error_goto(self.pos))
3602 else:
3603 error(self.pos, "Reraise not inside except clause")
3606 class AssertStatNode(StatNode):
3607 # assert statement
3608 #
3609 # cond ExprNode
3610 # value ExprNode or None
3612 child_attrs = ["cond", "value"]
3614 def analyse_expressions(self, env):
3615 self.cond = self.cond.analyse_boolean_expression(env)
3616 if self.value:
3617 self.value.analyse_types(env)
3618 self.value = self.value.coerce_to_pyobject(env)
3620 nogil_check = Node.gil_error
3621 gil_message = "Raising exception"
3623 def generate_execution_code(self, code):
3624 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3625 self.cond.generate_evaluation_code(code)
3626 code.putln(
3627 "if (unlikely(!%s)) {" %
3628 self.cond.result())
3629 if self.value:
3630 self.value.generate_evaluation_code(code)
3631 code.putln(
3632 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3633 self.value.py_result())
3634 self.value.generate_disposal_code(code)
3635 self.value.free_temps(code)
3636 else:
3637 code.putln(
3638 "PyErr_SetNone(PyExc_AssertionError);")
3639 code.putln(
3640 code.error_goto(self.pos))
3641 code.putln(
3642 "}")
3643 self.cond.generate_disposal_code(code)
3644 self.cond.free_temps(code)
3645 code.putln("#endif")
3647 def annotate(self, code):
3648 self.cond.annotate(code)
3649 if self.value:
3650 self.value.annotate(code)
3653 class IfStatNode(StatNode):
3654 # if statement
3655 #
3656 # if_clauses [IfClauseNode]
3657 # else_clause StatNode or None
3659 child_attrs = ["if_clauses", "else_clause"]
3661 def analyse_control_flow(self, env):
3662 env.start_branching(self.pos)
3663 for if_clause in self.if_clauses:
3664 if_clause.analyse_control_flow(env)
3665 env.next_branch(if_clause.end_pos())
3666 if self.else_clause:
3667 self.else_clause.analyse_control_flow(env)
3668 env.finish_branching(self.end_pos())
3670 def analyse_declarations(self, env):
3671 for if_clause in self.if_clauses:
3672 if_clause.analyse_declarations(env)
3673 if self.else_clause:
3674 self.else_clause.analyse_declarations(env)
3676 def analyse_expressions(self, env):
3677 for if_clause in self.if_clauses:
3678 if_clause.analyse_expressions(env)
3679 if self.else_clause:
3680 self.else_clause.analyse_expressions(env)
3682 def generate_execution_code(self, code):
3683 code.mark_pos(self.pos)
3684 end_label = code.new_label()
3685 for if_clause in self.if_clauses:
3686 if_clause.generate_execution_code(code, end_label)
3687 if self.else_clause:
3688 code.putln("/*else*/ {")
3689 self.else_clause.generate_execution_code(code)
3690 code.putln("}")
3691 code.put_label(end_label)
3693 def annotate(self, code):
3694 for if_clause in self.if_clauses:
3695 if_clause.annotate(code)
3696 if self.else_clause:
3697 self.else_clause.annotate(code)
3700 class IfClauseNode(Node):
3701 # if or elif clause in an if statement
3702 #
3703 # condition ExprNode
3704 # body StatNode
3706 child_attrs = ["condition", "body"]
3708 def analyse_control_flow(self, env):
3709 self.body.analyse_control_flow(env)
3711 def analyse_declarations(self, env):
3712 self.condition.analyse_declarations(env)
3713 self.body.analyse_declarations(env)
3715 def analyse_expressions(self, env):
3716 self.condition = \
3717 self.condition.analyse_temp_boolean_expression(env)
3718 self.body.analyse_expressions(env)
3720 def generate_execution_code(self, code, end_label):
3721 self.condition.generate_evaluation_code(code)
3722 code.putln(
3723 "if (%s) {" %
3724 self.condition.result())
3725 self.condition.generate_disposal_code(code)
3726 self.condition.free_temps(code)
3727 self.body.generate_execution_code(code)
3728 #code.putln(
3729 # "goto %s;" %
3730 # end_label)
3731 code.put_goto(end_label)
3732 code.putln("}")
3734 def annotate(self, code):
3735 self.condition.annotate(code)
3736 self.body.annotate(code)
3739 class SwitchCaseNode(StatNode):
3740 # Generated in the optimization of an if-elif-else node
3741 #
3742 # conditions [ExprNode]
3743 # body StatNode
3745 child_attrs = ['conditions', 'body']
3747 def generate_execution_code(self, code):
3748 for cond in self.conditions:
3749 code.mark_pos(cond.pos)
3750 cond.generate_evaluation_code(code)
3751 code.putln("case %s:" % cond.result())
3752 self.body.generate_execution_code(code)
3753 code.putln("break;")
3755 def annotate(self, code):
3756 for cond in self.conditions:
3757 cond.annotate(code)
3758 self.body.annotate(code)
3760 class SwitchStatNode(StatNode):
3761 # Generated in the optimization of an if-elif-else node
3762 #
3763 # test ExprNode
3764 # cases [SwitchCaseNode]
3765 # else_clause StatNode or None
3767 child_attrs = ['test', 'cases', 'else_clause']
3769 def generate_execution_code(self, code):
3770 code.putln("switch (%s) {" % self.test.result())
3771 for case in self.cases:
3772 case.generate_execution_code(code)
3773 if self.else_clause is not None:
3774 code.putln("default:")
3775 self.else_clause.generate_execution_code(code)
3776 code.putln("break;")
3777 code.putln("}")
3779 def annotate(self, code):
3780 self.test.annotate(code)
3781 for case in self.cases:
3782 case.annotate(code)
3783 if self.else_clause is not None:
3784 self.else_clause.annotate(code)
3786 class LoopNode(object):
3788 def analyse_control_flow(self, env):
3789 env.start_branching(self.pos)
3790 self.body.analyse_control_flow(env)
3791 env.next_branch(self.body.end_pos())
3792 if self.else_clause:
3793 self.else_clause.analyse_control_flow(env)
3794 env.finish_branching(self.end_pos())
3797 class WhileStatNode(LoopNode, StatNode):
3798 # while statement
3799 #
3800 # condition ExprNode
3801 # body StatNode
3802 # else_clause StatNode
3804 child_attrs = ["condition", "body", "else_clause"]
3806 def analyse_declarations(self, env):
3807 self.body.analyse_declarations(env)
3808 if self.else_clause:
3809 self.else_clause.analyse_declarations(env)
3811 def analyse_expressions(self, env):
3812 self.condition = \
3813 self.condition.analyse_temp_boolean_expression(env)
3814 self.body.analyse_expressions(env)
3815 if self.else_clause:
3816 self.else_clause.analyse_expressions(env)
3818 def generate_execution_code(self, code):
3819 old_loop_labels = code.new_loop_labels()
3820 code.putln(
3821 "while (1) {")
3822 self.condition.generate_evaluation_code(code)
3823 self.condition.generate_disposal_code(code)
3824 code.putln(
3825 "if (!%s) break;" %
3826 self.condition.result())
3827 self.condition.free_temps(code)
3828 self.body.generate_execution_code(code)
3829 code.put_label(code.continue_label)
3830 code.putln("}")
3831 break_label = code.break_label
3832 code.set_loop_labels(old_loop_labels)
3833 if self.else_clause:
3834 code.putln("/*else*/ {")
3835 self.else_clause.generate_execution_code(code)
3836 code.putln("}")
3837 code.put_label(break_label)
3839 def annotate(self, code):
3840 self.condition.annotate(code)
3841 self.body.annotate(code)
3842 if self.else_clause:
3843 self.else_clause.annotate(code)
3846 def ForStatNode(pos, **kw):
3847 if 'iterator' in kw:
3848 return ForInStatNode(pos, **kw)
3849 else:
3850 return ForFromStatNode(pos, **kw)
3852 class ForInStatNode(LoopNode, StatNode):
3853 # for statement
3854 #
3855 # target ExprNode
3856 # iterator IteratorNode
3857 # body StatNode
3858 # else_clause StatNode
3859 # item NextNode used internally
3861 child_attrs = ["target", "iterator", "body", "else_clause"]
3862 item = None
3864 def analyse_declarations(self, env):
3865 self.target.analyse_target_declaration(env)
3866 self.body.analyse_declarations(env)
3867 if self.else_clause:
3868 self.else_clause.analyse_declarations(env)
3870 def analyse_expressions(self, env):
3871 import ExprNodes
3872 self.target.analyse_target_types(env)
3873 self.iterator.analyse_expressions(env)
3874 self.item = ExprNodes.NextNode(self.iterator, env)
3875 self.item = self.item.coerce_to(self.target.type, env)
3876 self.body.analyse_expressions(env)
3877 if self.else_clause:
3878 self.else_clause.analyse_expressions(env)
3880 def generate_execution_code(self, code):
3881 old_loop_labels = code.new_loop_labels()
3882 self.iterator.allocate_counter_temp(code)
3883 self.iterator.generate_evaluation_code(code)
3884 code.putln(
3885 "for (;;) {")
3886 self.item.generate_evaluation_code(code)
3887 self.target.generate_assignment_code(self.item, code)
3888 self.body.generate_execution_code(code)
3889 code.put_label(code.continue_label)
3890 code.putln(
3891 "}")
3892 break_label = code.break_label
3893 code.set_loop_labels(old_loop_labels)
3894 if self.else_clause:
3895 code.putln("/*else*/ {")
3896 self.else_clause.generate_execution_code(code)
3897 code.putln("}")
3898 code.put_label(break_label)
3899 self.iterator.release_counter_temp(code)
3900 self.iterator.generate_disposal_code(code)
3901 self.iterator.free_temps(code)
3903 def annotate(self, code):
3904 self.target.annotate(code)
3905 self.iterator.annotate(code)
3906 self.body.annotate(code)
3907 if self.else_clause:
3908 self.else_clause.annotate(code)
3909 self.item.annotate(code)
3912 class ForFromStatNode(LoopNode, StatNode):
3913 # for name from expr rel name rel expr
3914 #
3915 # target NameNode
3916 # bound1 ExprNode
3917 # relation1 string
3918 # relation2 string
3919 # bound2 ExprNode
3920 # step ExprNode or None
3921 # body StatNode
3922 # else_clause StatNode or None
3923 #
3924 # Used internally:
3925 #
3926 # from_range bool
3927 # is_py_target bool
3928 # loopvar_node ExprNode (usually a NameNode or temp node)
3929 # py_loopvar_node PyTempNode or None
3930 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3932 is_py_target = False
3933 loopvar_node = None
3934 py_loopvar_node = None
3935 from_range = False
3937 gil_message = "For-loop using object bounds or target"
3939 def nogil_check(self, env):
3940 for x in (self.target, self.bound1, self.bound2):
3941 if x.type.is_pyobject:
3942 self.gil_error()
3944 def analyse_declarations(self, env):
3945 self.target.analyse_target_declaration(env)
3946 self.body.analyse_declarations(env)
3947 if self.else_clause:
3948 self.else_clause.analyse_declarations(env)
3950 def analyse_expressions(self, env):
3951 import ExprNodes
3952 self.target.analyse_target_types(env)
3953 self.bound1.analyse_types(env)
3954 self.bound2.analyse_types(env)
3955 if self.step is not None:
3956 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3957 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3958 self.step.analyse_types(env)
3960 target_type = self.target.type
3961 if self.target.type.is_numeric:
3962 loop_type = self.target.type
3963 else:
3964 loop_type = PyrexTypes.c_int_type
3965 if not self.bound1.type.is_pyobject:
3966 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
3967 if not self.bound2.type.is_pyobject:
3968 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
3969 if self.step is not None and not self.step.type.is_pyobject:
3970 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
3971 self.bound1 = self.bound1.coerce_to(loop_type, env)
3972 self.bound2 = self.bound2.coerce_to(loop_type, env)
3973 if not self.bound2.is_literal:
3974 self.bound2 = self.bound2.coerce_to_temp(env)
3975 if self.step is not None:
3976 self.step = self.step.coerce_to(loop_type, env)
3977 if not self.step.is_literal:
3978 self.step = self.step.coerce_to_temp(env)
3980 target_type = self.target.type
3981 if not (target_type.is_pyobject or target_type.is_numeric):
3982 error(self.target.pos,
3983 "for-from loop variable must be c numeric type or Python object")
3984 if target_type.is_numeric:
3985 self.is_py_target = False
3986 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3987 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3988 self.loopvar_node = self.target
3989 self.py_loopvar_node = None
3990 else:
3991 self.is_py_target = True
3992 c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
3993 self.loopvar_node = c_loopvar_node
3994 self.py_loopvar_node = \
3995 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3996 self.body.analyse_expressions(env)
3997 if self.else_clause:
3998 self.else_clause.analyse_expressions(env)
4000 def generate_execution_code(self, code):
4001 old_loop_labels = code.new_loop_labels()
4002 from_range = self.from_range
4003 self.bound1.generate_evaluation_code(code)
4004 self.bound2.generate_evaluation_code(code)
4005 offset, incop = self.relation_table[self.relation1]
4006 if self.step is not None:
4007 self.step.generate_evaluation_code(code)
4008 step = self.step.result()
4009 incop = "%s=%s" % (incop[0], step)
4010 import ExprNodes
4011 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4012 self.loopvar_node.allocate(code)
4013 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4014 self.py_loopvar_node.allocate(code)
4015 if from_range:
4016 loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
4017 else:
4018 loopvar_name = self.loopvar_node.result()
4019 code.putln(
4020 "for (%s = %s%s; %s %s %s; %s%s) {" % (
4021 loopvar_name,
4022 self.bound1.result(), offset,
4023 loopvar_name, self.relation2, self.bound2.result(),
4024 loopvar_name, incop))
4025 if self.py_loopvar_node:
4026 self.py_loopvar_node.generate_evaluation_code(code)
4027 self.target.generate_assignment_code(self.py_loopvar_node, code)
4028 elif from_range:
4029 code.putln("%s = %s;" % (
4030 self.target.result(), loopvar_name))
4031 self.body.generate_execution_code(code)
4032 code.put_label(code.continue_label)
4033 if self.py_loopvar_node:
4034 # This mess is to make for..from loops with python targets behave
4035 # exactly like those with C targets with regards to re-assignment
4036 # of the loop variable.
4037 import ExprNodes
4038 if self.target.entry.is_pyglobal:
4039 # We know target is a NameNode, this is the only ugly case.
4040 target_node = ExprNodes.PyTempNode(self.target.pos, None)
4041 target_node.allocate(code)
4042 interned_cname = code.intern_identifier(self.target.entry.name)
4043 code.putln("/*here*/")
4044 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
4045 target_node.result(),
4046 Naming.module_cname,
4047 interned_cname,
4048 code.error_goto_if_null(target_node.result(), self.target.pos)))
4049 code.put_gotref(target_node.result())
4050 else:
4051 target_node = self.target
4052 from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
4053 from_py_node.temp_code = loopvar_name
4054 from_py_node.generate_result_code(code)
4055 if self.target.entry.is_pyglobal:
4056 code.put_decref(target_node.result(), target_node.type)
4057 target_node.release(code)
4058 code.putln("}")
4059 if self.py_loopvar_node:
4060 # This is potentially wasteful, but we don't want the semantics to
4061 # depend on whether or not the loop is a python type.
4062 self.py_loopvar_node.generate_evaluation_code(code)
4063 self.target.generate_assignment_code(self.py_loopvar_node, code)
4064 if from_range:
4065 code.funcstate.release_temp(loopvar_name)
4066 break_label = code.break_label
4067 code.set_loop_labels(old_loop_labels)
4068 if self.else_clause:
4069 code.putln("/*else*/ {")
4070 self.else_clause.generate_execution_code(code)
4071 code.putln("}")
4072 code.put_label(break_label)
4073 self.bound1.generate_disposal_code(code)
4074 self.bound1.free_temps(code)
4075 self.bound2.generate_disposal_code(code)
4076 self.bound2.free_temps(code)
4077 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4078 self.loopvar_node.release(code)
4079 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4080 self.py_loopvar_node.release(code)
4081 if self.step is not None:
4082 self.step.generate_disposal_code(code)
4083 self.step.free_temps(code)
4085 relation_table = {
4086 # {relop : (initial offset, increment op)}
4087 '<=': ("", "++"),
4088 '<' : ("+1", "++"),
4089 '>=': ("", "--"),
4090 '>' : ("-1", "--")
4091 }
4093 def annotate(self, code):
4094 self.target.annotate(code)
4095 self.bound1.annotate(code)
4096 self.bound2.annotate(code)
4097 if self.step:
4098 self.bound2.annotate(code)
4099 self.body.annotate(code)
4100 if self.else_clause:
4101 self.else_clause.annotate(code)
4104 class WithStatNode(StatNode):
4105 """
4106 Represents a Python with statement.
4108 This is only used at parse tree level; and is not present in
4109 analysis or generation phases.
4110 """
4111 # manager The with statement manager object
4112 # target Node (lhs expression)
4113 # body StatNode
4114 child_attrs = ["manager", "target", "body"]
4116 class TryExceptStatNode(StatNode):
4117 # try .. except statement
4118 #
4119 # body StatNode
4120 # except_clauses [ExceptClauseNode]
4121 # else_clause StatNode or None
4123 child_attrs = ["body", "except_clauses", "else_clause"]
4125 def analyse_control_flow(self, env):
4126 env.start_branching(self.pos)
4127 self.body.analyse_control_flow(env)
4128 successful_try = env.control_flow # grab this for later
4129 env.next_branch(self.body.end_pos())
4130 env.finish_branching(self.body.end_pos())
4132 env.start_branching(self.except_clauses[0].pos)
4133 for except_clause in self.except_clauses:
4134 except_clause.analyse_control_flow(env)
4135 env.next_branch(except_clause.end_pos())
4137 # the else cause it executed only when the try clause finishes
4138 env.control_flow.incoming = successful_try
4139 if self.else_clause:
4140 self.else_clause.analyse_control_flow(env)
4141 env.finish_branching(self.end_pos())
4143 def analyse_declarations(self, env):
4144 self.body.analyse_declarations(env)
4145 for except_clause in self.except_clauses:
4146 except_clause.analyse_declarations(env)
4147 if self.else_clause:
4148 self.else_clause.analyse_declarations(env)
4149 env.use_utility_code(reset_exception_utility_code)
4151 def analyse_expressions(self, env):
4152 self.body.analyse_expressions(env)
4153 default_clause_seen = 0
4154 for except_clause in self.except_clauses:
4155 except_clause.analyse_expressions(env)
4156 if default_clause_seen:
4157 error(except_clause.pos, "default 'except:' must be last")
4158 if not except_clause.pattern:
4159 default_clause_seen = 1
4160 self.has_default_clause = default_clause_seen
4161 if self.else_clause:
4162 self.else_clause.analyse_expressions(env)
4164 nogil_check = Node.gil_error
4165 gil_message = "Try-except statement"
4167 def generate_execution_code(self, code):
4168 old_return_label = code.return_label
4169 old_break_label = code.break_label
4170 old_continue_label = code.continue_label
4171 old_error_label = code.new_error_label()
4172 our_error_label = code.error_label
4173 except_end_label = code.new_label('exception_handled')
4174 except_error_label = code.new_label('except_error')
4175 except_return_label = code.new_label('except_return')
4176 try_return_label = code.new_label('try_return')
4177 try_break_label = code.new_label('try_break')
4178 try_continue_label = code.new_label('try_continue')
4179 try_end_label = code.new_label('try_end')
4181 code.putln("{")
4182 code.putln("PyObject %s;" %
4183 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4184 code.putln("__Pyx_ExceptionSave(%s);" %
4185 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4186 for var in Naming.exc_save_vars:
4187 code.put_xgotref(var)
4188 code.putln(
4189 "/*try:*/ {")
4190 code.return_label = try_return_label
4191 code.break_label = try_break_label
4192 code.continue_label = try_continue_label
4193 self.body.generate_execution_code(code)
4194 code.putln(
4195 "}")
4196 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4197 code.error_label = except_error_label
4198 code.return_label = except_return_label
4199 if self.else_clause:
4200 code.putln(
4201 "/*else:*/ {")
4202 self.else_clause.generate_execution_code(code)
4203 code.putln(
4204 "}")
4205 for var in Naming.exc_save_vars:
4206 code.put_xdecref_clear(var, py_object_type)
4207 code.put_goto(try_end_label)
4208 if code.label_used(try_return_label):
4209 code.put_label(try_return_label)
4210 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4211 code.putln("__Pyx_ExceptionReset(%s);" %
4212 ', '.join(Naming.exc_save_vars))
4213 code.put_goto(old_return_label)
4214 code.put_label(our_error_label)
4215 for temp_name, type in temps_to_clean_up:
4216 code.put_xdecref_clear(temp_name, type)
4217 for except_clause in self.except_clauses:
4218 except_clause.generate_handling_code(code, except_end_label)
4220 error_label_used = code.label_used(except_error_label)
4221 if error_label_used or not self.has_default_clause:
4222 if error_label_used:
4223 code.put_label(except_error_label)
4224 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4225 code.putln("__Pyx_ExceptionReset(%s);" %
4226 ', '.join(Naming.exc_save_vars))
4227 code.put_goto(old_error_label)
4229 for exit_label, old_label in zip(
4230 [try_break_label, try_continue_label, except_return_label],
4231 [old_break_label, old_continue_label, old_return_label]):
4233 if code.label_used(exit_label):
4234 code.put_label(exit_label)
4235 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4236 code.putln("__Pyx_ExceptionReset(%s);" %
4237 ', '.join(Naming.exc_save_vars))
4238 code.put_goto(old_label)
4240 if code.label_used(except_end_label):
4241 code.put_label(except_end_label)
4242 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4243 code.putln("__Pyx_ExceptionReset(%s);" %
4244 ', '.join(Naming.exc_save_vars))
4245 code.put_label(try_end_label)
4246 code.putln("}")
4248 code.return_label = old_return_label
4249 code.break_label = old_break_label
4250 code.continue_label = old_continue_label
4251 code.error_label = old_error_label
4253 def annotate(self, code):
4254 self.body.annotate(code)
4255 for except_node in self.except_clauses:
4256 except_node.annotate(code)
4257 if self.else_clause:
4258 self.else_clause.annotate(code)
4261 class ExceptClauseNode(Node):
4262 # Part of try ... except statement.
4263 #
4264 # pattern ExprNode
4265 # target ExprNode or None
4266 # body StatNode
4267 # excinfo_target NameNode or None optional target for exception info
4268 # match_flag string result of exception match
4269 # exc_value ExcValueNode used internally
4270 # function_name string qualified name of enclosing function
4271 # exc_vars (string * 3) local exception variables
4273 # excinfo_target is never set by the parser, but can be set by a transform
4274 # in order to extract more extensive information about the exception as a
4275 # sys.exc_info()-style tuple into a target variable
4277 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4279 exc_value = None
4280 excinfo_target = None
4282 def analyse_declarations(self, env):
4283 if self.target:
4284 self.target.analyse_target_declaration(env)
4285 if self.excinfo_target is not None:
4286 self.excinfo_target.analyse_target_declaration(env)
4287 self.body.analyse_declarations(env)
4289 def analyse_expressions(self, env):
4290 import ExprNodes
4291 genv = env.global_scope()
4292 self.function_name = env.qualified_name
4293 if self.pattern:
4294 self.pattern.analyse_expressions(env)
4295 self.pattern = self.pattern.coerce_to_pyobject(env)
4297 if self.target:
4298 self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
4299 self.target.analyse_target_expression(env, self.exc_value)
4300 if self.excinfo_target is not None:
4301 import ExprNodes
4302 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4303 ExprNodes.ExcValueNode(pos=self.pos, env=env) for x in range(3)])
4304 self.excinfo_tuple.analyse_expressions(env)
4305 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4307 self.body.analyse_expressions(env)
4309 def generate_handling_code(self, code, end_label):
4310 code.mark_pos(self.pos)
4311 if self.pattern:
4312 self.pattern.generate_evaluation_code(code)
4314 match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
4315 code.putln(
4316 "%s = PyErr_ExceptionMatches(%s);" % (
4317 match_flag,
4318 self.pattern.py_result()))
4319 self.pattern.generate_disposal_code(code)
4320 self.pattern.free_temps(code)
4321 code.putln(
4322 "if (%s) {" %
4323 match_flag)
4324 code.funcstate.release_temp(match_flag)
4325 else:
4326 code.putln("/*except:*/ {")
4328 if not getattr(self.body, 'stats', True):
4329 # most simple case: no exception variable, empty body (pass)
4330 # => reset the exception state, done
4331 code.putln("PyErr_Restore(0,0,0);")
4332 code.put_goto(end_label)
4333 code.putln("}")
4334 return
4336 exc_vars = [code.funcstate.allocate_temp(py_object_type,
4337 manage_ref=True)
4338 for i in xrange(3)]
4339 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4340 # We always have to fetch the exception value even if
4341 # there is no target, because this also normalises the
4342 # exception and stores it in the thread state.
4343 code.globalstate.use_utility_code(get_exception_utility_code)
4344 exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4345 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4346 code.error_goto(self.pos)))
4347 for x in exc_vars:
4348 code.put_gotref(x)
4349 if self.target:
4350 self.exc_value.set_var(exc_vars[1])
4351 self.exc_value.generate_evaluation_code(code)
4352 self.target.generate_assignment_code(self.exc_value, code)
4353 if self.excinfo_target is not None:
4354 for tempvar, node in zip(exc_vars, self.excinfo_tuple.args):
4355 node.set_var(tempvar)
4356 self.excinfo_tuple.generate_evaluation_code(code)
4357 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4359 old_break_label, old_continue_label = code.break_label, code.continue_label
4360 code.break_label = code.new_label('except_break')
4361 code.continue_label = code.new_label('except_continue')
4363 old_exc_vars = code.funcstate.exc_vars
4364 code.funcstate.exc_vars = exc_vars
4365 self.body.generate_execution_code(code)
4366 code.funcstate.exc_vars = old_exc_vars
4367 for var in exc_vars:
4368 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4369 code.put_goto(end_label)
4371 if code.label_used(code.break_label):
4372 code.put_label(code.break_label)
4373 for var in exc_vars:
4374 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4375 code.put_goto(old_break_label)
4376 code.break_label = old_break_label
4378 if code.label_used(code.continue_label):
4379 code.put_label(code.continue_label)
4380 for var in exc_vars:
4381 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4382 code.put_goto(old_continue_label)
4383 code.continue_label = old_continue_label
4385 for temp in exc_vars:
4386 code.funcstate.release_temp(temp)
4388 code.putln(
4389 "}")
4391 def annotate(self, code):
4392 if self.pattern:
4393 self.pattern.annotate(code)
4394 if self.target:
4395 self.target.annotate(code)
4396 self.body.annotate(code)
4399 class TryFinallyStatNode(StatNode):
4400 # try ... finally statement
4401 #
4402 # body StatNode
4403 # finally_clause StatNode
4404 #
4405 # The plan is that we funnel all continue, break
4406 # return and error gotos into the beginning of the
4407 # finally block, setting a variable to remember which
4408 # one we're doing. At the end of the finally block, we
4409 # switch on the variable to figure out where to go.
4410 # In addition, if we're doing an error, we save the
4411 # exception on entry to the finally block and restore
4412 # it on exit.
4414 child_attrs = ["body", "finally_clause"]
4416 preserve_exception = 1
4418 disallow_continue_in_try_finally = 0
4419 # There doesn't seem to be any point in disallowing
4420 # continue in the try block, since we have no problem
4421 # handling it.
4423 def create_analysed(pos, env, body, finally_clause):
4424 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4425 return node
4426 create_analysed = staticmethod(create_analysed)
4428 def analyse_control_flow(self, env):
4429 env.start_branching(self.pos)
4430 self.body.analyse_control_flow(env)
4431 env.next_branch(self.body.end_pos())
4432 env.finish_branching(self.body.end_pos())
4433 self.finally_clause.analyse_control_flow(env)
4435 def analyse_declarations(self, env):
4436 self.body.analyse_declarations(env)
4437 self.finally_clause.analyse_declarations(env)
4439 def analyse_expressions(self, env):
4440 self.body.analyse_expressions(env)
4441 self.finally_clause.analyse_expressions(env)
4443 nogil_check = Node.gil_error
4444 gil_message = "Try-finally statement"
4446 def generate_execution_code(self, code):
4447 old_error_label = code.error_label
4448 old_labels = code.all_new_labels()
4449 new_labels = code.get_all_labels()
4450 new_error_label = code.error_label
4451 catch_label = code.new_label()
4452 code.putln(
4453 "/*try:*/ {")
4454 if self.disallow_continue_in_try_finally:
4455 was_in_try_finally = code.funcstate.in_try_finally
4456 code.funcstate.in_try_finally = 1
4457 self.body.generate_execution_code(code)
4458 if self.disallow_continue_in_try_finally:
4459 code.funcstate.in_try_finally = was_in_try_finally
4460 code.putln(
4461 "}")
4462 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4463 code.putln(
4464 "/*finally:*/ {")
4465 cases_used = []
4466 error_label_used = 0
4467 for i, new_label in enumerate(new_labels):
4468 if new_label in code.labels_used:
4469 cases_used.append(i)
4470 if new_label == new_error_label:
4471 error_label_used = 1
4472 error_label_case = i
4473 if cases_used:
4474 code.putln(
4475 "int __pyx_why;")
4476 if error_label_used and self.preserve_exception:
4477 code.putln(
4478 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4479 code.putln(
4480 "int %s;" % Naming.exc_lineno_name)
4481 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4482 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4483 code.putln(exc_var_init_zero)
4484 else:
4485 exc_var_init_zero = None
4486 code.use_label(catch_label)
4487 code.putln(
4488 "__pyx_why = 0; goto %s;" % catch_label)
4489 for i in cases_used:
4490 new_label = new_labels[i]
4491 #if new_label and new_label != "<try>":
4492 if new_label == new_error_label and self.preserve_exception:
4493 self.put_error_catcher(code,
4494 new_error_label, i+1, catch_label, temps_to_clean_up)
4495 else:
4496 code.put('%s: ' % new_label)
4497 if exc_var_init_zero:
4498 code.putln(exc_var_init_zero)
4499 code.putln("__pyx_why = %s; goto %s;" % (
4500 i+1,
4501 catch_label))
4502 code.put_label(catch_label)
4503 code.set_all_labels(old_labels)
4504 if error_label_used:
4505 code.new_error_label()
4506 finally_error_label = code.error_label
4507 self.finally_clause.generate_execution_code(code)
4508 if error_label_used:
4509 if finally_error_label in code.labels_used and self.preserve_exception:
4510 over_label = code.new_label()
4511 code.put_goto(over_label);
4512 code.put_label(finally_error_label)
4513 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4514 for var in Naming.exc_vars:
4515 code.putln("Py_XDECREF(%s);" % var)
4516 code.putln("}")
4517 code.put_goto(old_error_label)
4518 code.put_label(over_label)
4519 code.error_label = old_error_label
4520 if cases_used:
4521 code.putln(
4522 "switch (__pyx_why) {")
4523 for i in cases_used:
4524 old_label = old_labels[i]
4525 if old_label == old_error_label and self.preserve_exception:
4526 self.put_error_uncatcher(code, i+1, old_error_label)
4527 else:
4528 code.use_label(old_label)
4529 code.putln(
4530 "case %s: goto %s;" % (
4531 i+1,
4532 old_label))
4533 code.putln(
4534 "}")
4535 code.putln(
4536 "}")
4538 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4539 code.globalstate.use_utility_code(restore_exception_utility_code)
4540 code.putln(
4541 "%s: {" %
4542 error_label)
4543 code.putln(
4544 "__pyx_why = %s;" %
4545 i)
4546 for temp_name, type in temps_to_clean_up:
4547 code.put_xdecref_clear(temp_name, type)
4548 code.putln(
4549 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4550 Naming.exc_vars)
4551 code.putln(
4552 "%s = %s;" % (
4553 Naming.exc_lineno_name, Naming.lineno_cname))
4554 #code.putln(
4555 # "goto %s;" %
4556 # catch_label)
4557 code.put_goto(catch_label)
4558 code.putln(
4559 "}")
4561 def put_error_uncatcher(self, code, i, error_label):
4562 code.globalstate.use_utility_code(restore_exception_utility_code)
4563 code.putln(
4564 "case %s: {" %
4565 i)
4566 code.putln(
4567 "__Pyx_ErrRestore(%s, %s, %s);" %
4568 Naming.exc_vars)
4569 code.putln(
4570 "%s = %s;" % (
4571 Naming.lineno_cname, Naming.exc_lineno_name))
4572 for var in Naming.exc_vars:
4573 code.putln(
4574 "%s = 0;" %
4575 var)
4576 code.put_goto(error_label)
4577 code.putln(
4578 "}")
4580 def annotate(self, code):
4581 self.body.annotate(code)
4582 self.finally_clause.annotate(code)
4585 class GILStatNode(TryFinallyStatNode):
4586 # 'with gil' or 'with nogil' statement
4587 #
4588 # state string 'gil' or 'nogil'
4590 # child_attrs = []
4592 preserve_exception = 0
4594 def __init__(self, pos, state, body):
4595 self.state = state
4596 TryFinallyStatNode.__init__(self, pos,
4597 body = body,
4598 finally_clause = GILExitNode(pos, state = state))
4600 def analyse_expressions(self, env):
4601 env.use_utility_code(force_init_threads_utility_code)
4602 was_nogil = env.nogil
4603 env.nogil = 1
4604 TryFinallyStatNode.analyse_expressions(self, env)
4605 env.nogil = was_nogil
4607 nogil_check = None
4609 def generate_execution_code(self, code):
4610 code.mark_pos(self.pos)
4611 if self.state == 'gil':
4612 code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4613 else:
4614 code.putln("{ PyThreadState *_save;")
4615 code.putln("Py_UNBLOCK_THREADS")
4616 TryFinallyStatNode.generate_execution_code(self, code)
4617 code.putln("}")
4620 class GILExitNode(StatNode):
4621 # Used as the 'finally' block in a GILStatNode
4622 #
4623 # state string 'gil' or 'nogil'
4625 child_attrs = []
4627 def analyse_expressions(self, env):
4628 pass
4630 def generate_execution_code(self, code):
4631 if self.state == 'gil':
4632 code.putln("PyGILState_Release();")
4633 else:
4634 code.putln("Py_BLOCK_THREADS")
4637 class CImportStatNode(StatNode):
4638 # cimport statement
4639 #
4640 # module_name string Qualified name of module being imported
4641 # as_name string or None Name specified in "as" clause, if any
4643 child_attrs = []
4645 def analyse_declarations(self, env):
4646 if not env.is_module_scope:
4647 error(self.pos, "cimport only allowed at module level")
4648 return
4649 module_scope = env.find_module(self.module_name, self.pos)
4650 if "." in self.module_name:
4651 names = [EncodedString(name) for name in self.module_name.split(".")]
4652 top_name = names[0]
4653 top_module_scope = env.context.find_submodule(top_name)
4654 module_scope = top_module_scope
4655 for name in names[1:]:
4656 submodule_scope = module_scope.find_submodule(name)
4657 module_scope.declare_module(name, submodule_scope, self.pos)
4658 module_scope = submodule_scope
4659 if self.as_name:
4660 env.declare_module(self.as_name, module_scope, self.pos)
4661 else:
4662 env.declare_module(top_name, top_module_scope, self.pos)
4663 else:
4664 name = self.as_name or self.module_name
4665 env.declare_module(name, module_scope, self.pos)
4667 def analyse_expressions(self, env):
4668 pass
4670 def generate_execution_code(self, code):
4671 pass
4674 class FromCImportStatNode(StatNode):
4675 # from ... cimport statement
4676 #
4677 # module_name string Qualified name of module
4678 # imported_names [(pos, name, as_name, kind)] Names to be imported
4680 child_attrs = []
4682 def analyse_declarations(self, env):
4683 if not env.is_module_scope:
4684 error(self.pos, "cimport only allowed at module level")
4685 return
4686 module_scope = env.find_module(self.module_name, self.pos)
4687 env.add_imported_module(module_scope)
4688 for pos, name, as_name, kind in self.imported_names:
4689 if name == "*":
4690 for local_name, entry in module_scope.entries.items():
4691 env.add_imported_entry(local_name, entry, pos)
4692 else:
4693 entry = module_scope.lookup(name)
4694 if entry:
4695 if kind and not self.declaration_matches(entry, kind):
4696 entry.redeclared(pos)
4697 else:
4698 if kind == 'struct' or kind == 'union':
4699 entry = module_scope.declare_struct_or_union(name,
4700 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4701 elif kind == 'class':
4702 entry = module_scope.declare_c_class(name, pos = pos,
4703 module_name = self.module_name)
4704 else:
4705 submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
4706 if submodule_scope.parent_module is module_scope:
4707 env.declare_module(as_name or name, submodule_scope, self.pos)
4708 else:
4709 error(pos, "Name '%s' not declared in module '%s'"
4710 % (name, self.module_name))
4712 if entry:
4713 local_name = as_name or name
4714 env.add_imported_entry(local_name, entry, pos)
4716 def declaration_matches(self, entry, kind):
4717 if not entry.is_type:
4718 return 0
4719 type = entry.type
4720 if kind == 'class':
4721 if not type.is_extension_type:
4722 return 0
4723 else:
4724 if not type.is_struct_or_union:
4725 return 0
4726 if kind != type.kind:
4727 return 0
4728 return 1
4730 def analyse_expressions(self, env):
4731 pass
4733 def generate_execution_code(self, code):
4734 pass
4737 class FromImportStatNode(StatNode):
4738 # from ... import statement
4739 #
4740 # module ImportNode
4741 # items [(string, NameNode)]
4742 # interned_items [(string, NameNode, ExprNode)]
4743 # item PyTempNode used internally
4744 # import_star boolean used internally
4746 child_attrs = ["module"]
4747 import_star = 0
4749 def analyse_declarations(self, env):
4750 for name, target in self.items:
4751 if name == "*":
4752 if not env.is_module_scope:
4753 error(self.pos, "import * only allowed at module level")
4754 return
4755 env.has_import_star = 1
4756 self.import_star = 1
4757 else:
4758 target.analyse_target_declaration(env)
4760 def analyse_expressions(self, env):
4761 import ExprNodes
4762 self.module.analyse_expressions(env)
4763 self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
4764 self.interned_items = []
4765 for name, target in self.items:
4766 if name == '*':
4767 for _, entry in env.entries.items():
4768 if not entry.is_type and entry.type.is_extension_type:
4769 env.use_utility_code(ExprNodes.type_test_utility_code)
4770 break
4771 else:
4772 entry = env.lookup(target.name)
4773 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4774 continue # already cimported
4775 target.analyse_target_expression(env, None)
4776 if target.type is py_object_type:
4777 coerced_item = None
4778 else:
4779 coerced_item = self.item.coerce_to(target.type, env)
4780 self.interned_items.append(
4781 (name, target, coerced_item))
4783 def generate_execution_code(self, code):
4784 self.module.generate_evaluation_code(code)
4785 if self.import_star:
4786 code.putln(
4787 'if (%s(%s) < 0) %s;' % (
4788 Naming.import_star,
4789 self.module.py_result(),
4790 code.error_goto(self.pos)))
4791 item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
4792 self.item.set_cname(item_temp)
4793 for name, target, coerced_item in self.interned_items:
4794 cname = code.intern_identifier(name)
4795 code.putln(
4796 '%s = PyObject_GetAttr(%s, %s); %s' % (
4797 item_temp,
4798 self.module.py_result(),
4799 cname,
4800 code.error_goto_if_null(item_temp, self.pos)))
4801 code.put_gotref(item_temp)
4802 if coerced_item is None:
4803 target.generate_assignment_code(self.item, code)
4804 else:
4805 coerced_item.allocate_temp_result(code)
4806 coerced_item.generate_result_code(code)
4807 target.generate_assignment_code(coerced_item, code)
4808 code.put_decref_clear(item_temp, py_object_type)
4809 code.funcstate.release_temp(item_temp)
4810 self.module.generate_disposal_code(code)
4811 self.module.free_temps(code)
4815 #------------------------------------------------------------------------------------
4816 #
4817 # Runtime support code
4818 #
4819 #------------------------------------------------------------------------------------
4821 utility_function_predeclarations = \
4822 """
4823 #ifndef INLINE
4824 #if defined(__GNUC__)
4825 #define INLINE __inline__
4826 #elif defined(_MSC_VER)
4827 #define INLINE __inline
4828 #else
4829 #define INLINE
4830 #endif
4831 #endif
4833 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*/
4835 """
4837 if Options.gcc_branch_hints:
4838 branch_prediction_macros = \
4839 """
4840 #ifdef __GNUC__
4841 /* Test for GCC > 2.95 */
4842 #if __GNUC__ > 2 || \
4843 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4844 #define likely(x) __builtin_expect(!!(x), 1)
4845 #define unlikely(x) __builtin_expect(!!(x), 0)
4846 #else /* __GNUC__ > 2 ... */
4847 #define likely(x) (x)
4848 #define unlikely(x) (x)
4849 #endif /* __GNUC__ > 2 ... */
4850 #else /* __GNUC__ */
4851 #define likely(x) (x)
4852 #define unlikely(x) (x)
4853 #endif /* __GNUC__ */
4854 """
4855 else:
4856 branch_prediction_macros = \
4857 """
4858 #define likely(x) (x)
4859 #define unlikely(x) (x)
4860 """
4862 #get_name_predeclaration = \
4863 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4865 #get_name_interned_predeclaration = \
4866 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4868 #------------------------------------------------------------------------------------
4870 printing_utility_code = UtilityCode(
4871 proto = """
4872 static int __Pyx_Print(PyObject *, int); /*proto*/
4873 #if PY_MAJOR_VERSION >= 3
4874 static PyObject* %s = 0;
4875 static PyObject* %s = 0;
4876 #endif
4877 """ % (Naming.print_function, Naming.print_function_kwargs),
4878 impl = r"""
4879 #if PY_MAJOR_VERSION < 3
4880 static PyObject *__Pyx_GetStdout(void) {
4881 PyObject *f = PySys_GetObject((char *)"stdout");
4882 if (!f) {
4883 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4884 }
4885 return f;
4886 }
4888 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4889 PyObject *f;
4890 PyObject* v;
4891 int i;
4893 if (!(f = __Pyx_GetStdout()))
4894 return -1;
4895 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4896 if (PyFile_SoftSpace(f, 1)) {
4897 if (PyFile_WriteString(" ", f) < 0)
4898 return -1;
4899 }
4900 v = PyTuple_GET_ITEM(arg_tuple, i);
4901 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4902 return -1;
4903 if (PyString_Check(v)) {
4904 char *s = PyString_AsString(v);
4905 Py_ssize_t len = PyString_Size(v);
4906 if (len > 0 &&
4907 isspace(Py_CHARMASK(s[len-1])) &&
4908 s[len-1] != ' ')
4909 PyFile_SoftSpace(f, 0);
4910 }
4911 }
4912 if (newline) {
4913 if (PyFile_WriteString("\n", f) < 0)
4914 return -1;
4915 PyFile_SoftSpace(f, 0);
4916 }
4917 return 0;
4918 }
4920 #else /* Python 3 has a print function */
4922 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4923 PyObject* kwargs = 0;
4924 PyObject* result = 0;
4925 PyObject* end_string;
4926 if (!%(PRINT_FUNCTION)s) {
4927 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4928 if (!%(PRINT_FUNCTION)s)
4929 return -1;
4930 }
4931 if (!newline) {
4932 if (!%(PRINT_KWARGS)s) {
4933 %(PRINT_KWARGS)s = PyDict_New();
4934 if (!%(PRINT_KWARGS)s)
4935 return -1;
4936 end_string = PyUnicode_FromStringAndSize(" ", 1);
4937 if (!end_string)
4938 return -1;
4939 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4940 Py_DECREF(end_string);
4941 return -1;
4942 }
4943 Py_DECREF(end_string);
4944 }
4945 kwargs = %(PRINT_KWARGS)s;
4946 }
4947 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4948 if (!result)
4949 return -1;
4950 Py_DECREF(result);
4951 return 0;
4952 }
4954 #endif
4955 """ % {'BUILTINS' : Naming.builtins_cname,
4956 'PRINT_FUNCTION' : Naming.print_function,
4957 'PRINT_KWARGS' : Naming.print_function_kwargs}
4958 )
4961 printing_one_utility_code = UtilityCode(
4962 proto = """
4963 static int __Pyx_PrintOne(PyObject *o); /*proto*/
4964 """,
4965 impl = r"""
4966 #if PY_MAJOR_VERSION < 3
4968 static int __Pyx_PrintOne(PyObject *o) {
4969 PyObject *f;
4970 if (!(f = __Pyx_GetStdout()))
4971 return -1;
4972 if (PyFile_SoftSpace(f, 0)) {
4973 if (PyFile_WriteString(" ", f) < 0)
4974 return -1;
4975 }
4976 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
4977 return -1;
4978 if (PyFile_WriteString("\n", f) < 0)
4979 return -1;
4980 return 0;
4981 /* the line below is just to avoid compiler
4982 * compiler warnings about unused functions */
4983 return __Pyx_Print(NULL, 0);
4984 }
4986 #else /* Python 3 has a print function */
4988 static int __Pyx_PrintOne(PyObject *o) {
4989 int res;
4990 PyObject* arg_tuple = PyTuple_New(1);
4991 if (unlikely(!arg_tuple))
4992 return -1;
4993 Py_INCREF(o);
4994 PyTuple_SET_ITEM(arg_tuple, 0, o);
4995 res = __Pyx_Print(arg_tuple, 1);
4996 Py_DECREF(arg_tuple);
4997 return res;
4998 }
5000 #endif
5001 """,
5002 requires=[printing_utility_code])
5006 #------------------------------------------------------------------------------------
5008 # Exception raising code
5009 #
5010 # Exceptions are raised by __Pyx_Raise() and stored as plain
5011 # type/value/tb in PyThreadState->curexc_*. When being caught by an
5012 # 'except' statement, curexc_* is moved over to exc_* by
5013 # __Pyx_GetException()
5015 restore_exception_utility_code = UtilityCode(
5016 proto = """
5017 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5018 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5019 """,
5020 impl = """
5021 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5022 PyObject *tmp_type, *tmp_value, *tmp_tb;
5023 PyThreadState *tstate = PyThreadState_GET();
5025 tmp_type = tstate->curexc_type;
5026 tmp_value = tstate->curexc_value;
5027 tmp_tb = tstate->curexc_traceback;
5028 tstate->curexc_type = type;
5029 tstate->curexc_value = value;
5030 tstate->curexc_traceback = tb;
5031 Py_XDECREF(tmp_type);
5032 Py_XDECREF(tmp_value);
5033 Py_XDECREF(tmp_tb);
5034 }
5036 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5037 PyThreadState *tstate = PyThreadState_GET();
5038 *type = tstate->curexc_type;
5039 *value = tstate->curexc_value;
5040 *tb = tstate->curexc_traceback;
5042 tstate->curexc_type = 0;
5043 tstate->curexc_value = 0;
5044 tstate->curexc_traceback = 0;
5045 }
5047 """)
5049 # The following function is based on do_raise() from ceval.c. There
5050 # are separate versions for Python2 and Python3 as exception handling
5051 # has changed quite a lot between the two versions.
5053 raise_utility_code = UtilityCode(
5054 proto = """
5055 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5056 """,
5057 impl = """
5058 #if PY_MAJOR_VERSION < 3
5059 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5060 Py_XINCREF(type);
5061 Py_XINCREF(value);
5062 Py_XINCREF(tb);
5063 /* First, check the traceback argument, replacing None with NULL. */
5064 if (tb == Py_None) {
5065 Py_DECREF(tb);
5066 tb = 0;
5067 }
5068 else if (tb != NULL && !PyTraceBack_Check(tb)) {
5069 PyErr_SetString(PyExc_TypeError,
5070 "raise: arg 3 must be a traceback or None");
5071 goto raise_error;
5072 }
5073 /* Next, replace a missing value with None */
5074 if (value == NULL) {
5075 value = Py_None;
5076 Py_INCREF(value);
5077 }
5078 #if PY_VERSION_HEX < 0x02050000
5079 if (!PyClass_Check(type))
5080 #else
5081 if (!PyType_Check(type))
5082 #endif
5083 {
5084 /* Raising an instance. The value should be a dummy. */
5085 if (value != Py_None) {
5086 PyErr_SetString(PyExc_TypeError,
5087 "instance exception may not have a separate value");
5088 goto raise_error;
5089 }
5090 /* Normalize to raise <class>, <instance> */
5091 Py_DECREF(value);
5092 value = type;
5093 #if PY_VERSION_HEX < 0x02050000
5094 if (PyInstance_Check(type)) {
5095 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
5096 Py_INCREF(type);
5097 }
5098 else {
5099 type = 0;
5100 PyErr_SetString(PyExc_TypeError,
5101 "raise: exception must be an old-style class or instance");
5102 goto raise_error;
5103 }
5104 #else
5105 type = (PyObject*) Py_TYPE(type);
5106 Py_INCREF(type);
5107 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
5108 PyErr_SetString(PyExc_TypeError,
5109 "raise: exception class must be a subclass of BaseException");
5110 goto raise_error;
5111 }
5112 #endif
5113 }
5115 __Pyx_ErrRestore(type, value, tb);
5116 return;
5117 raise_error:
5118 Py_XDECREF(value);
5119 Py_XDECREF(type);
5120 Py_XDECREF(tb);
5121 return;
5122 }
5124 #else /* Python 3+ */
5126 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5127 if (tb == Py_None) {
5128 tb = 0;
5129 } else if (tb && !PyTraceBack_Check(tb)) {
5130 PyErr_SetString(PyExc_TypeError,
5131 "raise: arg 3 must be a traceback or None");
5132 goto bad;
5133 }
5134 if (value == Py_None)
5135 value = 0;
5137 if (PyExceptionInstance_Check(type)) {
5138 if (value) {
5139 PyErr_SetString(PyExc_TypeError,
5140 "instance exception may not have a separate value");
5141 goto bad;
5142 }
5143 value = type;
5144 type = (PyObject*) Py_TYPE(value);
5145 } else if (!PyExceptionClass_Check(type)) {
5146 PyErr_SetString(PyExc_TypeError,
5147 "raise: exception class must be a subclass of BaseException");
5148 goto bad;
5149 }
5151 PyErr_SetObject(type, value);
5153 if (tb) {
5154 PyThreadState *tstate = PyThreadState_GET();
5155 PyObject* tmp_tb = tstate->curexc_traceback;
5156 if (tb != tmp_tb) {
5157 Py_INCREF(tb);
5158 tstate->curexc_traceback = tb;
5159 Py_XDECREF(tmp_tb);
5160 }
5161 }
5163 bad:
5164 return;
5165 }
5166 #endif
5167 """,
5168 requires=[restore_exception_utility_code])
5170 #------------------------------------------------------------------------------------
5172 get_exception_utility_code = UtilityCode(
5173 proto = """
5174 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5175 """,
5176 impl = """
5177 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5178 PyObject *local_type, *local_value, *local_tb;
5179 PyObject *tmp_type, *tmp_value, *tmp_tb;
5180 PyThreadState *tstate = PyThreadState_GET();
5181 local_type = tstate->curexc_type;
5182 local_value = tstate->curexc_value;
5183 local_tb = tstate->curexc_traceback;
5184 tstate->curexc_type = 0;
5185 tstate->curexc_value = 0;
5186 tstate->curexc_traceback = 0;
5187 PyErr_NormalizeException(&local_type, &local_value, &local_tb);
5188 if (unlikely(tstate->curexc_type))
5189 goto bad;
5190 #if PY_MAJOR_VERSION >= 3
5191 if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
5192 goto bad;
5193 #endif
5194 *type = local_type;
5195 *value = local_value;
5196 *tb = local_tb;
5197 Py_INCREF(local_type);
5198 Py_INCREF(local_value);
5199 Py_INCREF(local_tb);
5200 tmp_type = tstate->exc_type;
5201 tmp_value = tstate->exc_value;
5202 tmp_tb = tstate->exc_traceback;
5203 tstate->exc_type = local_type;
5204 tstate->exc_value = local_value;
5205 tstate->exc_traceback = local_tb;
5206 /* Make sure tstate is in a consistent state when we XDECREF
5207 these objects (XDECREF may run arbitrary code). */
5208 Py_XDECREF(tmp_type);
5209 Py_XDECREF(tmp_value);
5210 Py_XDECREF(tmp_tb);
5211 return 0;
5212 bad:
5213 *type = 0;
5214 *value = 0;
5215 *tb = 0;
5216 Py_XDECREF(local_type);
5217 Py_XDECREF(local_value);
5218 Py_XDECREF(local_tb);
5219 return -1;
5220 }
5222 """)
5224 #------------------------------------------------------------------------------------
5226 get_exception_tuple_utility_code = UtilityCode(proto="""
5227 static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
5228 """,
5229 # I doubt that calling __Pyx_GetException() here is correct as it moves
5230 # the exception from tstate->curexc_* to tstate->exc_*, which prevents
5231 # exception handlers later on from receiving it.
5232 impl = """
5233 static PyObject *__Pyx_GetExceptionTuple(void) {
5234 PyObject *type = NULL, *value = NULL, *tb = NULL;
5235 if (__Pyx_GetException(&type, &value, &tb) == 0) {
5236 PyObject* exc_info = PyTuple_New(3);
5237 if (exc_info) {
5238 Py_INCREF(type);
5239 Py_INCREF(value);
5240 Py_INCREF(tb);
5241 PyTuple_SET_ITEM(exc_info, 0, type);
5242 PyTuple_SET_ITEM(exc_info, 1, value);
5243 PyTuple_SET_ITEM(exc_info, 2, tb);
5244 return exc_info;
5245 }
5246 }
5247 return NULL;
5248 }
5249 """,
5250 requires=[get_exception_utility_code])
5252 #------------------------------------------------------------------------------------
5254 reset_exception_utility_code = UtilityCode(
5255 proto = """
5256 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5257 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5258 """,
5259 impl = """
5260 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5261 PyThreadState *tstate = PyThreadState_GET();
5262 *type = tstate->exc_type;
5263 *value = tstate->exc_value;
5264 *tb = tstate->exc_traceback;
5265 Py_XINCREF(*type);
5266 Py_XINCREF(*value);
5267 Py_XINCREF(*tb);
5268 }
5270 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5271 PyObject *tmp_type, *tmp_value, *tmp_tb;
5272 PyThreadState *tstate = PyThreadState_GET();
5273 tmp_type = tstate->exc_type;
5274 tmp_value = tstate->exc_value;
5275 tmp_tb = tstate->exc_traceback;
5276 tstate->exc_type = type;
5277 tstate->exc_value = value;
5278 tstate->exc_traceback = tb;
5279 Py_XDECREF(tmp_type);
5280 Py_XDECREF(tmp_value);
5281 Py_XDECREF(tmp_tb);
5282 }
5283 """)
5285 #------------------------------------------------------------------------------------
5287 arg_type_test_utility_code = UtilityCode(
5288 proto = """
5289 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5290 const char *name, int exact); /*proto*/
5291 """,
5292 impl = """
5293 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5294 const char *name, int exact)
5295 {
5296 if (!type) {
5297 PyErr_Format(PyExc_SystemError, "Missing type object");
5298 return 0;
5299 }
5300 if (none_allowed && obj == Py_None) return 1;
5301 else if (exact) {
5302 if (Py_TYPE(obj) == type) return 1;
5303 }
5304 else {
5305 if (PyObject_TypeCheck(obj, type)) return 1;
5306 }
5307 PyErr_Format(PyExc_TypeError,
5308 "Argument '%s' has incorrect type (expected %s, got %s)",
5309 name, type->tp_name, Py_TYPE(obj)->tp_name);
5310 return 0;
5311 }
5312 """)
5314 #------------------------------------------------------------------------------------
5315 #
5316 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5317 # many or too few positional arguments were found. This handles
5318 # Py_ssize_t formatting correctly.
5320 raise_argtuple_invalid_utility_code = UtilityCode(
5321 proto = """
5322 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5323 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5324 """,
5325 impl = """
5326 static void __Pyx_RaiseArgtupleInvalid(
5327 const char* func_name,
5328 int exact,
5329 Py_ssize_t num_min,
5330 Py_ssize_t num_max,
5331 Py_ssize_t num_found)
5332 {
5333 Py_ssize_t num_expected;
5334 const char *number, *more_or_less;
5336 if (num_found < num_min) {
5337 num_expected = num_min;
5338 more_or_less = "at least";
5339 } else {
5340 num_expected = num_max;
5341 more_or_less = "at most";
5342 }
5343 if (exact) {
5344 more_or_less = "exactly";
5345 }
5346 number = (num_expected == 1) ? "" : "s";
5347 PyErr_Format(PyExc_TypeError,
5348 #if PY_VERSION_HEX < 0x02050000
5349 "%s() takes %s %d positional argument%s (%d given)",
5350 #else
5351 "%s() takes %s %zd positional argument%s (%zd given)",
5352 #endif
5353 func_name, more_or_less, num_expected, number, num_found);
5354 }
5355 """)
5357 raise_keyword_required_utility_code = UtilityCode(
5358 proto = """
5359 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5360 """,
5361 impl = """
5362 static INLINE void __Pyx_RaiseKeywordRequired(
5363 const char* func_name,
5364 PyObject* kw_name)
5365 {
5366 PyErr_Format(PyExc_TypeError,
5367 #if PY_MAJOR_VERSION >= 3
5368 "%s() needs keyword-only argument %U", func_name, kw_name);
5369 #else
5370 "%s() needs keyword-only argument %s", func_name,
5371 PyString_AS_STRING(kw_name));
5372 #endif
5373 }
5374 """)
5376 raise_double_keywords_utility_code = UtilityCode(
5377 proto = """
5378 static void __Pyx_RaiseDoubleKeywordsError(
5379 const char* func_name, PyObject* kw_name); /*proto*/
5380 """,
5381 impl = """
5382 static void __Pyx_RaiseDoubleKeywordsError(
5383 const char* func_name,
5384 PyObject* kw_name)
5385 {
5386 PyErr_Format(PyExc_TypeError,
5387 #if PY_MAJOR_VERSION >= 3
5388 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5389 #else
5390 "%s() got multiple values for keyword argument '%s'", func_name,
5391 PyString_AS_STRING(kw_name));
5392 #endif
5393 }
5394 """)
5396 #------------------------------------------------------------------------------------
5397 #
5398 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5399 # were passed to a function, or if any keywords were passed to a
5400 # function that does not accept them.
5402 keyword_string_check_utility_code = UtilityCode(
5403 proto = """
5404 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5405 const char* function_name, int kw_allowed); /*proto*/
5406 """,
5407 impl = """
5408 static INLINE int __Pyx_CheckKeywordStrings(
5409 PyObject *kwdict,
5410 const char* function_name,
5411 int kw_allowed)
5412 {
5413 PyObject* key = 0;
5414 Py_ssize_t pos = 0;
5415 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5416 #if PY_MAJOR_VERSION < 3
5417 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5418 #else
5419 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5420 #endif
5421 goto invalid_keyword_type;
5422 }
5423 if ((!kw_allowed) && unlikely(key))
5424 goto invalid_keyword;
5425 return 1;
5426 invalid_keyword_type:
5427 PyErr_Format(PyExc_TypeError,
5428 "%s() keywords must be strings", function_name);
5429 return 0;
5430 invalid_keyword:
5431 PyErr_Format(PyExc_TypeError,
5432 #if PY_MAJOR_VERSION < 3
5433 "%s() got an unexpected keyword argument '%s'",
5434 function_name, PyString_AsString(key));
5435 #else
5436 "%s() got an unexpected keyword argument '%U'",
5437 function_name, key);
5438 #endif
5439 return 0;
5440 }
5441 """)
5443 #------------------------------------------------------------------------------------
5444 #
5445 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5446 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5447 # keywords will raise an invalid keyword error.
5448 #
5449 # Three kinds of errors are checked: 1) non-string keywords, 2)
5450 # unexpected keywords and 3) overlap with positional arguments.
5451 #
5452 # If num_posargs is greater 0, it denotes the number of positional
5453 # arguments that were passed and that must therefore not appear
5454 # amongst the keywords as well.
5455 #
5456 # This method does not check for required keyword arguments.
5457 #
5459 parse_keywords_utility_code = UtilityCode(
5460 proto = """
5461 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5462 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5463 const char* function_name); /*proto*/
5464 """,
5465 impl = """
5466 static int __Pyx_ParseOptionalKeywords(
5467 PyObject *kwds,
5468 PyObject **argnames[],
5469 PyObject *kwds2,
5470 PyObject *values[],
5471 Py_ssize_t num_pos_args,
5472 const char* function_name)
5473 {
5474 PyObject *key = 0, *value = 0;
5475 Py_ssize_t pos = 0;
5476 PyObject*** name;
5477 PyObject*** first_kw_arg = argnames + num_pos_args;
5479 while (PyDict_Next(kwds, &pos, &key, &value)) {
5480 name = first_kw_arg;
5481 while (*name && (**name != key)) name++;
5482 if (*name) {
5483 values[name-argnames] = value;
5484 } else {
5485 #if PY_MAJOR_VERSION < 3
5486 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5487 #else
5488 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5489 #endif
5490 goto invalid_keyword_type;
5491 } else {
5492 for (name = first_kw_arg; *name; name++) {
5493 #if PY_MAJOR_VERSION >= 3
5494 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5495 PyUnicode_Compare(**name, key) == 0) break;
5496 #else
5497 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5498 _PyString_Eq(**name, key)) break;
5499 #endif
5500 }
5501 if (*name) {
5502 values[name-argnames] = value;
5503 } else {
5504 /* unexpected keyword found */
5505 for (name=argnames; name != first_kw_arg; name++) {
5506 if (**name == key) goto arg_passed_twice;
5507 #if PY_MAJOR_VERSION >= 3
5508 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5509 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5510 #else
5511 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5512 _PyString_Eq(**name, key)) goto arg_passed_twice;
5513 #endif
5514 }
5515 if (kwds2) {
5516 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5517 } else {
5518 goto invalid_keyword;
5519 }
5520 }
5521 }
5522 }
5523 }
5524 return 0;
5525 arg_passed_twice:
5526 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5527 goto bad;
5528 invalid_keyword_type:
5529 PyErr_Format(PyExc_TypeError,
5530 "%s() keywords must be strings", function_name);
5531 goto bad;
5532 invalid_keyword:
5533 PyErr_Format(PyExc_TypeError,
5534 #if PY_MAJOR_VERSION < 3
5535 "%s() got an unexpected keyword argument '%s'",
5536 function_name, PyString_AsString(key));
5537 #else
5538 "%s() got an unexpected keyword argument '%U'",
5539 function_name, key);
5540 #endif
5541 bad:
5542 return -1;
5543 }
5544 """)
5546 #------------------------------------------------------------------------------------
5548 traceback_utility_code = UtilityCode(
5549 proto = """
5550 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5551 """,
5552 impl = """
5553 #include "compile.h"
5554 #include "frameobject.h"
5555 #include "traceback.h"
5557 static void __Pyx_AddTraceback(const char *funcname) {
5558 PyObject *py_srcfile = 0;
5559 PyObject *py_funcname = 0;
5560 PyObject *py_globals = 0;
5561 PyCodeObject *py_code = 0;
5562 PyFrameObject *py_frame = 0;
5564 #if PY_MAJOR_VERSION < 3
5565 py_srcfile = PyString_FromString(%(FILENAME)s);
5566 #else
5567 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5568 #endif
5569 if (!py_srcfile) goto bad;
5570 if (%(CLINENO)s) {
5571 #if PY_MAJOR_VERSION < 3
5572 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5573 #else
5574 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5575 #endif
5576 }
5577 else {
5578 #if PY_MAJOR_VERSION < 3
5579 py_funcname = PyString_FromString(funcname);
5580 #else
5581 py_funcname = PyUnicode_FromString(funcname);
5582 #endif
5583 }
5584 if (!py_funcname) goto bad;
5585 py_globals = PyModule_GetDict(%(GLOBALS)s);
5586 if (!py_globals) goto bad;
5587 py_code = PyCode_New(
5588 0, /*int argcount,*/
5589 #if PY_MAJOR_VERSION >= 3
5590 0, /*int kwonlyargcount,*/
5591 #endif
5592 0, /*int nlocals,*/
5593 0, /*int stacksize,*/
5594 0, /*int flags,*/
5595 %(EMPTY_BYTES)s, /*PyObject *code,*/
5596 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5597 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5598 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5599 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5600 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5601 py_srcfile, /*PyObject *filename,*/
5602 py_funcname, /*PyObject *name,*/
5603 %(LINENO)s, /*int firstlineno,*/
5604 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5605 );
5606 if (!py_code) goto bad;
5607 py_frame = PyFrame_New(
5608 PyThreadState_GET(), /*PyThreadState *tstate,*/
5609 py_code, /*PyCodeObject *code,*/
5610 py_globals, /*PyObject *globals,*/
5611 0 /*PyObject *locals*/
5612 );
5613 if (!py_frame) goto bad;
5614 py_frame->f_lineno = %(LINENO)s;
5615 PyTraceBack_Here(py_frame);
5616 bad:
5617 Py_XDECREF(py_srcfile);
5618 Py_XDECREF(py_funcname);
5619 Py_XDECREF(py_code);
5620 Py_XDECREF(py_frame);
5621 }
5622 """ % {
5623 'FILENAME': Naming.filename_cname,
5624 'LINENO': Naming.lineno_cname,
5625 'CFILENAME': Naming.cfilenm_cname,
5626 'CLINENO': Naming.clineno_cname,
5627 'GLOBALS': Naming.module_cname,
5628 'EMPTY_TUPLE' : Naming.empty_tuple,
5629 'EMPTY_BYTES' : Naming.empty_bytes,
5630 })
5632 #------------------------------------------------------------------------------------
5634 unraisable_exception_utility_code = UtilityCode(
5635 proto = """
5636 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5637 """,
5638 impl = """
5639 static void __Pyx_WriteUnraisable(const char *name) {
5640 PyObject *old_exc, *old_val, *old_tb;
5641 PyObject *ctx;
5642 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5643 #if PY_MAJOR_VERSION < 3
5644 ctx = PyString_FromString(name);
5645 #else
5646 ctx = PyUnicode_FromString(name);
5647 #endif
5648 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5649 if (!ctx) {
5650 PyErr_WriteUnraisable(Py_None);
5651 } else {
5652 PyErr_WriteUnraisable(ctx);
5653 Py_DECREF(ctx);
5654 }
5655 }
5656 """,
5657 requires=[restore_exception_utility_code])
5659 #------------------------------------------------------------------------------------
5661 set_vtable_utility_code = UtilityCode(
5662 proto = """
5663 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5664 """,
5665 impl = """
5666 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5667 #if PY_VERSION_HEX < 0x03010000
5668 PyObject *ob = PyCObject_FromVoidPtr(vtable, 0);
5669 #else
5670 PyObject *ob = PyCapsule_New(vtable, 0, 0);
5671 #endif
5672 if (!ob)
5673 goto bad;
5674 if (PyDict_SetItemString(dict, "__pyx_vtable__", ob) < 0)
5675 goto bad;
5676 Py_DECREF(ob);
5677 return 0;
5678 bad:
5679 Py_XDECREF(ob);
5680 return -1;
5681 }
5682 """)
5684 #------------------------------------------------------------------------------------
5686 get_vtable_utility_code = UtilityCode(
5687 proto = """
5688 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5689 """,
5690 impl = r"""
5691 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5692 PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5693 if (!ob)
5694 goto bad;
5695 #if PY_VERSION_HEX < 0x03010000
5696 *(void **)vtabptr = PyCObject_AsVoidPtr(ob);
5697 #else
5698 *(void **)vtabptr = PyCapsule_GetPointer(ob, 0);
5699 #endif
5700 if (!*(void **)vtabptr)
5701 goto bad;
5702 Py_DECREF(ob);
5703 return 0;
5704 bad:
5705 Py_XDECREF(ob);
5706 return -1;
5707 }
5708 """)
5710 #------------------------------------------------------------------------------------
5712 init_string_tab_utility_code = UtilityCode(
5713 proto = """
5714 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5715 """,
5716 impl = """
5717 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5718 while (t->p) {
5719 #if PY_MAJOR_VERSION < 3
5720 if (t->is_unicode) {
5721 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5722 } else if (t->intern) {
5723 *t->p = PyString_InternFromString(t->s);
5724 } else {
5725 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5726 }
5727 #else /* Python 3+ has unicode identifiers */
5728 if (t->is_unicode | t->is_str) {
5729 if (t->intern) {
5730 *t->p = PyUnicode_InternFromString(t->s);
5731 } else if (t->encoding) {
5732 *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
5733 } else {
5734 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5735 }
5736 } else {
5737 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5738 }
5739 #endif
5740 if (!*t->p)
5741 return -1;
5742 ++t;
5743 }
5744 return 0;
5745 }
5746 """)
5748 #------------------------------------------------------------------------------------
5750 force_init_threads_utility_code = UtilityCode(
5751 proto="""
5752 #ifndef __PYX_FORCE_INIT_THREADS
5753 #if PY_VERSION_HEX < 0x02040200
5754 #define __PYX_FORCE_INIT_THREADS 1
5755 #else
5756 #define __PYX_FORCE_INIT_THREADS 0
5757 #endif
5758 #endif
5759 """)
5761 #------------------------------------------------------------------------------------
5763 # Note that cPython ignores PyTrace_EXCEPTION,
5764 # but maybe some other profilers don't.
5766 profile_utility_code = UtilityCode(proto="""
5767 #ifndef CYTHON_PROFILE
5768 #define CYTHON_PROFILE 1
5769 #endif
5771 #ifndef CYTHON_PROFILE_REUSE_FRAME
5772 #define CYTHON_PROFILE_REUSE_FRAME 0
5773 #endif
5775 #if CYTHON_PROFILE
5777 #include "compile.h"
5778 #include "frameobject.h"
5779 #include "traceback.h"
5781 #if CYTHON_PROFILE_REUSE_FRAME
5782 #define CYTHON_FRAME_MODIFIER static
5783 #define CYTHON_FRAME_DEL
5784 #else
5785 #define CYTHON_FRAME_MODIFIER
5786 #define CYTHON_FRAME_DEL Py_DECREF(%(FRAME)s)
5787 #endif
5789 #define __Pyx_TraceCall(funcname, srcfile, firstlineno) \\
5790 static PyCodeObject *%(FRAME_CODE)s = NULL; \\
5791 CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL; \\
5792 int __Pyx_use_tracing = 0; \\
5793 if (unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc)) { \\
5794 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&%(FRAME_CODE)s, &%(FRAME)s, funcname, srcfile, firstlineno); \\
5795 }
5797 #define __Pyx_TraceException() \\
5798 if (unlikely(__Pyx_use_tracing( && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5799 PyObject *exc_info = __Pyx_GetExceptionTuple(); \\
5800 if (exc_info) { \\
5801 PyThreadState_GET()->c_profilefunc( \\
5802 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_EXCEPTION, exc_info); \\
5803 Py_DECREF(exc_info); \\
5804 } \\
5805 }
5807 #define __Pyx_TraceReturn(result) \\
5808 if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5809 PyThreadState_GET()->c_profilefunc( \\
5810 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_RETURN, (PyObject*)result); \\
5811 CYTHON_FRAME_DEL; \\
5812 }
5814 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
5815 static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
5817 #else
5818 #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
5819 #define __Pyx_TraceException()
5820 #define __Pyx_TraceReturn(result)
5821 #endif /* CYTHON_PROFILE */
5822 """
5823 % {
5824 "FRAME": Naming.frame_cname,
5825 "FRAME_CODE": Naming.frame_code_cname,
5826 },
5827 impl = """
5829 #if CYTHON_PROFILE
5831 static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
5832 PyFrameObject** frame,
5833 const char *funcname,
5834 const char *srcfile,
5835 int firstlineno) {
5836 if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) {
5837 if (*code == NULL) {
5838 *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
5839 if (*code == NULL) return 0;
5840 }
5841 *frame = PyFrame_New(
5842 PyThreadState_GET(), /*PyThreadState *tstate*/
5843 *code, /*PyCodeObject *code*/
5844 PyModule_GetDict(%(MODULE)s), /*PyObject *globals*/
5845 0 /*PyObject *locals*/
5846 );
5847 if (*frame == NULL) return 0;
5848 }
5849 else {
5850 (*frame)->f_tstate = PyThreadState_GET();
5851 }
5852 return PyThreadState_GET()->c_profilefunc(PyThreadState_GET()->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
5853 }
5855 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
5856 PyObject *py_srcfile = 0;
5857 PyObject *py_funcname = 0;
5858 PyCodeObject *py_code = 0;
5860 #if PY_MAJOR_VERSION < 3
5861 py_funcname = PyString_FromString(funcname);
5862 py_srcfile = PyString_FromString(srcfile);
5863 #else
5864 py_funcname = PyUnicode_FromString(funcname);
5865 py_srcfile = PyUnicode_FromString(srcfile);
5866 #endif
5867 if (!py_funcname | !py_srcfile) goto bad;
5869 py_code = PyCode_New(
5870 0, /*int argcount,*/
5871 #if PY_MAJOR_VERSION >= 3
5872 0, /*int kwonlyargcount,*/
5873 #endif
5874 0, /*int nlocals,*/
5875 0, /*int stacksize,*/
5876 0, /*int flags,*/
5877 %(EMPTY_BYTES)s, /*PyObject *code,*/
5878 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5879 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5880 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5881 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5882 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5883 py_srcfile, /*PyObject *filename,*/
5884 py_funcname, /*PyObject *name,*/
5885 firstlineno, /*int firstlineno,*/
5886 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5887 );
5889 bad:
5890 Py_XDECREF(py_srcfile);
5891 Py_XDECREF(py_funcname);
5893 return py_code;
5894 }
5896 #endif /* CYTHON_PROFILE */
5897 """ % {
5898 'EMPTY_TUPLE' : Naming.empty_tuple,
5899 'EMPTY_BYTES' : Naming.empty_bytes,
5900 "MODULE": Naming.module_cname,
5901 })
