Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 2052:dcc78ab6a498

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