Cython has moved to github.
cython-devel
view Cython/Compiler/Nodes.py @ 2819:3bc6d034486a
INLINE -> CYTHON_INLINE to avoid conflicts
| author | Robert Bradshaw <robertwb@math.washington.edu> |
|---|---|
| date | Mon Jan 25 22:47:09 2010 -0800 (2 years ago) |
| parents | 720d2f3afee9 |
| children | 361c725b6a54 |
line source
1 #
2 # Pyrex - Parse tree nodes
3 #
5 import sys, os, time, copy
7 try:
8 set
9 except NameError:
10 # Python 2.3
11 from sets import Set as set
13 import Code
14 import Builtin
15 from Errors import error, warning, InternalError
16 import Naming
17 import PyrexTypes
18 import TypeSlots
19 from PyrexTypes import py_object_type, error_type, CFuncType
20 from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
21 StructOrUnionScope, PyClassScope, CClassScope
22 from Cython.Utils import open_new_file, replace_suffix
23 from Code import UtilityCode
24 from StringEncoding import EncodedString, escape_byte_string, split_docstring
25 import Options
26 import ControlFlow
27 import DebugFlags
29 absolute_path_length = 0
31 def relative_position(pos):
32 """
33 We embed the relative filename in the generated C file, since we
34 don't want to have to regnerate and compile all the source code
35 whenever the Python install directory moves (which could happen,
36 e.g,. when distributing binaries.)
38 INPUT:
39 a position tuple -- (absolute filename, line number column position)
41 OUTPUT:
42 relative filename
43 line number
45 AUTHOR: William Stein
46 """
47 global absolute_path_length
48 if absolute_path_length==0:
49 absolute_path_length = len(os.path.abspath(os.getcwd()))
50 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
52 def embed_position(pos, docstring):
53 if not Options.embed_pos_in_docstring:
54 return docstring
55 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
56 if docstring is None:
57 # unicode string
58 return EncodedString(pos_line)
60 # make sure we can encode the filename in the docstring encoding
61 # otherwise make the docstring a unicode string
62 encoding = docstring.encoding
63 if encoding is not None:
64 try:
65 encoded_bytes = pos_line.encode(encoding)
66 except UnicodeEncodeError:
67 encoding = None
69 if not docstring:
70 # reuse the string encoding of the original docstring
71 doc = EncodedString(pos_line)
72 else:
73 doc = EncodedString(pos_line + u'\n' + docstring)
74 doc.encoding = encoding
75 return doc
78 from Code import CCodeWriter
79 from types import FunctionType
81 def write_func_call(func):
82 def f(*args, **kwds):
83 if len(args) > 1 and isinstance(args[1], CCodeWriter):
84 # here we annotate the code with this function call
85 # but only if new code is generated
86 node, code = args[:2]
87 marker = ' /* %s -> %s.%s %s */' % (
88 ' ' * code.call_level,
89 node.__class__.__name__,
90 func.__name__,
91 node.pos[1:])
92 pristine = code.buffer.stream.tell()
93 code.putln(marker)
94 start = code.buffer.stream.tell()
95 code.call_level += 4
96 res = func(*args, **kwds)
97 code.call_level -= 4
98 if start == code.buffer.stream.tell():
99 code.buffer.stream.seek(pristine)
100 else:
101 marker = marker.replace('->', '<-')
102 code.putln(marker)
103 return res
104 else:
105 return func(*args, **kwds)
106 return f
108 class VerboseCodeWriter(type):
109 # Set this as a metaclass to trace function calls in code.
110 # This slows down code generation and makes much larger files.
111 def __new__(cls, name, bases, attrs):
112 attrs = dict(attrs)
113 for mname, m in attrs.items():
114 if isinstance(m, FunctionType):
115 attrs[mname] = write_func_call(m)
116 return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
119 class Node(object):
120 # pos (string, int, int) Source file position
121 # is_name boolean Is a NameNode
122 # is_literal boolean Is a ConstNode
124 if DebugFlags.debug_trace_code_generation:
125 __metaclass__ = VerboseCodeWriter
127 is_name = 0
128 is_literal = 0
129 temps = None
131 # All descandants should set child_attrs to a list of the attributes
132 # containing nodes considered "children" in the tree. Each such attribute
133 # can either contain a single node or a list of nodes. See Visitor.py.
134 child_attrs = None
136 def __init__(self, pos, **kw):
137 self.pos = pos
138 self.__dict__.update(kw)
140 gil_message = "Operation"
142 nogil_check = None
144 def gil_error(self, env=None):
145 error(self.pos, "%s not allowed without gil" % self.gil_message)
147 def clone_node(self):
148 """Clone the node. This is defined as a shallow copy, except for member lists
149 amongst the child attributes (from get_child_accessors) which are also
150 copied. Lists containing child nodes are thus seen as a way for the node
151 to hold multiple children directly; the list is not treated as a seperate
152 level in the tree."""
153 result = copy.copy(self)
154 for attrname in result.child_attrs:
155 value = getattr(result, attrname)
156 if isinstance(value, list):
157 setattr(result, attrname, [x for x in value])
158 return result
161 #
162 # There are 4 phases of parse tree processing, applied in order to
163 # all the statements in a given scope-block:
164 #
165 # (0) analyse_control_flow
166 # Create the control flow tree into which state can be asserted and
167 # queried.
168 #
169 # (1) analyse_declarations
170 # Make symbol table entries for all declarations at the current
171 # level, both explicit (def, cdef, etc.) and implicit (assignment
172 # to an otherwise undeclared name).
173 #
174 # (2) analyse_expressions
175 # Determine the result types of expressions and fill in the
176 # 'type' attribute of each ExprNode. Insert coercion nodes into the
177 # tree where needed to convert to and from Python objects.
178 # Allocate temporary locals for intermediate results. Fill
179 # in the 'result_code' attribute of each ExprNode with a C code
180 # fragment.
181 #
182 # (3) generate_code
183 # Emit C code for all declarations, statements and expressions.
184 # Recursively applies the 3 processing phases to the bodies of
185 # functions.
186 #
188 def analyse_control_flow(self, env):
189 pass
191 def analyse_declarations(self, env):
192 pass
194 def analyse_expressions(self, env):
195 raise InternalError("analyse_expressions not implemented for %s" % \
196 self.__class__.__name__)
198 def generate_code(self, code):
199 raise InternalError("generate_code not implemented for %s" % \
200 self.__class__.__name__)
202 def annotate(self, code):
203 # mro does the wrong thing
204 if isinstance(self, BlockNode):
205 self.body.annotate(code)
207 def end_pos(self):
208 try:
209 return self._end_pos
210 except AttributeError:
211 pos = self.pos
212 if not self.child_attrs:
213 self._end_pos = pos
214 return pos
215 for attr in self.child_attrs:
216 child = getattr(self, attr)
217 # Sometimes lists, sometimes nodes
218 if child is None:
219 pass
220 elif isinstance(child, list):
221 for c in child:
222 pos = max(pos, c.end_pos())
223 else:
224 pos = max(pos, child.end_pos())
225 self._end_pos = pos
226 return pos
228 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
229 if cutoff == 0:
230 return "<...nesting level cutoff...>"
231 if encountered is None:
232 encountered = set()
233 if id(self) in encountered:
234 return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
235 encountered.add(id(self))
237 def dump_child(x, level):
238 if isinstance(x, Node):
239 return x.dump(level, filter_out, cutoff-1, encountered)
240 elif isinstance(x, list):
241 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
242 else:
243 return repr(x)
246 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
247 if len(attrs) == 0:
248 return "<%s (%d)>" % (self.__class__.__name__, id(self))
249 else:
250 indent = " " * level
251 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
252 for key, value in attrs:
253 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
254 res += "%s>" % indent
255 return res
257 class CompilerDirectivesNode(Node):
258 """
259 Sets compiler directives for the children nodes
260 """
261 # directives {string:value} A dictionary holding the right value for
262 # *all* possible directives.
263 # body Node
264 child_attrs = ["body"]
266 def analyse_control_flow(self, env):
267 old = env.directives
268 env.directives = self.directives
269 self.body.analyse_control_flow(env)
270 env.directives = old
272 def analyse_declarations(self, env):
273 old = env.directives
274 env.directives = self.directives
275 self.body.analyse_declarations(env)
276 env.directives = old
278 def analyse_expressions(self, env):
279 old = env.directives
280 env.directives = self.directives
281 self.body.analyse_expressions(env)
282 env.directives = old
284 def generate_function_definitions(self, env, code):
285 env_old = env.directives
286 code_old = code.globalstate.directives
287 code.globalstate.directives = self.directives
288 self.body.generate_function_definitions(env, code)
289 env.directives = env_old
290 code.globalstate.directives = code_old
292 def generate_execution_code(self, code):
293 old = code.globalstate.directives
294 code.globalstate.directives = self.directives
295 self.body.generate_execution_code(code)
296 code.globalstate.directives = old
298 def annotate(self, code):
299 old = code.globalstate.directives
300 code.globalstate.directives = self.directives
301 self.body.annotate(code)
302 code.globalstate.directives = old
304 class BlockNode(object):
305 # Mixin class for nodes representing a declaration block.
307 def generate_cached_builtins_decls(self, env, code):
308 entries = env.global_scope().undeclared_cached_builtins
309 for entry in entries:
310 code.globalstate.add_cached_builtin_decl(entry)
311 del entries[:]
314 class StatListNode(Node):
315 # stats a list of StatNode
317 child_attrs = ["stats"]
319 def create_analysed(pos, env, *args, **kw):
320 node = StatListNode(pos, *args, **kw)
321 return node # No node-specific analysis necesarry
322 create_analysed = staticmethod(create_analysed)
324 def analyse_control_flow(self, env):
325 for stat in self.stats:
326 stat.analyse_control_flow(env)
328 def analyse_declarations(self, env):
329 #print "StatListNode.analyse_declarations" ###
330 for stat in self.stats:
331 stat.analyse_declarations(env)
333 def analyse_expressions(self, env):
334 #print "StatListNode.analyse_expressions" ###
335 for stat in self.stats:
336 stat.analyse_expressions(env)
338 def generate_function_definitions(self, env, code):
339 #print "StatListNode.generate_function_definitions" ###
340 for stat in self.stats:
341 stat.generate_function_definitions(env, code)
343 def generate_execution_code(self, code):
344 #print "StatListNode.generate_execution_code" ###
345 for stat in self.stats:
346 code.mark_pos(stat.pos)
347 stat.generate_execution_code(code)
349 def annotate(self, code):
350 for stat in self.stats:
351 stat.annotate(code)
354 class StatNode(Node):
355 #
356 # Code generation for statements is split into the following subphases:
357 #
358 # (1) generate_function_definitions
359 # Emit C code for the definitions of any structs,
360 # unions, enums and functions defined in the current
361 # scope-block.
362 #
363 # (2) generate_execution_code
364 # Emit C code for executable statements.
365 #
367 def generate_function_definitions(self, env, code):
368 pass
370 def generate_execution_code(self, code):
371 raise InternalError("generate_execution_code not implemented for %s" % \
372 self.__class__.__name__)
375 class CDefExternNode(StatNode):
376 # include_file string or None
377 # body StatNode
379 child_attrs = ["body"]
381 def analyse_declarations(self, env):
382 if self.include_file:
383 env.add_include_file(self.include_file)
384 old_cinclude_flag = env.in_cinclude
385 env.in_cinclude = 1
386 self.body.analyse_declarations(env)
387 env.in_cinclude = old_cinclude_flag
389 def analyse_expressions(self, env):
390 pass
392 def generate_execution_code(self, code):
393 pass
395 def annotate(self, code):
396 self.body.annotate(code)
399 class CDeclaratorNode(Node):
400 # Part of a C declaration.
401 #
402 # Processing during analyse_declarations phase:
403 #
404 # analyse
405 # Returns (name, type) pair where name is the
406 # CNameDeclaratorNode of the name being declared
407 # and type is the type it is being declared as.
408 #
409 # calling_convention string Calling convention of CFuncDeclaratorNode
410 # for which this is a base
412 child_attrs = []
414 calling_convention = ""
417 class CNameDeclaratorNode(CDeclaratorNode):
418 # name string The Pyrex name being declared
419 # cname string or None C name, if specified
420 # default ExprNode or None the value assigned on declaration
422 child_attrs = ['default']
424 default = None
426 def analyse(self, base_type, env, nonempty = 0):
427 if nonempty and self.name == '':
428 # May have mistaken the name for the type.
429 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
430 error(self.pos, "Missing argument name")
431 elif base_type.is_void:
432 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
433 else:
434 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
435 base_type = py_object_type
436 self.type = base_type
437 return self, base_type
439 class CPtrDeclaratorNode(CDeclaratorNode):
440 # base CDeclaratorNode
442 child_attrs = ["base"]
444 def analyse(self, base_type, env, nonempty = 0):
445 if base_type.is_pyobject:
446 error(self.pos,
447 "Pointer base type cannot be a Python object")
448 ptr_type = PyrexTypes.c_ptr_type(base_type)
449 return self.base.analyse(ptr_type, env, nonempty = nonempty)
451 class CArrayDeclaratorNode(CDeclaratorNode):
452 # base CDeclaratorNode
453 # dimension ExprNode
455 child_attrs = ["base", "dimension"]
457 def analyse(self, base_type, env, nonempty = 0):
458 if self.dimension:
459 self.dimension.analyse_const_expression(env)
460 if not self.dimension.type.is_int:
461 error(self.dimension.pos, "Array dimension not integer")
462 size = self.dimension.get_constant_c_result_code()
463 if size is not None:
464 try:
465 size = int(size)
466 except ValueError:
467 # runtime constant?
468 pass
469 else:
470 size = None
471 if not base_type.is_complete():
472 error(self.pos,
473 "Array element type '%s' is incomplete" % base_type)
474 if base_type.is_pyobject:
475 error(self.pos,
476 "Array element cannot be a Python object")
477 if base_type.is_cfunction:
478 error(self.pos,
479 "Array element cannot be a function")
480 array_type = PyrexTypes.c_array_type(base_type, size)
481 return self.base.analyse(array_type, env, nonempty = nonempty)
484 class CFuncDeclaratorNode(CDeclaratorNode):
485 # base CDeclaratorNode
486 # args [CArgDeclNode]
487 # has_varargs boolean
488 # exception_value ConstNode
489 # exception_check boolean True if PyErr_Occurred check needed
490 # nogil boolean Can be called without gil
491 # with_gil boolean Acquire gil around function body
493 child_attrs = ["base", "args", "exception_value"]
495 overridable = 0
496 optional_arg_count = 0
498 def analyse(self, return_type, env, nonempty = 0):
499 if nonempty:
500 nonempty -= 1
501 func_type_args = []
502 for arg_node in self.args:
503 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
504 name = name_declarator.name
505 if name_declarator.cname:
506 error(self.pos,
507 "Function argument cannot have C name specification")
508 # Turn *[] argument into **
509 if type.is_array:
510 type = PyrexTypes.c_ptr_type(type.base_type)
511 # Catch attempted C-style func(void) decl
512 if type.is_void:
513 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
514 func_type_args.append(
515 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
516 if arg_node.default:
517 self.optional_arg_count += 1
518 elif self.optional_arg_count:
519 error(self.pos, "Non-default argument follows default argument")
521 if self.optional_arg_count:
522 scope = StructOrUnionScope()
523 arg_count_member = '%sn' % Naming.pyrex_prefix
524 scope.declare_var(arg_count_member, PyrexTypes.c_int_type, self.pos)
525 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
526 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
527 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
528 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
529 kind = 'struct',
530 scope = scope,
531 typedef_flag = 0,
532 pos = self.pos,
533 cname = struct_cname)
534 self.op_args_struct.defined_in_pxd = 1
535 self.op_args_struct.used = 1
537 exc_val = None
538 exc_check = 0
539 if self.exception_check == '+':
540 env.add_include_file('stdexcept')
541 if return_type.is_pyobject \
542 and (self.exception_value or self.exception_check) \
543 and self.exception_check != '+':
544 error(self.pos,
545 "Exception clause not allowed for function returning Python object")
546 else:
547 if self.exception_value:
548 self.exception_value.analyse_const_expression(env)
549 if self.exception_check == '+':
550 self.exception_value.analyse_types(env)
551 exc_val_type = self.exception_value.type
552 if not exc_val_type.is_error and \
553 not exc_val_type.is_pyobject and \
554 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
555 error(self.exception_value.pos,
556 "Exception value must be a Python exception or cdef function with no arguments.")
557 exc_val = self.exception_value
558 else:
559 if self.exception_value.analyse_const_expression(env):
560 exc_val = self.exception_value.get_constant_c_result_code()
561 if exc_val is None:
562 raise InternalError("get_constant_c_result_code not implemented for %s" %
563 self.exception_value.__class__.__name__)
564 if not return_type.assignable_from(self.exception_value.type):
565 error(self.exception_value.pos,
566 "Exception value incompatible with function return type")
567 exc_check = self.exception_check
568 if return_type.is_array:
569 error(self.pos,
570 "Function cannot return an array")
571 if return_type.is_cfunction:
572 error(self.pos,
573 "Function cannot return a function")
574 func_type = PyrexTypes.CFuncType(
575 return_type, func_type_args, self.has_varargs,
576 optional_arg_count = self.optional_arg_count,
577 exception_value = exc_val, exception_check = exc_check,
578 calling_convention = self.base.calling_convention,
579 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
580 if self.optional_arg_count:
581 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
582 callspec = env.directives['callspec']
583 if callspec:
584 current = func_type.calling_convention
585 if current and current != callspec:
586 error(self.pos, "cannot have both '%s' and '%s' "
587 "calling conventions" % (current, callspec))
588 func_type.calling_convention = callspec
589 return self.base.analyse(func_type, env)
592 class CArgDeclNode(Node):
593 # Item in a function declaration argument list.
594 #
595 # base_type CBaseTypeNode
596 # declarator CDeclaratorNode
597 # not_none boolean Tagged with 'not None'
598 # default ExprNode or None
599 # default_value PyObjectConst constant for default value
600 # is_self_arg boolean Is the "self" arg of an extension type method
601 # is_type_arg boolean Is the "class" arg of an extension type classmethod
602 # is_kw_only boolean Is a keyword-only argument
604 child_attrs = ["base_type", "declarator", "default"]
606 is_self_arg = 0
607 is_type_arg = 0
608 is_generic = 1
609 type = None
610 name_declarator = None
611 default_value = None
613 def analyse(self, env, nonempty = 0):
614 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
615 if self.type is None:
616 # The parser may missinterpret names as types...
617 # We fix that here.
618 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
619 if nonempty:
620 self.declarator.name = self.base_type.name
621 self.base_type.name = None
622 self.base_type.is_basic_c_type = False
623 could_be_name = True
624 else:
625 could_be_name = False
626 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
627 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
628 self.declarator.name = self.base_type.arg_name
629 return self.declarator.analyse(base_type, env, nonempty = nonempty)
630 else:
631 return self.name_declarator, self.type
633 def calculate_default_value_code(self, code):
634 if self.default_value is None:
635 if self.default:
636 if self.default.is_literal:
637 # will not output any code, just assign the result_code
638 self.default.generate_evaluation_code(code)
639 return self.type.cast_code(self.default.result())
640 self.default_value = code.get_argument_default_const(self.type)
641 return self.default_value
643 def annotate(self, code):
644 if self.default:
645 self.default.annotate(code)
648 class CBaseTypeNode(Node):
649 # Abstract base class for C base type nodes.
650 #
651 # Processing during analyse_declarations phase:
652 #
653 # analyse
654 # Returns the type.
656 pass
658 class CAnalysedBaseTypeNode(Node):
659 # type type
661 child_attrs = []
663 def analyse(self, env, could_be_name = False):
664 return self.type
666 class CSimpleBaseTypeNode(CBaseTypeNode):
667 # name string
668 # module_path [string] Qualifying name components
669 # is_basic_c_type boolean
670 # signed boolean
671 # longness integer
672 # complex boolean
673 # is_self_arg boolean Is self argument of C method
674 # ##is_type_arg boolean Is type argument of class method
676 child_attrs = []
677 arg_name = None # in case the argument name was interpreted as a type
679 def analyse(self, env, could_be_name = False):
680 # Return type descriptor.
681 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
682 type = None
683 if self.is_basic_c_type:
684 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
685 if not type:
686 error(self.pos, "Unrecognised type modifier combination")
687 elif self.name == "object" and not self.module_path:
688 type = py_object_type
689 elif self.name is None:
690 if self.is_self_arg and env.is_c_class_scope:
691 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
692 type = env.parent_type
693 ## elif self.is_type_arg and env.is_c_class_scope:
694 ## type = Builtin.type_type
695 else:
696 type = py_object_type
697 else:
698 if self.module_path:
699 scope = env.find_imported_module(self.module_path, self.pos)
700 else:
701 scope = env
702 if scope:
703 if scope.is_c_class_scope:
704 scope = scope.global_scope()
705 entry = scope.lookup(self.name)
706 if entry and entry.is_type:
707 type = entry.type
708 elif could_be_name:
709 if self.is_self_arg and env.is_c_class_scope:
710 type = env.parent_type
711 ## elif self.is_type_arg and env.is_c_class_scope:
712 ## type = Builtin.type_type
713 else:
714 type = py_object_type
715 self.arg_name = self.name
716 else:
717 error(self.pos, "'%s' is not a type identifier" % self.name)
718 if self.complex:
719 if not type.is_numeric or type.is_complex:
720 error(self.pos, "can only complexify c numeric types")
721 type = PyrexTypes.CComplexType(type)
722 type.create_declaration_utility_code(env)
723 if type:
724 return type
725 else:
726 return PyrexTypes.error_type
728 class CBufferAccessTypeNode(CBaseTypeNode):
729 # After parsing:
730 # positional_args [ExprNode] List of positional arguments
731 # keyword_args DictNode Keyword arguments
732 # base_type_node CBaseTypeNode
734 # After analysis:
735 # type PyrexType.BufferType ...containing the right options
738 child_attrs = ["base_type_node", "positional_args",
739 "keyword_args", "dtype_node"]
741 dtype_node = None
743 name = None
745 def analyse(self, env, could_be_name = False):
746 base_type = self.base_type_node.analyse(env)
747 if base_type.is_error: return base_type
748 import Buffer
750 options = Buffer.analyse_buffer_options(
751 self.pos,
752 env,
753 self.positional_args,
754 self.keyword_args,
755 base_type.buffer_defaults)
757 if sys.version_info[0] < 3:
758 # Py 2.x enforces byte strings as keyword arguments ...
759 options = dict([ (name.encode('ASCII'), value)
760 for name, value in options.iteritems() ])
762 self.type = PyrexTypes.BufferType(base_type, **options)
763 return self.type
765 class CComplexBaseTypeNode(CBaseTypeNode):
766 # base_type CBaseTypeNode
767 # declarator CDeclaratorNode
769 child_attrs = ["base_type", "declarator"]
771 def analyse(self, env, could_be_name = False):
772 base = self.base_type.analyse(env, could_be_name)
773 _, type = self.declarator.analyse(base, env)
774 return type
777 class CVarDefNode(StatNode):
778 # C variable definition or forward/extern function declaration.
779 #
780 # visibility 'private' or 'public' or 'extern'
781 # base_type CBaseTypeNode
782 # declarators [CDeclaratorNode]
783 # in_pxd boolean
784 # api boolean
785 # need_properties [entry]
787 # decorators [cython.locals(...)] or None
788 # directive_locals { string : NameNode } locals defined by cython.locals(...)
790 child_attrs = ["base_type", "declarators"]
791 need_properties = ()
793 decorators = None
794 directive_locals = {}
796 def analyse_declarations(self, env, dest_scope = None):
797 if not dest_scope:
798 dest_scope = env
799 self.dest_scope = dest_scope
800 base_type = self.base_type.analyse(env)
802 # If the field is an external typedef, we cannot be sure about the type,
803 # so do conversion ourself rather than rely on the CPython mechanism (through
804 # a property; made in AnalyseDeclarationsTransform).
805 if (dest_scope.is_c_class_scope
806 and self.visibility == 'public'
807 and base_type.is_pyobject
808 and (base_type.is_builtin_type or base_type.is_extension_type)):
809 self.need_properties = []
810 need_property = True
811 visibility = 'private'
812 else:
813 need_property = False
814 visibility = self.visibility
816 for declarator in self.declarators:
817 name_declarator, type = declarator.analyse(base_type, env)
818 if not type.is_complete():
819 if not (self.visibility == 'extern' and type.is_array):
820 error(declarator.pos,
821 "Variable type '%s' is incomplete" % type)
822 if self.visibility == 'extern' and type.is_pyobject:
823 error(declarator.pos,
824 "Python object cannot be declared extern")
825 name = name_declarator.name
826 cname = name_declarator.cname
827 if name == '':
828 error(declarator.pos, "Missing name in declaration.")
829 return
830 if type.is_cfunction:
831 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
832 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
833 api = self.api)
834 if entry is not None:
835 entry.directive_locals = self.directive_locals
836 else:
837 if self.directive_locals:
838 s.error("Decorators can only be followed by functions")
839 if self.in_pxd and self.visibility != 'extern':
840 error(self.pos,
841 "Only 'extern' C variable declaration allowed in .pxd file")
842 entry = dest_scope.declare_var(name, type, declarator.pos,
843 cname = cname, visibility = visibility, is_cdef = 1)
844 if need_property:
845 self.need_properties.append(entry)
846 entry.needs_property = 1
849 class CStructOrUnionDefNode(StatNode):
850 # name string
851 # cname string or None
852 # kind "struct" or "union"
853 # typedef_flag boolean
854 # visibility "public" or "private"
855 # in_pxd boolean
856 # attributes [CVarDefNode] or None
857 # entry Entry
858 # packed boolean
860 child_attrs = ["attributes"]
862 def analyse_declarations(self, env):
863 scope = None
864 if self.visibility == 'extern' and self.packed:
865 error(self.pos, "Cannot declare extern struct as 'packed'")
866 if self.attributes is not None:
867 scope = StructOrUnionScope(self.name)
868 self.entry = env.declare_struct_or_union(
869 self.name, self.kind, scope, self.typedef_flag, self.pos,
870 self.cname, visibility = self.visibility, packed = self.packed)
871 if self.attributes is not None:
872 if self.in_pxd and not env.in_cinclude:
873 self.entry.defined_in_pxd = 1
874 for attr in self.attributes:
875 attr.analyse_declarations(env, scope)
876 if self.visibility != 'extern':
877 need_typedef_indirection = False
878 for attr in scope.var_entries:
879 type = attr.type
880 while type.is_array:
881 type = type.base_type
882 if type == self.entry.type:
883 error(attr.pos, "Struct cannot contain itself as a member.")
884 if self.typedef_flag:
885 while type.is_ptr:
886 type = type.base_type
887 if type == self.entry.type:
888 need_typedef_indirection = True
889 if need_typedef_indirection:
890 # C can't handle typedef structs that refer to themselves.
891 struct_entry = self.entry
892 self.entry = env.declare_typedef(
893 self.name, struct_entry.type, self.pos,
894 cname = self.cname, visibility='ignore')
895 struct_entry.type.typedef_flag = False
896 # FIXME: this might be considered a hack ;-)
897 struct_entry.cname = struct_entry.type.cname = \
898 '_' + self.entry.type.typedef_cname
900 def analyse_expressions(self, env):
901 pass
903 def generate_execution_code(self, code):
904 pass
907 class CEnumDefNode(StatNode):
908 # name string or None
909 # cname string or None
910 # items [CEnumDefItemNode]
911 # typedef_flag boolean
912 # visibility "public" or "private"
913 # in_pxd boolean
914 # entry Entry
916 child_attrs = ["items"]
918 def analyse_declarations(self, env):
919 self.entry = env.declare_enum(self.name, self.pos,
920 cname = self.cname, typedef_flag = self.typedef_flag,
921 visibility = self.visibility)
922 if self.items is not None:
923 if self.in_pxd and not env.in_cinclude:
924 self.entry.defined_in_pxd = 1
925 for item in self.items:
926 item.analyse_declarations(env, self.entry)
928 def analyse_expressions(self, env):
929 pass
931 def generate_execution_code(self, code):
932 if self.visibility == 'public':
933 temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
934 for item in self.entry.enum_values:
935 code.putln("%s = PyInt_FromLong(%s); %s" % (
936 temp,
937 item.cname,
938 code.error_goto_if_null(temp, item.pos)))
939 code.put_gotref(temp)
940 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
941 Naming.module_cname,
942 item.name,
943 temp,
944 code.error_goto(item.pos)))
945 code.put_decref_clear(temp, PyrexTypes.py_object_type)
946 code.funcstate.release_temp(temp)
949 class CEnumDefItemNode(StatNode):
950 # name string
951 # cname string or None
952 # value ExprNode or None
954 child_attrs = ["value"]
956 def analyse_declarations(self, env, enum_entry):
957 if self.value:
958 self.value.analyse_const_expression(env)
959 if not self.value.type.is_int:
960 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
961 self.value.analyse_const_expression(env)
962 entry = env.declare_const(self.name, enum_entry.type,
963 self.value, self.pos, cname = self.cname,
964 visibility = enum_entry.visibility)
965 enum_entry.enum_values.append(entry)
968 class CTypeDefNode(StatNode):
969 # base_type CBaseTypeNode
970 # declarator CDeclaratorNode
971 # visibility "public" or "private"
972 # in_pxd boolean
974 child_attrs = ["base_type", "declarator"]
976 def analyse_declarations(self, env):
977 base = self.base_type.analyse(env)
978 name_declarator, type = self.declarator.analyse(base, env)
979 name = name_declarator.name
980 cname = name_declarator.cname
981 entry = env.declare_typedef(name, type, self.pos,
982 cname = cname, visibility = self.visibility)
983 if self.in_pxd and not env.in_cinclude:
984 entry.defined_in_pxd = 1
986 def analyse_expressions(self, env):
987 pass
988 def generate_execution_code(self, code):
989 pass
992 class FuncDefNode(StatNode, BlockNode):
993 # Base class for function definition nodes.
994 #
995 # return_type PyrexType
996 # #filename string C name of filename string const
997 # entry Symtab.Entry
998 # needs_closure boolean Whether or not this function has inner functions/classes/yield
999 # directive_locals { string : NameNode } locals defined by cython.locals(...)
1001 py_func = None
1002 assmt = None
1003 needs_closure = False
1004 modifiers = []
1006 def analyse_default_values(self, env):
1007 genv = env.global_scope()
1008 default_seen = 0
1009 for arg in self.args:
1010 if arg.default:
1011 default_seen = 1
1012 if arg.is_generic:
1013 arg.default.analyse_types(env)
1014 arg.default = arg.default.coerce_to(arg.type, genv)
1015 else:
1016 error(arg.pos,
1017 "This argument cannot have a default value")
1018 arg.default = None
1019 elif arg.kw_only:
1020 default_seen = 1
1021 elif default_seen:
1022 error(arg.pos, "Non-default argument following default argument")
1024 def need_gil_acquisition(self, lenv):
1025 return 0
1027 def create_local_scope(self, env):
1028 genv = env
1029 while genv.is_py_class_scope or genv.is_c_class_scope:
1030 genv = env.outer_scope
1031 if self.needs_closure:
1032 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
1033 else:
1034 lenv = LocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
1035 lenv.return_type = self.return_type
1036 type = self.entry.type
1037 if type.is_cfunction:
1038 lenv.nogil = type.nogil and not type.with_gil
1039 self.local_scope = lenv
1040 lenv.directives = env.directives
1041 return lenv
1043 def generate_function_definitions(self, env, code):
1044 import Buffer
1046 lenv = self.local_scope
1048 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1049 self.entry.scope.is_c_class_scope)
1051 profile = code.globalstate.directives['profile']
1052 if profile:
1053 if lenv.nogil:
1054 error(self.pos, "Cannot profile nogil function.")
1055 code.globalstate.use_utility_code(profile_utility_code)
1057 # Generate C code for header and body of function
1058 code.enter_cfunc_scope()
1059 code.return_from_error_cleanup_label = code.new_label()
1061 # ----- Top-level constants used by this function
1062 code.mark_pos(self.pos)
1063 self.generate_cached_builtins_decls(lenv, code)
1064 # ----- Function header
1065 code.putln("")
1066 if self.py_func:
1067 self.py_func.generate_function_header(code,
1068 with_pymethdef = env.is_py_class_scope,
1069 proto_only=True)
1070 self.generate_function_header(code,
1071 with_pymethdef = env.is_py_class_scope)
1072 # ----- Local variable declarations
1073 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
1074 self.generate_argument_declarations(lenv, code)
1075 if self.needs_closure:
1076 code.putln("/* TODO: declare and create scope object */")
1077 code.put_var_declarations(lenv.var_entries)
1078 init = ""
1079 if not self.return_type.is_void:
1080 if self.return_type.is_pyobject:
1081 init = " = NULL"
1082 code.putln(
1083 "%s%s;" %
1084 (self.return_type.declaration_code(
1085 Naming.retval_cname),
1086 init))
1087 tempvardecl_code = code.insertion_point()
1088 self.generate_keyword_list(code)
1089 if profile:
1090 code.put_trace_declarations()
1091 # ----- Extern library function declarations
1092 lenv.generate_library_function_declarations(code)
1093 # ----- GIL acquisition
1094 acquire_gil = self.acquire_gil
1095 if acquire_gil:
1096 env.use_utility_code(force_init_threads_utility_code)
1097 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1098 # ----- Automatic lead-ins for certain special functions
1099 if not lenv.nogil:
1100 code.put_setup_refcount_context(self.entry.name)
1101 if profile:
1102 code.put_trace_call(self.entry.name, self.pos)
1103 if is_getbuffer_slot:
1104 self.getbuffer_init(code)
1105 # ----- Fetch arguments
1106 self.generate_argument_parsing_code(env, code)
1107 # If an argument is assigned to in the body, we must
1108 # incref it to properly keep track of refcounts.
1109 for entry in lenv.arg_entries:
1110 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1111 code.put_var_incref(entry)
1112 # ----- Initialise local variables
1113 for entry in lenv.var_entries:
1114 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1115 code.put_init_var_to_py_none(entry)
1116 # ----- Initialise local buffer auxiliary variables
1117 for entry in lenv.var_entries + lenv.arg_entries:
1118 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1119 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1120 # ----- Check and convert arguments
1121 self.generate_argument_type_tests(code)
1122 # ----- Acquire buffer arguments
1123 for entry in lenv.arg_entries:
1124 if entry.type.is_buffer:
1125 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1126 # ----- Function body
1127 self.body.generate_execution_code(code)
1128 # ----- Default return value
1129 code.putln("")
1130 if self.return_type.is_pyobject:
1131 #if self.return_type.is_extension_type:
1132 # lhs = "(PyObject *)%s" % Naming.retval_cname
1133 #else:
1134 lhs = Naming.retval_cname
1135 code.put_init_to_py_none(lhs, self.return_type)
1136 else:
1137 val = self.return_type.default_value
1138 if val:
1139 code.putln("%s = %s;" % (Naming.retval_cname, val))
1140 # ----- Error cleanup
1141 if code.error_label in code.labels_used:
1142 code.put_goto(code.return_label)
1143 code.put_label(code.error_label)
1144 for cname, type in code.funcstate.all_managed_temps():
1145 code.put_xdecref(cname, type)
1147 # Clean up buffers -- this calls a Python function
1148 # so need to save and restore error state
1149 buffers_present = len(lenv.buffer_entries) > 0
1150 if buffers_present:
1151 code.globalstate.use_utility_code(restore_exception_utility_code)
1152 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1153 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1154 for entry in lenv.buffer_entries:
1155 Buffer.put_release_buffer_code(code, entry)
1156 #code.putln("%s = 0;" % entry.cname)
1157 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1159 err_val = self.error_value()
1160 exc_check = self.caller_will_check_exceptions()
1161 if err_val is not None or exc_check:
1162 # TODO: Fix exception tracing (though currently unused by cProfile).
1163 # code.globalstate.use_utility_code(get_exception_tuple_utility_code)
1164 # code.put_trace_exception()
1165 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1166 else:
1167 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1168 % self.entry.qualified_name, 0)
1169 code.putln(
1170 '__Pyx_WriteUnraisable("%s");' %
1171 self.entry.qualified_name)
1172 env.use_utility_code(unraisable_exception_utility_code)
1173 env.use_utility_code(restore_exception_utility_code)
1174 default_retval = self.return_type.default_value
1175 if err_val is None and default_retval:
1176 err_val = default_retval
1177 if err_val is not None:
1178 code.putln(
1179 "%s = %s;" % (
1180 Naming.retval_cname,
1181 err_val))
1183 if is_getbuffer_slot:
1184 self.getbuffer_error_cleanup(code)
1186 # If we are using the non-error cleanup section we should
1187 # jump past it if we have an error. The if-test below determine
1188 # whether this section is used.
1189 if buffers_present or is_getbuffer_slot:
1190 code.put_goto(code.return_from_error_cleanup_label)
1193 # ----- Non-error return cleanup
1194 code.put_label(code.return_label)
1195 for entry in lenv.buffer_entries:
1196 if entry.used:
1197 Buffer.put_release_buffer_code(code, entry)
1198 if is_getbuffer_slot:
1199 self.getbuffer_normal_cleanup(code)
1200 # ----- Return cleanup for both error and no-error return
1201 code.put_label(code.return_from_error_cleanup_label)
1202 if not Options.init_local_none:
1203 for entry in lenv.var_entries:
1204 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1205 entry.xdecref_cleanup = 1
1206 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1207 # Decref any increfed args
1208 for entry in lenv.arg_entries:
1209 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1210 code.put_var_decref(entry)
1212 # code.putln("/* TODO: decref scope object */")
1213 # ----- Return
1214 # This code is duplicated in ModuleNode.generate_module_init_func
1215 if not lenv.nogil:
1216 default_retval = self.return_type.default_value
1217 err_val = self.error_value()
1218 if err_val is None and default_retval:
1219 err_val = default_retval
1220 if self.return_type.is_pyobject:
1221 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1223 if self.entry.is_special and self.entry.name == "__hash__":
1224 # Returning -1 for __hash__ is supposed to signal an error
1225 # We do as Python instances and coerce -1 into -2.
1226 code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (
1227 Naming.retval_cname, Naming.retval_cname))
1229 if profile:
1230 if self.return_type.is_pyobject:
1231 code.put_trace_return(Naming.retval_cname)
1232 else:
1233 code.put_trace_return("Py_None")
1234 if not lenv.nogil:
1235 code.put_finish_refcount_context()
1237 if acquire_gil:
1238 code.putln("PyGILState_Release(_save);")
1240 if not self.return_type.is_void:
1241 code.putln("return %s;" % Naming.retval_cname)
1243 code.putln("}")
1244 # ----- Go back and insert temp variable declarations
1245 tempvardecl_code.put_temp_declarations(code.funcstate)
1246 # ----- Python version
1247 code.exit_cfunc_scope()
1248 if self.py_func:
1249 self.py_func.generate_function_definitions(env, code)
1250 self.generate_wrapper_functions(code)
1252 def declare_argument(self, env, arg):
1253 if arg.type.is_void:
1254 error(arg.pos, "Invalid use of 'void'")
1255 elif not arg.type.is_complete() and not arg.type.is_array:
1256 error(arg.pos,
1257 "Argument type '%s' is incomplete" % arg.type)
1258 return env.declare_arg(arg.name, arg.type, arg.pos)
1260 def generate_wrapper_functions(self, code):
1261 pass
1263 def generate_execution_code(self, code):
1264 # Evaluate and store argument default values
1265 for arg in self.args:
1266 default = arg.default
1267 if default:
1268 if not default.is_literal:
1269 default.generate_evaluation_code(code)
1270 default.make_owned_reference(code)
1271 result = default.result_as(arg.type)
1272 code.putln(
1273 "%s = %s;" % (
1274 arg.calculate_default_value_code(code),
1275 result))
1276 if arg.type.is_pyobject:
1277 code.put_giveref(default.result())
1278 default.generate_post_assignment_code(code)
1279 default.free_temps(code)
1280 # For Python class methods, create and store function object
1281 if self.assmt:
1282 self.assmt.generate_execution_code(code)
1284 #
1285 # Special code for the __getbuffer__ function
1286 #
1287 def getbuffer_init(self, code):
1288 info = self.local_scope.arg_entries[1].cname
1289 # Python 3.0 betas have a bug in memoryview which makes it call
1290 # getbuffer with a NULL parameter. For now we work around this;
1291 # the following line should be removed when this bug is fixed.
1292 code.putln("if (%s == NULL) return 0;" % info)
1293 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1294 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1296 def getbuffer_error_cleanup(self, code):
1297 info = self.local_scope.arg_entries[1].cname
1298 code.put_gotref("%s->obj" % info)
1299 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1300 (info, info))
1302 def getbuffer_normal_cleanup(self, code):
1303 info = self.local_scope.arg_entries[1].cname
1304 code.putln("if (%s->obj == Py_None) {" % info)
1305 code.put_gotref("Py_None")
1306 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1307 code.putln("}")
1309 class CFuncDefNode(FuncDefNode):
1310 # C function definition.
1311 #
1312 # modifiers ['inline']
1313 # visibility 'private' or 'public' or 'extern'
1314 # base_type CBaseTypeNode
1315 # declarator CDeclaratorNode
1316 # body StatListNode
1317 # api boolean
1318 # decorators [DecoratorNode] list of decorators
1319 #
1320 # with_gil boolean Acquire GIL around body
1321 # type CFuncType
1322 # py_func wrapper for calling from Python
1323 # overridable whether or not this is a cpdef function
1324 # inline_in_pxd whether this is an inline function in a pxd file
1326 child_attrs = ["base_type", "declarator", "body", "py_func"]
1328 inline_in_pxd = False
1329 decorators = None
1330 directive_locals = {}
1332 def unqualified_name(self):
1333 return self.entry.name
1335 def analyse_declarations(self, env):
1336 self.directive_locals.update(env.directives['locals'])
1337 base_type = self.base_type.analyse(env)
1338 # The 2 here is because we need both function and argument names.
1339 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1340 if not type.is_cfunction:
1341 error(self.pos,
1342 "Suite attached to non-function declaration")
1343 # Remember the actual type according to the function header
1344 # written here, because the type in the symbol table entry
1345 # may be different if we're overriding a C method inherited
1346 # from the base type of an extension type.
1347 self.type = type
1348 type.is_overridable = self.overridable
1349 declarator = self.declarator
1350 while not hasattr(declarator, 'args'):
1351 declarator = declarator.base
1352 self.args = declarator.args
1353 for formal_arg, type_arg in zip(self.args, type.args):
1354 formal_arg.type = type_arg.type
1355 formal_arg.name = type_arg.name
1356 formal_arg.cname = type_arg.cname
1357 name = name_declarator.name
1358 cname = name_declarator.cname
1359 self.entry = env.declare_cfunction(
1360 name, type, self.pos,
1361 cname = cname, visibility = self.visibility,
1362 defining = self.body is not None,
1363 api = self.api, modifiers = self.modifiers)
1364 self.entry.inline_func_in_pxd = self.inline_in_pxd
1365 self.return_type = type.return_type
1367 if self.overridable and not env.is_module_scope:
1368 if len(self.args) < 1 or not self.args[0].type.is_pyobject:
1369 # An error will be produced in the cdef function
1370 self.overridable = False
1372 if self.overridable:
1373 import ExprNodes
1374 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1375 self.py_func = DefNode(pos = self.pos,
1376 name = self.entry.name,
1377 args = self.args,
1378 star_arg = None,
1379 starstar_arg = None,
1380 doc = self.doc,
1381 body = py_func_body,
1382 is_wrapper = 1)
1383 self.py_func.is_module_scope = env.is_module_scope
1384 self.py_func.analyse_declarations(env)
1385 self.entry.as_variable = self.py_func.entry
1386 # Reset scope entry the above cfunction
1387 env.entries[name] = self.entry
1388 if not env.is_module_scope or Options.lookup_module_cpdef:
1389 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1390 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1391 self.create_local_scope(env)
1393 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1394 import ExprNodes
1395 args = self.type.args
1396 if omit_optional_args:
1397 args = args[:len(args) - self.type.optional_arg_count]
1398 arg_names = [arg.name for arg in args]
1399 if is_module_scope:
1400 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1401 else:
1402 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1403 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1404 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1405 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)
1406 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1408 def declare_arguments(self, env):
1409 for arg in self.type.args:
1410 if not arg.name:
1411 error(arg.pos, "Missing argument name")
1412 self.declare_argument(env, arg)
1414 def need_gil_acquisition(self, lenv):
1415 return self.type.with_gil
1417 def nogil_check(self, env):
1418 type = self.type
1419 with_gil = type.with_gil
1420 if type.nogil and not with_gil:
1421 if type.return_type.is_pyobject:
1422 error(self.pos,
1423 "Function with Python return type cannot be declared nogil")
1424 for entry in self.local_scope.var_entries:
1425 if entry.type.is_pyobject:
1426 error(self.pos, "Function declared nogil has Python locals or temporaries")
1428 def analyse_expressions(self, env):
1429 self.local_scope.directives = env.directives
1430 if self.py_func is not None:
1431 # this will also analyse the default values
1432 self.py_func.analyse_expressions(env)
1433 else:
1434 self.analyse_default_values(env)
1435 self.acquire_gil = self.need_gil_acquisition(self.local_scope)
1437 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1438 arg_decls = []
1439 type = self.type
1440 visibility = self.entry.visibility
1441 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1442 arg_decls.append(arg.declaration_code())
1443 if with_dispatch and self.overridable:
1444 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1445 if type.optional_arg_count and with_opt_args:
1446 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1447 if type.has_varargs:
1448 arg_decls.append("...")
1449 if not arg_decls:
1450 arg_decls = ["void"]
1451 if cname is None:
1452 cname = self.entry.func_cname
1453 entity = type.function_header_code(cname, ', '.join(arg_decls))
1454 if visibility == 'public':
1455 dll_linkage = "DL_EXPORT"
1456 else:
1457 dll_linkage = None
1458 header = self.return_type.declaration_code(entity,
1459 dll_linkage = dll_linkage)
1460 if visibility == 'extern':
1461 storage_class = "%s " % Naming.extern_c_macro
1462 elif visibility == 'public':
1463 storage_class = ""
1464 else:
1465 storage_class = "static "
1466 if 'inline' in self.modifiers:
1467 self.modifiers[self.modifiers.index('inline')] = 'cython_inline'
1468 code.putln("%s%s %s {" % (
1469 storage_class,
1470 ' '.join(self.modifiers).upper(), # macro forms
1471 header))
1473 def generate_argument_declarations(self, env, code):
1474 for arg in self.args:
1475 if arg.default:
1476 result = arg.calculate_default_value_code(code)
1477 code.putln('%s = %s;' % (
1478 arg.type.declaration_code(arg.cname), result))
1480 def generate_keyword_list(self, code):
1481 pass
1483 def generate_argument_parsing_code(self, env, code):
1484 i = 0
1485 if self.type.optional_arg_count:
1486 code.putln('if (%s) {' % Naming.optional_args_cname)
1487 for arg in self.args:
1488 if arg.default:
1489 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1490 declarator = arg.declarator
1491 while not hasattr(declarator, 'name'):
1492 declarator = declarator.base
1493 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, self.type.opt_arg_cname(declarator.name)))
1494 i += 1
1495 for _ in range(self.type.optional_arg_count):
1496 code.putln('}')
1497 code.putln('}')
1499 def generate_argument_conversion_code(self, code):
1500 pass
1502 def generate_argument_type_tests(self, code):
1503 # Generate type tests for args whose type in a parent
1504 # class is a supertype of the declared type.
1505 for arg in self.type.args:
1506 if arg.needs_type_test:
1507 self.generate_arg_type_test(arg, code)
1509 def generate_arg_type_test(self, arg, code):
1510 # Generate type test for one argument.
1511 if arg.type.typeobj_is_available():
1512 typeptr_cname = arg.type.typeptr_cname
1513 arg_code = "((PyObject *)%s)" % arg.cname
1514 code.putln(
1515 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1516 arg_code,
1517 typeptr_cname,
1518 not arg.not_none,
1519 arg.name,
1520 type.is_builtin_type,
1521 code.error_goto(arg.pos)))
1522 else:
1523 error(arg.pos, "Cannot test type of extern C class "
1524 "without type object name specification")
1526 def error_value(self):
1527 if self.return_type.is_pyobject:
1528 return "0"
1529 else:
1530 #return None
1531 return self.entry.type.exception_value
1533 def caller_will_check_exceptions(self):
1534 return self.entry.type.exception_check
1536 def generate_wrapper_functions(self, code):
1537 # If the C signature of a function has changed, we need to generate
1538 # wrappers to put in the slots here.
1539 k = 0
1540 entry = self.entry
1541 func_type = entry.type
1542 while entry.prev_entry is not None:
1543 k += 1
1544 entry = entry.prev_entry
1545 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1546 code.putln()
1547 self.generate_function_header(code,
1548 0,
1549 with_dispatch = entry.type.is_overridable,
1550 with_opt_args = entry.type.optional_arg_count,
1551 cname = entry.func_cname)
1552 if not self.return_type.is_void:
1553 code.put('return ')
1554 args = self.type.args
1555 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1556 if entry.type.is_overridable:
1557 arglist.append(Naming.skip_dispatch_cname)
1558 elif func_type.is_overridable:
1559 arglist.append('0')
1560 if entry.type.optional_arg_count:
1561 arglist.append(Naming.optional_args_cname)
1562 elif func_type.optional_arg_count:
1563 arglist.append('NULL')
1564 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1565 code.putln('}')
1568 class PyArgDeclNode(Node):
1569 # Argument which must be a Python object (used
1570 # for * and ** arguments).
1571 #
1572 # name string
1573 # entry Symtab.Entry
1574 child_attrs = []
1577 class DecoratorNode(Node):
1578 # A decorator
1579 #
1580 # decorator NameNode or CallNode
1581 child_attrs = ['decorator']
1584 class DefNode(FuncDefNode):
1585 # A Python function definition.
1586 #
1587 # name string the Python name of the function
1588 # decorators [DecoratorNode] list of decorators
1589 # args [CArgDeclNode] formal arguments
1590 # star_arg PyArgDeclNode or None * argument
1591 # starstar_arg PyArgDeclNode or None ** argument
1592 # doc EncodedString or None
1593 # body StatListNode
1594 #
1595 # The following subnode is constructed internally
1596 # when the def statement is inside a Python class definition.
1597 #
1598 # assmt AssignmentNode Function construction/assignment
1600 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1602 assmt = None
1603 num_kwonly_args = 0
1604 num_required_kw_args = 0
1605 reqd_kw_flags_cname = "0"
1606 is_wrapper = 0
1607 decorators = None
1608 entry = None
1609 acquire_gil = 0
1610 self_in_stararg = 0
1612 def __init__(self, pos, **kwds):
1613 FuncDefNode.__init__(self, pos, **kwds)
1614 k = rk = r = 0
1615 for arg in self.args:
1616 if arg.kw_only:
1617 k += 1
1618 if not arg.default:
1619 rk += 1
1620 if not arg.default:
1621 r += 1
1622 self.num_kwonly_args = k
1623 self.num_required_kw_args = rk
1624 self.num_required_args = r
1626 def as_cfunction(self, cfunc=None, scope=None):
1627 if self.star_arg:
1628 error(self.star_arg.pos, "cdef function cannot have star argument")
1629 if self.starstar_arg:
1630 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1631 if cfunc is None:
1632 cfunc_args = []
1633 for formal_arg in self.args:
1634 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1635 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1636 cname = None,
1637 type = py_object_type,
1638 pos = formal_arg.pos))
1639 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1640 args = cfunc_args,
1641 has_varargs = False,
1642 exception_value = None,
1643 exception_check = False,
1644 nogil = False,
1645 with_gil = False,
1646 is_overridable = True)
1647 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1648 else:
1649 cfunc_type = cfunc.type
1650 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1651 error(self.pos, "wrong number of arguments")
1652 error(declarator.pos, "previous declaration here")
1653 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1654 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1655 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1656 formal_arg.type = type_arg.type
1657 formal_arg.name_declarator = name_declarator
1658 import ExprNodes
1659 if cfunc_type.exception_value is None:
1660 exception_value = None
1661 else:
1662 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1663 declarator = CFuncDeclaratorNode(self.pos,
1664 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1665 args = self.args,
1666 has_varargs = False,
1667 exception_check = cfunc_type.exception_check,
1668 exception_value = exception_value,
1669 with_gil = cfunc_type.with_gil,
1670 nogil = cfunc_type.nogil)
1671 return CFuncDefNode(self.pos,
1672 modifiers = [],
1673 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1674 declarator = declarator,
1675 body = self.body,
1676 doc = self.doc,
1677 overridable = cfunc_type.is_overridable,
1678 type = cfunc_type,
1679 with_gil = cfunc_type.with_gil,
1680 nogil = cfunc_type.nogil,
1681 visibility = 'private',
1682 api = False,
1683 directive_locals = getattr(cfunc, 'directive_locals', {}))
1685 def analyse_declarations(self, env):
1686 self.is_classmethod = self.is_staticmethod = False
1687 if self.decorators:
1688 for decorator in self.decorators:
1689 func = decorator.decorator
1690 if func.is_name:
1691 self.is_classmethod |= func.name == 'classmethod'
1692 self.is_staticmethod |= func.name == 'staticmethod'
1694 if self.is_classmethod and env.lookup_here('classmethod'):
1695 # classmethod() was overridden - not much we can do here ...
1696 self.is_classmethod = False
1697 if self.is_staticmethod and env.lookup_here('staticmethod'):
1698 # staticmethod() was overridden - not much we can do here ...
1699 self.is_staticmethod = False
1701 self.analyse_argument_types(env)
1702 self.declare_pyfunction(env)
1703 self.analyse_signature(env)
1704 self.return_type = self.entry.signature.return_type()
1705 self.create_local_scope(env)
1707 def analyse_argument_types(self, env):
1708 directive_locals = self.directive_locals = env.directives['locals']
1709 for arg in self.args:
1710 if hasattr(arg, 'name'):
1711 type = arg.type
1712 name_declarator = None
1713 else:
1714 base_type = arg.base_type.analyse(env)
1715 name_declarator, type = \
1716 arg.declarator.analyse(base_type, env)
1717 arg.name = name_declarator.name
1718 if arg.name in directive_locals:
1719 type_node = directive_locals[arg.name]
1720 other_type = type_node.analyse_as_type(env)
1721 if other_type is None:
1722 error(type_node.pos, "Not a type")
1723 elif (type is not PyrexTypes.py_object_type
1724 and not type.same_as(other_type)):
1725 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1726 error(type_node.pos, "Previous declaration here")
1727 else:
1728 type = other_type
1729 if name_declarator and name_declarator.cname:
1730 error(self.pos,
1731 "Python function argument cannot have C name specification")
1732 arg.type = type.as_argument_type()
1733 arg.hdr_type = None
1734 arg.needs_conversion = 0
1735 arg.needs_type_test = 0
1736 arg.is_generic = 1
1737 if arg.not_none and not arg.type.is_extension_type:
1738 error(self.pos,
1739 "Only extension type arguments can have 'not None'")
1741 def analyse_signature(self, env):
1742 any_type_tests_needed = 0
1743 if self.entry.is_special:
1744 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1745 elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
1746 # Use the simpler calling signature for zero- and one-argument functions.
1747 if self.entry.signature is TypeSlots.pyfunction_signature:
1748 if len(self.args) == 0:
1749 self.entry.signature = TypeSlots.pyfunction_noargs
1750 elif len(self.args) == 1:
1751 if self.args[0].default is None and not self.args[0].kw_only:
1752 self.entry.signature = TypeSlots.pyfunction_onearg
1753 elif self.entry.signature is TypeSlots.pymethod_signature:
1754 if len(self.args) == 1:
1755 self.entry.signature = TypeSlots.unaryfunc
1756 elif len(self.args) == 2:
1757 if self.args[1].default is None and not self.args[1].kw_only:
1758 self.entry.signature = TypeSlots.ibinaryfunc
1760 sig = self.entry.signature
1761 nfixed = sig.num_fixed_args()
1762 if sig is TypeSlots.pymethod_signature and nfixed == 1 \
1763 and len(self.args) == 0 and self.star_arg:
1764 # this is the only case where a diverging number of
1765 # arguments is not an error - when we have no explicit
1766 # 'self' parameter as in method(*args)
1767 sig = self.entry.signature = TypeSlots.pyfunction_signature # self is not 'really' used
1768 self.self_in_stararg = 1
1769 nfixed = 0
1771 for i in range(min(nfixed, len(self.args))):
1772 arg = self.args[i]
1773 arg.is_generic = 0
1774 if sig.is_self_arg(i) and not self.is_staticmethod:
1775 if self.is_classmethod:
1776 arg.is_type_arg = 1
1777 arg.hdr_type = arg.type = Builtin.type_type
1778 else:
1779 arg.is_self_arg = 1
1780 arg.hdr_type = arg.type = env.parent_type
1781 arg.needs_conversion = 0
1782 else:
1783 arg.hdr_type = sig.fixed_arg_type(i)
1784 if not arg.type.same_as(arg.hdr_type):
1785 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1786 arg.needs_type_test = 1
1787 any_type_tests_needed = 1
1788 else:
1789 arg.needs_conversion = 1
1790 if arg.needs_conversion:
1791 arg.hdr_cname = Naming.arg_prefix + arg.name
1792 else:
1793 arg.hdr_cname = Naming.var_prefix + arg.name
1795 if nfixed > len(self.args):
1796 self.bad_signature()
1797 return
1798 elif nfixed < len(self.args):
1799 if not sig.has_generic_args:
1800 self.bad_signature()
1801 for arg in self.args:
1802 if arg.is_generic and \
1803 (arg.type.is_extension_type or arg.type.is_builtin_type):
1804 arg.needs_type_test = 1
1805 any_type_tests_needed = 1
1806 if any_type_tests_needed:
1807 env.use_utility_code(arg_type_test_utility_code)
1809 def bad_signature(self):
1810 sig = self.entry.signature
1811 expected_str = "%d" % sig.num_fixed_args()
1812 if sig.has_generic_args:
1813 expected_str = expected_str + " or more"
1814 name = self.name
1815 if name.startswith("__") and name.endswith("__"):
1816 desc = "Special method"
1817 else:
1818 desc = "Method"
1819 error(self.pos,
1820 "%s %s has wrong number of arguments "
1821 "(%d declared, %s expected)" % (
1822 desc, self.name, len(self.args), expected_str))
1824 def signature_has_nongeneric_args(self):
1825 argcount = len(self.args)
1826 if argcount == 0 or (
1827 argcount == 1 and (self.args[0].is_self_arg or
1828 self.args[0].is_type_arg)):
1829 return 0
1830 return 1
1832 def signature_has_generic_args(self):
1833 return self.entry.signature.has_generic_args
1835 def declare_pyfunction(self, env):
1836 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1837 name = self.name
1838 entry = env.lookup_here(self.name)
1839 if entry and entry.type.is_cfunction and not self.is_wrapper:
1840 warning(self.pos, "Overriding cdef method with def method.", 5)
1841 entry = env.declare_pyfunction(self.name, self.pos)
1842 self.entry = entry
1843 prefix = env.scope_prefix
1844 entry.func_cname = \
1845 Naming.pyfunc_prefix + prefix + name
1846 entry.pymethdef_cname = \
1847 Naming.pymethdef_prefix + prefix + name
1848 if Options.docstrings:
1849 entry.doc = embed_position(self.pos, self.doc)
1850 entry.doc_cname = \
1851 Naming.funcdoc_prefix + prefix + name
1852 else:
1853 entry.doc = None
1855 def declare_arguments(self, env):
1856 for arg in self.args:
1857 if not arg.name:
1858 error(arg.pos, "Missing argument name")
1859 if arg.needs_conversion:
1860 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1861 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1862 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1863 if arg.type.is_pyobject:
1864 arg.entry.init = "0"
1865 arg.entry.init_to_none = 0
1866 else:
1867 arg.entry = self.declare_argument(env, arg)
1868 arg.entry.used = 1
1869 arg.entry.is_self_arg = arg.is_self_arg
1870 if arg.hdr_type:
1871 if arg.is_self_arg or arg.is_type_arg or \
1872 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1873 arg.entry.is_declared_generic = 1
1874 self.declare_python_arg(env, self.star_arg)
1875 self.declare_python_arg(env, self.starstar_arg)
1877 def declare_python_arg(self, env, arg):
1878 if arg:
1879 if env.directives['infer_types'] != 'none':
1880 type = PyrexTypes.unspecified_type
1881 else:
1882 type = py_object_type
1883 entry = env.declare_var(arg.name, type, arg.pos)
1884 entry.used = 1
1885 entry.init = "0"
1886 entry.init_to_none = 0
1887 entry.xdecref_cleanup = 1
1888 arg.entry = entry
1889 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1891 def analyse_expressions(self, env):
1892 self.local_scope.directives = env.directives
1893 self.analyse_default_values(env)
1894 if env.is_py_class_scope:
1895 self.synthesize_assignment_node(env)
1897 def synthesize_assignment_node(self, env):
1898 import ExprNodes
1899 self.assmt = SingleAssignmentNode(self.pos,
1900 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1901 rhs = ExprNodes.UnboundMethodNode(self.pos,
1902 function = ExprNodes.PyCFunctionNode(self.pos,
1903 pymethdef_cname = self.entry.pymethdef_cname)))
1904 self.assmt.analyse_declarations(env)
1905 self.assmt.analyse_expressions(env)
1907 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1908 arg_code_list = []
1909 sig = self.entry.signature
1910 if sig.has_dummy_arg or self.self_in_stararg:
1911 arg_code_list.append(
1912 "PyObject *%s" % Naming.self_cname)
1913 for arg in self.args:
1914 if not arg.is_generic:
1915 if arg.is_self_arg or arg.is_type_arg:
1916 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1917 else:
1918 arg_code_list.append(
1919 arg.hdr_type.declaration_code(arg.hdr_cname))
1920 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1921 arg_code_list.append("PyObject *unused")
1922 if sig.has_generic_args:
1923 arg_code_list.append(
1924 "PyObject *%s, PyObject *%s"
1925 % (Naming.args_cname, Naming.kwds_cname))
1926 arg_code = ", ".join(arg_code_list)
1927 dc = self.return_type.declaration_code(self.entry.func_cname)
1928 header = "static %s(%s)" % (dc, arg_code)
1929 code.putln("%s; /*proto*/" % header)
1930 if proto_only:
1931 return
1932 if self.entry.doc and Options.docstrings:
1933 docstr = self.entry.doc
1934 if docstr.is_unicode:
1935 docstr = docstr.utf8encode()
1936 code.putln(
1937 'static char %s[] = "%s";' % (
1938 self.entry.doc_cname,
1939 split_docstring(escape_byte_string(docstr))))
1940 if with_pymethdef:
1941 code.put(
1942 "static PyMethodDef %s = " %
1943 self.entry.pymethdef_cname)
1944 code.put_pymethoddef(self.entry, ";")
1945 code.putln("%s {" % header)
1947 def generate_argument_declarations(self, env, code):
1948 for arg in self.args:
1949 if arg.is_generic: # or arg.needs_conversion:
1950 if arg.needs_conversion:
1951 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1952 else:
1953 code.put_var_declaration(arg.entry)
1955 def generate_keyword_list(self, code):
1956 if self.signature_has_generic_args() and \
1957 self.signature_has_nongeneric_args():
1958 code.put(
1959 "static PyObject **%s[] = {" %
1960 Naming.pykwdlist_cname)
1961 for arg in self.args:
1962 if arg.is_generic:
1963 pystring_cname = code.intern_identifier(arg.name)
1964 code.put('&%s,' % pystring_cname)
1965 code.putln("0};")
1967 def generate_argument_parsing_code(self, env, code):
1968 # Generate PyArg_ParseTuple call for generic
1969 # arguments, if any.
1970 if self.entry.signature.has_dummy_arg and not self.self_in_stararg:
1971 # get rid of unused argument warning
1972 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1974 old_error_label = code.new_error_label()
1975 our_error_label = code.error_label
1976 end_label = code.new_label("argument_unpacking_done")
1978 has_kwonly_args = self.num_kwonly_args > 0
1979 has_star_or_kw_args = self.star_arg is not None \
1980 or self.starstar_arg is not None or has_kwonly_args
1982 for arg in self.args:
1983 if not arg.type.is_pyobject:
1984 done = arg.type.create_from_py_utility_code(env)
1985 if not done: pass # will fail later
1987 if not self.signature_has_generic_args():
1988 if has_star_or_kw_args:
1989 error(self.pos, "This method cannot have * or keyword arguments")
1990 self.generate_argument_conversion_code(code)
1992 elif not self.signature_has_nongeneric_args():
1993 # func(*args) or func(**kw) or func(*args, **kw)
1994 self.generate_stararg_copy_code(code)
1996 else:
1997 positional_args = []
1998 kw_only_args = []
1999 for arg in self.args:
2000 arg_entry = arg.entry
2001 if arg.is_generic:
2002 if arg.default:
2003 if not arg.is_self_arg and not arg.is_type_arg:
2004 if arg.kw_only:
2005 kw_only_args.append(arg)
2006 else:
2007 positional_args.append(arg)
2008 elif arg.kw_only:
2009 kw_only_args.append(arg)
2010 elif not arg.is_self_arg and not arg.is_type_arg:
2011 positional_args.append(arg)
2013 self.generate_tuple_and_keyword_parsing_code(
2014 positional_args, kw_only_args, end_label, code)
2016 code.error_label = old_error_label
2017 if code.label_used(our_error_label):
2018 if not code.label_used(end_label):
2019 code.put_goto(end_label)
2020 code.put_label(our_error_label)
2021 if has_star_or_kw_args:
2022 self.generate_arg_decref(self.star_arg, code)
2023 if self.starstar_arg:
2024 if self.starstar_arg.entry.xdecref_cleanup:
2025 code.put_var_xdecref(self.starstar_arg.entry)
2026 else:
2027 code.put_var_decref(self.starstar_arg.entry)
2028 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
2029 code.putln("return %s;" % self.error_value())
2030 if code.label_used(end_label):
2031 code.put_label(end_label)
2033 def generate_arg_assignment(self, arg, item, code):
2034 if arg.type.is_pyobject:
2035 if arg.is_generic:
2036 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
2037 code.putln("%s = %s;" % (arg.entry.cname, item))
2038 else:
2039 func = arg.type.from_py_function
2040 if func:
2041 code.putln("%s = %s(%s); %s" % (
2042 arg.entry.cname,
2043 func,
2044 item,
2045 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
2046 else:
2047 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
2049 def generate_arg_xdecref(self, arg, code):
2050 if arg:
2051 code.put_var_xdecref(arg.entry)
2053 def generate_arg_decref(self, arg, code):
2054 if arg:
2055 code.put_var_decref(arg.entry)
2057 def generate_stararg_copy_code(self, code):
2058 if not self.star_arg:
2059 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2060 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
2061 Naming.args_cname)
2062 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2063 self.name, Naming.args_cname, self.error_value()))
2064 code.putln("}")
2066 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2068 if self.starstar_arg:
2069 if self.star_arg:
2070 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2071 else:
2072 kwarg_check = "%s" % Naming.kwds_cname
2073 else:
2074 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2075 Naming.kwds_cname, Naming.kwds_cname)
2076 code.putln(
2077 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2078 kwarg_check, Naming.kwds_cname, self.name,
2079 bool(self.starstar_arg), self.error_value()))
2081 if self.starstar_arg:
2082 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2083 self.starstar_arg.entry.cname,
2084 Naming.kwds_cname,
2085 Naming.kwds_cname))
2086 code.putln("if (unlikely(!%s)) return %s;" % (
2087 self.starstar_arg.entry.cname, self.error_value()))
2088 self.starstar_arg.entry.xdecref_cleanup = 0
2089 code.put_gotref(self.starstar_arg.entry.cname)
2091 if self.self_in_stararg:
2092 # need to create a new tuple with 'self' inserted as first item
2093 code.put("%s = PyTuple_New(PyTuple_GET_SIZE(%s)+1); if (unlikely(!%s)) " % (
2094 self.star_arg.entry.cname,
2095 Naming.args_cname,
2096 self.star_arg.entry.cname))
2097 if self.starstar_arg:
2098 code.putln("{")
2099 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2100 code.putln("return %s;" % self.error_value())
2101 code.putln("}")
2102 else:
2103 code.putln("return %s;" % self.error_value())
2104 code.put_gotref(self.star_arg.entry.cname)
2105 code.put_incref(Naming.self_cname, py_object_type)
2106 code.put_giveref(Naming.self_cname)
2107 code.putln("PyTuple_SET_ITEM(%s, 0, %s);" % (
2108 self.star_arg.entry.cname, Naming.self_cname))
2109 temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False)
2110 code.putln("for (%s=0; %s < PyTuple_GET_SIZE(%s); %s++) {" % (
2111 temp, temp, Naming.args_cname, temp))
2112 code.putln("PyObject* item = PyTuple_GET_ITEM(%s, %s);" % (
2113 Naming.args_cname, temp))
2114 code.put_incref("item", py_object_type)
2115 code.put_giveref("item")
2116 code.putln("PyTuple_SET_ITEM(%s, %s+1, item);" % (
2117 self.star_arg.entry.cname, temp))
2118 code.putln("}")
2119 code.funcstate.release_temp(temp)
2120 self.star_arg.entry.xdecref_cleanup = 0
2121 elif self.star_arg:
2122 code.put_incref(Naming.args_cname, py_object_type)
2123 code.putln("%s = %s;" % (
2124 self.star_arg.entry.cname,
2125 Naming.args_cname))
2126 self.star_arg.entry.xdecref_cleanup = 0
2128 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2129 kw_only_args, success_label, code):
2130 argtuple_error_label = code.new_label("argtuple_error")
2132 min_positional_args = self.num_required_args - self.num_required_kw_args
2133 if len(self.args) > 0 and (self.args[0].is_self_arg or self.args[0].is_type_arg):
2134 min_positional_args -= 1
2135 max_positional_args = len(positional_args)
2136 has_fixed_positional_count = not self.star_arg and \
2137 min_positional_args == max_positional_args
2139 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2140 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2141 if self.num_required_kw_args:
2142 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2144 if self.starstar_arg or self.star_arg:
2145 self.generate_stararg_init_code(max_positional_args, code)
2147 # --- optimised code when we receive keyword arguments
2148 if self.num_required_kw_args:
2149 likely_hint = "likely"
2150 else:
2151 likely_hint = "unlikely"
2152 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2153 self.generate_keyword_unpacking_code(
2154 min_positional_args, max_positional_args,
2155 has_fixed_positional_count,
2156 positional_args, kw_only_args, argtuple_error_label, code)
2158 # --- optimised code when we do not receive any keyword arguments
2159 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2160 # Python raises arg tuple related errors first, so we must
2161 # check the length here
2162 if min_positional_args == max_positional_args and not self.star_arg:
2163 compare = '!='
2164 else:
2165 compare = '<'
2166 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2167 Naming.args_cname, compare, min_positional_args))
2168 code.put_goto(argtuple_error_label)
2170 if self.num_required_kw_args:
2171 # pure error case: keywords required but not passed
2172 if max_positional_args > min_positional_args and not self.star_arg:
2173 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2174 Naming.args_cname, max_positional_args))
2175 code.put_goto(argtuple_error_label)
2176 code.putln('} else {')
2177 for i, arg in enumerate(kw_only_args):
2178 if not arg.default:
2179 pystring_cname = code.intern_identifier(arg.name)
2180 # required keyword-only argument missing
2181 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2182 self.name,
2183 pystring_cname))
2184 code.putln(code.error_goto(self.pos))
2185 break
2187 elif min_positional_args == max_positional_args:
2188 # parse the exact number of positional arguments from the
2189 # args tuple
2190 code.putln('} else {')
2191 for i, arg in enumerate(positional_args):
2192 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2193 self.generate_arg_assignment(arg, item, code)
2194 self.generate_arg_default_assignments(code)
2196 else:
2197 # parse the positional arguments from the variable length
2198 # args tuple
2199 code.putln('} else {')
2200 self.generate_arg_default_assignments(code)
2201 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2202 if self.star_arg:
2203 code.putln('default:')
2204 reversed_args = list(enumerate(positional_args))[::-1]
2205 for i, arg in reversed_args:
2206 if i >= min_positional_args-1:
2207 if min_positional_args > 1:
2208 code.putln('case %2d:' % (i+1)) # pure code beautification
2209 else:
2210 code.put('case %2d: ' % (i+1))
2211 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2212 self.generate_arg_assignment(arg, item, code)
2213 if min_positional_args == 0:
2214 code.put('case 0: ')
2215 code.putln('break;')
2216 if self.star_arg:
2217 if min_positional_args:
2218 for i in range(min_positional_args-1, -1, -1):
2219 code.putln('case %2d:' % i)
2220 code.put_goto(argtuple_error_label)
2221 else:
2222 code.put('default: ')
2223 code.put_goto(argtuple_error_label)
2224 code.putln('}')
2226 code.putln('}')
2228 if code.label_used(argtuple_error_label):
2229 code.put_goto(success_label)
2230 code.put_label(argtuple_error_label)
2231 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2232 self.name, has_fixed_positional_count,
2233 min_positional_args, max_positional_args,
2234 Naming.args_cname))
2235 code.putln(code.error_goto(self.pos))
2237 def generate_arg_default_assignments(self, code):
2238 for arg in self.args:
2239 if arg.is_generic and arg.default:
2240 code.putln(
2241 "%s = %s;" % (
2242 arg.entry.cname,
2243 arg.calculate_default_value_code(code)))
2245 def generate_stararg_init_code(self, max_positional_args, code):
2246 if self.starstar_arg:
2247 self.starstar_arg.entry.xdecref_cleanup = 0
2248 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2249 self.starstar_arg.entry.cname,
2250 self.starstar_arg.entry.cname,
2251 self.error_value()))
2252 code.put_gotref(self.starstar_arg.entry.cname)
2253 if self.star_arg:
2254 self.star_arg.entry.xdecref_cleanup = 0
2255 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2256 Naming.args_cname,
2257 max_positional_args))
2258 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2259 self.star_arg.entry.cname, Naming.args_cname,
2260 max_positional_args, Naming.args_cname))
2261 code.put_gotref(self.star_arg.entry.cname)
2262 if self.starstar_arg:
2263 code.putln("")
2264 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2265 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2266 code.putln('return %s;' % self.error_value())
2267 code.putln('}')
2268 else:
2269 code.putln("if (unlikely(!%s)) return %s;" % (
2270 self.star_arg.entry.cname, self.error_value()))
2271 code.putln('} else {')
2272 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2273 code.put_incref(Naming.empty_tuple, py_object_type)
2274 code.putln('}')
2276 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2277 has_fixed_positional_count, positional_args,
2278 kw_only_args, argtuple_error_label, code):
2279 all_args = tuple(positional_args) + tuple(kw_only_args)
2280 max_args = len(all_args)
2282 default_args = []
2283 for i, arg in enumerate(all_args):
2284 if arg.default and arg.type.is_pyobject:
2285 default_value = arg.calculate_default_value_code(code)
2286 if arg.type is not PyrexTypes.py_object_type:
2287 default_value = "(PyObject*)"+default_value
2288 default_args.append((i, default_value))
2290 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2291 Naming.kwds_cname)
2292 # it looks funny to separate the init-to-0 from setting the
2293 # default value, but C89 needs this
2294 code.putln("PyObject* values[%d] = {%s};" % (
2295 max_args, ','.join(['0']*max_args)))
2296 for i, default_value in default_args:
2297 code.putln('values[%d] = %s;' % (i, default_value))
2299 # parse the tuple and check that it's not too long
2300 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2301 if self.star_arg:
2302 code.putln('default:')
2303 for i in range(max_positional_args-1, -1, -1):
2304 code.put('case %2d: ' % (i+1))
2305 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2306 i, Naming.args_cname, i))
2307 code.putln('case 0: break;')
2308 if not self.star_arg:
2309 code.put('default: ') # more arguments than allowed
2310 code.put_goto(argtuple_error_label)
2311 code.putln('}')
2313 # now fill up the positional/required arguments with values
2314 # from the kw dict
2315 if self.num_required_args or max_positional_args > 0:
2316 last_required_arg = -1
2317 for i, arg in enumerate(all_args):
2318 if not arg.default:
2319 last_required_arg = i
2320 if last_required_arg < max_positional_args:
2321 last_required_arg = max_positional_args-1
2322 num_required_args = self.num_required_args
2323 if max_positional_args > 0:
2324 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2325 for i, arg in enumerate(all_args[:last_required_arg+1]):
2326 if max_positional_args > 0 and i <= max_positional_args:
2327 if self.star_arg and i == max_positional_args:
2328 code.putln('default:')
2329 else:
2330 code.putln('case %2d:' % i)
2331 pystring_cname = code.intern_identifier(arg.name)
2332 if arg.default:
2333 if arg.kw_only:
2334 # handled separately below
2335 continue
2336 code.putln('if (kw_args > %d) {' % num_required_args)
2337 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2338 Naming.kwds_cname, pystring_cname))
2339 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2340 code.putln('}')
2341 else:
2342 num_required_args -= 1
2343 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2344 i, Naming.kwds_cname, pystring_cname))
2345 code.putln('if (likely(values[%d])) kw_args--;' % i);
2346 if i < min_positional_args:
2347 if i == 0:
2348 # special case: we know arg 0 is missing
2349 code.put('else ')
2350 code.put_goto(argtuple_error_label)
2351 else:
2352 # print the correct number of values (args or
2353 # kwargs) that were passed into positional
2354 # arguments up to this point
2355 code.putln('else {')
2356 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2357 self.name, has_fixed_positional_count,
2358 min_positional_args, max_positional_args, i))
2359 code.putln(code.error_goto(self.pos))
2360 code.putln('}')
2361 elif arg.kw_only:
2362 code.putln('else {')
2363 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2364 self.name, pystring_cname))
2365 code.putln(code.error_goto(self.pos))
2366 code.putln('}')
2367 if max_positional_args > 0:
2368 code.putln('}')
2370 if kw_only_args and not self.starstar_arg:
2371 # unpack optional keyword-only arguments
2372 # checking for interned strings in a dict is faster than iterating
2373 # but it's too likely that we must iterate if we expect **kwargs
2374 optional_args = []
2375 for i, arg in enumerate(all_args[max_positional_args:]):
2376 if not arg.kw_only or not arg.default:
2377 continue
2378 optional_args.append((i+max_positional_args, arg))
2379 if optional_args:
2380 # this mimics an unrolled loop so that we can "break" out of it
2381 code.putln('while (kw_args > 0) {')
2382 code.putln('PyObject* value;')
2383 for i, arg in optional_args:
2384 pystring_cname = code.intern_identifier(arg.name)
2385 code.putln(
2386 'value = PyDict_GetItem(%s, %s);' % (
2387 Naming.kwds_cname, pystring_cname))
2388 code.putln(
2389 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2390 code.putln('break;')
2391 code.putln('}')
2393 code.putln('if (unlikely(kw_args > 0)) {')
2394 # non-positional/-required kw args left in dict: default args,
2395 # kw-only args, **kwargs or error
2396 #
2397 # This is sort of a catch-all: except for checking required
2398 # arguments, this will always do the right thing for unpacking
2399 # keyword arguments, so that we can concentrate on optimising
2400 # common cases above.
2401 if max_positional_args == 0:
2402 pos_arg_count = "0"
2403 elif self.star_arg:
2404 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2405 Naming.args_cname, max_positional_args,
2406 Naming.args_cname, max_positional_args))
2407 pos_arg_count = "used_pos_args"
2408 else:
2409 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2410 code.globalstate.use_utility_code(parse_keywords_utility_code)
2411 code.put(
2412 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2413 Naming.kwds_cname,
2414 Naming.pykwdlist_cname,
2415 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2416 pos_arg_count,
2417 self.name))
2418 code.putln(code.error_goto(self.pos))
2419 code.putln('}')
2421 # convert arg values to their final type and assign them
2422 for i, arg in enumerate(all_args):
2423 if arg.default and not arg.type.is_pyobject:
2424 code.putln("if (values[%d]) {" % i)
2425 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2426 if arg.default and not arg.type.is_pyobject:
2427 code.putln('} else {')
2428 code.putln(
2429 "%s = %s;" % (
2430 arg.entry.cname,
2431 arg.calculate_default_value_code(code)))
2432 code.putln('}')
2434 def generate_argument_conversion_code(self, code):
2435 # Generate code to convert arguments from
2436 # signature type to declared type, if needed.
2437 for arg in self.args:
2438 if arg.needs_conversion:
2439 self.generate_arg_conversion(arg, code)
2441 def generate_arg_conversion(self, arg, code):
2442 # Generate conversion code for one argument.
2443 old_type = arg.hdr_type
2444 new_type = arg.type
2445 if old_type.is_pyobject:
2446 if arg.default:
2447 code.putln("if (%s) {" % arg.hdr_cname)
2448 else:
2449 code.putln("assert(%s); {" % arg.hdr_cname)
2450 self.generate_arg_conversion_from_pyobject(arg, code)
2451 code.putln("}")
2452 elif new_type.is_pyobject:
2453 self.generate_arg_conversion_to_pyobject(arg, code)
2454 else:
2455 if new_type.assignable_from(old_type):
2456 code.putln(
2457 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2458 else:
2459 error(arg.pos,
2460 "Cannot convert 1 argument from '%s' to '%s'" %
2461 (old_type, new_type))
2463 def generate_arg_conversion_from_pyobject(self, arg, code):
2464 new_type = arg.type
2465 func = new_type.from_py_function
2466 # copied from CoerceFromPyTypeNode
2467 if func:
2468 code.putln("%s = %s(%s); %s" % (
2469 arg.entry.cname,
2470 func,
2471 arg.hdr_cname,
2472 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2473 else:
2474 error(arg.pos,
2475 "Cannot convert Python object argument to type '%s'"
2476 % new_type)
2478 def generate_arg_conversion_to_pyobject(self, arg, code):
2479 old_type = arg.hdr_type
2480 func = old_type.to_py_function
2481 if func:
2482 code.putln("%s = %s(%s); %s" % (
2483 arg.entry.cname,
2484 func,
2485 arg.hdr_cname,
2486 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2487 code.put_var_gotref(arg.entry)
2488 else:
2489 error(arg.pos,
2490 "Cannot convert argument of type '%s' to Python object"
2491 % old_type)
2493 def generate_argument_type_tests(self, code):
2494 # Generate type tests for args whose signature
2495 # type is PyObject * and whose declared type is
2496 # a subtype thereof.
2497 for arg in self.args:
2498 if arg.needs_type_test:
2499 self.generate_arg_type_test(arg, code)
2501 def generate_arg_type_test(self, arg, code):
2502 # Generate type test for one argument.
2503 if arg.type.typeobj_is_available():
2504 typeptr_cname = arg.type.typeptr_cname
2505 arg_code = "((PyObject *)%s)" % arg.entry.cname
2506 code.putln(
2507 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2508 arg_code,
2509 typeptr_cname,
2510 not arg.not_none,
2511 arg.name,
2512 arg.type.is_builtin_type,
2513 code.error_goto(arg.pos)))
2514 else:
2515 error(arg.pos, "Cannot test type of extern C class "
2516 "without type object name specification")
2518 def error_value(self):
2519 return self.entry.signature.error_value
2521 def caller_will_check_exceptions(self):
2522 return 1
2524 class OverrideCheckNode(StatNode):
2525 # A Node for dispatching to the def method if it
2526 # is overriden.
2527 #
2528 # py_func
2529 #
2530 # args
2531 # func_temp
2532 # body
2534 child_attrs = ['body']
2536 body = None
2538 def analyse_expressions(self, env):
2539 self.args = env.arg_entries
2540 if self.py_func.is_module_scope:
2541 first_arg = 0
2542 else:
2543 first_arg = 1
2544 import ExprNodes
2545 self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
2546 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2547 call_node = ExprNodes.SimpleCallNode(self.pos,
2548 function=self.func_node,
2549 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2550 self.body = ReturnStatNode(self.pos, value=call_node)
2551 self.body.analyse_expressions(env)
2553 def generate_execution_code(self, code):
2554 interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
2555 # Check to see if we are an extension type
2556 if self.py_func.is_module_scope:
2557 self_arg = "((PyObject *)%s)" % Naming.module_cname
2558 else:
2559 self_arg = "((PyObject *)%s)" % self.args[0].cname
2560 code.putln("/* Check if called by wrapper */")
2561 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2562 code.putln("/* Check if overriden in Python */")
2563 if self.py_func.is_module_scope:
2564 code.putln("else {")
2565 else:
2566 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2567 func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
2568 self.func_node.set_cname(func_node_temp)
2569 # need to get attribute manually--scope would return cdef method
2570 err = code.error_goto_if_null(func_node_temp, self.pos)
2571 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
2572 func_node_temp, self_arg, interned_attr_cname, err))
2573 code.put_gotref(func_node_temp)
2574 is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
2575 is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)" % (
2576 func_node_temp, self.py_func.entry.func_cname)
2577 code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
2578 self.body.generate_execution_code(code)
2579 code.putln("}")
2580 code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
2581 code.funcstate.release_temp(func_node_temp)
2582 code.putln("}")
2584 class ClassDefNode(StatNode, BlockNode):
2585 pass
2587 class PyClassDefNode(ClassDefNode):
2588 # A Python class definition.
2589 #
2590 # name EncodedString Name of the class
2591 # doc string or None
2592 # body StatNode Attribute definition code
2593 # entry Symtab.Entry
2594 # scope PyClassScope
2595 # decorators [DecoratorNode] list of decorators or None
2596 #
2597 # The following subnodes are constructed internally:
2598 #
2599 # dict DictNode Class dictionary
2600 # classobj ClassNode Class object
2601 # target NameNode Variable to assign class object to
2603 child_attrs = ["body", "dict", "classobj", "target"]
2604 decorators = None
2606 def __init__(self, pos, name, bases, doc, body, decorators = None):
2607 StatNode.__init__(self, pos)
2608 self.name = name
2609 self.doc = doc
2610 self.body = body
2611 self.decorators = decorators
2612 import ExprNodes
2613 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2614 if self.doc and Options.docstrings:
2615 doc = embed_position(self.pos, self.doc)
2616 # FIXME: correct string node?
2617 doc_node = ExprNodes.StringNode(pos, value = doc)
2618 else:
2619 doc_node = None
2620 self.classobj = ExprNodes.ClassNode(pos, name = name,
2621 bases = bases, dict = self.dict, doc = doc_node)
2622 self.target = ExprNodes.NameNode(pos, name = name)
2624 def as_cclass(self):
2625 """
2626 Return this node as if it were declared as an extension class
2627 """
2628 bases = self.classobj.bases.args
2629 if len(bases) == 0:
2630 base_class_name = None
2631 base_class_module = None
2632 elif len(bases) == 1:
2633 base = bases[0]
2634 path = []
2635 from ExprNodes import AttributeNode, NameNode
2636 while isinstance(base, AttributeNode):
2637 path.insert(0, base.attribute)
2638 base = base.obj
2639 if isinstance(base, NameNode):
2640 path.insert(0, base.name)
2641 base_class_name = path[-1]
2642 if len(path) > 1:
2643 base_class_module = u'.'.join(path[:-1])
2644 else:
2645 base_class_module = None
2646 else:
2647 error(self.classobj.bases.args.pos, "Invalid base class")
2648 else:
2649 error(self.classobj.bases.args.pos, "C class may only have one base class")
2650 return None
2652 return CClassDefNode(self.pos,
2653 visibility = 'private',
2654 module_name = None,
2655 class_name = self.name,
2656 base_class_module = base_class_module,
2657 base_class_name = base_class_name,
2658 decorators = self.decorators,
2659 body = self.body,
2660 in_pxd = False,
2661 doc = self.doc)
2663 def create_scope(self, env):
2664 genv = env
2665 while env.is_py_class_scope or env.is_c_class_scope:
2666 env = env.outer_scope
2667 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2668 return cenv
2670 def analyse_declarations(self, env):
2671 self.target.analyse_target_declaration(env)
2672 cenv = self.create_scope(env)
2673 cenv.directives = env.directives
2674 cenv.class_obj_cname = self.target.entry.cname
2675 self.body.analyse_declarations(cenv)
2677 def analyse_expressions(self, env):
2678 self.dict.analyse_expressions(env)
2679 self.classobj.analyse_expressions(env)
2680 genv = env.global_scope()
2681 cenv = self.scope
2682 self.body.analyse_expressions(cenv)
2683 self.target.analyse_target_expression(env, self.classobj)
2685 def generate_function_definitions(self, env, code):
2686 self.body.generate_function_definitions(self.scope, code)
2688 def generate_execution_code(self, code):
2689 code.pyclass_stack.append(self)
2690 cenv = self.scope
2691 self.dict.generate_evaluation_code(code)
2692 self.classobj.generate_evaluation_code(code)
2693 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2694 self.body.generate_execution_code(code)
2695 self.target.generate_assignment_code(self.classobj, code)
2696 self.dict.generate_disposal_code(code)
2697 self.dict.free_temps(code)
2698 code.pyclass_stack.pop()
2701 class CClassDefNode(ClassDefNode):
2702 # An extension type definition.
2703 #
2704 # visibility 'private' or 'public' or 'extern'
2705 # typedef_flag boolean
2706 # api boolean
2707 # module_name string or None For import of extern type objects
2708 # class_name string Unqualified name of class
2709 # as_name string or None Name to declare as in this scope
2710 # base_class_module string or None Module containing the base class
2711 # base_class_name string or None Name of the base class
2712 # objstruct_name string or None Specified C name of object struct
2713 # typeobj_name string or None Specified C name of type object
2714 # in_pxd boolean Is in a .pxd file
2715 # decorators [DecoratorNode] list of decorators or None
2716 # doc string or None
2717 # body StatNode or None
2718 # entry Symtab.Entry
2719 # base_type PyExtensionType or None
2720 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2721 # buffer_defaults_pos
2723 child_attrs = ["body"]
2724 buffer_defaults_node = None
2725 buffer_defaults_pos = None
2726 typedef_flag = False
2727 api = False
2728 objstruct_name = None
2729 typeobj_name = None
2730 decorators = None
2732 def analyse_declarations(self, env):
2733 #print "CClassDefNode.analyse_declarations:", self.class_name
2734 #print "...visibility =", self.visibility
2735 #print "...module_name =", self.module_name
2737 import Buffer
2738 if self.buffer_defaults_node:
2739 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2740 env, [], self.buffer_defaults_node,
2741 need_complete=False)
2742 else:
2743 buffer_defaults = None
2745 if env.in_cinclude and not self.objstruct_name:
2746 error(self.pos, "Object struct name specification required for "
2747 "C class defined in 'extern from' block")
2748 self.base_type = None
2749 # Now that module imports are cached, we need to
2750 # import the modules for extern classes.
2751 if self.module_name:
2752 self.module = None
2753 for module in env.cimported_modules:
2754 if module.name == self.module_name:
2755 self.module = module
2756 if self.module is None:
2757 self.module = ModuleScope(self.module_name, None, env.context)
2758 self.module.has_extern_class = 1
2759 env.add_imported_module(self.module)
2761 if self.base_class_name:
2762 if self.base_class_module:
2763 base_class_scope = env.find_module(self.base_class_module, self.pos)
2764 else:
2765 base_class_scope = env
2766 if self.base_class_name == 'object':
2767 # extension classes are special and don't need to inherit from object
2768 if base_class_scope is None or base_class_scope.lookup('object') is None:
2769 self.base_class_name = None
2770 self.base_class_module = None
2771 base_class_scope = None
2772 if base_class_scope:
2773 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2774 if base_class_entry:
2775 if not base_class_entry.is_type:
2776 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2777 elif not base_class_entry.type.is_extension_type:
2778 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2779 elif not base_class_entry.type.is_complete():
2780 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2781 else:
2782 self.base_type = base_class_entry.type
2783 has_body = self.body is not None
2784 if self.module_name and self.visibility != 'extern':
2785 module_path = self.module_name.split(".")
2786 home_scope = env.find_imported_module(module_path, self.pos)
2787 if not home_scope:
2788 return
2789 else:
2790 home_scope = env
2792 if self.visibility == 'extern':
2793 if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
2794 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
2796 self.entry = home_scope.declare_c_class(
2797 name = self.class_name,
2798 pos = self.pos,
2799 defining = has_body and self.in_pxd,
2800 implementing = has_body and not self.in_pxd,
2801 module_name = self.module_name,
2802 base_type = self.base_type,
2803 objstruct_cname = self.objstruct_name,
2804 typeobj_cname = self.typeobj_name,
2805 visibility = self.visibility,
2806 typedef_flag = self.typedef_flag,
2807 api = self.api,
2808 buffer_defaults = buffer_defaults)
2809 if home_scope is not env and self.visibility == 'extern':
2810 env.add_imported_entry(self.class_name, self.entry, pos)
2811 self.scope = scope = self.entry.type.scope
2812 if scope is not None:
2813 scope.directives = env.directives
2815 if self.doc and Options.docstrings:
2816 scope.doc = embed_position(self.pos, self.doc)
2818 if has_body:
2819 self.body.analyse_declarations(scope)
2820 if self.in_pxd:
2821 scope.defined = 1
2822 else:
2823 scope.implemented = 1
2824 env.allocate_vtable_names(self.entry)
2826 def analyse_expressions(self, env):
2827 if self.body:
2828 scope = self.entry.type.scope
2829 self.body.analyse_expressions(scope)
2831 def generate_function_definitions(self, env, code):
2832 if self.body:
2833 self.body.generate_function_definitions(
2834 self.entry.type.scope, code)
2836 def generate_execution_code(self, code):
2837 # This is needed to generate evaluation code for
2838 # default values of method arguments.
2839 if self.body:
2840 self.body.generate_execution_code(code)
2842 def annotate(self, code):
2843 if self.body:
2844 self.body.annotate(code)
2847 class PropertyNode(StatNode):
2848 # Definition of a property in an extension type.
2849 #
2850 # name string
2851 # doc EncodedString or None Doc string
2852 # body StatListNode
2854 child_attrs = ["body"]
2856 def analyse_declarations(self, env):
2857 entry = env.declare_property(self.name, self.doc, self.pos)
2858 if entry:
2859 entry.scope.directives = env.directives
2860 self.body.analyse_declarations(entry.scope)
2862 def analyse_expressions(self, env):
2863 self.body.analyse_expressions(env)
2865 def generate_function_definitions(self, env, code):
2866 self.body.generate_function_definitions(env, code)
2868 def generate_execution_code(self, code):
2869 pass
2871 def annotate(self, code):
2872 self.body.annotate(code)
2875 class GlobalNode(StatNode):
2876 # Global variable declaration.
2877 #
2878 # names [string]
2880 child_attrs = []
2882 def analyse_declarations(self, env):
2883 for name in self.names:
2884 env.declare_global(name, self.pos)
2886 def analyse_expressions(self, env):
2887 pass
2889 def generate_execution_code(self, code):
2890 pass
2893 class ExprStatNode(StatNode):
2894 # Expression used as a statement.
2895 #
2896 # expr ExprNode
2898 child_attrs = ["expr"]
2900 def analyse_declarations(self, env):
2901 import ExprNodes
2902 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2903 func = self.expr.function.as_cython_attribute()
2904 if func == u'declare':
2905 args, kwds = self.expr.explicit_args_kwds()
2906 if len(args):
2907 error(self.expr.pos, "Variable names must be specified.")
2908 for var, type_node in kwds.key_value_pairs:
2909 type = type_node.analyse_as_type(env)
2910 if type is None:
2911 error(type_node.pos, "Unknown type")
2912 else:
2913 env.declare_var(var.value, type, var.pos, is_cdef = True)
2914 self.__class__ = PassStatNode
2916 def analyse_expressions(self, env):
2917 self.expr.analyse_expressions(env)
2919 def generate_execution_code(self, code):
2920 self.expr.generate_evaluation_code(code)
2921 if not self.expr.is_temp and self.expr.result():
2922 code.putln("%s;" % self.expr.result())
2923 self.expr.generate_disposal_code(code)
2924 self.expr.free_temps(code)
2926 def annotate(self, code):
2927 self.expr.annotate(code)
2930 class AssignmentNode(StatNode):
2931 # Abstract base class for assignment nodes.
2932 #
2933 # The analyse_expressions and generate_execution_code
2934 # phases of assignments are split into two sub-phases
2935 # each, to enable all the right hand sides of a
2936 # parallel assignment to be evaluated before assigning
2937 # to any of the left hand sides.
2939 def analyse_expressions(self, env):
2940 self.analyse_types(env)
2942 # def analyse_expressions(self, env):
2943 # self.analyse_expressions_1(env)
2944 # self.analyse_expressions_2(env)
2946 def generate_execution_code(self, code):
2947 self.generate_rhs_evaluation_code(code)
2948 self.generate_assignment_code(code)
2951 class SingleAssignmentNode(AssignmentNode):
2952 # The simplest case:
2953 #
2954 # a = b
2955 #
2956 # lhs ExprNode Left hand side
2957 # rhs ExprNode Right hand side
2958 # first bool Is this guaranteed the first assignment to lhs?
2960 child_attrs = ["lhs", "rhs"]
2961 first = False
2962 declaration_only = False
2964 def analyse_declarations(self, env):
2965 import ExprNodes
2967 # handle declarations of the form x = cython.foo()
2968 if isinstance(self.rhs, ExprNodes.CallNode):
2969 func_name = self.rhs.function.as_cython_attribute()
2970 if func_name:
2971 args, kwds = self.rhs.explicit_args_kwds()
2973 if func_name in ['declare', 'typedef']:
2974 if len(args) > 2 or kwds is not None:
2975 error(rhs.pos, "Can only declare one type at a time.")
2976 return
2977 type = args[0].analyse_as_type(env)
2978 if type is None:
2979 error(args[0].pos, "Unknown type")
2980 return
2981 lhs = self.lhs
2982 if func_name == 'declare':
2983 if isinstance(lhs, ExprNodes.NameNode):
2984 vars = [(lhs.name, lhs.pos)]
2985 elif isinstance(lhs, ExprNodes.TupleNode):
2986 vars = [(var.name, var.pos) for var in lhs.args]
2987 else:
2988 error(lhs.pos, "Invalid declaration")
2989 return
2990 for var, pos in vars:
2991 env.declare_var(var, type, pos, is_cdef = True)
2992 if len(args) == 2:
2993 # we have a value
2994 self.rhs = args[1]
2995 else:
2996 self.declaration_only = True
2997 else:
2998 self.declaration_only = True
2999 if not isinstance(lhs, ExprNodes.NameNode):
3000 error(lhs.pos, "Invalid declaration.")
3001 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
3003 elif func_name in ['struct', 'union']:
3004 self.declaration_only = True
3005 if len(args) > 0 or kwds is None:
3006 error(rhs.pos, "Struct or union members must be given by name.")
3007 return
3008 members = []
3009 for member, type_node in kwds.key_value_pairs:
3010 type = type_node.analyse_as_type(env)
3011 if type is None:
3012 error(type_node.pos, "Unknown type")
3013 else:
3014 members.append((member.value, type, member.pos))
3015 if len(members) < len(kwds.key_value_pairs):
3016 return
3017 if not isinstance(self.lhs, ExprNodes.NameNode):
3018 error(self.lhs.pos, "Invalid declaration.")
3019 name = self.lhs.name
3020 scope = StructOrUnionScope(name)
3021 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
3022 for member, type, pos in members:
3023 scope.declare_var(member, type, pos)
3025 if self.declaration_only:
3026 return
3027 else:
3028 self.lhs.analyse_target_declaration(env)
3030 def analyse_types(self, env, use_temp = 0):
3031 self.rhs.analyse_types(env)
3032 self.lhs.analyse_target_types(env)
3033 self.lhs.gil_assignment_check(env)
3034 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3035 if use_temp:
3036 self.rhs = self.rhs.coerce_to_temp(env)
3038 def generate_rhs_evaluation_code(self, code):
3039 self.rhs.generate_evaluation_code(code)
3041 def generate_assignment_code(self, code):
3042 self.lhs.generate_assignment_code(self.rhs, code)
3044 def annotate(self, code):
3045 self.lhs.annotate(code)
3046 self.rhs.annotate(code)
3049 class CascadedAssignmentNode(AssignmentNode):
3050 # An assignment with multiple left hand sides:
3051 #
3052 # a = b = c
3053 #
3054 # lhs_list [ExprNode] Left hand sides
3055 # rhs ExprNode Right hand sides
3056 #
3057 # Used internally:
3058 #
3059 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
3061 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
3062 coerced_rhs_list = None
3064 def analyse_declarations(self, env):
3065 for lhs in self.lhs_list:
3066 lhs.analyse_target_declaration(env)
3068 def analyse_types(self, env, use_temp = 0):
3069 self.rhs.analyse_types(env)
3070 if not self.rhs.is_simple():
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.put_goto(end_label)
3733 code.putln("}")
3735 def annotate(self, code):
3736 self.condition.annotate(code)
3737 self.body.annotate(code)
3740 class SwitchCaseNode(StatNode):
3741 # Generated in the optimization of an if-elif-else node
3742 #
3743 # conditions [ExprNode]
3744 # body StatNode
3746 child_attrs = ['conditions', 'body']
3748 def generate_execution_code(self, code):
3749 for cond in self.conditions:
3750 code.mark_pos(cond.pos)
3751 cond.generate_evaluation_code(code)
3752 code.putln("case %s:" % cond.result())
3753 self.body.generate_execution_code(code)
3754 code.putln("break;")
3756 def annotate(self, code):
3757 for cond in self.conditions:
3758 cond.annotate(code)
3759 self.body.annotate(code)
3761 class SwitchStatNode(StatNode):
3762 # Generated in the optimization of an if-elif-else node
3763 #
3764 # test ExprNode
3765 # cases [SwitchCaseNode]
3766 # else_clause StatNode or None
3768 child_attrs = ['test', 'cases', 'else_clause']
3770 def generate_execution_code(self, code):
3771 code.putln("switch (%s) {" % self.test.result())
3772 for case in self.cases:
3773 case.generate_execution_code(code)
3774 if self.else_clause is not None:
3775 code.putln("default:")
3776 self.else_clause.generate_execution_code(code)
3777 code.putln("break;")
3778 code.putln("}")
3780 def annotate(self, code):
3781 self.test.annotate(code)
3782 for case in self.cases:
3783 case.annotate(code)
3784 if self.else_clause is not None:
3785 self.else_clause.annotate(code)
3787 class LoopNode(object):
3789 def analyse_control_flow(self, env):
3790 env.start_branching(self.pos)
3791 self.body.analyse_control_flow(env)
3792 env.next_branch(self.body.end_pos())
3793 if self.else_clause:
3794 self.else_clause.analyse_control_flow(env)
3795 env.finish_branching(self.end_pos())
3798 class WhileStatNode(LoopNode, StatNode):
3799 # while statement
3800 #
3801 # condition ExprNode
3802 # body StatNode
3803 # else_clause StatNode
3805 child_attrs = ["condition", "body", "else_clause"]
3807 def analyse_declarations(self, env):
3808 self.body.analyse_declarations(env)
3809 if self.else_clause:
3810 self.else_clause.analyse_declarations(env)
3812 def analyse_expressions(self, env):
3813 self.condition = \
3814 self.condition.analyse_temp_boolean_expression(env)
3815 self.body.analyse_expressions(env)
3816 if self.else_clause:
3817 self.else_clause.analyse_expressions(env)
3819 def generate_execution_code(self, code):
3820 old_loop_labels = code.new_loop_labels()
3821 code.putln(
3822 "while (1) {")
3823 self.condition.generate_evaluation_code(code)
3824 self.condition.generate_disposal_code(code)
3825 code.putln(
3826 "if (!%s) break;" %
3827 self.condition.result())
3828 self.condition.free_temps(code)
3829 self.body.generate_execution_code(code)
3830 code.put_label(code.continue_label)
3831 code.putln("}")
3832 break_label = code.break_label
3833 code.set_loop_labels(old_loop_labels)
3834 if self.else_clause:
3835 code.putln("/*else*/ {")
3836 self.else_clause.generate_execution_code(code)
3837 code.putln("}")
3838 code.put_label(break_label)
3840 def annotate(self, code):
3841 self.condition.annotate(code)
3842 self.body.annotate(code)
3843 if self.else_clause:
3844 self.else_clause.annotate(code)
3847 def ForStatNode(pos, **kw):
3848 if 'iterator' in kw:
3849 return ForInStatNode(pos, **kw)
3850 else:
3851 return ForFromStatNode(pos, **kw)
3853 class ForInStatNode(LoopNode, StatNode):
3854 # for statement
3855 #
3856 # target ExprNode
3857 # iterator IteratorNode
3858 # body StatNode
3859 # else_clause StatNode
3860 # item NextNode used internally
3862 child_attrs = ["target", "iterator", "body", "else_clause"]
3863 item = None
3865 def analyse_declarations(self, env):
3866 self.target.analyse_target_declaration(env)
3867 self.body.analyse_declarations(env)
3868 if self.else_clause:
3869 self.else_clause.analyse_declarations(env)
3871 def analyse_expressions(self, env):
3872 import ExprNodes
3873 self.target.analyse_target_types(env)
3874 self.iterator.analyse_expressions(env)
3875 self.item = ExprNodes.NextNode(self.iterator, env)
3876 self.item = self.item.coerce_to(self.target.type, env)
3877 self.body.analyse_expressions(env)
3878 if self.else_clause:
3879 self.else_clause.analyse_expressions(env)
3881 def generate_execution_code(self, code):
3882 old_loop_labels = code.new_loop_labels()
3883 self.iterator.allocate_counter_temp(code)
3884 self.iterator.generate_evaluation_code(code)
3885 code.putln(
3886 "for (;;) {")
3887 self.item.generate_evaluation_code(code)
3888 self.target.generate_assignment_code(self.item, code)
3889 self.body.generate_execution_code(code)
3890 code.put_label(code.continue_label)
3891 code.putln(
3892 "}")
3893 break_label = code.break_label
3894 code.set_loop_labels(old_loop_labels)
3895 if self.else_clause:
3896 code.putln("/*else*/ {")
3897 self.else_clause.generate_execution_code(code)
3898 code.putln("}")
3899 code.put_label(break_label)
3900 self.iterator.release_counter_temp(code)
3901 self.iterator.generate_disposal_code(code)
3902 self.iterator.free_temps(code)
3904 def annotate(self, code):
3905 self.target.annotate(code)
3906 self.iterator.annotate(code)
3907 self.body.annotate(code)
3908 if self.else_clause:
3909 self.else_clause.annotate(code)
3910 self.item.annotate(code)
3913 class ForFromStatNode(LoopNode, StatNode):
3914 # for name from expr rel name rel expr
3915 #
3916 # target NameNode
3917 # bound1 ExprNode
3918 # relation1 string
3919 # relation2 string
3920 # bound2 ExprNode
3921 # step ExprNode or None
3922 # body StatNode
3923 # else_clause StatNode or None
3924 #
3925 # Used internally:
3926 #
3927 # from_range bool
3928 # is_py_target bool
3929 # loopvar_node ExprNode (usually a NameNode or temp node)
3930 # py_loopvar_node PyTempNode or None
3931 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3933 is_py_target = False
3934 loopvar_node = None
3935 py_loopvar_node = None
3936 from_range = False
3938 gil_message = "For-loop using object bounds or target"
3940 def nogil_check(self, env):
3941 for x in (self.target, self.bound1, self.bound2):
3942 if x.type.is_pyobject:
3943 self.gil_error()
3945 def analyse_declarations(self, env):
3946 self.target.analyse_target_declaration(env)
3947 self.body.analyse_declarations(env)
3948 if self.else_clause:
3949 self.else_clause.analyse_declarations(env)
3951 def analyse_expressions(self, env):
3952 import ExprNodes
3953 self.target.analyse_target_types(env)
3954 self.bound1.analyse_types(env)
3955 self.bound2.analyse_types(env)
3956 if self.step is not None:
3957 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3958 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3959 self.step.analyse_types(env)
3961 target_type = self.target.type
3962 if self.target.type.is_numeric:
3963 loop_type = self.target.type
3964 else:
3965 loop_type = PyrexTypes.c_int_type
3966 if not self.bound1.type.is_pyobject:
3967 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
3968 if not self.bound2.type.is_pyobject:
3969 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
3970 if self.step is not None and not self.step.type.is_pyobject:
3971 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
3972 self.bound1 = self.bound1.coerce_to(loop_type, env)
3973 self.bound2 = self.bound2.coerce_to(loop_type, env)
3974 if not self.bound2.is_literal:
3975 self.bound2 = self.bound2.coerce_to_temp(env)
3976 if self.step is not None:
3977 self.step = self.step.coerce_to(loop_type, env)
3978 if not self.step.is_literal:
3979 self.step = self.step.coerce_to_temp(env)
3981 target_type = self.target.type
3982 if not (target_type.is_pyobject or target_type.is_numeric):
3983 error(self.target.pos,
3984 "for-from loop variable must be c numeric type or Python object")
3985 if target_type.is_numeric:
3986 self.is_py_target = False
3987 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3988 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3989 self.loopvar_node = self.target
3990 self.py_loopvar_node = None
3991 else:
3992 self.is_py_target = True
3993 c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
3994 self.loopvar_node = c_loopvar_node
3995 self.py_loopvar_node = \
3996 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3997 self.body.analyse_expressions(env)
3998 if self.else_clause:
3999 self.else_clause.analyse_expressions(env)
4001 def generate_execution_code(self, code):
4002 old_loop_labels = code.new_loop_labels()
4003 from_range = self.from_range
4004 self.bound1.generate_evaluation_code(code)
4005 self.bound2.generate_evaluation_code(code)
4006 offset, incop = self.relation_table[self.relation1]
4007 if self.step is not None:
4008 self.step.generate_evaluation_code(code)
4009 step = self.step.result()
4010 incop = "%s=%s" % (incop[0], step)
4011 import ExprNodes
4012 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4013 self.loopvar_node.allocate(code)
4014 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4015 self.py_loopvar_node.allocate(code)
4016 if from_range:
4017 loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
4018 else:
4019 loopvar_name = self.loopvar_node.result()
4020 code.putln(
4021 "for (%s = %s%s; %s %s %s; %s%s) {" % (
4022 loopvar_name,
4023 self.bound1.result(), offset,
4024 loopvar_name, self.relation2, self.bound2.result(),
4025 loopvar_name, incop))
4026 if self.py_loopvar_node:
4027 self.py_loopvar_node.generate_evaluation_code(code)
4028 self.target.generate_assignment_code(self.py_loopvar_node, code)
4029 elif from_range:
4030 code.putln("%s = %s;" % (
4031 self.target.result(), loopvar_name))
4032 self.body.generate_execution_code(code)
4033 code.put_label(code.continue_label)
4034 if self.py_loopvar_node:
4035 # This mess is to make for..from loops with python targets behave
4036 # exactly like those with C targets with regards to re-assignment
4037 # of the loop variable.
4038 import ExprNodes
4039 if self.target.entry.is_pyglobal:
4040 # We know target is a NameNode, this is the only ugly case.
4041 target_node = ExprNodes.PyTempNode(self.target.pos, None)
4042 target_node.allocate(code)
4043 interned_cname = code.intern_identifier(self.target.entry.name)
4044 code.putln("/*here*/")
4045 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
4046 target_node.result(),
4047 Naming.module_cname,
4048 interned_cname,
4049 code.error_goto_if_null(target_node.result(), self.target.pos)))
4050 code.put_gotref(target_node.result())
4051 else:
4052 target_node = self.target
4053 from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
4054 from_py_node.temp_code = loopvar_name
4055 from_py_node.generate_result_code(code)
4056 if self.target.entry.is_pyglobal:
4057 code.put_decref(target_node.result(), target_node.type)
4058 target_node.release(code)
4059 code.putln("}")
4060 if self.py_loopvar_node:
4061 # This is potentially wasteful, but we don't want the semantics to
4062 # depend on whether or not the loop is a python type.
4063 self.py_loopvar_node.generate_evaluation_code(code)
4064 self.target.generate_assignment_code(self.py_loopvar_node, code)
4065 if from_range:
4066 code.funcstate.release_temp(loopvar_name)
4067 break_label = code.break_label
4068 code.set_loop_labels(old_loop_labels)
4069 if self.else_clause:
4070 code.putln("/*else*/ {")
4071 self.else_clause.generate_execution_code(code)
4072 code.putln("}")
4073 code.put_label(break_label)
4074 self.bound1.generate_disposal_code(code)
4075 self.bound1.free_temps(code)
4076 self.bound2.generate_disposal_code(code)
4077 self.bound2.free_temps(code)
4078 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4079 self.loopvar_node.release(code)
4080 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4081 self.py_loopvar_node.release(code)
4082 if self.step is not None:
4083 self.step.generate_disposal_code(code)
4084 self.step.free_temps(code)
4086 relation_table = {
4087 # {relop : (initial offset, increment op)}
4088 '<=': ("", "++"),
4089 '<' : ("+1", "++"),
4090 '>=': ("", "--"),
4091 '>' : ("-1", "--")
4092 }
4094 def annotate(self, code):
4095 self.target.annotate(code)
4096 self.bound1.annotate(code)
4097 self.bound2.annotate(code)
4098 if self.step:
4099 self.bound2.annotate(code)
4100 self.body.annotate(code)
4101 if self.else_clause:
4102 self.else_clause.annotate(code)
4105 class WithStatNode(StatNode):
4106 """
4107 Represents a Python with statement.
4109 This is only used at parse tree level; and is not present in
4110 analysis or generation phases.
4111 """
4112 # manager The with statement manager object
4113 # target Node (lhs expression)
4114 # body StatNode
4115 child_attrs = ["manager", "target", "body"]
4117 class TryExceptStatNode(StatNode):
4118 # try .. except statement
4119 #
4120 # body StatNode
4121 # except_clauses [ExceptClauseNode]
4122 # else_clause StatNode or None
4124 child_attrs = ["body", "except_clauses", "else_clause"]
4126 def analyse_control_flow(self, env):
4127 env.start_branching(self.pos)
4128 self.body.analyse_control_flow(env)
4129 successful_try = env.control_flow # grab this for later
4130 env.next_branch(self.body.end_pos())
4131 env.finish_branching(self.body.end_pos())
4133 env.start_branching(self.except_clauses[0].pos)
4134 for except_clause in self.except_clauses:
4135 except_clause.analyse_control_flow(env)
4136 env.next_branch(except_clause.end_pos())
4138 # the else cause it executed only when the try clause finishes
4139 env.control_flow.incoming = successful_try
4140 if self.else_clause:
4141 self.else_clause.analyse_control_flow(env)
4142 env.finish_branching(self.end_pos())
4144 def analyse_declarations(self, env):
4145 self.body.analyse_declarations(env)
4146 for except_clause in self.except_clauses:
4147 except_clause.analyse_declarations(env)
4148 if self.else_clause:
4149 self.else_clause.analyse_declarations(env)
4150 env.use_utility_code(reset_exception_utility_code)
4152 def analyse_expressions(self, env):
4153 self.body.analyse_expressions(env)
4154 default_clause_seen = 0
4155 for except_clause in self.except_clauses:
4156 except_clause.analyse_expressions(env)
4157 if default_clause_seen:
4158 error(except_clause.pos, "default 'except:' must be last")
4159 if not except_clause.pattern:
4160 default_clause_seen = 1
4161 self.has_default_clause = default_clause_seen
4162 if self.else_clause:
4163 self.else_clause.analyse_expressions(env)
4165 nogil_check = Node.gil_error
4166 gil_message = "Try-except statement"
4168 def generate_execution_code(self, code):
4169 old_return_label = code.return_label
4170 old_break_label = code.break_label
4171 old_continue_label = code.continue_label
4172 old_error_label = code.new_error_label()
4173 our_error_label = code.error_label
4174 except_end_label = code.new_label('exception_handled')
4175 except_error_label = code.new_label('except_error')
4176 except_return_label = code.new_label('except_return')
4177 try_return_label = code.new_label('try_return')
4178 try_break_label = code.new_label('try_break')
4179 try_continue_label = code.new_label('try_continue')
4180 try_end_label = code.new_label('try_end')
4182 code.putln("{")
4183 code.putln("PyObject %s;" %
4184 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4185 code.putln("__Pyx_ExceptionSave(%s);" %
4186 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4187 for var in Naming.exc_save_vars:
4188 code.put_xgotref(var)
4189 code.putln(
4190 "/*try:*/ {")
4191 code.return_label = try_return_label
4192 code.break_label = try_break_label
4193 code.continue_label = try_continue_label
4194 self.body.generate_execution_code(code)
4195 code.putln(
4196 "}")
4197 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4198 code.error_label = except_error_label
4199 code.return_label = except_return_label
4200 if self.else_clause:
4201 code.putln(
4202 "/*else:*/ {")
4203 self.else_clause.generate_execution_code(code)
4204 code.putln(
4205 "}")
4206 for var in Naming.exc_save_vars:
4207 code.put_xdecref_clear(var, py_object_type)
4208 code.put_goto(try_end_label)
4209 if code.label_used(try_return_label):
4210 code.put_label(try_return_label)
4211 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4212 code.putln("__Pyx_ExceptionReset(%s);" %
4213 ', '.join(Naming.exc_save_vars))
4214 code.put_goto(old_return_label)
4215 code.put_label(our_error_label)
4216 for temp_name, type in temps_to_clean_up:
4217 code.put_xdecref_clear(temp_name, type)
4218 for except_clause in self.except_clauses:
4219 except_clause.generate_handling_code(code, except_end_label)
4221 error_label_used = code.label_used(except_error_label)
4222 if error_label_used or not self.has_default_clause:
4223 if error_label_used:
4224 code.put_label(except_error_label)
4225 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4226 code.putln("__Pyx_ExceptionReset(%s);" %
4227 ', '.join(Naming.exc_save_vars))
4228 code.put_goto(old_error_label)
4230 for exit_label, old_label in zip(
4231 [try_break_label, try_continue_label, except_return_label],
4232 [old_break_label, old_continue_label, old_return_label]):
4234 if code.label_used(exit_label):
4235 code.put_label(exit_label)
4236 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4237 code.putln("__Pyx_ExceptionReset(%s);" %
4238 ', '.join(Naming.exc_save_vars))
4239 code.put_goto(old_label)
4241 if code.label_used(except_end_label):
4242 code.put_label(except_end_label)
4243 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4244 code.putln("__Pyx_ExceptionReset(%s);" %
4245 ', '.join(Naming.exc_save_vars))
4246 code.put_label(try_end_label)
4247 code.putln("}")
4249 code.return_label = old_return_label
4250 code.break_label = old_break_label
4251 code.continue_label = old_continue_label
4252 code.error_label = old_error_label
4254 def annotate(self, code):
4255 self.body.annotate(code)
4256 for except_node in self.except_clauses:
4257 except_node.annotate(code)
4258 if self.else_clause:
4259 self.else_clause.annotate(code)
4262 class ExceptClauseNode(Node):
4263 # Part of try ... except statement.
4264 #
4265 # pattern ExprNode
4266 # target ExprNode or None
4267 # body StatNode
4268 # excinfo_target NameNode or None optional target for exception info
4269 # match_flag string result of exception match
4270 # exc_value ExcValueNode used internally
4271 # function_name string qualified name of enclosing function
4272 # exc_vars (string * 3) local exception variables
4274 # excinfo_target is never set by the parser, but can be set by a transform
4275 # in order to extract more extensive information about the exception as a
4276 # sys.exc_info()-style tuple into a target variable
4278 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4280 exc_value = None
4281 excinfo_target = None
4283 def analyse_declarations(self, env):
4284 if self.target:
4285 self.target.analyse_target_declaration(env)
4286 if self.excinfo_target is not None:
4287 self.excinfo_target.analyse_target_declaration(env)
4288 self.body.analyse_declarations(env)
4290 def analyse_expressions(self, env):
4291 import ExprNodes
4292 genv = env.global_scope()
4293 self.function_name = env.qualified_name
4294 if self.pattern:
4295 self.pattern.analyse_expressions(env)
4296 self.pattern = self.pattern.coerce_to_pyobject(env)
4298 if self.target:
4299 self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
4300 self.target.analyse_target_expression(env, self.exc_value)
4301 if self.excinfo_target is not None:
4302 import ExprNodes
4303 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4304 ExprNodes.ExcValueNode(pos=self.pos, env=env) for x in range(3)])
4305 self.excinfo_tuple.analyse_expressions(env)
4306 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4308 self.body.analyse_expressions(env)
4310 def generate_handling_code(self, code, end_label):
4311 code.mark_pos(self.pos)
4312 if self.pattern:
4313 self.pattern.generate_evaluation_code(code)
4315 match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
4316 code.putln(
4317 "%s = PyErr_ExceptionMatches(%s);" % (
4318 match_flag,
4319 self.pattern.py_result()))
4320 self.pattern.generate_disposal_code(code)
4321 self.pattern.free_temps(code)
4322 code.putln(
4323 "if (%s) {" %
4324 match_flag)
4325 code.funcstate.release_temp(match_flag)
4326 else:
4327 code.putln("/*except:*/ {")
4329 if not getattr(self.body, 'stats', True):
4330 # most simple case: no exception variable, empty body (pass)
4331 # => reset the exception state, done
4332 code.putln("PyErr_Restore(0,0,0);")
4333 code.put_goto(end_label)
4334 code.putln("}")
4335 return
4337 exc_vars = [code.funcstate.allocate_temp(py_object_type,
4338 manage_ref=True)
4339 for i in xrange(3)]
4340 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4341 # We always have to fetch the exception value even if
4342 # there is no target, because this also normalises the
4343 # exception and stores it in the thread state.
4344 code.globalstate.use_utility_code(get_exception_utility_code)
4345 exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4346 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4347 code.error_goto(self.pos)))
4348 for x in exc_vars:
4349 code.put_gotref(x)
4350 if self.target:
4351 self.exc_value.set_var(exc_vars[1])
4352 self.exc_value.generate_evaluation_code(code)
4353 self.target.generate_assignment_code(self.exc_value, code)
4354 if self.excinfo_target is not None:
4355 for tempvar, node in zip(exc_vars, self.excinfo_tuple.args):
4356 node.set_var(tempvar)
4357 self.excinfo_tuple.generate_evaluation_code(code)
4358 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4360 old_break_label, old_continue_label = code.break_label, code.continue_label
4361 code.break_label = code.new_label('except_break')
4362 code.continue_label = code.new_label('except_continue')
4364 old_exc_vars = code.funcstate.exc_vars
4365 code.funcstate.exc_vars = exc_vars
4366 self.body.generate_execution_code(code)
4367 code.funcstate.exc_vars = old_exc_vars
4368 for var in exc_vars:
4369 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4370 code.put_goto(end_label)
4372 if code.label_used(code.break_label):
4373 code.put_label(code.break_label)
4374 for var in exc_vars:
4375 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4376 code.put_goto(old_break_label)
4377 code.break_label = old_break_label
4379 if code.label_used(code.continue_label):
4380 code.put_label(code.continue_label)
4381 for var in exc_vars:
4382 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4383 code.put_goto(old_continue_label)
4384 code.continue_label = old_continue_label
4386 for temp in exc_vars:
4387 code.funcstate.release_temp(temp)
4389 code.putln(
4390 "}")
4392 def annotate(self, code):
4393 if self.pattern:
4394 self.pattern.annotate(code)
4395 if self.target:
4396 self.target.annotate(code)
4397 self.body.annotate(code)
4400 class TryFinallyStatNode(StatNode):
4401 # try ... finally statement
4402 #
4403 # body StatNode
4404 # finally_clause StatNode
4405 #
4406 # The plan is that we funnel all continue, break
4407 # return and error gotos into the beginning of the
4408 # finally block, setting a variable to remember which
4409 # one we're doing. At the end of the finally block, we
4410 # switch on the variable to figure out where to go.
4411 # In addition, if we're doing an error, we save the
4412 # exception on entry to the finally block and restore
4413 # it on exit.
4415 child_attrs = ["body", "finally_clause"]
4417 preserve_exception = 1
4419 disallow_continue_in_try_finally = 0
4420 # There doesn't seem to be any point in disallowing
4421 # continue in the try block, since we have no problem
4422 # handling it.
4424 def create_analysed(pos, env, body, finally_clause):
4425 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4426 return node
4427 create_analysed = staticmethod(create_analysed)
4429 def analyse_control_flow(self, env):
4430 env.start_branching(self.pos)
4431 self.body.analyse_control_flow(env)
4432 env.next_branch(self.body.end_pos())
4433 env.finish_branching(self.body.end_pos())
4434 self.finally_clause.analyse_control_flow(env)
4436 def analyse_declarations(self, env):
4437 self.body.analyse_declarations(env)
4438 self.finally_clause.analyse_declarations(env)
4440 def analyse_expressions(self, env):
4441 self.body.analyse_expressions(env)
4442 self.finally_clause.analyse_expressions(env)
4444 nogil_check = Node.gil_error
4445 gil_message = "Try-finally statement"
4447 def generate_execution_code(self, code):
4448 old_error_label = code.error_label
4449 old_labels = code.all_new_labels()
4450 new_labels = code.get_all_labels()
4451 new_error_label = code.error_label
4452 catch_label = code.new_label()
4453 code.putln(
4454 "/*try:*/ {")
4455 if self.disallow_continue_in_try_finally:
4456 was_in_try_finally = code.funcstate.in_try_finally
4457 code.funcstate.in_try_finally = 1
4458 self.body.generate_execution_code(code)
4459 if self.disallow_continue_in_try_finally:
4460 code.funcstate.in_try_finally = was_in_try_finally
4461 code.putln(
4462 "}")
4463 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4464 code.putln(
4465 "/*finally:*/ {")
4466 cases_used = []
4467 error_label_used = 0
4468 for i, new_label in enumerate(new_labels):
4469 if new_label in code.labels_used:
4470 cases_used.append(i)
4471 if new_label == new_error_label:
4472 error_label_used = 1
4473 error_label_case = i
4474 if cases_used:
4475 code.putln(
4476 "int __pyx_why;")
4477 if error_label_used and self.preserve_exception:
4478 code.putln(
4479 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4480 code.putln(
4481 "int %s;" % Naming.exc_lineno_name)
4482 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4483 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4484 code.putln(exc_var_init_zero)
4485 else:
4486 exc_var_init_zero = None
4487 code.use_label(catch_label)
4488 code.putln(
4489 "__pyx_why = 0; goto %s;" % catch_label)
4490 for i in cases_used:
4491 new_label = new_labels[i]
4492 #if new_label and new_label != "<try>":
4493 if new_label == new_error_label and self.preserve_exception:
4494 self.put_error_catcher(code,
4495 new_error_label, i+1, catch_label, temps_to_clean_up)
4496 else:
4497 code.put('%s: ' % new_label)
4498 if exc_var_init_zero:
4499 code.putln(exc_var_init_zero)
4500 code.putln("__pyx_why = %s; goto %s;" % (
4501 i+1,
4502 catch_label))
4503 code.put_label(catch_label)
4504 code.set_all_labels(old_labels)
4505 if error_label_used:
4506 code.new_error_label()
4507 finally_error_label = code.error_label
4508 self.finally_clause.generate_execution_code(code)
4509 if error_label_used:
4510 if finally_error_label in code.labels_used and self.preserve_exception:
4511 over_label = code.new_label()
4512 code.put_goto(over_label);
4513 code.put_label(finally_error_label)
4514 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4515 for var in Naming.exc_vars:
4516 code.putln("Py_XDECREF(%s);" % var)
4517 code.putln("}")
4518 code.put_goto(old_error_label)
4519 code.put_label(over_label)
4520 code.error_label = old_error_label
4521 if cases_used:
4522 code.putln(
4523 "switch (__pyx_why) {")
4524 for i in cases_used:
4525 old_label = old_labels[i]
4526 if old_label == old_error_label and self.preserve_exception:
4527 self.put_error_uncatcher(code, i+1, old_error_label)
4528 else:
4529 code.use_label(old_label)
4530 code.putln(
4531 "case %s: goto %s;" % (
4532 i+1,
4533 old_label))
4534 code.putln(
4535 "}")
4536 code.putln(
4537 "}")
4539 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4540 code.globalstate.use_utility_code(restore_exception_utility_code)
4541 code.putln(
4542 "%s: {" %
4543 error_label)
4544 code.putln(
4545 "__pyx_why = %s;" %
4546 i)
4547 for temp_name, type in temps_to_clean_up:
4548 code.put_xdecref_clear(temp_name, type)
4549 code.putln(
4550 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4551 Naming.exc_vars)
4552 code.putln(
4553 "%s = %s;" % (
4554 Naming.exc_lineno_name, Naming.lineno_cname))
4555 code.put_goto(catch_label)
4556 code.putln("}")
4558 def put_error_uncatcher(self, code, i, error_label):
4559 code.globalstate.use_utility_code(restore_exception_utility_code)
4560 code.putln(
4561 "case %s: {" %
4562 i)
4563 code.putln(
4564 "__Pyx_ErrRestore(%s, %s, %s);" %
4565 Naming.exc_vars)
4566 code.putln(
4567 "%s = %s;" % (
4568 Naming.lineno_cname, Naming.exc_lineno_name))
4569 for var in Naming.exc_vars:
4570 code.putln(
4571 "%s = 0;" %
4572 var)
4573 code.put_goto(error_label)
4574 code.putln(
4575 "}")
4577 def annotate(self, code):
4578 self.body.annotate(code)
4579 self.finally_clause.annotate(code)
4582 class GILStatNode(TryFinallyStatNode):
4583 # 'with gil' or 'with nogil' statement
4584 #
4585 # state string 'gil' or 'nogil'
4587 # child_attrs = []
4589 preserve_exception = 0
4591 def __init__(self, pos, state, body):
4592 self.state = state
4593 TryFinallyStatNode.__init__(self, pos,
4594 body = body,
4595 finally_clause = GILExitNode(pos, state = state))
4597 def analyse_expressions(self, env):
4598 env.use_utility_code(force_init_threads_utility_code)
4599 was_nogil = env.nogil
4600 env.nogil = 1
4601 TryFinallyStatNode.analyse_expressions(self, env)
4602 env.nogil = was_nogil
4604 nogil_check = None
4606 def generate_execution_code(self, code):
4607 code.mark_pos(self.pos)
4608 if self.state == 'gil':
4609 code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4610 else:
4611 code.putln("{ PyThreadState *_save;")
4612 code.putln("Py_UNBLOCK_THREADS")
4613 TryFinallyStatNode.generate_execution_code(self, code)
4614 code.putln("}")
4617 class GILExitNode(StatNode):
4618 # Used as the 'finally' block in a GILStatNode
4619 #
4620 # state string 'gil' or 'nogil'
4622 child_attrs = []
4624 def analyse_expressions(self, env):
4625 pass
4627 def generate_execution_code(self, code):
4628 if self.state == 'gil':
4629 code.putln("PyGILState_Release();")
4630 else:
4631 code.putln("Py_BLOCK_THREADS")
4634 class CImportStatNode(StatNode):
4635 # cimport statement
4636 #
4637 # module_name string Qualified name of module being imported
4638 # as_name string or None Name specified in "as" clause, if any
4640 child_attrs = []
4642 def analyse_declarations(self, env):
4643 if not env.is_module_scope:
4644 error(self.pos, "cimport only allowed at module level")
4645 return
4646 module_scope = env.find_module(self.module_name, self.pos)
4647 if "." in self.module_name:
4648 names = [EncodedString(name) for name in self.module_name.split(".")]
4649 top_name = names[0]
4650 top_module_scope = env.context.find_submodule(top_name)
4651 module_scope = top_module_scope
4652 for name in names[1:]:
4653 submodule_scope = module_scope.find_submodule(name)
4654 module_scope.declare_module(name, submodule_scope, self.pos)
4655 module_scope = submodule_scope
4656 if self.as_name:
4657 env.declare_module(self.as_name, module_scope, self.pos)
4658 else:
4659 env.declare_module(top_name, top_module_scope, self.pos)
4660 else:
4661 name = self.as_name or self.module_name
4662 env.declare_module(name, module_scope, self.pos)
4664 def analyse_expressions(self, env):
4665 pass
4667 def generate_execution_code(self, code):
4668 pass
4671 class FromCImportStatNode(StatNode):
4672 # from ... cimport statement
4673 #
4674 # module_name string Qualified name of module
4675 # imported_names [(pos, name, as_name, kind)] Names to be imported
4677 child_attrs = []
4679 def analyse_declarations(self, env):
4680 if not env.is_module_scope:
4681 error(self.pos, "cimport only allowed at module level")
4682 return
4683 module_scope = env.find_module(self.module_name, self.pos)
4684 env.add_imported_module(module_scope)
4685 for pos, name, as_name, kind in self.imported_names:
4686 if name == "*":
4687 for local_name, entry in module_scope.entries.items():
4688 env.add_imported_entry(local_name, entry, pos)
4689 else:
4690 entry = module_scope.lookup(name)
4691 if entry:
4692 if kind and not self.declaration_matches(entry, kind):
4693 entry.redeclared(pos)
4694 else:
4695 if kind == 'struct' or kind == 'union':
4696 entry = module_scope.declare_struct_or_union(name,
4697 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4698 elif kind == 'class':
4699 entry = module_scope.declare_c_class(name, pos = pos,
4700 module_name = self.module_name)
4701 else:
4702 submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
4703 if submodule_scope.parent_module is module_scope:
4704 env.declare_module(as_name or name, submodule_scope, self.pos)
4705 else:
4706 error(pos, "Name '%s' not declared in module '%s'"
4707 % (name, self.module_name))
4709 if entry:
4710 local_name = as_name or name
4711 env.add_imported_entry(local_name, entry, pos)
4713 def declaration_matches(self, entry, kind):
4714 if not entry.is_type:
4715 return 0
4716 type = entry.type
4717 if kind == 'class':
4718 if not type.is_extension_type:
4719 return 0
4720 else:
4721 if not type.is_struct_or_union:
4722 return 0
4723 if kind != type.kind:
4724 return 0
4725 return 1
4727 def analyse_expressions(self, env):
4728 pass
4730 def generate_execution_code(self, code):
4731 pass
4734 class FromImportStatNode(StatNode):
4735 # from ... import statement
4736 #
4737 # module ImportNode
4738 # items [(string, NameNode)]
4739 # interned_items [(string, NameNode, ExprNode)]
4740 # item PyTempNode used internally
4741 # import_star boolean used internally
4743 child_attrs = ["module"]
4744 import_star = 0
4746 def analyse_declarations(self, env):
4747 for name, target in self.items:
4748 if name == "*":
4749 if not env.is_module_scope:
4750 error(self.pos, "import * only allowed at module level")
4751 return
4752 env.has_import_star = 1
4753 self.import_star = 1
4754 else:
4755 target.analyse_target_declaration(env)
4757 def analyse_expressions(self, env):
4758 import ExprNodes
4759 self.module.analyse_expressions(env)
4760 self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
4761 self.interned_items = []
4762 for name, target in self.items:
4763 if name == '*':
4764 for _, entry in env.entries.items():
4765 if not entry.is_type and entry.type.is_extension_type:
4766 env.use_utility_code(ExprNodes.type_test_utility_code)
4767 break
4768 else:
4769 entry = env.lookup(target.name)
4770 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4771 continue # already cimported
4772 target.analyse_target_expression(env, None)
4773 if target.type is py_object_type:
4774 coerced_item = None
4775 else:
4776 coerced_item = self.item.coerce_to(target.type, env)
4777 self.interned_items.append(
4778 (name, target, coerced_item))
4780 def generate_execution_code(self, code):
4781 self.module.generate_evaluation_code(code)
4782 if self.import_star:
4783 code.putln(
4784 'if (%s(%s) < 0) %s;' % (
4785 Naming.import_star,
4786 self.module.py_result(),
4787 code.error_goto(self.pos)))
4788 item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
4789 self.item.set_cname(item_temp)
4790 for name, target, coerced_item in self.interned_items:
4791 cname = code.intern_identifier(name)
4792 code.putln(
4793 '%s = PyObject_GetAttr(%s, %s); %s' % (
4794 item_temp,
4795 self.module.py_result(),
4796 cname,
4797 code.error_goto_if_null(item_temp, self.pos)))
4798 code.put_gotref(item_temp)
4799 if coerced_item is None:
4800 target.generate_assignment_code(self.item, code)
4801 else:
4802 coerced_item.allocate_temp_result(code)
4803 coerced_item.generate_result_code(code)
4804 target.generate_assignment_code(coerced_item, code)
4805 code.put_decref_clear(item_temp, py_object_type)
4806 code.funcstate.release_temp(item_temp)
4807 self.module.generate_disposal_code(code)
4808 self.module.free_temps(code)
4812 #------------------------------------------------------------------------------------
4813 #
4814 # Runtime support code
4815 #
4816 #------------------------------------------------------------------------------------
4818 utility_function_predeclarations = \
4819 """
4820 #ifndef CYTHON_INLINE
4821 #if defined(__GNUC__)
4822 #define CYTHON_INLINE __inline__
4823 #elif defined(_MSC_VER)
4824 #define CYTHON_INLINE __inline
4825 #else
4826 #define CYTHON_INLINE
4827 #endif
4828 #endif
4830 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*/
4832 """
4834 if Options.gcc_branch_hints:
4835 branch_prediction_macros = \
4836 """
4837 #ifdef __GNUC__
4838 /* Test for GCC > 2.95 */
4839 #if __GNUC__ > 2 || \
4840 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4841 #define likely(x) __builtin_expect(!!(x), 1)
4842 #define unlikely(x) __builtin_expect(!!(x), 0)
4843 #else /* __GNUC__ > 2 ... */
4844 #define likely(x) (x)
4845 #define unlikely(x) (x)
4846 #endif /* __GNUC__ > 2 ... */
4847 #else /* __GNUC__ */
4848 #define likely(x) (x)
4849 #define unlikely(x) (x)
4850 #endif /* __GNUC__ */
4851 """
4852 else:
4853 branch_prediction_macros = \
4854 """
4855 #define likely(x) (x)
4856 #define unlikely(x) (x)
4857 """
4859 #get_name_predeclaration = \
4860 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4862 #get_name_interned_predeclaration = \
4863 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4865 #------------------------------------------------------------------------------------
4867 printing_utility_code = UtilityCode(
4868 proto = """
4869 static int __Pyx_Print(PyObject *, int); /*proto*/
4870 #if PY_MAJOR_VERSION >= 3
4871 static PyObject* %s = 0;
4872 static PyObject* %s = 0;
4873 #endif
4874 """ % (Naming.print_function, Naming.print_function_kwargs),
4875 impl = r"""
4876 #if PY_MAJOR_VERSION < 3
4877 static PyObject *__Pyx_GetStdout(void) {
4878 PyObject *f = PySys_GetObject((char *)"stdout");
4879 if (!f) {
4880 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4881 }
4882 return f;
4883 }
4885 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4886 PyObject *f;
4887 PyObject* v;
4888 int i;
4890 if (!(f = __Pyx_GetStdout()))
4891 return -1;
4892 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4893 if (PyFile_SoftSpace(f, 1)) {
4894 if (PyFile_WriteString(" ", f) < 0)
4895 return -1;
4896 }
4897 v = PyTuple_GET_ITEM(arg_tuple, i);
4898 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4899 return -1;
4900 if (PyString_Check(v)) {
4901 char *s = PyString_AsString(v);
4902 Py_ssize_t len = PyString_Size(v);
4903 if (len > 0 &&
4904 isspace(Py_CHARMASK(s[len-1])) &&
4905 s[len-1] != ' ')
4906 PyFile_SoftSpace(f, 0);
4907 }
4908 }
4909 if (newline) {
4910 if (PyFile_WriteString("\n", f) < 0)
4911 return -1;
4912 PyFile_SoftSpace(f, 0);
4913 }
4914 return 0;
4915 }
4917 #else /* Python 3 has a print function */
4919 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4920 PyObject* kwargs = 0;
4921 PyObject* result = 0;
4922 PyObject* end_string;
4923 if (!%(PRINT_FUNCTION)s) {
4924 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4925 if (!%(PRINT_FUNCTION)s)
4926 return -1;
4927 }
4928 if (!newline) {
4929 if (!%(PRINT_KWARGS)s) {
4930 %(PRINT_KWARGS)s = PyDict_New();
4931 if (!%(PRINT_KWARGS)s)
4932 return -1;
4933 end_string = PyUnicode_FromStringAndSize(" ", 1);
4934 if (!end_string)
4935 return -1;
4936 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4937 Py_DECREF(end_string);
4938 return -1;
4939 }
4940 Py_DECREF(end_string);
4941 }
4942 kwargs = %(PRINT_KWARGS)s;
4943 }
4944 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4945 if (!result)
4946 return -1;
4947 Py_DECREF(result);
4948 return 0;
4949 }
4951 #endif
4952 """ % {'BUILTINS' : Naming.builtins_cname,
4953 'PRINT_FUNCTION' : Naming.print_function,
4954 'PRINT_KWARGS' : Naming.print_function_kwargs}
4955 )
4958 printing_one_utility_code = UtilityCode(
4959 proto = """
4960 static int __Pyx_PrintOne(PyObject *o); /*proto*/
4961 """,
4962 impl = r"""
4963 #if PY_MAJOR_VERSION < 3
4965 static int __Pyx_PrintOne(PyObject *o) {
4966 PyObject *f;
4967 if (!(f = __Pyx_GetStdout()))
4968 return -1;
4969 if (PyFile_SoftSpace(f, 0)) {
4970 if (PyFile_WriteString(" ", f) < 0)
4971 return -1;
4972 }
4973 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
4974 return -1;
4975 if (PyFile_WriteString("\n", f) < 0)
4976 return -1;
4977 return 0;
4978 /* the line below is just to avoid compiler
4979 * compiler warnings about unused functions */
4980 return __Pyx_Print(NULL, 0);
4981 }
4983 #else /* Python 3 has a print function */
4985 static int __Pyx_PrintOne(PyObject *o) {
4986 int res;
4987 PyObject* arg_tuple = PyTuple_New(1);
4988 if (unlikely(!arg_tuple))
4989 return -1;
4990 Py_INCREF(o);
4991 PyTuple_SET_ITEM(arg_tuple, 0, o);
4992 res = __Pyx_Print(arg_tuple, 1);
4993 Py_DECREF(arg_tuple);
4994 return res;
4995 }
4997 #endif
4998 """,
4999 requires=[printing_utility_code])
5003 #------------------------------------------------------------------------------------
5005 # Exception raising code
5006 #
5007 # Exceptions are raised by __Pyx_Raise() and stored as plain
5008 # type/value/tb in PyThreadState->curexc_*. When being caught by an
5009 # 'except' statement, curexc_* is moved over to exc_* by
5010 # __Pyx_GetException()
5012 restore_exception_utility_code = UtilityCode(
5013 proto = """
5014 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5015 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5016 """,
5017 impl = """
5018 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5019 PyObject *tmp_type, *tmp_value, *tmp_tb;
5020 PyThreadState *tstate = PyThreadState_GET();
5022 tmp_type = tstate->curexc_type;
5023 tmp_value = tstate->curexc_value;
5024 tmp_tb = tstate->curexc_traceback;
5025 tstate->curexc_type = type;
5026 tstate->curexc_value = value;
5027 tstate->curexc_traceback = tb;
5028 Py_XDECREF(tmp_type);
5029 Py_XDECREF(tmp_value);
5030 Py_XDECREF(tmp_tb);
5031 }
5033 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5034 PyThreadState *tstate = PyThreadState_GET();
5035 *type = tstate->curexc_type;
5036 *value = tstate->curexc_value;
5037 *tb = tstate->curexc_traceback;
5039 tstate->curexc_type = 0;
5040 tstate->curexc_value = 0;
5041 tstate->curexc_traceback = 0;
5042 }
5044 """)
5046 # The following function is based on do_raise() from ceval.c. There
5047 # are separate versions for Python2 and Python3 as exception handling
5048 # has changed quite a lot between the two versions.
5050 raise_utility_code = UtilityCode(
5051 proto = """
5052 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5053 """,
5054 impl = """
5055 #if PY_MAJOR_VERSION < 3
5056 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5057 Py_XINCREF(type);
5058 Py_XINCREF(value);
5059 Py_XINCREF(tb);
5060 /* First, check the traceback argument, replacing None with NULL. */
5061 if (tb == Py_None) {
5062 Py_DECREF(tb);
5063 tb = 0;
5064 }
5065 else if (tb != NULL && !PyTraceBack_Check(tb)) {
5066 PyErr_SetString(PyExc_TypeError,
5067 "raise: arg 3 must be a traceback or None");
5068 goto raise_error;
5069 }
5070 /* Next, replace a missing value with None */
5071 if (value == NULL) {
5072 value = Py_None;
5073 Py_INCREF(value);
5074 }
5075 #if PY_VERSION_HEX < 0x02050000
5076 if (!PyClass_Check(type))
5077 #else
5078 if (!PyType_Check(type))
5079 #endif
5080 {
5081 /* Raising an instance. The value should be a dummy. */
5082 if (value != Py_None) {
5083 PyErr_SetString(PyExc_TypeError,
5084 "instance exception may not have a separate value");
5085 goto raise_error;
5086 }
5087 /* Normalize to raise <class>, <instance> */
5088 Py_DECREF(value);
5089 value = type;
5090 #if PY_VERSION_HEX < 0x02050000
5091 if (PyInstance_Check(type)) {
5092 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
5093 Py_INCREF(type);
5094 }
5095 else {
5096 type = 0;
5097 PyErr_SetString(PyExc_TypeError,
5098 "raise: exception must be an old-style class or instance");
5099 goto raise_error;
5100 }
5101 #else
5102 type = (PyObject*) Py_TYPE(type);
5103 Py_INCREF(type);
5104 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
5105 PyErr_SetString(PyExc_TypeError,
5106 "raise: exception class must be a subclass of BaseException");
5107 goto raise_error;
5108 }
5109 #endif
5110 }
5112 __Pyx_ErrRestore(type, value, tb);
5113 return;
5114 raise_error:
5115 Py_XDECREF(value);
5116 Py_XDECREF(type);
5117 Py_XDECREF(tb);
5118 return;
5119 }
5121 #else /* Python 3+ */
5123 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5124 if (tb == Py_None) {
5125 tb = 0;
5126 } else if (tb && !PyTraceBack_Check(tb)) {
5127 PyErr_SetString(PyExc_TypeError,
5128 "raise: arg 3 must be a traceback or None");
5129 goto bad;
5130 }
5131 if (value == Py_None)
5132 value = 0;
5134 if (PyExceptionInstance_Check(type)) {
5135 if (value) {
5136 PyErr_SetString(PyExc_TypeError,
5137 "instance exception may not have a separate value");
5138 goto bad;
5139 }
5140 value = type;
5141 type = (PyObject*) Py_TYPE(value);
5142 } else if (!PyExceptionClass_Check(type)) {
5143 PyErr_SetString(PyExc_TypeError,
5144 "raise: exception class must be a subclass of BaseException");
5145 goto bad;
5146 }
5148 PyErr_SetObject(type, value);
5150 if (tb) {
5151 PyThreadState *tstate = PyThreadState_GET();
5152 PyObject* tmp_tb = tstate->curexc_traceback;
5153 if (tb != tmp_tb) {
5154 Py_INCREF(tb);
5155 tstate->curexc_traceback = tb;
5156 Py_XDECREF(tmp_tb);
5157 }
5158 }
5160 bad:
5161 return;
5162 }
5163 #endif
5164 """,
5165 requires=[restore_exception_utility_code])
5167 #------------------------------------------------------------------------------------
5169 get_exception_utility_code = UtilityCode(
5170 proto = """
5171 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5172 """,
5173 impl = """
5174 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5175 PyObject *local_type, *local_value, *local_tb;
5176 PyObject *tmp_type, *tmp_value, *tmp_tb;
5177 PyThreadState *tstate = PyThreadState_GET();
5178 local_type = tstate->curexc_type;
5179 local_value = tstate->curexc_value;
5180 local_tb = tstate->curexc_traceback;
5181 tstate->curexc_type = 0;
5182 tstate->curexc_value = 0;
5183 tstate->curexc_traceback = 0;
5184 PyErr_NormalizeException(&local_type, &local_value, &local_tb);
5185 if (unlikely(tstate->curexc_type))
5186 goto bad;
5187 #if PY_MAJOR_VERSION >= 3
5188 if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
5189 goto bad;
5190 #endif
5191 *type = local_type;
5192 *value = local_value;
5193 *tb = local_tb;
5194 Py_INCREF(local_type);
5195 Py_INCREF(local_value);
5196 Py_INCREF(local_tb);
5197 tmp_type = tstate->exc_type;
5198 tmp_value = tstate->exc_value;
5199 tmp_tb = tstate->exc_traceback;
5200 tstate->exc_type = local_type;
5201 tstate->exc_value = local_value;
5202 tstate->exc_traceback = local_tb;
5203 /* Make sure tstate is in a consistent state when we XDECREF
5204 these objects (XDECREF may run arbitrary code). */
5205 Py_XDECREF(tmp_type);
5206 Py_XDECREF(tmp_value);
5207 Py_XDECREF(tmp_tb);
5208 return 0;
5209 bad:
5210 *type = 0;
5211 *value = 0;
5212 *tb = 0;
5213 Py_XDECREF(local_type);
5214 Py_XDECREF(local_value);
5215 Py_XDECREF(local_tb);
5216 return -1;
5217 }
5219 """)
5221 #------------------------------------------------------------------------------------
5223 get_exception_tuple_utility_code = UtilityCode(proto="""
5224 static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
5225 """,
5226 # I doubt that calling __Pyx_GetException() here is correct as it moves
5227 # the exception from tstate->curexc_* to tstate->exc_*, which prevents
5228 # exception handlers later on from receiving it.
5229 impl = """
5230 static PyObject *__Pyx_GetExceptionTuple(void) {
5231 PyObject *type = NULL, *value = NULL, *tb = NULL;
5232 if (__Pyx_GetException(&type, &value, &tb) == 0) {
5233 PyObject* exc_info = PyTuple_New(3);
5234 if (exc_info) {
5235 Py_INCREF(type);
5236 Py_INCREF(value);
5237 Py_INCREF(tb);
5238 PyTuple_SET_ITEM(exc_info, 0, type);
5239 PyTuple_SET_ITEM(exc_info, 1, value);
5240 PyTuple_SET_ITEM(exc_info, 2, tb);
5241 return exc_info;
5242 }
5243 }
5244 return NULL;
5245 }
5246 """,
5247 requires=[get_exception_utility_code])
5249 #------------------------------------------------------------------------------------
5251 reset_exception_utility_code = UtilityCode(
5252 proto = """
5253 static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5254 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5255 """,
5256 impl = """
5257 static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5258 PyThreadState *tstate = PyThreadState_GET();
5259 *type = tstate->exc_type;
5260 *value = tstate->exc_value;
5261 *tb = tstate->exc_traceback;
5262 Py_XINCREF(*type);
5263 Py_XINCREF(*value);
5264 Py_XINCREF(*tb);
5265 }
5267 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5268 PyObject *tmp_type, *tmp_value, *tmp_tb;
5269 PyThreadState *tstate = PyThreadState_GET();
5270 tmp_type = tstate->exc_type;
5271 tmp_value = tstate->exc_value;
5272 tmp_tb = tstate->exc_traceback;
5273 tstate->exc_type = type;
5274 tstate->exc_value = value;
5275 tstate->exc_traceback = tb;
5276 Py_XDECREF(tmp_type);
5277 Py_XDECREF(tmp_value);
5278 Py_XDECREF(tmp_tb);
5279 }
5280 """)
5282 #------------------------------------------------------------------------------------
5284 arg_type_test_utility_code = UtilityCode(
5285 proto = """
5286 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5287 const char *name, int exact); /*proto*/
5288 """,
5289 impl = """
5290 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5291 const char *name, int exact)
5292 {
5293 if (!type) {
5294 PyErr_Format(PyExc_SystemError, "Missing type object");
5295 return 0;
5296 }
5297 if (none_allowed && obj == Py_None) return 1;
5298 else if (exact) {
5299 if (Py_TYPE(obj) == type) return 1;
5300 }
5301 else {
5302 if (PyObject_TypeCheck(obj, type)) return 1;
5303 }
5304 PyErr_Format(PyExc_TypeError,
5305 "Argument '%s' has incorrect type (expected %s, got %s)",
5306 name, type->tp_name, Py_TYPE(obj)->tp_name);
5307 return 0;
5308 }
5309 """)
5311 #------------------------------------------------------------------------------------
5312 #
5313 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5314 # many or too few positional arguments were found. This handles
5315 # Py_ssize_t formatting correctly.
5317 raise_argtuple_invalid_utility_code = UtilityCode(
5318 proto = """
5319 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5320 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5321 """,
5322 impl = """
5323 static void __Pyx_RaiseArgtupleInvalid(
5324 const char* func_name,
5325 int exact,
5326 Py_ssize_t num_min,
5327 Py_ssize_t num_max,
5328 Py_ssize_t num_found)
5329 {
5330 Py_ssize_t num_expected;
5331 const char *number, *more_or_less;
5333 if (num_found < num_min) {
5334 num_expected = num_min;
5335 more_or_less = "at least";
5336 } else {
5337 num_expected = num_max;
5338 more_or_less = "at most";
5339 }
5340 if (exact) {
5341 more_or_less = "exactly";
5342 }
5343 number = (num_expected == 1) ? "" : "s";
5344 PyErr_Format(PyExc_TypeError,
5345 #if PY_VERSION_HEX < 0x02050000
5346 "%s() takes %s %d positional argument%s (%d given)",
5347 #else
5348 "%s() takes %s %zd positional argument%s (%zd given)",
5349 #endif
5350 func_name, more_or_less, num_expected, number, num_found);
5351 }
5352 """)
5354 raise_keyword_required_utility_code = UtilityCode(
5355 proto = """
5356 static CYTHON_INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5357 """,
5358 impl = """
5359 static CYTHON_INLINE void __Pyx_RaiseKeywordRequired(
5360 const char* func_name,
5361 PyObject* kw_name)
5362 {
5363 PyErr_Format(PyExc_TypeError,
5364 #if PY_MAJOR_VERSION >= 3
5365 "%s() needs keyword-only argument %U", func_name, kw_name);
5366 #else
5367 "%s() needs keyword-only argument %s", func_name,
5368 PyString_AS_STRING(kw_name));
5369 #endif
5370 }
5371 """)
5373 raise_double_keywords_utility_code = UtilityCode(
5374 proto = """
5375 static void __Pyx_RaiseDoubleKeywordsError(
5376 const char* func_name, PyObject* kw_name); /*proto*/
5377 """,
5378 impl = """
5379 static void __Pyx_RaiseDoubleKeywordsError(
5380 const char* func_name,
5381 PyObject* kw_name)
5382 {
5383 PyErr_Format(PyExc_TypeError,
5384 #if PY_MAJOR_VERSION >= 3
5385 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5386 #else
5387 "%s() got multiple values for keyword argument '%s'", func_name,
5388 PyString_AS_STRING(kw_name));
5389 #endif
5390 }
5391 """)
5393 #------------------------------------------------------------------------------------
5394 #
5395 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5396 # were passed to a function, or if any keywords were passed to a
5397 # function that does not accept them.
5399 keyword_string_check_utility_code = UtilityCode(
5400 proto = """
5401 static CYTHON_INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5402 const char* function_name, int kw_allowed); /*proto*/
5403 """,
5404 impl = """
5405 static CYTHON_INLINE int __Pyx_CheckKeywordStrings(
5406 PyObject *kwdict,
5407 const char* function_name,
5408 int kw_allowed)
5409 {
5410 PyObject* key = 0;
5411 Py_ssize_t pos = 0;
5412 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5413 #if PY_MAJOR_VERSION < 3
5414 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5415 #else
5416 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5417 #endif
5418 goto invalid_keyword_type;
5419 }
5420 if ((!kw_allowed) && unlikely(key))
5421 goto invalid_keyword;
5422 return 1;
5423 invalid_keyword_type:
5424 PyErr_Format(PyExc_TypeError,
5425 "%s() keywords must be strings", function_name);
5426 return 0;
5427 invalid_keyword:
5428 PyErr_Format(PyExc_TypeError,
5429 #if PY_MAJOR_VERSION < 3
5430 "%s() got an unexpected keyword argument '%s'",
5431 function_name, PyString_AsString(key));
5432 #else
5433 "%s() got an unexpected keyword argument '%U'",
5434 function_name, key);
5435 #endif
5436 return 0;
5437 }
5438 """)
5440 #------------------------------------------------------------------------------------
5441 #
5442 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5443 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5444 # keywords will raise an invalid keyword error.
5445 #
5446 # Three kinds of errors are checked: 1) non-string keywords, 2)
5447 # unexpected keywords and 3) overlap with positional arguments.
5448 #
5449 # If num_posargs is greater 0, it denotes the number of positional
5450 # arguments that were passed and that must therefore not appear
5451 # amongst the keywords as well.
5452 #
5453 # This method does not check for required keyword arguments.
5454 #
5456 parse_keywords_utility_code = UtilityCode(
5457 proto = """
5458 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5459 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5460 const char* function_name); /*proto*/
5461 """,
5462 impl = """
5463 static int __Pyx_ParseOptionalKeywords(
5464 PyObject *kwds,
5465 PyObject **argnames[],
5466 PyObject *kwds2,
5467 PyObject *values[],
5468 Py_ssize_t num_pos_args,
5469 const char* function_name)
5470 {
5471 PyObject *key = 0, *value = 0;
5472 Py_ssize_t pos = 0;
5473 PyObject*** name;
5474 PyObject*** first_kw_arg = argnames + num_pos_args;
5476 while (PyDict_Next(kwds, &pos, &key, &value)) {
5477 name = first_kw_arg;
5478 while (*name && (**name != key)) name++;
5479 if (*name) {
5480 values[name-argnames] = value;
5481 } else {
5482 #if PY_MAJOR_VERSION < 3
5483 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5484 #else
5485 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5486 #endif
5487 goto invalid_keyword_type;
5488 } else {
5489 for (name = first_kw_arg; *name; name++) {
5490 #if PY_MAJOR_VERSION >= 3
5491 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5492 PyUnicode_Compare(**name, key) == 0) break;
5493 #else
5494 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5495 _PyString_Eq(**name, key)) break;
5496 #endif
5497 }
5498 if (*name) {
5499 values[name-argnames] = value;
5500 } else {
5501 /* unexpected keyword found */
5502 for (name=argnames; name != first_kw_arg; name++) {
5503 if (**name == key) goto arg_passed_twice;
5504 #if PY_MAJOR_VERSION >= 3
5505 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5506 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5507 #else
5508 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5509 _PyString_Eq(**name, key)) goto arg_passed_twice;
5510 #endif
5511 }
5512 if (kwds2) {
5513 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5514 } else {
5515 goto invalid_keyword;
5516 }
5517 }
5518 }
5519 }
5520 }
5521 return 0;
5522 arg_passed_twice:
5523 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5524 goto bad;
5525 invalid_keyword_type:
5526 PyErr_Format(PyExc_TypeError,
5527 "%s() keywords must be strings", function_name);
5528 goto bad;
5529 invalid_keyword:
5530 PyErr_Format(PyExc_TypeError,
5531 #if PY_MAJOR_VERSION < 3
5532 "%s() got an unexpected keyword argument '%s'",
5533 function_name, PyString_AsString(key));
5534 #else
5535 "%s() got an unexpected keyword argument '%U'",
5536 function_name, key);
5537 #endif
5538 bad:
5539 return -1;
5540 }
5541 """)
5543 #------------------------------------------------------------------------------------
5545 traceback_utility_code = UtilityCode(
5546 proto = """
5547 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5548 """,
5549 impl = """
5550 #include "compile.h"
5551 #include "frameobject.h"
5552 #include "traceback.h"
5554 static void __Pyx_AddTraceback(const char *funcname) {
5555 PyObject *py_srcfile = 0;
5556 PyObject *py_funcname = 0;
5557 PyObject *py_globals = 0;
5558 PyCodeObject *py_code = 0;
5559 PyFrameObject *py_frame = 0;
5561 #if PY_MAJOR_VERSION < 3
5562 py_srcfile = PyString_FromString(%(FILENAME)s);
5563 #else
5564 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5565 #endif
5566 if (!py_srcfile) goto bad;
5567 if (%(CLINENO)s) {
5568 #if PY_MAJOR_VERSION < 3
5569 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5570 #else
5571 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5572 #endif
5573 }
5574 else {
5575 #if PY_MAJOR_VERSION < 3
5576 py_funcname = PyString_FromString(funcname);
5577 #else
5578 py_funcname = PyUnicode_FromString(funcname);
5579 #endif
5580 }
5581 if (!py_funcname) goto bad;
5582 py_globals = PyModule_GetDict(%(GLOBALS)s);
5583 if (!py_globals) goto bad;
5584 py_code = PyCode_New(
5585 0, /*int argcount,*/
5586 #if PY_MAJOR_VERSION >= 3
5587 0, /*int kwonlyargcount,*/
5588 #endif
5589 0, /*int nlocals,*/
5590 0, /*int stacksize,*/
5591 0, /*int flags,*/
5592 %(EMPTY_BYTES)s, /*PyObject *code,*/
5593 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5594 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5595 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5596 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5597 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5598 py_srcfile, /*PyObject *filename,*/
5599 py_funcname, /*PyObject *name,*/
5600 %(LINENO)s, /*int firstlineno,*/
5601 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5602 );
5603 if (!py_code) goto bad;
5604 py_frame = PyFrame_New(
5605 PyThreadState_GET(), /*PyThreadState *tstate,*/
5606 py_code, /*PyCodeObject *code,*/
5607 py_globals, /*PyObject *globals,*/
5608 0 /*PyObject *locals*/
5609 );
5610 if (!py_frame) goto bad;
5611 py_frame->f_lineno = %(LINENO)s;
5612 PyTraceBack_Here(py_frame);
5613 bad:
5614 Py_XDECREF(py_srcfile);
5615 Py_XDECREF(py_funcname);
5616 Py_XDECREF(py_code);
5617 Py_XDECREF(py_frame);
5618 }
5619 """ % {
5620 'FILENAME': Naming.filename_cname,
5621 'LINENO': Naming.lineno_cname,
5622 'CFILENAME': Naming.cfilenm_cname,
5623 'CLINENO': Naming.clineno_cname,
5624 'GLOBALS': Naming.module_cname,
5625 'EMPTY_TUPLE' : Naming.empty_tuple,
5626 'EMPTY_BYTES' : Naming.empty_bytes,
5627 })
5629 #------------------------------------------------------------------------------------
5631 unraisable_exception_utility_code = UtilityCode(
5632 proto = """
5633 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5634 """,
5635 impl = """
5636 static void __Pyx_WriteUnraisable(const char *name) {
5637 PyObject *old_exc, *old_val, *old_tb;
5638 PyObject *ctx;
5639 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5640 #if PY_MAJOR_VERSION < 3
5641 ctx = PyString_FromString(name);
5642 #else
5643 ctx = PyUnicode_FromString(name);
5644 #endif
5645 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5646 if (!ctx) {
5647 PyErr_WriteUnraisable(Py_None);
5648 } else {
5649 PyErr_WriteUnraisable(ctx);
5650 Py_DECREF(ctx);
5651 }
5652 }
5653 """,
5654 requires=[restore_exception_utility_code])
5656 #------------------------------------------------------------------------------------
5658 set_vtable_utility_code = UtilityCode(
5659 proto = """
5660 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5661 """,
5662 impl = """
5663 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5664 #if PY_VERSION_HEX < 0x03010000
5665 PyObject *ob = PyCObject_FromVoidPtr(vtable, 0);
5666 #else
5667 PyObject *ob = PyCapsule_New(vtable, 0, 0);
5668 #endif
5669 if (!ob)
5670 goto bad;
5671 if (PyDict_SetItemString(dict, "__pyx_vtable__", ob) < 0)
5672 goto bad;
5673 Py_DECREF(ob);
5674 return 0;
5675 bad:
5676 Py_XDECREF(ob);
5677 return -1;
5678 }
5679 """)
5681 #------------------------------------------------------------------------------------
5683 get_vtable_utility_code = UtilityCode(
5684 proto = """
5685 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5686 """,
5687 impl = r"""
5688 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5689 PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5690 if (!ob)
5691 goto bad;
5692 #if PY_VERSION_HEX < 0x03010000
5693 *(void **)vtabptr = PyCObject_AsVoidPtr(ob);
5694 #else
5695 *(void **)vtabptr = PyCapsule_GetPointer(ob, 0);
5696 #endif
5697 if (!*(void **)vtabptr)
5698 goto bad;
5699 Py_DECREF(ob);
5700 return 0;
5701 bad:
5702 Py_XDECREF(ob);
5703 return -1;
5704 }
5705 """)
5707 #------------------------------------------------------------------------------------
5709 init_string_tab_utility_code = UtilityCode(
5710 proto = """
5711 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5712 """,
5713 impl = """
5714 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5715 while (t->p) {
5716 #if PY_MAJOR_VERSION < 3
5717 if (t->is_unicode) {
5718 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5719 } else if (t->intern) {
5720 *t->p = PyString_InternFromString(t->s);
5721 } else {
5722 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5723 }
5724 #else /* Python 3+ has unicode identifiers */
5725 if (t->is_unicode | t->is_str) {
5726 if (t->intern) {
5727 *t->p = PyUnicode_InternFromString(t->s);
5728 } else if (t->encoding) {
5729 *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
5730 } else {
5731 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5732 }
5733 } else {
5734 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5735 }
5736 #endif
5737 if (!*t->p)
5738 return -1;
5739 ++t;
5740 }
5741 return 0;
5742 }
5743 """)
5745 #------------------------------------------------------------------------------------
5747 force_init_threads_utility_code = UtilityCode(
5748 proto="""
5749 #ifndef __PYX_FORCE_INIT_THREADS
5750 #if PY_VERSION_HEX < 0x02040200
5751 #define __PYX_FORCE_INIT_THREADS 1
5752 #else
5753 #define __PYX_FORCE_INIT_THREADS 0
5754 #endif
5755 #endif
5756 """)
5758 #------------------------------------------------------------------------------------
5760 # Note that cPython ignores PyTrace_EXCEPTION,
5761 # but maybe some other profilers don't.
5763 profile_utility_code = UtilityCode(proto="""
5764 #ifndef CYTHON_PROFILE
5765 #define CYTHON_PROFILE 1
5766 #endif
5768 #ifndef CYTHON_PROFILE_REUSE_FRAME
5769 #define CYTHON_PROFILE_REUSE_FRAME 0
5770 #endif
5772 #if CYTHON_PROFILE
5774 #include "compile.h"
5775 #include "frameobject.h"
5776 #include "traceback.h"
5778 #if CYTHON_PROFILE_REUSE_FRAME
5779 #define CYTHON_FRAME_MODIFIER static
5780 #define CYTHON_FRAME_DEL
5781 #else
5782 #define CYTHON_FRAME_MODIFIER
5783 #define CYTHON_FRAME_DEL Py_DECREF(%(FRAME)s)
5784 #endif
5786 #define __Pyx_TraceDeclarations \\
5787 static PyCodeObject *%(FRAME_CODE)s = NULL; \\
5788 CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL; \\
5789 int __Pyx_use_tracing = 0;
5791 #define __Pyx_TraceCall(funcname, srcfile, firstlineno) \\
5792 if (unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc)) { \\
5793 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&%(FRAME_CODE)s, &%(FRAME)s, funcname, srcfile, firstlineno); \\
5794 }
5796 #define __Pyx_TraceException() \\
5797 if (unlikely(__Pyx_use_tracing( && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5798 PyObject *exc_info = __Pyx_GetExceptionTuple(); \\
5799 if (exc_info) { \\
5800 PyThreadState_GET()->c_profilefunc( \\
5801 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_EXCEPTION, exc_info); \\
5802 Py_DECREF(exc_info); \\
5803 } \\
5804 }
5806 #define __Pyx_TraceReturn(result) \\
5807 if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5808 PyThreadState_GET()->c_profilefunc( \\
5809 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_RETURN, (PyObject*)result); \\
5810 CYTHON_FRAME_DEL; \\
5811 }
5813 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
5814 static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
5816 #else
5818 #define __Pyx_TraceDeclarations
5819 #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
5820 #define __Pyx_TraceException()
5821 #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 })
