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