Cython has moved to github.
cython-devel
view Cython/Compiler/Nodes.py @ 2744:25af3c07d7c3
minor refactoring; fix handling first argument in classmethods; fix ticket #462: allow method(*args) in cdef classes
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Sat Dec 05 23:39:57 2009 +0100 (2 years ago) |
| parents | 723772dbc385 |
| children | d3155772b36f |
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 entry = env.declare_var(arg.name,
1876 PyrexTypes.py_object_type, arg.pos)
1877 entry.used = 1
1878 entry.init = "0"
1879 entry.init_to_none = 0
1880 entry.xdecref_cleanup = 1
1881 arg.entry = entry
1882 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1884 def analyse_expressions(self, env):
1885 self.local_scope.directives = env.directives
1886 self.analyse_default_values(env)
1887 if env.is_py_class_scope:
1888 self.synthesize_assignment_node(env)
1890 def synthesize_assignment_node(self, env):
1891 import ExprNodes
1892 self.assmt = SingleAssignmentNode(self.pos,
1893 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1894 rhs = ExprNodes.UnboundMethodNode(self.pos,
1895 function = ExprNodes.PyCFunctionNode(self.pos,
1896 pymethdef_cname = self.entry.pymethdef_cname)))
1897 self.assmt.analyse_declarations(env)
1898 self.assmt.analyse_expressions(env)
1900 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1901 arg_code_list = []
1902 sig = self.entry.signature
1903 if sig.has_dummy_arg or self.self_in_stararg:
1904 arg_code_list.append(
1905 "PyObject *%s" % Naming.self_cname)
1906 for arg in self.args:
1907 if not arg.is_generic:
1908 if arg.is_self_arg or arg.is_type_arg:
1909 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1910 else:
1911 arg_code_list.append(
1912 arg.hdr_type.declaration_code(arg.hdr_cname))
1913 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1914 arg_code_list.append("PyObject *unused")
1915 if sig.has_generic_args:
1916 arg_code_list.append(
1917 "PyObject *%s, PyObject *%s"
1918 % (Naming.args_cname, Naming.kwds_cname))
1919 arg_code = ", ".join(arg_code_list)
1920 dc = self.return_type.declaration_code(self.entry.func_cname)
1921 header = "static %s(%s)" % (dc, arg_code)
1922 code.putln("%s; /*proto*/" % header)
1923 if proto_only:
1924 return
1925 if self.entry.doc and Options.docstrings:
1926 docstr = self.entry.doc
1927 if docstr.is_unicode:
1928 docstr = docstr.utf8encode()
1929 code.putln(
1930 'static char %s[] = "%s";' % (
1931 self.entry.doc_cname,
1932 split_docstring(escape_byte_string(docstr))))
1933 if with_pymethdef:
1934 code.put(
1935 "static PyMethodDef %s = " %
1936 self.entry.pymethdef_cname)
1937 code.put_pymethoddef(self.entry, ";")
1938 code.putln("%s {" % header)
1940 def generate_argument_declarations(self, env, code):
1941 for arg in self.args:
1942 if arg.is_generic: # or arg.needs_conversion:
1943 if arg.needs_conversion:
1944 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1945 else:
1946 code.put_var_declaration(arg.entry)
1948 def generate_keyword_list(self, code):
1949 if self.signature_has_generic_args() and \
1950 self.signature_has_nongeneric_args():
1951 code.put(
1952 "static PyObject **%s[] = {" %
1953 Naming.pykwdlist_cname)
1954 for arg in self.args:
1955 if arg.is_generic:
1956 pystring_cname = code.intern_identifier(arg.name)
1957 code.put('&%s,' % pystring_cname)
1958 code.putln("0};")
1960 def generate_argument_parsing_code(self, env, code):
1961 # Generate PyArg_ParseTuple call for generic
1962 # arguments, if any.
1963 if self.entry.signature.has_dummy_arg and not self.self_in_stararg:
1964 # get rid of unused argument warning
1965 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1967 old_error_label = code.new_error_label()
1968 our_error_label = code.error_label
1969 end_label = code.new_label("argument_unpacking_done")
1971 has_kwonly_args = self.num_kwonly_args > 0
1972 has_star_or_kw_args = self.star_arg is not None \
1973 or self.starstar_arg is not None or has_kwonly_args
1975 for arg in self.args:
1976 if not arg.type.is_pyobject:
1977 done = arg.type.create_from_py_utility_code(env)
1978 if not done: pass # will fail later
1980 if not self.signature_has_generic_args():
1981 if has_star_or_kw_args:
1982 error(self.pos, "This method cannot have * or keyword arguments")
1983 self.generate_argument_conversion_code(code)
1985 elif not self.signature_has_nongeneric_args():
1986 # func(*args) or func(**kw) or func(*args, **kw)
1987 self.generate_stararg_copy_code(code)
1989 else:
1990 positional_args = []
1991 kw_only_args = []
1992 for arg in self.args:
1993 arg_entry = arg.entry
1994 if arg.is_generic:
1995 if arg.default:
1996 if not arg.is_self_arg and not arg.is_type_arg:
1997 if arg.kw_only:
1998 kw_only_args.append(arg)
1999 else:
2000 positional_args.append(arg)
2001 elif arg.kw_only:
2002 kw_only_args.append(arg)
2003 elif not arg.is_self_arg and not arg.is_type_arg:
2004 positional_args.append(arg)
2006 self.generate_tuple_and_keyword_parsing_code(
2007 positional_args, kw_only_args, end_label, code)
2009 code.error_label = old_error_label
2010 if code.label_used(our_error_label):
2011 if not code.label_used(end_label):
2012 code.put_goto(end_label)
2013 code.put_label(our_error_label)
2014 if has_star_or_kw_args:
2015 self.generate_arg_decref(self.star_arg, code)
2016 if self.starstar_arg:
2017 if self.starstar_arg.entry.xdecref_cleanup:
2018 code.put_var_xdecref(self.starstar_arg.entry)
2019 else:
2020 code.put_var_decref(self.starstar_arg.entry)
2021 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
2022 code.putln("return %s;" % self.error_value())
2023 if code.label_used(end_label):
2024 code.put_label(end_label)
2026 def generate_arg_assignment(self, arg, item, code):
2027 if arg.type.is_pyobject:
2028 if arg.is_generic:
2029 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
2030 code.putln("%s = %s;" % (arg.entry.cname, item))
2031 else:
2032 func = arg.type.from_py_function
2033 if func:
2034 code.putln("%s = %s(%s); %s" % (
2035 arg.entry.cname,
2036 func,
2037 item,
2038 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
2039 else:
2040 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
2042 def generate_arg_xdecref(self, arg, code):
2043 if arg:
2044 code.put_var_xdecref(arg.entry)
2046 def generate_arg_decref(self, arg, code):
2047 if arg:
2048 code.put_var_decref(arg.entry)
2050 def generate_stararg_copy_code(self, code):
2051 if not self.star_arg:
2052 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2053 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
2054 Naming.args_cname)
2055 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2056 self.name, Naming.args_cname, self.error_value()))
2057 code.putln("}")
2059 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2061 if self.starstar_arg:
2062 if self.star_arg:
2063 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2064 else:
2065 kwarg_check = "%s" % Naming.kwds_cname
2066 else:
2067 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2068 Naming.kwds_cname, Naming.kwds_cname)
2069 code.putln(
2070 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2071 kwarg_check, Naming.kwds_cname, self.name,
2072 bool(self.starstar_arg), self.error_value()))
2074 if self.starstar_arg:
2075 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2076 self.starstar_arg.entry.cname,
2077 Naming.kwds_cname,
2078 Naming.kwds_cname))
2079 code.putln("if (unlikely(!%s)) return %s;" % (
2080 self.starstar_arg.entry.cname, self.error_value()))
2081 self.starstar_arg.entry.xdecref_cleanup = 0
2082 code.put_gotref(self.starstar_arg.entry.cname)
2084 if self.self_in_stararg:
2085 # need to create a new tuple with 'self' inserted as first item
2086 code.put("%s = PyTuple_New(PyTuple_GET_SIZE(%s)+1); if (unlikely(!%s)) " % (
2087 self.star_arg.entry.cname,
2088 Naming.args_cname,
2089 self.star_arg.entry.cname))
2090 if self.starstar_arg:
2091 code.putln("{")
2092 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2093 code.putln("return %s;" % self.error_value())
2094 code.putln("}")
2095 else:
2096 code.putln("return %s;" % self.error_value())
2097 code.put_gotref(self.star_arg.entry.cname)
2098 code.put_incref(Naming.self_cname, py_object_type)
2099 code.put_giveref(Naming.self_cname)
2100 code.putln("PyTuple_SET_ITEM(%s, 0, %s);" % (
2101 self.star_arg.entry.cname, Naming.self_cname))
2102 temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False)
2103 code.putln("for (%s=0; %s < PyTuple_GET_SIZE(%s); %s++) {" % (
2104 temp, temp, Naming.args_cname, temp))
2105 code.putln("PyObject* item = PyTuple_GET_ITEM(%s, %s);" % (
2106 Naming.args_cname, temp))
2107 code.put_incref("item", py_object_type)
2108 code.put_giveref("item")
2109 code.putln("PyTuple_SET_ITEM(%s, %s+1, item);" % (
2110 self.star_arg.entry.cname, temp))
2111 code.putln("}")
2112 code.funcstate.release_temp(temp)
2113 self.star_arg.entry.xdecref_cleanup = 0
2114 elif self.star_arg:
2115 code.put_incref(Naming.args_cname, py_object_type)
2116 code.putln("%s = %s;" % (
2117 self.star_arg.entry.cname,
2118 Naming.args_cname))
2119 self.star_arg.entry.xdecref_cleanup = 0
2121 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2122 kw_only_args, success_label, code):
2123 argtuple_error_label = code.new_label("argtuple_error")
2125 min_positional_args = self.num_required_args - self.num_required_kw_args
2126 if len(self.args) > 0 and (self.args[0].is_self_arg or self.args[0].is_type_arg):
2127 min_positional_args -= 1
2128 max_positional_args = len(positional_args)
2129 has_fixed_positional_count = not self.star_arg and \
2130 min_positional_args == max_positional_args
2132 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2133 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2134 if self.num_required_kw_args:
2135 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2137 if self.starstar_arg or self.star_arg:
2138 self.generate_stararg_init_code(max_positional_args, code)
2140 # --- optimised code when we receive keyword arguments
2141 if self.num_required_kw_args:
2142 likely_hint = "likely"
2143 else:
2144 likely_hint = "unlikely"
2145 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2146 self.generate_keyword_unpacking_code(
2147 min_positional_args, max_positional_args,
2148 has_fixed_positional_count,
2149 positional_args, kw_only_args, argtuple_error_label, code)
2151 # --- optimised code when we do not receive any keyword arguments
2152 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2153 # Python raises arg tuple related errors first, so we must
2154 # check the length here
2155 if min_positional_args == max_positional_args and not self.star_arg:
2156 compare = '!='
2157 else:
2158 compare = '<'
2159 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2160 Naming.args_cname, compare, min_positional_args))
2161 code.put_goto(argtuple_error_label)
2163 if self.num_required_kw_args:
2164 # pure error case: keywords required but not passed
2165 if max_positional_args > min_positional_args and not self.star_arg:
2166 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2167 Naming.args_cname, max_positional_args))
2168 code.put_goto(argtuple_error_label)
2169 code.putln('} else {')
2170 for i, arg in enumerate(kw_only_args):
2171 if not arg.default:
2172 pystring_cname = code.intern_identifier(arg.name)
2173 # required keyword-only argument missing
2174 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2175 self.name,
2176 pystring_cname))
2177 code.putln(code.error_goto(self.pos))
2178 break
2180 elif min_positional_args == max_positional_args:
2181 # parse the exact number of positional arguments from the
2182 # args tuple
2183 code.putln('} else {')
2184 for i, arg in enumerate(positional_args):
2185 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2186 self.generate_arg_assignment(arg, item, code)
2187 self.generate_arg_default_assignments(code)
2189 else:
2190 # parse the positional arguments from the variable length
2191 # args tuple
2192 code.putln('} else {')
2193 self.generate_arg_default_assignments(code)
2194 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2195 if self.star_arg:
2196 code.putln('default:')
2197 reversed_args = list(enumerate(positional_args))[::-1]
2198 for i, arg in reversed_args:
2199 if i >= min_positional_args-1:
2200 if min_positional_args > 1:
2201 code.putln('case %2d:' % (i+1)) # pure code beautification
2202 else:
2203 code.put('case %2d: ' % (i+1))
2204 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2205 self.generate_arg_assignment(arg, item, code)
2206 if min_positional_args == 0:
2207 code.put('case 0: ')
2208 code.putln('break;')
2209 if self.star_arg:
2210 if min_positional_args:
2211 for i in range(min_positional_args-1, -1, -1):
2212 code.putln('case %2d:' % i)
2213 code.put_goto(argtuple_error_label)
2214 else:
2215 code.put('default: ')
2216 code.put_goto(argtuple_error_label)
2217 code.putln('}')
2219 code.putln('}')
2221 if code.label_used(argtuple_error_label):
2222 code.put_goto(success_label)
2223 code.put_label(argtuple_error_label)
2224 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2225 self.name, has_fixed_positional_count,
2226 min_positional_args, max_positional_args,
2227 Naming.args_cname))
2228 code.putln(code.error_goto(self.pos))
2230 def generate_arg_default_assignments(self, code):
2231 for arg in self.args:
2232 if arg.is_generic and arg.default:
2233 code.putln(
2234 "%s = %s;" % (
2235 arg.entry.cname,
2236 arg.calculate_default_value_code(code)))
2238 def generate_stararg_init_code(self, max_positional_args, code):
2239 if self.starstar_arg:
2240 self.starstar_arg.entry.xdecref_cleanup = 0
2241 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2242 self.starstar_arg.entry.cname,
2243 self.starstar_arg.entry.cname,
2244 self.error_value()))
2245 code.put_gotref(self.starstar_arg.entry.cname)
2246 if self.star_arg:
2247 self.star_arg.entry.xdecref_cleanup = 0
2248 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2249 Naming.args_cname,
2250 max_positional_args))
2251 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2252 self.star_arg.entry.cname, Naming.args_cname,
2253 max_positional_args, Naming.args_cname))
2254 code.put_gotref(self.star_arg.entry.cname)
2255 if self.starstar_arg:
2256 code.putln("")
2257 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2258 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2259 code.putln('return %s;' % self.error_value())
2260 code.putln('}')
2261 else:
2262 code.putln("if (unlikely(!%s)) return %s;" % (
2263 self.star_arg.entry.cname, self.error_value()))
2264 code.putln('} else {')
2265 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2266 code.put_incref(Naming.empty_tuple, py_object_type)
2267 code.putln('}')
2269 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2270 has_fixed_positional_count, positional_args,
2271 kw_only_args, argtuple_error_label, code):
2272 all_args = tuple(positional_args) + tuple(kw_only_args)
2273 max_args = len(all_args)
2275 default_args = []
2276 for i, arg in enumerate(all_args):
2277 if arg.default and arg.type.is_pyobject:
2278 default_value = arg.calculate_default_value_code(code)
2279 if arg.type is not PyrexTypes.py_object_type:
2280 default_value = "(PyObject*)"+default_value
2281 default_args.append((i, default_value))
2283 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2284 Naming.kwds_cname)
2285 # it looks funny to separate the init-to-0 from setting the
2286 # default value, but C89 needs this
2287 code.putln("PyObject* values[%d] = {%s};" % (
2288 max_args, ','.join(['0']*max_args)))
2289 for i, default_value in default_args:
2290 code.putln('values[%d] = %s;' % (i, default_value))
2292 # parse the tuple and check that it's not too long
2293 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2294 if self.star_arg:
2295 code.putln('default:')
2296 for i in range(max_positional_args-1, -1, -1):
2297 code.put('case %2d: ' % (i+1))
2298 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2299 i, Naming.args_cname, i))
2300 code.putln('case 0: break;')
2301 if not self.star_arg:
2302 code.put('default: ') # more arguments than allowed
2303 code.put_goto(argtuple_error_label)
2304 code.putln('}')
2306 # now fill up the positional/required arguments with values
2307 # from the kw dict
2308 if self.num_required_args or max_positional_args > 0:
2309 last_required_arg = -1
2310 for i, arg in enumerate(all_args):
2311 if not arg.default:
2312 last_required_arg = i
2313 if last_required_arg < max_positional_args:
2314 last_required_arg = max_positional_args-1
2315 num_required_args = self.num_required_args
2316 if max_positional_args > 0:
2317 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2318 for i, arg in enumerate(all_args[:last_required_arg+1]):
2319 if max_positional_args > 0 and i <= max_positional_args:
2320 if self.star_arg and i == max_positional_args:
2321 code.putln('default:')
2322 else:
2323 code.putln('case %2d:' % i)
2324 pystring_cname = code.intern_identifier(arg.name)
2325 if arg.default:
2326 if arg.kw_only:
2327 # handled separately below
2328 continue
2329 code.putln('if (kw_args > %d) {' % num_required_args)
2330 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2331 Naming.kwds_cname, pystring_cname))
2332 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2333 code.putln('}')
2334 else:
2335 num_required_args -= 1
2336 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2337 i, Naming.kwds_cname, pystring_cname))
2338 code.putln('if (likely(values[%d])) kw_args--;' % i);
2339 if i < min_positional_args:
2340 if i == 0:
2341 # special case: we know arg 0 is missing
2342 code.put('else ')
2343 code.put_goto(argtuple_error_label)
2344 else:
2345 # print the correct number of values (args or
2346 # kwargs) that were passed into positional
2347 # arguments up to this point
2348 code.putln('else {')
2349 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2350 self.name, has_fixed_positional_count,
2351 min_positional_args, max_positional_args, i))
2352 code.putln(code.error_goto(self.pos))
2353 code.putln('}')
2354 elif arg.kw_only:
2355 code.putln('else {')
2356 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2357 self.name, pystring_cname))
2358 code.putln(code.error_goto(self.pos))
2359 code.putln('}')
2360 if max_positional_args > 0:
2361 code.putln('}')
2363 if kw_only_args and not self.starstar_arg:
2364 # unpack optional keyword-only arguments
2365 # checking for interned strings in a dict is faster than iterating
2366 # but it's too likely that we must iterate if we expect **kwargs
2367 optional_args = []
2368 for i, arg in enumerate(all_args[max_positional_args:]):
2369 if not arg.kw_only or not arg.default:
2370 continue
2371 optional_args.append((i+max_positional_args, arg))
2372 if optional_args:
2373 # this mimics an unrolled loop so that we can "break" out of it
2374 code.putln('while (kw_args > 0) {')
2375 code.putln('PyObject* value;')
2376 for i, arg in optional_args:
2377 pystring_cname = code.intern_identifier(arg.name)
2378 code.putln(
2379 'value = PyDict_GetItem(%s, %s);' % (
2380 Naming.kwds_cname, pystring_cname))
2381 code.putln(
2382 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2383 code.putln('break;')
2384 code.putln('}')
2386 code.putln('if (unlikely(kw_args > 0)) {')
2387 # non-positional/-required kw args left in dict: default args,
2388 # kw-only args, **kwargs or error
2389 #
2390 # This is sort of a catch-all: except for checking required
2391 # arguments, this will always do the right thing for unpacking
2392 # keyword arguments, so that we can concentrate on optimising
2393 # common cases above.
2394 if max_positional_args == 0:
2395 pos_arg_count = "0"
2396 elif self.star_arg:
2397 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2398 Naming.args_cname, max_positional_args,
2399 Naming.args_cname, max_positional_args))
2400 pos_arg_count = "used_pos_args"
2401 else:
2402 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2403 code.globalstate.use_utility_code(parse_keywords_utility_code)
2404 code.put(
2405 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2406 Naming.kwds_cname,
2407 Naming.pykwdlist_cname,
2408 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2409 pos_arg_count,
2410 self.name))
2411 code.putln(code.error_goto(self.pos))
2412 code.putln('}')
2414 # convert arg values to their final type and assign them
2415 for i, arg in enumerate(all_args):
2416 if arg.default and not arg.type.is_pyobject:
2417 code.putln("if (values[%d]) {" % i)
2418 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2419 if arg.default and not arg.type.is_pyobject:
2420 code.putln('} else {')
2421 code.putln(
2422 "%s = %s;" % (
2423 arg.entry.cname,
2424 arg.calculate_default_value_code(code)))
2425 code.putln('}')
2427 def generate_argument_conversion_code(self, code):
2428 # Generate code to convert arguments from
2429 # signature type to declared type, if needed.
2430 for arg in self.args:
2431 if arg.needs_conversion:
2432 self.generate_arg_conversion(arg, code)
2434 def generate_arg_conversion(self, arg, code):
2435 # Generate conversion code for one argument.
2436 old_type = arg.hdr_type
2437 new_type = arg.type
2438 if old_type.is_pyobject:
2439 if arg.default:
2440 code.putln("if (%s) {" % arg.hdr_cname)
2441 else:
2442 code.putln("assert(%s); {" % arg.hdr_cname)
2443 self.generate_arg_conversion_from_pyobject(arg, code)
2444 code.putln("}")
2445 elif new_type.is_pyobject:
2446 self.generate_arg_conversion_to_pyobject(arg, code)
2447 else:
2448 if new_type.assignable_from(old_type):
2449 code.putln(
2450 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2451 else:
2452 error(arg.pos,
2453 "Cannot convert 1 argument from '%s' to '%s'" %
2454 (old_type, new_type))
2456 def generate_arg_conversion_from_pyobject(self, arg, code):
2457 new_type = arg.type
2458 func = new_type.from_py_function
2459 # copied from CoerceFromPyTypeNode
2460 if func:
2461 code.putln("%s = %s(%s); %s" % (
2462 arg.entry.cname,
2463 func,
2464 arg.hdr_cname,
2465 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2466 else:
2467 error(arg.pos,
2468 "Cannot convert Python object argument to type '%s'"
2469 % new_type)
2471 def generate_arg_conversion_to_pyobject(self, arg, code):
2472 old_type = arg.hdr_type
2473 func = old_type.to_py_function
2474 if func:
2475 code.putln("%s = %s(%s); %s" % (
2476 arg.entry.cname,
2477 func,
2478 arg.hdr_cname,
2479 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2480 code.put_var_gotref(arg.entry)
2481 else:
2482 error(arg.pos,
2483 "Cannot convert argument of type '%s' to Python object"
2484 % old_type)
2486 def generate_argument_type_tests(self, code):
2487 # Generate type tests for args whose signature
2488 # type is PyObject * and whose declared type is
2489 # a subtype thereof.
2490 for arg in self.args:
2491 if arg.needs_type_test:
2492 self.generate_arg_type_test(arg, code)
2494 def generate_arg_type_test(self, arg, code):
2495 # Generate type test for one argument.
2496 if arg.type.typeobj_is_available():
2497 typeptr_cname = arg.type.typeptr_cname
2498 arg_code = "((PyObject *)%s)" % arg.entry.cname
2499 code.putln(
2500 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2501 arg_code,
2502 typeptr_cname,
2503 not arg.not_none,
2504 arg.name,
2505 arg.type.is_builtin_type,
2506 code.error_goto(arg.pos)))
2507 else:
2508 error(arg.pos, "Cannot test type of extern C class "
2509 "without type object name specification")
2511 def error_value(self):
2512 return self.entry.signature.error_value
2514 def caller_will_check_exceptions(self):
2515 return 1
2517 class OverrideCheckNode(StatNode):
2518 # A Node for dispatching to the def method if it
2519 # is overriden.
2520 #
2521 # py_func
2522 #
2523 # args
2524 # func_temp
2525 # body
2527 child_attrs = ['body']
2529 body = None
2531 def analyse_expressions(self, env):
2532 self.args = env.arg_entries
2533 if self.py_func.is_module_scope:
2534 first_arg = 0
2535 else:
2536 first_arg = 1
2537 import ExprNodes
2538 self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
2539 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2540 call_node = ExprNodes.SimpleCallNode(self.pos,
2541 function=self.func_node,
2542 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2543 self.body = ReturnStatNode(self.pos, value=call_node)
2544 self.body.analyse_expressions(env)
2546 def generate_execution_code(self, code):
2547 interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
2548 # Check to see if we are an extension type
2549 if self.py_func.is_module_scope:
2550 self_arg = "((PyObject *)%s)" % Naming.module_cname
2551 else:
2552 self_arg = "((PyObject *)%s)" % self.args[0].cname
2553 code.putln("/* Check if called by wrapper */")
2554 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2555 code.putln("/* Check if overriden in Python */")
2556 if self.py_func.is_module_scope:
2557 code.putln("else {")
2558 else:
2559 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2560 func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
2561 self.func_node.set_cname(func_node_temp)
2562 # need to get attribute manually--scope would return cdef method
2563 err = code.error_goto_if_null(func_node_temp, self.pos)
2564 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
2565 func_node_temp, self_arg, interned_attr_cname, err))
2566 code.put_gotref(func_node_temp)
2567 is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
2568 is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)" % (
2569 func_node_temp, self.py_func.entry.func_cname)
2570 code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
2571 self.body.generate_execution_code(code)
2572 code.putln("}")
2573 code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
2574 code.funcstate.release_temp(func_node_temp)
2575 code.putln("}")
2577 class ClassDefNode(StatNode, BlockNode):
2578 pass
2580 class PyClassDefNode(ClassDefNode):
2581 # A Python class definition.
2582 #
2583 # name EncodedString Name of the class
2584 # doc string or None
2585 # body StatNode Attribute definition code
2586 # entry Symtab.Entry
2587 # scope PyClassScope
2588 # decorators [DecoratorNode] list of decorators or None
2589 #
2590 # The following subnodes are constructed internally:
2591 #
2592 # dict DictNode Class dictionary
2593 # classobj ClassNode Class object
2594 # target NameNode Variable to assign class object to
2596 child_attrs = ["body", "dict", "classobj", "target"]
2597 decorators = None
2599 def __init__(self, pos, name, bases, doc, body, decorators = None):
2600 StatNode.__init__(self, pos)
2601 self.name = name
2602 self.doc = doc
2603 self.body = body
2604 self.decorators = decorators
2605 import ExprNodes
2606 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2607 if self.doc and Options.docstrings:
2608 doc = embed_position(self.pos, self.doc)
2609 # FIXME: correct string node?
2610 doc_node = ExprNodes.StringNode(pos, value = doc)
2611 else:
2612 doc_node = None
2613 self.classobj = ExprNodes.ClassNode(pos, name = name,
2614 bases = bases, dict = self.dict, doc = doc_node)
2615 self.target = ExprNodes.NameNode(pos, name = name)
2617 def as_cclass(self):
2618 """
2619 Return this node as if it were declared as an extension class
2620 """
2621 bases = self.classobj.bases.args
2622 if len(bases) == 0:
2623 base_class_name = None
2624 base_class_module = None
2625 elif len(bases) == 1:
2626 base = bases[0]
2627 path = []
2628 from ExprNodes import AttributeNode, NameNode
2629 while isinstance(base, AttributeNode):
2630 path.insert(0, base.attribute)
2631 base = base.obj
2632 if isinstance(base, NameNode):
2633 path.insert(0, base.name)
2634 base_class_name = path[-1]
2635 if len(path) > 1:
2636 base_class_module = u'.'.join(path[:-1])
2637 else:
2638 base_class_module = None
2639 else:
2640 error(self.classobj.bases.args.pos, "Invalid base class")
2641 else:
2642 error(self.classobj.bases.args.pos, "C class may only have one base class")
2643 return None
2645 return CClassDefNode(self.pos,
2646 visibility = 'private',
2647 module_name = None,
2648 class_name = self.name,
2649 base_class_module = base_class_module,
2650 base_class_name = base_class_name,
2651 decorators = self.decorators,
2652 body = self.body,
2653 in_pxd = False,
2654 doc = self.doc)
2656 def create_scope(self, env):
2657 genv = env
2658 while env.is_py_class_scope or env.is_c_class_scope:
2659 env = env.outer_scope
2660 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2661 return cenv
2663 def analyse_declarations(self, env):
2664 self.target.analyse_target_declaration(env)
2665 cenv = self.create_scope(env)
2666 cenv.directives = env.directives
2667 cenv.class_obj_cname = self.target.entry.cname
2668 self.body.analyse_declarations(cenv)
2670 def analyse_expressions(self, env):
2671 self.dict.analyse_expressions(env)
2672 self.classobj.analyse_expressions(env)
2673 genv = env.global_scope()
2674 cenv = self.scope
2675 self.body.analyse_expressions(cenv)
2676 self.target.analyse_target_expression(env, self.classobj)
2678 def generate_function_definitions(self, env, code):
2679 self.body.generate_function_definitions(self.scope, code)
2681 def generate_execution_code(self, code):
2682 code.pyclass_stack.append(self)
2683 cenv = self.scope
2684 self.dict.generate_evaluation_code(code)
2685 self.classobj.generate_evaluation_code(code)
2686 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2687 self.body.generate_execution_code(code)
2688 self.target.generate_assignment_code(self.classobj, code)
2689 self.dict.generate_disposal_code(code)
2690 self.dict.free_temps(code)
2691 code.pyclass_stack.pop()
2694 class CClassDefNode(ClassDefNode):
2695 # An extension type definition.
2696 #
2697 # visibility 'private' or 'public' or 'extern'
2698 # typedef_flag boolean
2699 # api boolean
2700 # module_name string or None For import of extern type objects
2701 # class_name string Unqualified name of class
2702 # as_name string or None Name to declare as in this scope
2703 # base_class_module string or None Module containing the base class
2704 # base_class_name string or None Name of the base class
2705 # objstruct_name string or None Specified C name of object struct
2706 # typeobj_name string or None Specified C name of type object
2707 # in_pxd boolean Is in a .pxd file
2708 # decorators [DecoratorNode] list of decorators or None
2709 # doc string or None
2710 # body StatNode or None
2711 # entry Symtab.Entry
2712 # base_type PyExtensionType or None
2713 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2714 # buffer_defaults_pos
2716 child_attrs = ["body"]
2717 buffer_defaults_node = None
2718 buffer_defaults_pos = None
2719 typedef_flag = False
2720 api = False
2721 objstruct_name = None
2722 typeobj_name = None
2723 decorators = None
2725 def analyse_declarations(self, env):
2726 #print "CClassDefNode.analyse_declarations:", self.class_name
2727 #print "...visibility =", self.visibility
2728 #print "...module_name =", self.module_name
2730 import Buffer
2731 if self.buffer_defaults_node:
2732 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2733 env, [], self.buffer_defaults_node,
2734 need_complete=False)
2735 else:
2736 buffer_defaults = None
2738 if env.in_cinclude and not self.objstruct_name:
2739 error(self.pos, "Object struct name specification required for "
2740 "C class defined in 'extern from' block")
2741 self.base_type = None
2742 # Now that module imports are cached, we need to
2743 # import the modules for extern classes.
2744 if self.module_name:
2745 self.module = None
2746 for module in env.cimported_modules:
2747 if module.name == self.module_name:
2748 self.module = module
2749 if self.module is None:
2750 self.module = ModuleScope(self.module_name, None, env.context)
2751 self.module.has_extern_class = 1
2752 env.add_imported_module(self.module)
2754 if self.base_class_name:
2755 if self.base_class_module:
2756 base_class_scope = env.find_module(self.base_class_module, self.pos)
2757 else:
2758 base_class_scope = env
2759 if self.base_class_name == 'object':
2760 # extension classes are special and don't need to inherit from object
2761 if base_class_scope is None or base_class_scope.lookup('object') is None:
2762 self.base_class_name = None
2763 self.base_class_module = None
2764 base_class_scope = None
2765 if base_class_scope:
2766 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2767 if base_class_entry:
2768 if not base_class_entry.is_type:
2769 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2770 elif not base_class_entry.type.is_extension_type:
2771 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2772 elif not base_class_entry.type.is_complete():
2773 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2774 else:
2775 self.base_type = base_class_entry.type
2776 has_body = self.body is not None
2777 if self.module_name and self.visibility != 'extern':
2778 module_path = self.module_name.split(".")
2779 home_scope = env.find_imported_module(module_path, self.pos)
2780 if not home_scope:
2781 return
2782 else:
2783 home_scope = env
2785 if self.visibility == 'extern':
2786 if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
2787 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
2789 self.entry = home_scope.declare_c_class(
2790 name = self.class_name,
2791 pos = self.pos,
2792 defining = has_body and self.in_pxd,
2793 implementing = has_body and not self.in_pxd,
2794 module_name = self.module_name,
2795 base_type = self.base_type,
2796 objstruct_cname = self.objstruct_name,
2797 typeobj_cname = self.typeobj_name,
2798 visibility = self.visibility,
2799 typedef_flag = self.typedef_flag,
2800 api = self.api,
2801 buffer_defaults = buffer_defaults)
2802 if home_scope is not env and self.visibility == 'extern':
2803 env.add_imported_entry(self.class_name, self.entry, pos)
2804 self.scope = scope = self.entry.type.scope
2805 if scope is not None:
2806 scope.directives = env.directives
2808 if self.doc and Options.docstrings:
2809 scope.doc = embed_position(self.pos, self.doc)
2811 if has_body:
2812 self.body.analyse_declarations(scope)
2813 if self.in_pxd:
2814 scope.defined = 1
2815 else:
2816 scope.implemented = 1
2817 env.allocate_vtable_names(self.entry)
2819 def analyse_expressions(self, env):
2820 if self.body:
2821 scope = self.entry.type.scope
2822 self.body.analyse_expressions(scope)
2824 def generate_function_definitions(self, env, code):
2825 if self.body:
2826 self.body.generate_function_definitions(
2827 self.entry.type.scope, code)
2829 def generate_execution_code(self, code):
2830 # This is needed to generate evaluation code for
2831 # default values of method arguments.
2832 if self.body:
2833 self.body.generate_execution_code(code)
2835 def annotate(self, code):
2836 if self.body:
2837 self.body.annotate(code)
2840 class PropertyNode(StatNode):
2841 # Definition of a property in an extension type.
2842 #
2843 # name string
2844 # doc EncodedString or None Doc string
2845 # body StatListNode
2847 child_attrs = ["body"]
2849 def analyse_declarations(self, env):
2850 entry = env.declare_property(self.name, self.doc, self.pos)
2851 if entry:
2852 entry.scope.directives = env.directives
2853 self.body.analyse_declarations(entry.scope)
2855 def analyse_expressions(self, env):
2856 self.body.analyse_expressions(env)
2858 def generate_function_definitions(self, env, code):
2859 self.body.generate_function_definitions(env, code)
2861 def generate_execution_code(self, code):
2862 pass
2864 def annotate(self, code):
2865 self.body.annotate(code)
2868 class GlobalNode(StatNode):
2869 # Global variable declaration.
2870 #
2871 # names [string]
2873 child_attrs = []
2875 def analyse_declarations(self, env):
2876 for name in self.names:
2877 env.declare_global(name, self.pos)
2879 def analyse_expressions(self, env):
2880 pass
2882 def generate_execution_code(self, code):
2883 pass
2886 class ExprStatNode(StatNode):
2887 # Expression used as a statement.
2888 #
2889 # expr ExprNode
2891 child_attrs = ["expr"]
2893 def analyse_declarations(self, env):
2894 import ExprNodes
2895 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2896 func = self.expr.function.as_cython_attribute()
2897 if func == u'declare':
2898 args, kwds = self.expr.explicit_args_kwds()
2899 if len(args):
2900 error(self.expr.pos, "Variable names must be specified.")
2901 for var, type_node in kwds.key_value_pairs:
2902 type = type_node.analyse_as_type(env)
2903 if type is None:
2904 error(type_node.pos, "Unknown type")
2905 else:
2906 env.declare_var(var.value, type, var.pos, is_cdef = True)
2907 self.__class__ = PassStatNode
2909 def analyse_expressions(self, env):
2910 self.expr.analyse_expressions(env)
2912 def generate_execution_code(self, code):
2913 self.expr.generate_evaluation_code(code)
2914 if not self.expr.is_temp and self.expr.result():
2915 code.putln("%s;" % self.expr.result())
2916 self.expr.generate_disposal_code(code)
2917 self.expr.free_temps(code)
2919 def annotate(self, code):
2920 self.expr.annotate(code)
2923 class AssignmentNode(StatNode):
2924 # Abstract base class for assignment nodes.
2925 #
2926 # The analyse_expressions and generate_execution_code
2927 # phases of assignments are split into two sub-phases
2928 # each, to enable all the right hand sides of a
2929 # parallel assignment to be evaluated before assigning
2930 # to any of the left hand sides.
2932 def analyse_expressions(self, env):
2933 self.analyse_types(env)
2935 # def analyse_expressions(self, env):
2936 # self.analyse_expressions_1(env)
2937 # self.analyse_expressions_2(env)
2939 def generate_execution_code(self, code):
2940 self.generate_rhs_evaluation_code(code)
2941 self.generate_assignment_code(code)
2944 class SingleAssignmentNode(AssignmentNode):
2945 # The simplest case:
2946 #
2947 # a = b
2948 #
2949 # lhs ExprNode Left hand side
2950 # rhs ExprNode Right hand side
2951 # first bool Is this guaranteed the first assignment to lhs?
2953 child_attrs = ["lhs", "rhs"]
2954 first = False
2955 declaration_only = False
2957 def analyse_declarations(self, env):
2958 import ExprNodes
2960 # handle declarations of the form x = cython.foo()
2961 if isinstance(self.rhs, ExprNodes.CallNode):
2962 func_name = self.rhs.function.as_cython_attribute()
2963 if func_name:
2964 args, kwds = self.rhs.explicit_args_kwds()
2966 if func_name in ['declare', 'typedef']:
2967 if len(args) > 2 or kwds is not None:
2968 error(rhs.pos, "Can only declare one type at a time.")
2969 return
2970 type = args[0].analyse_as_type(env)
2971 if type is None:
2972 error(args[0].pos, "Unknown type")
2973 return
2974 lhs = self.lhs
2975 if func_name == 'declare':
2976 if isinstance(lhs, ExprNodes.NameNode):
2977 vars = [(lhs.name, lhs.pos)]
2978 elif isinstance(lhs, ExprNodes.TupleNode):
2979 vars = [(var.name, var.pos) for var in lhs.args]
2980 else:
2981 error(lhs.pos, "Invalid declaration")
2982 return
2983 for var, pos in vars:
2984 env.declare_var(var, type, pos, is_cdef = True)
2985 if len(args) == 2:
2986 # we have a value
2987 self.rhs = args[1]
2988 else:
2989 self.declaration_only = True
2990 else:
2991 self.declaration_only = True
2992 if not isinstance(lhs, ExprNodes.NameNode):
2993 error(lhs.pos, "Invalid declaration.")
2994 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2996 elif func_name in ['struct', 'union']:
2997 self.declaration_only = True
2998 if len(args) > 0 or kwds is None:
2999 error(rhs.pos, "Struct or union members must be given by name.")
3000 return
3001 members = []
3002 for member, type_node in kwds.key_value_pairs:
3003 type = type_node.analyse_as_type(env)
3004 if type is None:
3005 error(type_node.pos, "Unknown type")
3006 else:
3007 members.append((member.value, type, member.pos))
3008 if len(members) < len(kwds.key_value_pairs):
3009 return
3010 if not isinstance(self.lhs, ExprNodes.NameNode):
3011 error(self.lhs.pos, "Invalid declaration.")
3012 name = self.lhs.name
3013 scope = StructOrUnionScope(name)
3014 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
3015 for member, type, pos in members:
3016 scope.declare_var(member, type, pos)
3018 if self.declaration_only:
3019 return
3020 else:
3021 self.lhs.analyse_target_declaration(env)
3023 def analyse_types(self, env, use_temp = 0):
3024 self.rhs.analyse_types(env)
3025 self.lhs.analyse_target_types(env)
3026 self.lhs.gil_assignment_check(env)
3027 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3028 if use_temp:
3029 self.rhs = self.rhs.coerce_to_temp(env)
3031 def generate_rhs_evaluation_code(self, code):
3032 self.rhs.generate_evaluation_code(code)
3034 def generate_assignment_code(self, code):
3035 self.lhs.generate_assignment_code(self.rhs, code)
3037 def annotate(self, code):
3038 self.lhs.annotate(code)
3039 self.rhs.annotate(code)
3042 class CascadedAssignmentNode(AssignmentNode):
3043 # An assignment with multiple left hand sides:
3044 #
3045 # a = b = c
3046 #
3047 # lhs_list [ExprNode] Left hand sides
3048 # rhs ExprNode Right hand sides
3049 #
3050 # Used internally:
3051 #
3052 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
3054 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
3055 coerced_rhs_list = None
3057 def analyse_declarations(self, env):
3058 for lhs in self.lhs_list:
3059 lhs.analyse_target_declaration(env)
3061 def analyse_types(self, env, use_temp = 0):
3062 self.rhs.analyse_types(env)
3063 if use_temp:
3064 self.rhs = self.rhs.coerce_to_temp(env)
3065 else:
3066 self.rhs = self.rhs.coerce_to_simple(env)
3067 from ExprNodes import CloneNode
3068 self.coerced_rhs_list = []
3069 for lhs in self.lhs_list:
3070 lhs.analyse_target_types(env)
3071 lhs.gil_assignment_check(env)
3072 rhs = CloneNode(self.rhs)
3073 rhs = rhs.coerce_to(lhs.type, env)
3074 self.coerced_rhs_list.append(rhs)
3076 def generate_rhs_evaluation_code(self, code):
3077 self.rhs.generate_evaluation_code(code)
3079 def generate_assignment_code(self, code):
3080 for i in range(len(self.lhs_list)):
3081 lhs = self.lhs_list[i]
3082 rhs = self.coerced_rhs_list[i]
3083 rhs.generate_evaluation_code(code)
3084 lhs.generate_assignment_code(rhs, code)
3085 # Assignment has disposed of the cloned RHS
3086 self.rhs.generate_disposal_code(code)
3087 self.rhs.free_temps(code)
3089 def annotate(self, code):
3090 for i in range(len(self.lhs_list)):
3091 lhs = self.lhs_list[i].annotate(code)
3092 rhs = self.coerced_rhs_list[i].annotate(code)
3093 self.rhs.annotate(code)
3096 class ParallelAssignmentNode(AssignmentNode):
3097 # A combined packing/unpacking assignment:
3098 #
3099 # a, b, c = d, e, f
3100 #
3101 # This has been rearranged by the parser into
3102 #
3103 # a = d ; b = e ; c = f
3104 #
3105 # but we must evaluate all the right hand sides
3106 # before assigning to any of the left hand sides.
3107 #
3108 # stats [AssignmentNode] The constituent assignments
3110 child_attrs = ["stats"]
3112 def analyse_declarations(self, env):
3113 for stat in self.stats:
3114 stat.analyse_declarations(env)
3116 def analyse_expressions(self, env):
3117 for stat in self.stats:
3118 stat.analyse_types(env, use_temp = 1)
3120 # def analyse_expressions(self, env):
3121 # for stat in self.stats:
3122 # stat.analyse_expressions_1(env, use_temp = 1)
3123 # for stat in self.stats:
3124 # stat.analyse_expressions_2(env)
3126 def generate_execution_code(self, code):
3127 for stat in self.stats:
3128 stat.generate_rhs_evaluation_code(code)
3129 for stat in self.stats:
3130 stat.generate_assignment_code(code)
3132 def annotate(self, code):
3133 for stat in self.stats:
3134 stat.annotate(code)
3137 class InPlaceAssignmentNode(AssignmentNode):
3138 # An in place arithmatic operand:
3139 #
3140 # a += b
3141 # a -= b
3142 # ...
3143 #
3144 # lhs ExprNode Left hand side
3145 # rhs ExprNode Right hand side
3146 # op char one of "+-*/%^&|"
3147 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3148 #
3149 # This code is a bit tricky because in order to obey Python
3150 # semantics the sub-expressions (e.g. indices) of the lhs must
3151 # not be evaluated twice. So we must re-use the values calculated
3152 # in evaluation phase for the assignment phase as well.
3153 # Fortunately, the type of the lhs node is fairly constrained
3154 # (it must be a NameNode, AttributeNode, or IndexNode).
3156 child_attrs = ["lhs", "rhs"]
3157 dup = None
3159 def analyse_declarations(self, env):
3160 self.lhs.analyse_target_declaration(env)
3162 def analyse_types(self, env):
3163 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3164 self.rhs.analyse_types(env)
3165 self.lhs.analyse_target_types(env)
3166 import ExprNodes
3167 if self.lhs.type.is_pyobject:
3168 self.rhs = self.rhs.coerce_to_pyobject(env)
3169 elif self.rhs.type.is_pyobject:
3170 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3171 if self.lhs.type.is_pyobject:
3172 self.result_value_temp = ExprNodes.PyTempNode(self.pos, env)
3173 self.result_value = self.result_value_temp.coerce_to(self.lhs.type, env)
3175 def generate_execution_code(self, code):
3176 import ExprNodes
3177 self.rhs.generate_evaluation_code(code)
3178 self.dup.generate_subexpr_evaluation_code(code)
3179 if self.dup.is_temp:
3180 self.dup.allocate_temp_result(code)
3181 # self.dup.generate_result_code is run only if it is not buffer access
3182 if self.operator == "**":
3183 extra = ", Py_None"
3184 else:
3185 extra = ""
3186 if self.lhs.type.is_pyobject:
3187 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3188 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3189 self.dup.generate_result_code(code)
3190 self.result_value_temp.allocate(code)
3191 code.putln(
3192 "%s = %s(%s, %s%s); %s" % (
3193 self.result_value.result(),
3194 self.py_operation_function(),
3195 self.dup.py_result(),
3196 self.rhs.py_result(),
3197 extra,
3198 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3199 code.put_gotref(self.result_value.py_result())
3200 self.result_value.generate_evaluation_code(code) # May be a type check...
3201 self.rhs.generate_disposal_code(code)
3202 self.rhs.free_temps(code)
3203 self.dup.generate_disposal_code(code)
3204 self.dup.free_temps(code)
3205 self.lhs.generate_assignment_code(self.result_value, code)
3206 self.result_value_temp.release(code)
3207 else:
3208 c_op = self.operator
3209 if c_op == "//":
3210 c_op = "/"
3211 elif c_op == "**":
3212 error(self.pos, "No C inplace power operator")
3213 elif self.lhs.type.is_complex:
3214 error(self.pos, "Inplace operators not implemented for complex types.")
3216 # have to do assignment directly to avoid side-effects
3217 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3218 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3219 else:
3220 self.dup.generate_result_code(code)
3221 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3222 self.rhs.generate_disposal_code(code)
3223 self.rhs.free_temps(code)
3224 if self.dup.is_temp:
3225 self.dup.generate_subexpr_disposal_code(code)
3226 self.dup.free_subexpr_temps(code)
3228 def create_dup_node(self, env):
3229 import ExprNodes
3230 self.dup = self.lhs
3231 self.dup.analyse_types(env)
3232 if isinstance(self.lhs, ExprNodes.NameNode):
3233 target_lhs = ExprNodes.NameNode(self.dup.pos,
3234 name = self.dup.name,
3235 is_temp = self.dup.is_temp,
3236 entry = self.dup.entry)
3237 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3238 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3239 obj = ExprNodes.CloneNode(self.lhs.obj),
3240 attribute = self.dup.attribute,
3241 is_temp = self.dup.is_temp)
3242 elif isinstance(self.lhs, ExprNodes.IndexNode):
3243 if self.lhs.index:
3244 index = ExprNodes.CloneNode(self.lhs.index)
3245 else:
3246 index = None
3247 if self.lhs.indices:
3248 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3249 else:
3250 indices = []
3251 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3252 base = ExprNodes.CloneNode(self.dup.base),
3253 index = index,
3254 indices = indices,
3255 is_temp = self.dup.is_temp)
3256 else:
3257 assert False
3258 self.lhs = target_lhs
3259 return self.dup
3261 def py_operation_function(self):
3262 return self.py_functions[self.operator]
3264 py_functions = {
3265 "|": "PyNumber_InPlaceOr",
3266 "^": "PyNumber_InPlaceXor",
3267 "&": "PyNumber_InPlaceAnd",
3268 "+": "PyNumber_InPlaceAdd",
3269 "-": "PyNumber_InPlaceSubtract",
3270 "*": "PyNumber_InPlaceMultiply",
3271 "/": "__Pyx_PyNumber_InPlaceDivide",
3272 "%": "PyNumber_InPlaceRemainder",
3273 "<<": "PyNumber_InPlaceLshift",
3274 ">>": "PyNumber_InPlaceRshift",
3275 "**": "PyNumber_InPlacePower",
3276 "//": "PyNumber_InPlaceFloorDivide",
3277 }
3279 def annotate(self, code):
3280 self.lhs.annotate(code)
3281 self.rhs.annotate(code)
3282 self.dup.annotate(code)
3284 def create_binop_node(self):
3285 import ExprNodes
3286 return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
3289 class PrintStatNode(StatNode):
3290 # print statement
3291 #
3292 # arg_tuple TupleNode
3293 # append_newline boolean
3295 child_attrs = ["arg_tuple"]
3297 def analyse_expressions(self, env):
3298 self.arg_tuple.analyse_expressions(env)
3299 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3300 env.use_utility_code(printing_utility_code)
3301 if len(self.arg_tuple.args) == 1 and self.append_newline:
3302 env.use_utility_code(printing_one_utility_code)
3304 nogil_check = Node.gil_error
3305 gil_message = "Python print statement"
3307 def generate_execution_code(self, code):
3308 if len(self.arg_tuple.args) == 1 and self.append_newline:
3309 arg = self.arg_tuple.args[0]
3310 arg.generate_evaluation_code(code)
3312 code.putln(
3313 "if (__Pyx_PrintOne(%s) < 0) %s" % (
3314 arg.py_result(),
3315 code.error_goto(self.pos)))
3316 arg.generate_disposal_code(code)
3317 arg.free_temps(code)
3318 else:
3319 self.arg_tuple.generate_evaluation_code(code)
3320 code.putln(
3321 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3322 self.arg_tuple.py_result(),
3323 self.append_newline,
3324 code.error_goto(self.pos)))
3325 self.arg_tuple.generate_disposal_code(code)
3326 self.arg_tuple.free_temps(code)
3328 def annotate(self, code):
3329 self.arg_tuple.annotate(code)
3332 class ExecStatNode(StatNode):
3333 # exec statement
3334 #
3335 # args [ExprNode]
3337 child_attrs = ["args"]
3339 def analyse_expressions(self, env):
3340 for i, arg in enumerate(self.args):
3341 arg.analyse_expressions(env)
3342 arg = arg.coerce_to_pyobject(env)
3343 self.args[i] = arg
3344 env.use_utility_code(Builtin.pyexec_utility_code)
3346 nogil_check = Node.gil_error
3347 gil_message = "Python exec statement"
3349 def generate_execution_code(self, code):
3350 args = []
3351 for arg in self.args:
3352 arg.generate_evaluation_code(code)
3353 args.append( arg.py_result() )
3354 args = tuple(args + ['0', '0'][:3-len(args)])
3355 temp_result = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
3356 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3357 (temp_result,) + args))
3358 for arg in self.args:
3359 arg.generate_disposal_code(code)
3360 arg.free_temps(code)
3361 code.putln(
3362 code.error_goto_if_null(temp_result, self.pos))
3363 code.put_gotref(temp_result)
3364 code.put_decref_clear(temp_result, py_object_type)
3365 code.funcstate.release_temp(temp_result)
3367 def annotate(self, code):
3368 for arg in self.args:
3369 arg.annotate(code)
3372 class DelStatNode(StatNode):
3373 # del statement
3374 #
3375 # args [ExprNode]
3377 child_attrs = ["args"]
3379 def analyse_declarations(self, env):
3380 for arg in self.args:
3381 arg.analyse_target_declaration(env)
3383 def analyse_expressions(self, env):
3384 for arg in self.args:
3385 arg.analyse_target_expression(env, None)
3386 if not arg.type.is_pyobject:
3387 error(arg.pos, "Deletion of non-Python object")
3388 #arg.release_target_temp(env)
3390 def nogil_check(self, env):
3391 for arg in self.args:
3392 if arg.type.is_pyobject:
3393 self.gil_error()
3395 gil_message = "Deleting Python object"
3397 def generate_execution_code(self, code):
3398 for arg in self.args:
3399 if arg.type.is_pyobject:
3400 arg.generate_deletion_code(code)
3401 # else error reported earlier
3403 def annotate(self, code):
3404 for arg in self.args:
3405 arg.annotate(code)
3408 class PassStatNode(StatNode):
3409 # pass statement
3411 child_attrs = []
3413 def analyse_expressions(self, env):
3414 pass
3416 def generate_execution_code(self, code):
3417 pass
3420 class BreakStatNode(StatNode):
3422 child_attrs = []
3424 def analyse_expressions(self, env):
3425 pass
3427 def generate_execution_code(self, code):
3428 if not code.break_label:
3429 error(self.pos, "break statement not inside loop")
3430 else:
3431 code.put_goto(code.break_label)
3434 class ContinueStatNode(StatNode):
3436 child_attrs = []
3438 def analyse_expressions(self, env):
3439 pass
3441 def generate_execution_code(self, code):
3442 if code.funcstate.in_try_finally:
3443 error(self.pos, "continue statement inside try of try...finally")
3444 elif not code.continue_label:
3445 error(self.pos, "continue statement not inside loop")
3446 else:
3447 code.put_goto(code.continue_label)
3450 class ReturnStatNode(StatNode):
3451 # return statement
3452 #
3453 # value ExprNode or None
3454 # return_type PyrexType
3456 child_attrs = ["value"]
3458 def analyse_expressions(self, env):
3459 return_type = env.return_type
3460 self.return_type = return_type
3461 if not return_type:
3462 error(self.pos, "Return not inside a function body")
3463 return
3464 if self.value:
3465 self.value.analyse_types(env)
3466 if return_type.is_void or return_type.is_returncode:
3467 error(self.value.pos,
3468 "Return with value in void function")
3469 else:
3470 self.value = self.value.coerce_to(env.return_type, env)
3471 else:
3472 if (not return_type.is_void
3473 and not return_type.is_pyobject
3474 and not return_type.is_returncode):
3475 error(self.pos, "Return value required")
3477 def nogil_check(self, env):
3478 if self.return_type.is_pyobject:
3479 self.gil_error()
3481 gil_message = "Returning Python object"
3483 def generate_execution_code(self, code):
3484 code.mark_pos(self.pos)
3485 if not self.return_type:
3486 # error reported earlier
3487 return
3488 if self.return_type.is_pyobject:
3489 code.put_xdecref(Naming.retval_cname,
3490 self.return_type)
3491 if self.value:
3492 self.value.generate_evaluation_code(code)
3493 self.value.make_owned_reference(code)
3494 code.putln(
3495 "%s = %s;" % (
3496 Naming.retval_cname,
3497 self.value.result_as(self.return_type)))
3498 self.value.generate_post_assignment_code(code)
3499 self.value.free_temps(code)
3500 else:
3501 if self.return_type.is_pyobject:
3502 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3503 elif self.return_type.is_returncode:
3504 code.putln(
3505 "%s = %s;" % (
3506 Naming.retval_cname,
3507 self.return_type.default_value))
3508 for cname, type in code.funcstate.temps_holding_reference():
3509 code.put_decref_clear(cname, type)
3510 code.put_goto(code.return_label)
3512 def annotate(self, code):
3513 if self.value:
3514 self.value.annotate(code)
3517 class RaiseStatNode(StatNode):
3518 # raise statement
3519 #
3520 # exc_type ExprNode or None
3521 # exc_value ExprNode or None
3522 # exc_tb ExprNode or None
3524 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3526 def analyse_expressions(self, env):
3527 if self.exc_type:
3528 self.exc_type.analyse_types(env)
3529 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3530 if self.exc_value:
3531 self.exc_value.analyse_types(env)
3532 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3533 if self.exc_tb:
3534 self.exc_tb.analyse_types(env)
3535 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3536 env.use_utility_code(raise_utility_code)
3538 nogil_check = Node.gil_error
3539 gil_message = "Raising exception"
3541 def generate_execution_code(self, code):
3542 if self.exc_type:
3543 self.exc_type.generate_evaluation_code(code)
3544 type_code = self.exc_type.py_result()
3545 else:
3546 type_code = "0"
3547 if self.exc_value:
3548 self.exc_value.generate_evaluation_code(code)
3549 value_code = self.exc_value.py_result()
3550 else:
3551 value_code = "0"
3552 if self.exc_tb:
3553 self.exc_tb.generate_evaluation_code(code)
3554 tb_code = self.exc_tb.py_result()
3555 else:
3556 tb_code = "0"
3557 code.putln(
3558 "__Pyx_Raise(%s, %s, %s);" % (
3559 type_code,
3560 value_code,
3561 tb_code))
3562 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3563 if obj:
3564 obj.generate_disposal_code(code)
3565 obj.free_temps(code)
3566 code.putln(
3567 code.error_goto(self.pos))
3569 def annotate(self, code):
3570 if self.exc_type:
3571 self.exc_type.annotate(code)
3572 if self.exc_value:
3573 self.exc_value.annotate(code)
3574 if self.exc_tb:
3575 self.exc_tb.annotate(code)
3578 class ReraiseStatNode(StatNode):
3580 child_attrs = []
3582 def analyse_expressions(self, env):
3583 env.use_utility_code(restore_exception_utility_code)
3585 nogil_check = Node.gil_error
3586 gil_message = "Raising exception"
3588 def generate_execution_code(self, code):
3589 vars = code.funcstate.exc_vars
3590 if vars:
3591 for varname in vars:
3592 code.put_giveref(varname)
3593 code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars))
3594 for varname in vars:
3595 code.put("%s = 0; " % varname)
3596 code.putln()
3597 code.putln(code.error_goto(self.pos))
3598 else:
3599 error(self.pos, "Reraise not inside except clause")
3602 class AssertStatNode(StatNode):
3603 # assert statement
3604 #
3605 # cond ExprNode
3606 # value ExprNode or None
3608 child_attrs = ["cond", "value"]
3610 def analyse_expressions(self, env):
3611 self.cond = self.cond.analyse_boolean_expression(env)
3612 if self.value:
3613 self.value.analyse_types(env)
3614 self.value = self.value.coerce_to_pyobject(env)
3616 nogil_check = Node.gil_error
3617 gil_message = "Raising exception"
3619 def generate_execution_code(self, code):
3620 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3621 self.cond.generate_evaluation_code(code)
3622 code.putln(
3623 "if (unlikely(!%s)) {" %
3624 self.cond.result())
3625 if self.value:
3626 self.value.generate_evaluation_code(code)
3627 code.putln(
3628 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3629 self.value.py_result())
3630 self.value.generate_disposal_code(code)
3631 self.value.free_temps(code)
3632 else:
3633 code.putln(
3634 "PyErr_SetNone(PyExc_AssertionError);")
3635 code.putln(
3636 code.error_goto(self.pos))
3637 code.putln(
3638 "}")
3639 self.cond.generate_disposal_code(code)
3640 self.cond.free_temps(code)
3641 code.putln("#endif")
3643 def annotate(self, code):
3644 self.cond.annotate(code)
3645 if self.value:
3646 self.value.annotate(code)
3649 class IfStatNode(StatNode):
3650 # if statement
3651 #
3652 # if_clauses [IfClauseNode]
3653 # else_clause StatNode or None
3655 child_attrs = ["if_clauses", "else_clause"]
3657 def analyse_control_flow(self, env):
3658 env.start_branching(self.pos)
3659 for if_clause in self.if_clauses:
3660 if_clause.analyse_control_flow(env)
3661 env.next_branch(if_clause.end_pos())
3662 if self.else_clause:
3663 self.else_clause.analyse_control_flow(env)
3664 env.finish_branching(self.end_pos())
3666 def analyse_declarations(self, env):
3667 for if_clause in self.if_clauses:
3668 if_clause.analyse_declarations(env)
3669 if self.else_clause:
3670 self.else_clause.analyse_declarations(env)
3672 def analyse_expressions(self, env):
3673 for if_clause in self.if_clauses:
3674 if_clause.analyse_expressions(env)
3675 if self.else_clause:
3676 self.else_clause.analyse_expressions(env)
3678 def generate_execution_code(self, code):
3679 code.mark_pos(self.pos)
3680 end_label = code.new_label()
3681 for if_clause in self.if_clauses:
3682 if_clause.generate_execution_code(code, end_label)
3683 if self.else_clause:
3684 code.putln("/*else*/ {")
3685 self.else_clause.generate_execution_code(code)
3686 code.putln("}")
3687 code.put_label(end_label)
3689 def annotate(self, code):
3690 for if_clause in self.if_clauses:
3691 if_clause.annotate(code)
3692 if self.else_clause:
3693 self.else_clause.annotate(code)
3696 class IfClauseNode(Node):
3697 # if or elif clause in an if statement
3698 #
3699 # condition ExprNode
3700 # body StatNode
3702 child_attrs = ["condition", "body"]
3704 def analyse_control_flow(self, env):
3705 self.body.analyse_control_flow(env)
3707 def analyse_declarations(self, env):
3708 self.condition.analyse_declarations(env)
3709 self.body.analyse_declarations(env)
3711 def analyse_expressions(self, env):
3712 self.condition = \
3713 self.condition.analyse_temp_boolean_expression(env)
3714 self.body.analyse_expressions(env)
3716 def generate_execution_code(self, code, end_label):
3717 self.condition.generate_evaluation_code(code)
3718 code.putln(
3719 "if (%s) {" %
3720 self.condition.result())
3721 self.condition.generate_disposal_code(code)
3722 self.condition.free_temps(code)
3723 self.body.generate_execution_code(code)
3724 #code.putln(
3725 # "goto %s;" %
3726 # end_label)
3727 code.put_goto(end_label)
3728 code.putln("}")
3730 def annotate(self, code):
3731 self.condition.annotate(code)
3732 self.body.annotate(code)
3735 class SwitchCaseNode(StatNode):
3736 # Generated in the optimization of an if-elif-else node
3737 #
3738 # conditions [ExprNode]
3739 # body StatNode
3741 child_attrs = ['conditions', 'body']
3743 def generate_execution_code(self, code):
3744 for cond in self.conditions:
3745 code.mark_pos(cond.pos)
3746 cond.generate_evaluation_code(code)
3747 code.putln("case %s:" % cond.result())
3748 self.body.generate_execution_code(code)
3749 code.putln("break;")
3751 def annotate(self, code):
3752 for cond in self.conditions:
3753 cond.annotate(code)
3754 self.body.annotate(code)
3756 class SwitchStatNode(StatNode):
3757 # Generated in the optimization of an if-elif-else node
3758 #
3759 # test ExprNode
3760 # cases [SwitchCaseNode]
3761 # else_clause StatNode or None
3763 child_attrs = ['test', 'cases', 'else_clause']
3765 def generate_execution_code(self, code):
3766 code.putln("switch (%s) {" % self.test.result())
3767 for case in self.cases:
3768 case.generate_execution_code(code)
3769 if self.else_clause is not None:
3770 code.putln("default:")
3771 self.else_clause.generate_execution_code(code)
3772 code.putln("break;")
3773 code.putln("}")
3775 def annotate(self, code):
3776 self.test.annotate(code)
3777 for case in self.cases:
3778 case.annotate(code)
3779 if self.else_clause is not None:
3780 self.else_clause.annotate(code)
3782 class LoopNode(object):
3784 def analyse_control_flow(self, env):
3785 env.start_branching(self.pos)
3786 self.body.analyse_control_flow(env)
3787 env.next_branch(self.body.end_pos())
3788 if self.else_clause:
3789 self.else_clause.analyse_control_flow(env)
3790 env.finish_branching(self.end_pos())
3793 class WhileStatNode(LoopNode, StatNode):
3794 # while statement
3795 #
3796 # condition ExprNode
3797 # body StatNode
3798 # else_clause StatNode
3800 child_attrs = ["condition", "body", "else_clause"]
3802 def analyse_declarations(self, env):
3803 self.body.analyse_declarations(env)
3804 if self.else_clause:
3805 self.else_clause.analyse_declarations(env)
3807 def analyse_expressions(self, env):
3808 self.condition = \
3809 self.condition.analyse_temp_boolean_expression(env)
3810 self.body.analyse_expressions(env)
3811 if self.else_clause:
3812 self.else_clause.analyse_expressions(env)
3814 def generate_execution_code(self, code):
3815 old_loop_labels = code.new_loop_labels()
3816 code.putln(
3817 "while (1) {")
3818 self.condition.generate_evaluation_code(code)
3819 self.condition.generate_disposal_code(code)
3820 code.putln(
3821 "if (!%s) break;" %
3822 self.condition.result())
3823 self.condition.free_temps(code)
3824 self.body.generate_execution_code(code)
3825 code.put_label(code.continue_label)
3826 code.putln("}")
3827 break_label = code.break_label
3828 code.set_loop_labels(old_loop_labels)
3829 if self.else_clause:
3830 code.putln("/*else*/ {")
3831 self.else_clause.generate_execution_code(code)
3832 code.putln("}")
3833 code.put_label(break_label)
3835 def annotate(self, code):
3836 self.condition.annotate(code)
3837 self.body.annotate(code)
3838 if self.else_clause:
3839 self.else_clause.annotate(code)
3842 def ForStatNode(pos, **kw):
3843 if 'iterator' in kw:
3844 return ForInStatNode(pos, **kw)
3845 else:
3846 return ForFromStatNode(pos, **kw)
3848 class ForInStatNode(LoopNode, StatNode):
3849 # for statement
3850 #
3851 # target ExprNode
3852 # iterator IteratorNode
3853 # body StatNode
3854 # else_clause StatNode
3855 # item NextNode used internally
3857 child_attrs = ["target", "iterator", "body", "else_clause"]
3858 item = None
3860 def analyse_declarations(self, env):
3861 self.target.analyse_target_declaration(env)
3862 self.body.analyse_declarations(env)
3863 if self.else_clause:
3864 self.else_clause.analyse_declarations(env)
3866 def analyse_expressions(self, env):
3867 import ExprNodes
3868 self.target.analyse_target_types(env)
3869 self.iterator.analyse_expressions(env)
3870 self.item = ExprNodes.NextNode(self.iterator, env)
3871 self.item = self.item.coerce_to(self.target.type, env)
3872 self.body.analyse_expressions(env)
3873 if self.else_clause:
3874 self.else_clause.analyse_expressions(env)
3876 def generate_execution_code(self, code):
3877 old_loop_labels = code.new_loop_labels()
3878 self.iterator.allocate_counter_temp(code)
3879 self.iterator.generate_evaluation_code(code)
3880 code.putln(
3881 "for (;;) {")
3882 self.item.generate_evaluation_code(code)
3883 self.target.generate_assignment_code(self.item, code)
3884 self.body.generate_execution_code(code)
3885 code.put_label(code.continue_label)
3886 code.putln(
3887 "}")
3888 break_label = code.break_label
3889 code.set_loop_labels(old_loop_labels)
3890 if self.else_clause:
3891 code.putln("/*else*/ {")
3892 self.else_clause.generate_execution_code(code)
3893 code.putln("}")
3894 code.put_label(break_label)
3895 self.iterator.release_counter_temp(code)
3896 self.iterator.generate_disposal_code(code)
3897 self.iterator.free_temps(code)
3899 def annotate(self, code):
3900 self.target.annotate(code)
3901 self.iterator.annotate(code)
3902 self.body.annotate(code)
3903 if self.else_clause:
3904 self.else_clause.annotate(code)
3905 self.item.annotate(code)
3908 class ForFromStatNode(LoopNode, StatNode):
3909 # for name from expr rel name rel expr
3910 #
3911 # target NameNode
3912 # bound1 ExprNode
3913 # relation1 string
3914 # relation2 string
3915 # bound2 ExprNode
3916 # step ExprNode or None
3917 # body StatNode
3918 # else_clause StatNode or None
3919 #
3920 # Used internally:
3921 #
3922 # from_range bool
3923 # is_py_target bool
3924 # loopvar_node ExprNode (usually a NameNode or temp node)
3925 # py_loopvar_node PyTempNode or None
3926 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3928 is_py_target = False
3929 loopvar_node = None
3930 py_loopvar_node = None
3931 from_range = False
3933 gil_message = "For-loop using object bounds or target"
3935 def nogil_check(self, env):
3936 for x in (self.target, self.bound1, self.bound2):
3937 if x.type.is_pyobject:
3938 self.gil_error()
3940 def analyse_declarations(self, env):
3941 self.target.analyse_target_declaration(env)
3942 self.body.analyse_declarations(env)
3943 if self.else_clause:
3944 self.else_clause.analyse_declarations(env)
3946 def analyse_expressions(self, env):
3947 import ExprNodes
3948 self.target.analyse_target_types(env)
3949 self.bound1.analyse_types(env)
3950 self.bound2.analyse_types(env)
3951 if self.step is not None:
3952 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3953 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3954 self.step.analyse_types(env)
3956 target_type = self.target.type
3957 if self.target.type.is_numeric:
3958 loop_type = self.target.type
3959 else:
3960 loop_type = PyrexTypes.c_int_type
3961 if not self.bound1.type.is_pyobject:
3962 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
3963 if not self.bound2.type.is_pyobject:
3964 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
3965 if self.step is not None and not self.step.type.is_pyobject:
3966 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
3967 self.bound1 = self.bound1.coerce_to(loop_type, env)
3968 self.bound2 = self.bound2.coerce_to(loop_type, env)
3969 if not self.bound2.is_literal:
3970 self.bound2 = self.bound2.coerce_to_temp(env)
3971 if self.step is not None:
3972 self.step = self.step.coerce_to(loop_type, env)
3973 if not self.step.is_literal:
3974 self.step = self.step.coerce_to_temp(env)
3976 target_type = self.target.type
3977 if not (target_type.is_pyobject or target_type.is_numeric):
3978 error(self.target.pos,
3979 "for-from loop variable must be c numeric type or Python object")
3980 if target_type.is_numeric:
3981 self.is_py_target = False
3982 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3983 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3984 self.loopvar_node = self.target
3985 self.py_loopvar_node = None
3986 else:
3987 self.is_py_target = True
3988 c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
3989 self.loopvar_node = c_loopvar_node
3990 self.py_loopvar_node = \
3991 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3992 self.body.analyse_expressions(env)
3993 if self.else_clause:
3994 self.else_clause.analyse_expressions(env)
3996 def generate_execution_code(self, code):
3997 old_loop_labels = code.new_loop_labels()
3998 from_range = self.from_range
3999 self.bound1.generate_evaluation_code(code)
4000 self.bound2.generate_evaluation_code(code)
4001 offset, incop = self.relation_table[self.relation1]
4002 if self.step is not None:
4003 self.step.generate_evaluation_code(code)
4004 step = self.step.result()
4005 incop = "%s=%s" % (incop[0], step)
4006 import ExprNodes
4007 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4008 self.loopvar_node.allocate(code)
4009 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4010 self.py_loopvar_node.allocate(code)
4011 if from_range:
4012 loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
4013 else:
4014 loopvar_name = self.loopvar_node.result()
4015 code.putln(
4016 "for (%s = %s%s; %s %s %s; %s%s) {" % (
4017 loopvar_name,
4018 self.bound1.result(), offset,
4019 loopvar_name, self.relation2, self.bound2.result(),
4020 loopvar_name, incop))
4021 if self.py_loopvar_node:
4022 self.py_loopvar_node.generate_evaluation_code(code)
4023 self.target.generate_assignment_code(self.py_loopvar_node, code)
4024 elif from_range:
4025 code.putln("%s = %s;" % (
4026 self.target.result(), loopvar_name))
4027 self.body.generate_execution_code(code)
4028 code.put_label(code.continue_label)
4029 if self.py_loopvar_node:
4030 # This mess is to make for..from loops with python targets behave
4031 # exactly like those with C targets with regards to re-assignment
4032 # of the loop variable.
4033 import ExprNodes
4034 if self.target.entry.is_pyglobal:
4035 # We know target is a NameNode, this is the only ugly case.
4036 target_node = ExprNodes.PyTempNode(self.target.pos, None)
4037 target_node.allocate(code)
4038 interned_cname = code.intern_identifier(self.target.entry.name)
4039 code.putln("/*here*/")
4040 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
4041 target_node.result(),
4042 Naming.module_cname,
4043 interned_cname,
4044 code.error_goto_if_null(target_node.result(), self.target.pos)))
4045 code.put_gotref(target_node.result())
4046 else:
4047 target_node = self.target
4048 from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
4049 from_py_node.temp_code = loopvar_name
4050 from_py_node.generate_result_code(code)
4051 if self.target.entry.is_pyglobal:
4052 code.put_decref(target_node.result(), target_node.type)
4053 target_node.release(code)
4054 code.putln("}")
4055 if self.py_loopvar_node:
4056 # This is potentially wasteful, but we don't want the semantics to
4057 # depend on whether or not the loop is a python type.
4058 self.py_loopvar_node.generate_evaluation_code(code)
4059 self.target.generate_assignment_code(self.py_loopvar_node, code)
4060 if from_range:
4061 code.funcstate.release_temp(loopvar_name)
4062 break_label = code.break_label
4063 code.set_loop_labels(old_loop_labels)
4064 if self.else_clause:
4065 code.putln("/*else*/ {")
4066 self.else_clause.generate_execution_code(code)
4067 code.putln("}")
4068 code.put_label(break_label)
4069 self.bound1.generate_disposal_code(code)
4070 self.bound1.free_temps(code)
4071 self.bound2.generate_disposal_code(code)
4072 self.bound2.free_temps(code)
4073 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4074 self.loopvar_node.release(code)
4075 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4076 self.py_loopvar_node.release(code)
4077 if self.step is not None:
4078 self.step.generate_disposal_code(code)
4079 self.step.free_temps(code)
4081 relation_table = {
4082 # {relop : (initial offset, increment op)}
4083 '<=': ("", "++"),
4084 '<' : ("+1", "++"),
4085 '>=': ("", "--"),
4086 '>' : ("-1", "--")
4087 }
4089 def annotate(self, code):
4090 self.target.annotate(code)
4091 self.bound1.annotate(code)
4092 self.bound2.annotate(code)
4093 if self.step:
4094 self.bound2.annotate(code)
4095 self.body.annotate(code)
4096 if self.else_clause:
4097 self.else_clause.annotate(code)
4100 class WithStatNode(StatNode):
4101 """
4102 Represents a Python with statement.
4104 This is only used at parse tree level; and is not present in
4105 analysis or generation phases.
4106 """
4107 # manager The with statement manager object
4108 # target Node (lhs expression)
4109 # body StatNode
4110 child_attrs = ["manager", "target", "body"]
4112 class TryExceptStatNode(StatNode):
4113 # try .. except statement
4114 #
4115 # body StatNode
4116 # except_clauses [ExceptClauseNode]
4117 # else_clause StatNode or None
4119 child_attrs = ["body", "except_clauses", "else_clause"]
4121 def analyse_control_flow(self, env):
4122 env.start_branching(self.pos)
4123 self.body.analyse_control_flow(env)
4124 successful_try = env.control_flow # grab this for later
4125 env.next_branch(self.body.end_pos())
4126 env.finish_branching(self.body.end_pos())
4128 env.start_branching(self.except_clauses[0].pos)
4129 for except_clause in self.except_clauses:
4130 except_clause.analyse_control_flow(env)
4131 env.next_branch(except_clause.end_pos())
4133 # the else cause it executed only when the try clause finishes
4134 env.control_flow.incoming = successful_try
4135 if self.else_clause:
4136 self.else_clause.analyse_control_flow(env)
4137 env.finish_branching(self.end_pos())
4139 def analyse_declarations(self, env):
4140 self.body.analyse_declarations(env)
4141 for except_clause in self.except_clauses:
4142 except_clause.analyse_declarations(env)
4143 if self.else_clause:
4144 self.else_clause.analyse_declarations(env)
4145 env.use_utility_code(reset_exception_utility_code)
4147 def analyse_expressions(self, env):
4148 self.body.analyse_expressions(env)
4149 default_clause_seen = 0
4150 for except_clause in self.except_clauses:
4151 except_clause.analyse_expressions(env)
4152 if default_clause_seen:
4153 error(except_clause.pos, "default 'except:' must be last")
4154 if not except_clause.pattern:
4155 default_clause_seen = 1
4156 self.has_default_clause = default_clause_seen
4157 if self.else_clause:
4158 self.else_clause.analyse_expressions(env)
4160 nogil_check = Node.gil_error
4161 gil_message = "Try-except statement"
4163 def generate_execution_code(self, code):
4164 old_return_label = code.return_label
4165 old_break_label = code.break_label
4166 old_continue_label = code.continue_label
4167 old_error_label = code.new_error_label()
4168 our_error_label = code.error_label
4169 except_end_label = code.new_label('exception_handled')
4170 except_error_label = code.new_label('except_error')
4171 except_return_label = code.new_label('except_return')
4172 try_return_label = code.new_label('try_return')
4173 try_break_label = code.new_label('try_break')
4174 try_continue_label = code.new_label('try_continue')
4175 try_end_label = code.new_label('try_end')
4177 code.putln("{")
4178 code.putln("PyObject %s;" %
4179 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4180 code.putln("__Pyx_ExceptionSave(%s);" %
4181 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4182 for var in Naming.exc_save_vars:
4183 code.put_xgotref(var)
4184 code.putln(
4185 "/*try:*/ {")
4186 code.return_label = try_return_label
4187 code.break_label = try_break_label
4188 code.continue_label = try_continue_label
4189 self.body.generate_execution_code(code)
4190 code.putln(
4191 "}")
4192 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4193 code.error_label = except_error_label
4194 code.return_label = except_return_label
4195 if self.else_clause:
4196 code.putln(
4197 "/*else:*/ {")
4198 self.else_clause.generate_execution_code(code)
4199 code.putln(
4200 "}")
4201 for var in Naming.exc_save_vars:
4202 code.put_xdecref_clear(var, py_object_type)
4203 code.put_goto(try_end_label)
4204 if code.label_used(try_return_label):
4205 code.put_label(try_return_label)
4206 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4207 code.putln("__Pyx_ExceptionReset(%s);" %
4208 ', '.join(Naming.exc_save_vars))
4209 code.put_goto(old_return_label)
4210 code.put_label(our_error_label)
4211 for temp_name, type in temps_to_clean_up:
4212 code.put_xdecref_clear(temp_name, type)
4213 for except_clause in self.except_clauses:
4214 except_clause.generate_handling_code(code, except_end_label)
4216 error_label_used = code.label_used(except_error_label)
4217 if error_label_used or not self.has_default_clause:
4218 if error_label_used:
4219 code.put_label(except_error_label)
4220 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4221 code.putln("__Pyx_ExceptionReset(%s);" %
4222 ', '.join(Naming.exc_save_vars))
4223 code.put_goto(old_error_label)
4225 for exit_label, old_label in zip(
4226 [try_break_label, try_continue_label, except_return_label],
4227 [old_break_label, old_continue_label, old_return_label]):
4229 if code.label_used(exit_label):
4230 code.put_label(exit_label)
4231 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4232 code.putln("__Pyx_ExceptionReset(%s);" %
4233 ', '.join(Naming.exc_save_vars))
4234 code.put_goto(old_label)
4236 if code.label_used(except_end_label):
4237 code.put_label(except_end_label)
4238 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4239 code.putln("__Pyx_ExceptionReset(%s);" %
4240 ', '.join(Naming.exc_save_vars))
4241 code.put_label(try_end_label)
4242 code.putln("}")
4244 code.return_label = old_return_label
4245 code.break_label = old_break_label
4246 code.continue_label = old_continue_label
4247 code.error_label = old_error_label
4249 def annotate(self, code):
4250 self.body.annotate(code)
4251 for except_node in self.except_clauses:
4252 except_node.annotate(code)
4253 if self.else_clause:
4254 self.else_clause.annotate(code)
4257 class ExceptClauseNode(Node):
4258 # Part of try ... except statement.
4259 #
4260 # pattern ExprNode
4261 # target ExprNode or None
4262 # body StatNode
4263 # excinfo_target NameNode or None optional target for exception info
4264 # match_flag string result of exception match
4265 # exc_value ExcValueNode used internally
4266 # function_name string qualified name of enclosing function
4267 # exc_vars (string * 3) local exception variables
4269 # excinfo_target is never set by the parser, but can be set by a transform
4270 # in order to extract more extensive information about the exception as a
4271 # sys.exc_info()-style tuple into a target variable
4273 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4275 exc_value = None
4276 excinfo_target = None
4278 def analyse_declarations(self, env):
4279 if self.target:
4280 self.target.analyse_target_declaration(env)
4281 if self.excinfo_target is not None:
4282 self.excinfo_target.analyse_target_declaration(env)
4283 self.body.analyse_declarations(env)
4285 def analyse_expressions(self, env):
4286 import ExprNodes
4287 genv = env.global_scope()
4288 self.function_name = env.qualified_name
4289 if self.pattern:
4290 self.pattern.analyse_expressions(env)
4291 self.pattern = self.pattern.coerce_to_pyobject(env)
4293 if self.target:
4294 self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
4295 self.target.analyse_target_expression(env, self.exc_value)
4296 if self.excinfo_target is not None:
4297 import ExprNodes
4298 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4299 ExprNodes.ExcValueNode(pos=self.pos, env=env) for x in range(3)])
4300 self.excinfo_tuple.analyse_expressions(env)
4301 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4303 self.body.analyse_expressions(env)
4305 def generate_handling_code(self, code, end_label):
4306 code.mark_pos(self.pos)
4307 if self.pattern:
4308 self.pattern.generate_evaluation_code(code)
4310 match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
4311 code.putln(
4312 "%s = PyErr_ExceptionMatches(%s);" % (
4313 match_flag,
4314 self.pattern.py_result()))
4315 self.pattern.generate_disposal_code(code)
4316 self.pattern.free_temps(code)
4317 code.putln(
4318 "if (%s) {" %
4319 match_flag)
4320 code.funcstate.release_temp(match_flag)
4321 else:
4322 code.putln("/*except:*/ {")
4324 if not getattr(self.body, 'stats', True):
4325 # most simple case: no exception variable, empty body (pass)
4326 # => reset the exception state, done
4327 code.putln("PyErr_Restore(0,0,0);")
4328 code.put_goto(end_label)
4329 code.putln("}")
4330 return
4332 exc_vars = [code.funcstate.allocate_temp(py_object_type,
4333 manage_ref=True)
4334 for i in xrange(3)]
4335 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4336 # We always have to fetch the exception value even if
4337 # there is no target, because this also normalises the
4338 # exception and stores it in the thread state.
4339 code.globalstate.use_utility_code(get_exception_utility_code)
4340 exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4341 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4342 code.error_goto(self.pos)))
4343 for x in exc_vars:
4344 code.put_gotref(x)
4345 if self.target:
4346 self.exc_value.set_var(exc_vars[1])
4347 self.exc_value.generate_evaluation_code(code)
4348 self.target.generate_assignment_code(self.exc_value, code)
4349 if self.excinfo_target is not None:
4350 for tempvar, node in zip(exc_vars, self.excinfo_tuple.args):
4351 node.set_var(tempvar)
4352 self.excinfo_tuple.generate_evaluation_code(code)
4353 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4355 old_break_label, old_continue_label = code.break_label, code.continue_label
4356 code.break_label = code.new_label('except_break')
4357 code.continue_label = code.new_label('except_continue')
4359 old_exc_vars = code.funcstate.exc_vars
4360 code.funcstate.exc_vars = exc_vars
4361 self.body.generate_execution_code(code)
4362 code.funcstate.exc_vars = old_exc_vars
4363 for var in exc_vars:
4364 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4365 code.put_goto(end_label)
4367 if code.label_used(code.break_label):
4368 code.put_label(code.break_label)
4369 for var in exc_vars:
4370 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4371 code.put_goto(old_break_label)
4372 code.break_label = old_break_label
4374 if code.label_used(code.continue_label):
4375 code.put_label(code.continue_label)
4376 for var in exc_vars:
4377 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4378 code.put_goto(old_continue_label)
4379 code.continue_label = old_continue_label
4381 for temp in exc_vars:
4382 code.funcstate.release_temp(temp)
4384 code.putln(
4385 "}")
4387 def annotate(self, code):
4388 if self.pattern:
4389 self.pattern.annotate(code)
4390 if self.target:
4391 self.target.annotate(code)
4392 self.body.annotate(code)
4395 class TryFinallyStatNode(StatNode):
4396 # try ... finally statement
4397 #
4398 # body StatNode
4399 # finally_clause StatNode
4400 #
4401 # The plan is that we funnel all continue, break
4402 # return and error gotos into the beginning of the
4403 # finally block, setting a variable to remember which
4404 # one we're doing. At the end of the finally block, we
4405 # switch on the variable to figure out where to go.
4406 # In addition, if we're doing an error, we save the
4407 # exception on entry to the finally block and restore
4408 # it on exit.
4410 child_attrs = ["body", "finally_clause"]
4412 preserve_exception = 1
4414 disallow_continue_in_try_finally = 0
4415 # There doesn't seem to be any point in disallowing
4416 # continue in the try block, since we have no problem
4417 # handling it.
4419 def create_analysed(pos, env, body, finally_clause):
4420 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4421 return node
4422 create_analysed = staticmethod(create_analysed)
4424 def analyse_control_flow(self, env):
4425 env.start_branching(self.pos)
4426 self.body.analyse_control_flow(env)
4427 env.next_branch(self.body.end_pos())
4428 env.finish_branching(self.body.end_pos())
4429 self.finally_clause.analyse_control_flow(env)
4431 def analyse_declarations(self, env):
4432 self.body.analyse_declarations(env)
4433 self.finally_clause.analyse_declarations(env)
4435 def analyse_expressions(self, env):
4436 self.body.analyse_expressions(env)
4437 self.finally_clause.analyse_expressions(env)
4439 nogil_check = Node.gil_error
4440 gil_message = "Try-finally statement"
4442 def generate_execution_code(self, code):
4443 old_error_label = code.error_label
4444 old_labels = code.all_new_labels()
4445 new_labels = code.get_all_labels()
4446 new_error_label = code.error_label
4447 catch_label = code.new_label()
4448 code.putln(
4449 "/*try:*/ {")
4450 if self.disallow_continue_in_try_finally:
4451 was_in_try_finally = code.funcstate.in_try_finally
4452 code.funcstate.in_try_finally = 1
4453 self.body.generate_execution_code(code)
4454 if self.disallow_continue_in_try_finally:
4455 code.funcstate.in_try_finally = was_in_try_finally
4456 code.putln(
4457 "}")
4458 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4459 code.putln(
4460 "/*finally:*/ {")
4461 cases_used = []
4462 error_label_used = 0
4463 for i, new_label in enumerate(new_labels):
4464 if new_label in code.labels_used:
4465 cases_used.append(i)
4466 if new_label == new_error_label:
4467 error_label_used = 1
4468 error_label_case = i
4469 if cases_used:
4470 code.putln(
4471 "int __pyx_why;")
4472 if error_label_used and self.preserve_exception:
4473 code.putln(
4474 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4475 code.putln(
4476 "int %s;" % Naming.exc_lineno_name)
4477 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4478 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4479 code.putln(exc_var_init_zero)
4480 else:
4481 exc_var_init_zero = None
4482 code.use_label(catch_label)
4483 code.putln(
4484 "__pyx_why = 0; goto %s;" % catch_label)
4485 for i in cases_used:
4486 new_label = new_labels[i]
4487 #if new_label and new_label != "<try>":
4488 if new_label == new_error_label and self.preserve_exception:
4489 self.put_error_catcher(code,
4490 new_error_label, i+1, catch_label, temps_to_clean_up)
4491 else:
4492 code.put('%s: ' % new_label)
4493 if exc_var_init_zero:
4494 code.putln(exc_var_init_zero)
4495 code.putln("__pyx_why = %s; goto %s;" % (
4496 i+1,
4497 catch_label))
4498 code.put_label(catch_label)
4499 code.set_all_labels(old_labels)
4500 if error_label_used:
4501 code.new_error_label()
4502 finally_error_label = code.error_label
4503 self.finally_clause.generate_execution_code(code)
4504 if error_label_used:
4505 if finally_error_label in code.labels_used and self.preserve_exception:
4506 over_label = code.new_label()
4507 code.put_goto(over_label);
4508 code.put_label(finally_error_label)
4509 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4510 for var in Naming.exc_vars:
4511 code.putln("Py_XDECREF(%s);" % var)
4512 code.putln("}")
4513 code.put_goto(old_error_label)
4514 code.put_label(over_label)
4515 code.error_label = old_error_label
4516 if cases_used:
4517 code.putln(
4518 "switch (__pyx_why) {")
4519 for i in cases_used:
4520 old_label = old_labels[i]
4521 if old_label == old_error_label and self.preserve_exception:
4522 self.put_error_uncatcher(code, i+1, old_error_label)
4523 else:
4524 code.use_label(old_label)
4525 code.putln(
4526 "case %s: goto %s;" % (
4527 i+1,
4528 old_label))
4529 code.putln(
4530 "}")
4531 code.putln(
4532 "}")
4534 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4535 code.globalstate.use_utility_code(restore_exception_utility_code)
4536 code.putln(
4537 "%s: {" %
4538 error_label)
4539 code.putln(
4540 "__pyx_why = %s;" %
4541 i)
4542 for temp_name, type in temps_to_clean_up:
4543 code.put_xdecref_clear(temp_name, type)
4544 code.putln(
4545 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4546 Naming.exc_vars)
4547 code.putln(
4548 "%s = %s;" % (
4549 Naming.exc_lineno_name, Naming.lineno_cname))
4550 #code.putln(
4551 # "goto %s;" %
4552 # catch_label)
4553 code.put_goto(catch_label)
4554 code.putln(
4555 "}")
4557 def put_error_uncatcher(self, code, i, error_label):
4558 code.globalstate.use_utility_code(restore_exception_utility_code)
4559 code.putln(
4560 "case %s: {" %
4561 i)
4562 code.putln(
4563 "__Pyx_ErrRestore(%s, %s, %s);" %
4564 Naming.exc_vars)
4565 code.putln(
4566 "%s = %s;" % (
4567 Naming.lineno_cname, Naming.exc_lineno_name))
4568 for var in Naming.exc_vars:
4569 code.putln(
4570 "%s = 0;" %
4571 var)
4572 code.put_goto(error_label)
4573 code.putln(
4574 "}")
4576 def annotate(self, code):
4577 self.body.annotate(code)
4578 self.finally_clause.annotate(code)
4581 class GILStatNode(TryFinallyStatNode):
4582 # 'with gil' or 'with nogil' statement
4583 #
4584 # state string 'gil' or 'nogil'
4586 # child_attrs = []
4588 preserve_exception = 0
4590 def __init__(self, pos, state, body):
4591 self.state = state
4592 TryFinallyStatNode.__init__(self, pos,
4593 body = body,
4594 finally_clause = GILExitNode(pos, state = state))
4596 def analyse_expressions(self, env):
4597 env.use_utility_code(force_init_threads_utility_code)
4598 was_nogil = env.nogil
4599 env.nogil = 1
4600 TryFinallyStatNode.analyse_expressions(self, env)
4601 env.nogil = was_nogil
4603 nogil_check = None
4605 def generate_execution_code(self, code):
4606 code.mark_pos(self.pos)
4607 if self.state == 'gil':
4608 code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4609 else:
4610 code.putln("{ PyThreadState *_save;")
4611 code.putln("Py_UNBLOCK_THREADS")
4612 TryFinallyStatNode.generate_execution_code(self, code)
4613 code.putln("}")
4616 class GILExitNode(StatNode):
4617 # Used as the 'finally' block in a GILStatNode
4618 #
4619 # state string 'gil' or 'nogil'
4621 child_attrs = []
4623 def analyse_expressions(self, env):
4624 pass
4626 def generate_execution_code(self, code):
4627 if self.state == 'gil':
4628 code.putln("PyGILState_Release();")
4629 else:
4630 code.putln("Py_BLOCK_THREADS")
4633 class CImportStatNode(StatNode):
4634 # cimport statement
4635 #
4636 # module_name string Qualified name of module being imported
4637 # as_name string or None Name specified in "as" clause, if any
4639 child_attrs = []
4641 def analyse_declarations(self, env):
4642 if not env.is_module_scope:
4643 error(self.pos, "cimport only allowed at module level")
4644 return
4645 module_scope = env.find_module(self.module_name, self.pos)
4646 if "." in self.module_name:
4647 names = [EncodedString(name) for name in self.module_name.split(".")]
4648 top_name = names[0]
4649 top_module_scope = env.context.find_submodule(top_name)
4650 module_scope = top_module_scope
4651 for name in names[1:]:
4652 submodule_scope = module_scope.find_submodule(name)
4653 module_scope.declare_module(name, submodule_scope, self.pos)
4654 module_scope = submodule_scope
4655 if self.as_name:
4656 env.declare_module(self.as_name, module_scope, self.pos)
4657 else:
4658 env.declare_module(top_name, top_module_scope, self.pos)
4659 else:
4660 name = self.as_name or self.module_name
4661 env.declare_module(name, module_scope, self.pos)
4663 def analyse_expressions(self, env):
4664 pass
4666 def generate_execution_code(self, code):
4667 pass
4670 class FromCImportStatNode(StatNode):
4671 # from ... cimport statement
4672 #
4673 # module_name string Qualified name of module
4674 # imported_names [(pos, name, as_name, kind)] Names to be imported
4676 child_attrs = []
4678 def analyse_declarations(self, env):
4679 if not env.is_module_scope:
4680 error(self.pos, "cimport only allowed at module level")
4681 return
4682 module_scope = env.find_module(self.module_name, self.pos)
4683 env.add_imported_module(module_scope)
4684 for pos, name, as_name, kind in self.imported_names:
4685 if name == "*":
4686 for local_name, entry in module_scope.entries.items():
4687 env.add_imported_entry(local_name, entry, pos)
4688 else:
4689 entry = module_scope.lookup(name)
4690 if entry:
4691 if kind and not self.declaration_matches(entry, kind):
4692 entry.redeclared(pos)
4693 else:
4694 if kind == 'struct' or kind == 'union':
4695 entry = module_scope.declare_struct_or_union(name,
4696 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4697 elif kind == 'class':
4698 entry = module_scope.declare_c_class(name, pos = pos,
4699 module_name = self.module_name)
4700 else:
4701 submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
4702 if submodule_scope.parent_module is module_scope:
4703 env.declare_module(as_name or name, submodule_scope, self.pos)
4704 else:
4705 error(pos, "Name '%s' not declared in module '%s'"
4706 % (name, self.module_name))
4708 if entry:
4709 local_name = as_name or name
4710 env.add_imported_entry(local_name, entry, pos)
4712 def declaration_matches(self, entry, kind):
4713 if not entry.is_type:
4714 return 0
4715 type = entry.type
4716 if kind == 'class':
4717 if not type.is_extension_type:
4718 return 0
4719 else:
4720 if not type.is_struct_or_union:
4721 return 0
4722 if kind != type.kind:
4723 return 0
4724 return 1
4726 def analyse_expressions(self, env):
4727 pass
4729 def generate_execution_code(self, code):
4730 pass
4733 class FromImportStatNode(StatNode):
4734 # from ... import statement
4735 #
4736 # module ImportNode
4737 # items [(string, NameNode)]
4738 # interned_items [(string, NameNode, ExprNode)]
4739 # item PyTempNode used internally
4740 # import_star boolean used internally
4742 child_attrs = ["module"]
4743 import_star = 0
4745 def analyse_declarations(self, env):
4746 for name, target in self.items:
4747 if name == "*":
4748 if not env.is_module_scope:
4749 error(self.pos, "import * only allowed at module level")
4750 return
4751 env.has_import_star = 1
4752 self.import_star = 1
4753 else:
4754 target.analyse_target_declaration(env)
4756 def analyse_expressions(self, env):
4757 import ExprNodes
4758 self.module.analyse_expressions(env)
4759 self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
4760 self.interned_items = []
4761 for name, target in self.items:
4762 if name == '*':
4763 for _, entry in env.entries.items():
4764 if not entry.is_type and entry.type.is_extension_type:
4765 env.use_utility_code(ExprNodes.type_test_utility_code)
4766 break
4767 else:
4768 entry = env.lookup(target.name)
4769 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4770 continue # already cimported
4771 target.analyse_target_expression(env, None)
4772 if target.type is py_object_type:
4773 coerced_item = None
4774 else:
4775 coerced_item = self.item.coerce_to(target.type, env)
4776 self.interned_items.append(
4777 (name, target, coerced_item))
4779 def generate_execution_code(self, code):
4780 self.module.generate_evaluation_code(code)
4781 if self.import_star:
4782 code.putln(
4783 'if (%s(%s) < 0) %s;' % (
4784 Naming.import_star,
4785 self.module.py_result(),
4786 code.error_goto(self.pos)))
4787 item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
4788 self.item.set_cname(item_temp)
4789 for name, target, coerced_item in self.interned_items:
4790 cname = code.intern_identifier(name)
4791 code.putln(
4792 '%s = PyObject_GetAttr(%s, %s); %s' % (
4793 item_temp,
4794 self.module.py_result(),
4795 cname,
4796 code.error_goto_if_null(item_temp, self.pos)))
4797 code.put_gotref(item_temp)
4798 if coerced_item is None:
4799 target.generate_assignment_code(self.item, code)
4800 else:
4801 coerced_item.allocate_temp_result(code)
4802 coerced_item.generate_result_code(code)
4803 target.generate_assignment_code(coerced_item, code)
4804 code.put_decref_clear(item_temp, py_object_type)
4805 code.funcstate.release_temp(item_temp)
4806 self.module.generate_disposal_code(code)
4807 self.module.free_temps(code)
4811 #------------------------------------------------------------------------------------
4812 #
4813 # Runtime support code
4814 #
4815 #------------------------------------------------------------------------------------
4817 utility_function_predeclarations = \
4818 """
4819 #ifdef __GNUC__
4820 #define INLINE __inline__
4821 #elif _WIN32
4822 #define INLINE __inline
4823 #else
4824 #define INLINE
4825 #endif
4827 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*/
4829 """
4831 if Options.gcc_branch_hints:
4832 branch_prediction_macros = \
4833 """
4834 #ifdef __GNUC__
4835 /* Test for GCC > 2.95 */
4836 #if __GNUC__ > 2 || \
4837 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4838 #define likely(x) __builtin_expect(!!(x), 1)
4839 #define unlikely(x) __builtin_expect(!!(x), 0)
4840 #else /* __GNUC__ > 2 ... */
4841 #define likely(x) (x)
4842 #define unlikely(x) (x)
4843 #endif /* __GNUC__ > 2 ... */
4844 #else /* __GNUC__ */
4845 #define likely(x) (x)
4846 #define unlikely(x) (x)
4847 #endif /* __GNUC__ */
4848 """
4849 else:
4850 branch_prediction_macros = \
4851 """
4852 #define likely(x) (x)
4853 #define unlikely(x) (x)
4854 """
4856 #get_name_predeclaration = \
4857 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4859 #get_name_interned_predeclaration = \
4860 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4862 #------------------------------------------------------------------------------------
4864 printing_utility_code = UtilityCode(
4865 proto = """
4866 static int __Pyx_Print(PyObject *, int); /*proto*/
4867 #if PY_MAJOR_VERSION >= 3
4868 static PyObject* %s = 0;
4869 static PyObject* %s = 0;
4870 #endif
4871 """ % (Naming.print_function, Naming.print_function_kwargs),
4872 impl = r"""
4873 #if PY_MAJOR_VERSION < 3
4874 static PyObject *__Pyx_GetStdout(void) {
4875 PyObject *f = PySys_GetObject((char *)"stdout");
4876 if (!f) {
4877 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4878 }
4879 return f;
4880 }
4882 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4883 PyObject *f;
4884 PyObject* v;
4885 int i;
4887 if (!(f = __Pyx_GetStdout()))
4888 return -1;
4889 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4890 if (PyFile_SoftSpace(f, 1)) {
4891 if (PyFile_WriteString(" ", f) < 0)
4892 return -1;
4893 }
4894 v = PyTuple_GET_ITEM(arg_tuple, i);
4895 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4896 return -1;
4897 if (PyString_Check(v)) {
4898 char *s = PyString_AsString(v);
4899 Py_ssize_t len = PyString_Size(v);
4900 if (len > 0 &&
4901 isspace(Py_CHARMASK(s[len-1])) &&
4902 s[len-1] != ' ')
4903 PyFile_SoftSpace(f, 0);
4904 }
4905 }
4906 if (newline) {
4907 if (PyFile_WriteString("\n", f) < 0)
4908 return -1;
4909 PyFile_SoftSpace(f, 0);
4910 }
4911 return 0;
4912 }
4914 #else /* Python 3 has a print function */
4916 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4917 PyObject* kwargs = 0;
4918 PyObject* result = 0;
4919 PyObject* end_string;
4920 if (!%(PRINT_FUNCTION)s) {
4921 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4922 if (!%(PRINT_FUNCTION)s)
4923 return -1;
4924 }
4925 if (!newline) {
4926 if (!%(PRINT_KWARGS)s) {
4927 %(PRINT_KWARGS)s = PyDict_New();
4928 if (!%(PRINT_KWARGS)s)
4929 return -1;
4930 end_string = PyUnicode_FromStringAndSize(" ", 1);
4931 if (!end_string)
4932 return -1;
4933 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4934 Py_DECREF(end_string);
4935 return -1;
4936 }
4937 Py_DECREF(end_string);
4938 }
4939 kwargs = %(PRINT_KWARGS)s;
4940 }
4941 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4942 if (!result)
4943 return -1;
4944 Py_DECREF(result);
4945 return 0;
4946 }
4948 #endif
4949 """ % {'BUILTINS' : Naming.builtins_cname,
4950 'PRINT_FUNCTION' : Naming.print_function,
4951 'PRINT_KWARGS' : Naming.print_function_kwargs}
4952 )
4955 printing_one_utility_code = UtilityCode(
4956 proto = """
4957 static int __Pyx_PrintOne(PyObject *o); /*proto*/
4958 """,
4959 impl = r"""
4960 #if PY_MAJOR_VERSION < 3
4962 static int __Pyx_PrintOne(PyObject *o) {
4963 PyObject *f;
4964 if (!(f = __Pyx_GetStdout()))
4965 return -1;
4966 if (PyFile_SoftSpace(f, 0)) {
4967 if (PyFile_WriteString(" ", f) < 0)
4968 return -1;
4969 }
4970 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
4971 return -1;
4972 if (PyFile_WriteString("\n", f) < 0)
4973 return -1;
4974 return 0;
4975 /* the line below is just to avoid compiler
4976 * compiler warnings about unused functions */
4977 return __Pyx_Print(NULL, 0);
4978 }
4980 #else /* Python 3 has a print function */
4982 static int __Pyx_PrintOne(PyObject *o) {
4983 int res;
4984 PyObject* arg_tuple = PyTuple_New(1);
4985 if (unlikely(!arg_tuple))
4986 return -1;
4987 Py_INCREF(o);
4988 PyTuple_SET_ITEM(arg_tuple, 0, o);
4989 res = __Pyx_Print(arg_tuple, 1);
4990 Py_DECREF(arg_tuple);
4991 return res;
4992 }
4994 #endif
4995 """,
4996 requires=[printing_utility_code])
5000 #------------------------------------------------------------------------------------
5002 # Exception raising code
5003 #
5004 # Exceptions are raised by __Pyx_Raise() and stored as plain
5005 # type/value/tb in PyThreadState->curexc_*. When being caught by an
5006 # 'except' statement, curexc_* is moved over to exc_* by
5007 # __Pyx_GetException()
5009 restore_exception_utility_code = UtilityCode(
5010 proto = """
5011 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5012 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5013 """,
5014 impl = """
5015 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5016 PyObject *tmp_type, *tmp_value, *tmp_tb;
5017 PyThreadState *tstate = PyThreadState_GET();
5019 tmp_type = tstate->curexc_type;
5020 tmp_value = tstate->curexc_value;
5021 tmp_tb = tstate->curexc_traceback;
5022 tstate->curexc_type = type;
5023 tstate->curexc_value = value;
5024 tstate->curexc_traceback = tb;
5025 Py_XDECREF(tmp_type);
5026 Py_XDECREF(tmp_value);
5027 Py_XDECREF(tmp_tb);
5028 }
5030 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5031 PyThreadState *tstate = PyThreadState_GET();
5032 *type = tstate->curexc_type;
5033 *value = tstate->curexc_value;
5034 *tb = tstate->curexc_traceback;
5036 tstate->curexc_type = 0;
5037 tstate->curexc_value = 0;
5038 tstate->curexc_traceback = 0;
5039 }
5041 """)
5043 # The following function is based on do_raise() from ceval.c. There
5044 # are separate versions for Python2 and Python3 as exception handling
5045 # has changed quite a lot between the two versions.
5047 raise_utility_code = UtilityCode(
5048 proto = """
5049 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5050 """,
5051 impl = """
5052 #if PY_MAJOR_VERSION < 3
5053 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5054 Py_XINCREF(type);
5055 Py_XINCREF(value);
5056 Py_XINCREF(tb);
5057 /* First, check the traceback argument, replacing None with NULL. */
5058 if (tb == Py_None) {
5059 Py_DECREF(tb);
5060 tb = 0;
5061 }
5062 else if (tb != NULL && !PyTraceBack_Check(tb)) {
5063 PyErr_SetString(PyExc_TypeError,
5064 "raise: arg 3 must be a traceback or None");
5065 goto raise_error;
5066 }
5067 /* Next, replace a missing value with None */
5068 if (value == NULL) {
5069 value = Py_None;
5070 Py_INCREF(value);
5071 }
5072 #if PY_VERSION_HEX < 0x02050000
5073 if (!PyClass_Check(type))
5074 #else
5075 if (!PyType_Check(type))
5076 #endif
5077 {
5078 /* Raising an instance. The value should be a dummy. */
5079 if (value != Py_None) {
5080 PyErr_SetString(PyExc_TypeError,
5081 "instance exception may not have a separate value");
5082 goto raise_error;
5083 }
5084 /* Normalize to raise <class>, <instance> */
5085 Py_DECREF(value);
5086 value = type;
5087 #if PY_VERSION_HEX < 0x02050000
5088 if (PyInstance_Check(type)) {
5089 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
5090 Py_INCREF(type);
5091 }
5092 else {
5093 type = 0;
5094 PyErr_SetString(PyExc_TypeError,
5095 "raise: exception must be an old-style class or instance");
5096 goto raise_error;
5097 }
5098 #else
5099 type = (PyObject*) Py_TYPE(type);
5100 Py_INCREF(type);
5101 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
5102 PyErr_SetString(PyExc_TypeError,
5103 "raise: exception class must be a subclass of BaseException");
5104 goto raise_error;
5105 }
5106 #endif
5107 }
5109 __Pyx_ErrRestore(type, value, tb);
5110 return;
5111 raise_error:
5112 Py_XDECREF(value);
5113 Py_XDECREF(type);
5114 Py_XDECREF(tb);
5115 return;
5116 }
5118 #else /* Python 3+ */
5120 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5121 if (tb == Py_None) {
5122 tb = 0;
5123 } else if (tb && !PyTraceBack_Check(tb)) {
5124 PyErr_SetString(PyExc_TypeError,
5125 "raise: arg 3 must be a traceback or None");
5126 goto bad;
5127 }
5128 if (value == Py_None)
5129 value = 0;
5131 if (PyExceptionInstance_Check(type)) {
5132 if (value) {
5133 PyErr_SetString(PyExc_TypeError,
5134 "instance exception may not have a separate value");
5135 goto bad;
5136 }
5137 value = type;
5138 type = (PyObject*) Py_TYPE(value);
5139 } else if (!PyExceptionClass_Check(type)) {
5140 PyErr_SetString(PyExc_TypeError,
5141 "raise: exception class must be a subclass of BaseException");
5142 goto bad;
5143 }
5145 PyErr_SetObject(type, value);
5147 if (tb) {
5148 PyThreadState *tstate = PyThreadState_GET();
5149 PyObject* tmp_tb = tstate->curexc_traceback;
5150 if (tb != tmp_tb) {
5151 Py_INCREF(tb);
5152 tstate->curexc_traceback = tb;
5153 Py_XDECREF(tmp_tb);
5154 }
5155 }
5157 bad:
5158 return;
5159 }
5160 #endif
5161 """,
5162 requires=[restore_exception_utility_code])
5164 #------------------------------------------------------------------------------------
5166 get_exception_utility_code = UtilityCode(
5167 proto = """
5168 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5169 """,
5170 impl = """
5171 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5172 PyObject *local_type, *local_value, *local_tb;
5173 PyObject *tmp_type, *tmp_value, *tmp_tb;
5174 PyThreadState *tstate = PyThreadState_GET();
5175 local_type = tstate->curexc_type;
5176 local_value = tstate->curexc_value;
5177 local_tb = tstate->curexc_traceback;
5178 tstate->curexc_type = 0;
5179 tstate->curexc_value = 0;
5180 tstate->curexc_traceback = 0;
5181 PyErr_NormalizeException(&local_type, &local_value, &local_tb);
5182 if (unlikely(tstate->curexc_type))
5183 goto bad;
5184 #if PY_MAJOR_VERSION >= 3
5185 if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
5186 goto bad;
5187 #endif
5188 *type = local_type;
5189 *value = local_value;
5190 *tb = local_tb;
5191 Py_INCREF(local_type);
5192 Py_INCREF(local_value);
5193 Py_INCREF(local_tb);
5194 tmp_type = tstate->exc_type;
5195 tmp_value = tstate->exc_value;
5196 tmp_tb = tstate->exc_traceback;
5197 tstate->exc_type = local_type;
5198 tstate->exc_value = local_value;
5199 tstate->exc_traceback = local_tb;
5200 /* Make sure tstate is in a consistent state when we XDECREF
5201 these objects (XDECREF may run arbitrary code). */
5202 Py_XDECREF(tmp_type);
5203 Py_XDECREF(tmp_value);
5204 Py_XDECREF(tmp_tb);
5205 return 0;
5206 bad:
5207 *type = 0;
5208 *value = 0;
5209 *tb = 0;
5210 Py_XDECREF(local_type);
5211 Py_XDECREF(local_value);
5212 Py_XDECREF(local_tb);
5213 return -1;
5214 }
5216 """)
5218 #------------------------------------------------------------------------------------
5220 get_exception_tuple_utility_code = UtilityCode(proto="""
5221 static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
5222 """,
5223 # I doubt that calling __Pyx_GetException() here is correct as it moves
5224 # the exception from tstate->curexc_* to tstate->exc_*, which prevents
5225 # exception handlers later on from receiving it.
5226 impl = """
5227 static PyObject *__Pyx_GetExceptionTuple(void) {
5228 PyObject *type = NULL, *value = NULL, *tb = NULL;
5229 if (__Pyx_GetException(&type, &value, &tb) == 0) {
5230 PyObject* exc_info = PyTuple_New(3);
5231 if (exc_info) {
5232 Py_INCREF(type);
5233 Py_INCREF(value);
5234 Py_INCREF(tb);
5235 PyTuple_SET_ITEM(exc_info, 0, type);
5236 PyTuple_SET_ITEM(exc_info, 1, value);
5237 PyTuple_SET_ITEM(exc_info, 2, tb);
5238 return exc_info;
5239 }
5240 }
5241 return NULL;
5242 }
5243 """,
5244 requires=[get_exception_utility_code])
5246 #------------------------------------------------------------------------------------
5248 reset_exception_utility_code = UtilityCode(
5249 proto = """
5250 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5251 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5252 """,
5253 impl = """
5254 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5255 PyThreadState *tstate = PyThreadState_GET();
5256 *type = tstate->exc_type;
5257 *value = tstate->exc_value;
5258 *tb = tstate->exc_traceback;
5259 Py_XINCREF(*type);
5260 Py_XINCREF(*value);
5261 Py_XINCREF(*tb);
5262 }
5264 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5265 PyObject *tmp_type, *tmp_value, *tmp_tb;
5266 PyThreadState *tstate = PyThreadState_GET();
5267 tmp_type = tstate->exc_type;
5268 tmp_value = tstate->exc_value;
5269 tmp_tb = tstate->exc_traceback;
5270 tstate->exc_type = type;
5271 tstate->exc_value = value;
5272 tstate->exc_traceback = tb;
5273 Py_XDECREF(tmp_type);
5274 Py_XDECREF(tmp_value);
5275 Py_XDECREF(tmp_tb);
5276 }
5277 """)
5279 #------------------------------------------------------------------------------------
5281 arg_type_test_utility_code = UtilityCode(
5282 proto = """
5283 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5284 const char *name, int exact); /*proto*/
5285 """,
5286 impl = """
5287 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5288 const char *name, int exact)
5289 {
5290 if (!type) {
5291 PyErr_Format(PyExc_SystemError, "Missing type object");
5292 return 0;
5293 }
5294 if (none_allowed && obj == Py_None) return 1;
5295 else if (exact) {
5296 if (Py_TYPE(obj) == type) return 1;
5297 }
5298 else {
5299 if (PyObject_TypeCheck(obj, type)) return 1;
5300 }
5301 PyErr_Format(PyExc_TypeError,
5302 "Argument '%s' has incorrect type (expected %s, got %s)",
5303 name, type->tp_name, Py_TYPE(obj)->tp_name);
5304 return 0;
5305 }
5306 """)
5308 #------------------------------------------------------------------------------------
5309 #
5310 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5311 # many or too few positional arguments were found. This handles
5312 # Py_ssize_t formatting correctly.
5314 raise_argtuple_invalid_utility_code = UtilityCode(
5315 proto = """
5316 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5317 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5318 """,
5319 impl = """
5320 static void __Pyx_RaiseArgtupleInvalid(
5321 const char* func_name,
5322 int exact,
5323 Py_ssize_t num_min,
5324 Py_ssize_t num_max,
5325 Py_ssize_t num_found)
5326 {
5327 Py_ssize_t num_expected;
5328 const char *number, *more_or_less;
5330 if (num_found < num_min) {
5331 num_expected = num_min;
5332 more_or_less = "at least";
5333 } else {
5334 num_expected = num_max;
5335 more_or_less = "at most";
5336 }
5337 if (exact) {
5338 more_or_less = "exactly";
5339 }
5340 number = (num_expected == 1) ? "" : "s";
5341 PyErr_Format(PyExc_TypeError,
5342 #if PY_VERSION_HEX < 0x02050000
5343 "%s() takes %s %d positional argument%s (%d given)",
5344 #else
5345 "%s() takes %s %zd positional argument%s (%zd given)",
5346 #endif
5347 func_name, more_or_less, num_expected, number, num_found);
5348 }
5349 """)
5351 raise_keyword_required_utility_code = UtilityCode(
5352 proto = """
5353 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5354 """,
5355 impl = """
5356 static INLINE void __Pyx_RaiseKeywordRequired(
5357 const char* func_name,
5358 PyObject* kw_name)
5359 {
5360 PyErr_Format(PyExc_TypeError,
5361 #if PY_MAJOR_VERSION >= 3
5362 "%s() needs keyword-only argument %U", func_name, kw_name);
5363 #else
5364 "%s() needs keyword-only argument %s", func_name,
5365 PyString_AS_STRING(kw_name));
5366 #endif
5367 }
5368 """)
5370 raise_double_keywords_utility_code = UtilityCode(
5371 proto = """
5372 static void __Pyx_RaiseDoubleKeywordsError(
5373 const char* func_name, PyObject* kw_name); /*proto*/
5374 """,
5375 impl = """
5376 static void __Pyx_RaiseDoubleKeywordsError(
5377 const char* func_name,
5378 PyObject* kw_name)
5379 {
5380 PyErr_Format(PyExc_TypeError,
5381 #if PY_MAJOR_VERSION >= 3
5382 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5383 #else
5384 "%s() got multiple values for keyword argument '%s'", func_name,
5385 PyString_AS_STRING(kw_name));
5386 #endif
5387 }
5388 """)
5390 #------------------------------------------------------------------------------------
5391 #
5392 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5393 # were passed to a function, or if any keywords were passed to a
5394 # function that does not accept them.
5396 keyword_string_check_utility_code = UtilityCode(
5397 proto = """
5398 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5399 const char* function_name, int kw_allowed); /*proto*/
5400 """,
5401 impl = """
5402 static INLINE int __Pyx_CheckKeywordStrings(
5403 PyObject *kwdict,
5404 const char* function_name,
5405 int kw_allowed)
5406 {
5407 PyObject* key = 0;
5408 Py_ssize_t pos = 0;
5409 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5410 #if PY_MAJOR_VERSION < 3
5411 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5412 #else
5413 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5414 #endif
5415 goto invalid_keyword_type;
5416 }
5417 if ((!kw_allowed) && unlikely(key))
5418 goto invalid_keyword;
5419 return 1;
5420 invalid_keyword_type:
5421 PyErr_Format(PyExc_TypeError,
5422 "%s() keywords must be strings", function_name);
5423 return 0;
5424 invalid_keyword:
5425 PyErr_Format(PyExc_TypeError,
5426 #if PY_MAJOR_VERSION < 3
5427 "%s() got an unexpected keyword argument '%s'",
5428 function_name, PyString_AsString(key));
5429 #else
5430 "%s() got an unexpected keyword argument '%U'",
5431 function_name, key);
5432 #endif
5433 return 0;
5434 }
5435 """)
5437 #------------------------------------------------------------------------------------
5438 #
5439 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5440 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5441 # keywords will raise an invalid keyword error.
5442 #
5443 # Three kinds of errors are checked: 1) non-string keywords, 2)
5444 # unexpected keywords and 3) overlap with positional arguments.
5445 #
5446 # If num_posargs is greater 0, it denotes the number of positional
5447 # arguments that were passed and that must therefore not appear
5448 # amongst the keywords as well.
5449 #
5450 # This method does not check for required keyword arguments.
5451 #
5453 parse_keywords_utility_code = UtilityCode(
5454 proto = """
5455 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5456 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5457 const char* function_name); /*proto*/
5458 """,
5459 impl = """
5460 static int __Pyx_ParseOptionalKeywords(
5461 PyObject *kwds,
5462 PyObject **argnames[],
5463 PyObject *kwds2,
5464 PyObject *values[],
5465 Py_ssize_t num_pos_args,
5466 const char* function_name)
5467 {
5468 PyObject *key = 0, *value = 0;
5469 Py_ssize_t pos = 0;
5470 PyObject*** name;
5471 PyObject*** first_kw_arg = argnames + num_pos_args;
5473 while (PyDict_Next(kwds, &pos, &key, &value)) {
5474 name = first_kw_arg;
5475 while (*name && (**name != key)) name++;
5476 if (*name) {
5477 values[name-argnames] = value;
5478 } else {
5479 #if PY_MAJOR_VERSION < 3
5480 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5481 #else
5482 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5483 #endif
5484 goto invalid_keyword_type;
5485 } else {
5486 for (name = first_kw_arg; *name; name++) {
5487 #if PY_MAJOR_VERSION >= 3
5488 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5489 PyUnicode_Compare(**name, key) == 0) break;
5490 #else
5491 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5492 _PyString_Eq(**name, key)) break;
5493 #endif
5494 }
5495 if (*name) {
5496 values[name-argnames] = value;
5497 } else {
5498 /* unexpected keyword found */
5499 for (name=argnames; name != first_kw_arg; name++) {
5500 if (**name == key) goto arg_passed_twice;
5501 #if PY_MAJOR_VERSION >= 3
5502 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5503 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5504 #else
5505 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5506 _PyString_Eq(**name, key)) goto arg_passed_twice;
5507 #endif
5508 }
5509 if (kwds2) {
5510 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5511 } else {
5512 goto invalid_keyword;
5513 }
5514 }
5515 }
5516 }
5517 }
5518 return 0;
5519 arg_passed_twice:
5520 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5521 goto bad;
5522 invalid_keyword_type:
5523 PyErr_Format(PyExc_TypeError,
5524 "%s() keywords must be strings", function_name);
5525 goto bad;
5526 invalid_keyword:
5527 PyErr_Format(PyExc_TypeError,
5528 #if PY_MAJOR_VERSION < 3
5529 "%s() got an unexpected keyword argument '%s'",
5530 function_name, PyString_AsString(key));
5531 #else
5532 "%s() got an unexpected keyword argument '%U'",
5533 function_name, key);
5534 #endif
5535 bad:
5536 return -1;
5537 }
5538 """)
5540 #------------------------------------------------------------------------------------
5542 traceback_utility_code = UtilityCode(
5543 proto = """
5544 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5545 """,
5546 impl = """
5547 #include "compile.h"
5548 #include "frameobject.h"
5549 #include "traceback.h"
5551 static void __Pyx_AddTraceback(const char *funcname) {
5552 PyObject *py_srcfile = 0;
5553 PyObject *py_funcname = 0;
5554 PyObject *py_globals = 0;
5555 PyCodeObject *py_code = 0;
5556 PyFrameObject *py_frame = 0;
5558 #if PY_MAJOR_VERSION < 3
5559 py_srcfile = PyString_FromString(%(FILENAME)s);
5560 #else
5561 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5562 #endif
5563 if (!py_srcfile) goto bad;
5564 if (%(CLINENO)s) {
5565 #if PY_MAJOR_VERSION < 3
5566 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5567 #else
5568 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5569 #endif
5570 }
5571 else {
5572 #if PY_MAJOR_VERSION < 3
5573 py_funcname = PyString_FromString(funcname);
5574 #else
5575 py_funcname = PyUnicode_FromString(funcname);
5576 #endif
5577 }
5578 if (!py_funcname) goto bad;
5579 py_globals = PyModule_GetDict(%(GLOBALS)s);
5580 if (!py_globals) goto bad;
5581 py_code = PyCode_New(
5582 0, /*int argcount,*/
5583 #if PY_MAJOR_VERSION >= 3
5584 0, /*int kwonlyargcount,*/
5585 #endif
5586 0, /*int nlocals,*/
5587 0, /*int stacksize,*/
5588 0, /*int flags,*/
5589 %(EMPTY_BYTES)s, /*PyObject *code,*/
5590 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5591 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5592 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5593 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5594 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5595 py_srcfile, /*PyObject *filename,*/
5596 py_funcname, /*PyObject *name,*/
5597 %(LINENO)s, /*int firstlineno,*/
5598 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5599 );
5600 if (!py_code) goto bad;
5601 py_frame = PyFrame_New(
5602 PyThreadState_GET(), /*PyThreadState *tstate,*/
5603 py_code, /*PyCodeObject *code,*/
5604 py_globals, /*PyObject *globals,*/
5605 0 /*PyObject *locals*/
5606 );
5607 if (!py_frame) goto bad;
5608 py_frame->f_lineno = %(LINENO)s;
5609 PyTraceBack_Here(py_frame);
5610 bad:
5611 Py_XDECREF(py_srcfile);
5612 Py_XDECREF(py_funcname);
5613 Py_XDECREF(py_code);
5614 Py_XDECREF(py_frame);
5615 }
5616 """ % {
5617 'FILENAME': Naming.filename_cname,
5618 'LINENO': Naming.lineno_cname,
5619 'CFILENAME': Naming.cfilenm_cname,
5620 'CLINENO': Naming.clineno_cname,
5621 'GLOBALS': Naming.module_cname,
5622 'EMPTY_TUPLE' : Naming.empty_tuple,
5623 'EMPTY_BYTES' : Naming.empty_bytes,
5624 })
5626 #------------------------------------------------------------------------------------
5628 unraisable_exception_utility_code = UtilityCode(
5629 proto = """
5630 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5631 """,
5632 impl = """
5633 static void __Pyx_WriteUnraisable(const char *name) {
5634 PyObject *old_exc, *old_val, *old_tb;
5635 PyObject *ctx;
5636 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5637 #if PY_MAJOR_VERSION < 3
5638 ctx = PyString_FromString(name);
5639 #else
5640 ctx = PyUnicode_FromString(name);
5641 #endif
5642 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5643 if (!ctx) {
5644 PyErr_WriteUnraisable(Py_None);
5645 } else {
5646 PyErr_WriteUnraisable(ctx);
5647 Py_DECREF(ctx);
5648 }
5649 }
5650 """,
5651 requires=[restore_exception_utility_code])
5653 #------------------------------------------------------------------------------------
5655 set_vtable_utility_code = UtilityCode(
5656 proto = """
5657 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5658 """,
5659 impl = """
5660 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5661 #if PY_VERSION_HEX < 0x03010000
5662 PyObject *ob = PyCObject_FromVoidPtr(vtable, 0);
5663 #else
5664 PyObject *ob = PyCapsule_New(vtable, 0, 0);
5665 #endif
5666 if (!ob)
5667 goto bad;
5668 if (PyDict_SetItemString(dict, "__pyx_vtable__", ob) < 0)
5669 goto bad;
5670 Py_DECREF(ob);
5671 return 0;
5672 bad:
5673 Py_XDECREF(ob);
5674 return -1;
5675 }
5676 """)
5678 #------------------------------------------------------------------------------------
5680 get_vtable_utility_code = UtilityCode(
5681 proto = """
5682 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5683 """,
5684 impl = r"""
5685 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5686 PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5687 if (!ob)
5688 goto bad;
5689 #if PY_VERSION_HEX < 0x03010000
5690 *(void **)vtabptr = PyCObject_AsVoidPtr(ob);
5691 #else
5692 *(void **)vtabptr = PyCapsule_GetPointer(ob, 0);
5693 #endif
5694 if (!*(void **)vtabptr)
5695 goto bad;
5696 Py_DECREF(ob);
5697 return 0;
5698 bad:
5699 Py_XDECREF(ob);
5700 return -1;
5701 }
5702 """)
5704 #------------------------------------------------------------------------------------
5706 init_string_tab_utility_code = UtilityCode(
5707 proto = """
5708 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5709 """,
5710 impl = """
5711 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5712 while (t->p) {
5713 #if PY_MAJOR_VERSION < 3
5714 if (t->is_unicode) {
5715 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5716 } else if (t->intern) {
5717 *t->p = PyString_InternFromString(t->s);
5718 } else {
5719 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5720 }
5721 #else /* Python 3+ has unicode identifiers */
5722 if (t->is_unicode | t->is_str) {
5723 if (t->intern) {
5724 *t->p = PyUnicode_InternFromString(t->s);
5725 } else if (t->encoding) {
5726 *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
5727 } else {
5728 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5729 }
5730 } else {
5731 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5732 }
5733 #endif
5734 if (!*t->p)
5735 return -1;
5736 ++t;
5737 }
5738 return 0;
5739 }
5740 """)
5742 #------------------------------------------------------------------------------------
5744 force_init_threads_utility_code = UtilityCode(
5745 proto="""
5746 #ifndef __PYX_FORCE_INIT_THREADS
5747 #if PY_VERSION_HEX < 0x02040200
5748 #define __PYX_FORCE_INIT_THREADS 1
5749 #else
5750 #define __PYX_FORCE_INIT_THREADS 0
5751 #endif
5752 #endif
5753 """)
5755 #------------------------------------------------------------------------------------
5757 # Note that cPython ignores PyTrace_EXCEPTION,
5758 # but maybe some other profilers don't.
5760 profile_utility_code = UtilityCode(proto="""
5761 #ifndef CYTHON_PROFILE
5762 #define CYTHON_PROFILE 1
5763 #endif
5765 #ifndef CYTHON_PROFILE_REUSE_FRAME
5766 #define CYTHON_PROFILE_REUSE_FRAME 0
5767 #endif
5769 #if CYTHON_PROFILE
5771 #include "compile.h"
5772 #include "frameobject.h"
5773 #include "traceback.h"
5775 #if CYTHON_PROFILE_REUSE_FRAME
5776 #define CYTHON_FRAME_MODIFIER static
5777 #define CYTHON_FRAME_DEL
5778 #else
5779 #define CYTHON_FRAME_MODIFIER
5780 #define CYTHON_FRAME_DEL Py_DECREF(%(FRAME)s)
5781 #endif
5783 #define __Pyx_TraceCall(funcname, srcfile, firstlineno) \\
5784 static PyCodeObject *%(FRAME_CODE)s = NULL; \\
5785 CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL; \\
5786 int __Pyx_use_tracing = 0; \\
5787 if (unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc)) { \\
5788 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&%(FRAME_CODE)s, &%(FRAME)s, funcname, srcfile, firstlineno); \\
5789 }
5791 #define __Pyx_TraceException() \\
5792 if (unlikely(__Pyx_use_tracing( && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5793 PyObject *exc_info = __Pyx_GetExceptionTuple(); \\
5794 if (exc_info) { \\
5795 PyThreadState_GET()->c_profilefunc( \\
5796 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_EXCEPTION, exc_info); \\
5797 Py_DECREF(exc_info); \\
5798 } \\
5799 }
5801 #define __Pyx_TraceReturn(result) \\
5802 if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5803 PyThreadState_GET()->c_profilefunc( \\
5804 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_RETURN, (PyObject*)result); \\
5805 CYTHON_FRAME_DEL; \\
5806 }
5808 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
5809 static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
5811 #else
5812 #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
5813 #define __Pyx_TraceException()
5814 #define __Pyx_TraceReturn(result)
5815 #endif /* CYTHON_PROFILE */
5816 """
5817 % {
5818 "FRAME": Naming.frame_cname,
5819 "FRAME_CODE": Naming.frame_code_cname,
5820 },
5821 impl = """
5823 #if CYTHON_PROFILE
5825 static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
5826 PyFrameObject** frame,
5827 const char *funcname,
5828 const char *srcfile,
5829 int firstlineno) {
5830 if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) {
5831 if (*code == NULL) {
5832 *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
5833 if (*code == NULL) return 0;
5834 }
5835 *frame = PyFrame_New(
5836 PyThreadState_GET(), /*PyThreadState *tstate*/
5837 *code, /*PyCodeObject *code*/
5838 PyModule_GetDict(%(MODULE)s), /*PyObject *globals*/
5839 0 /*PyObject *locals*/
5840 );
5841 if (*frame == NULL) return 0;
5842 }
5843 else {
5844 (*frame)->f_tstate = PyThreadState_GET();
5845 }
5846 return PyThreadState_GET()->c_profilefunc(PyThreadState_GET()->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
5847 }
5849 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
5850 PyObject *py_srcfile = 0;
5851 PyObject *py_funcname = 0;
5852 PyCodeObject *py_code = 0;
5854 #if PY_MAJOR_VERSION < 3
5855 py_funcname = PyString_FromString(funcname);
5856 py_srcfile = PyString_FromString(srcfile);
5857 #else
5858 py_funcname = PyUnicode_FromString(funcname);
5859 py_srcfile = PyUnicode_FromString(srcfile);
5860 #endif
5861 if (!py_funcname | !py_srcfile) goto bad;
5863 py_code = PyCode_New(
5864 0, /*int argcount,*/
5865 #if PY_MAJOR_VERSION >= 3
5866 0, /*int kwonlyargcount,*/
5867 #endif
5868 0, /*int nlocals,*/
5869 0, /*int stacksize,*/
5870 0, /*int flags,*/
5871 %(EMPTY_BYTES)s, /*PyObject *code,*/
5872 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5873 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5874 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5875 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5876 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5877 py_srcfile, /*PyObject *filename,*/
5878 py_funcname, /*PyObject *name,*/
5879 firstlineno, /*int firstlineno,*/
5880 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5881 );
5883 bad:
5884 Py_XDECREF(py_srcfile);
5885 Py_XDECREF(py_funcname);
5887 return py_code;
5888 }
5890 #endif /* CYTHON_PROFILE */
5891 """ % {
5892 'EMPTY_TUPLE' : Naming.empty_tuple,
5893 'EMPTY_BYTES' : Naming.empty_bytes,
5894 "MODULE": Naming.module_cname,
5895 })
