Cython has moved to github.
cython-devel
view Cython/Compiler/Nodes.py @ 2054:ddaf43291b55
Fixing up flawed fix for #303
| author | Dag Sverre Seljebotn <dagss@student.matnat.uio.no> |
|---|---|
| date | Thu May 14 17:28:50 2009 +0200 (3 years ago) |
| parents | dcc78ab6a498 |
| children | 915e04bb7c49 |
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 need_property = False
798 if (dest_scope.is_c_class_scope
799 and self.visibility == 'public'
800 and base_type.is_pyobject
801 and (base_type.is_builtin_type or base_type.is_extension_type)):
802 # If the field is settable and extension type, then the CPython mechanism does
803 # not do enough type-checking for us.
804 need_property = True
805 elif (base_type.is_typedef and base_type.typedef_is_external
806 and (self.visibility in ('public', 'readonly'))):
807 # If the field is an external typedef, we cannot be sure about the type,
808 # so do conversion ourself rather than rely on the CPython mechanism (through
809 # a property; made in AnalyseDeclarationsTransform).
810 need_property = True
812 if need_property:
813 visibility = 'private'
814 self.need_properties = []
815 else:
816 visibility = self.visibility
818 for declarator in self.declarators:
819 name_declarator, type = declarator.analyse(base_type, env)
820 if not type.is_complete():
821 if not (self.visibility == 'extern' and type.is_array):
822 error(declarator.pos,
823 "Variable type '%s' is incomplete" % type)
824 if self.visibility == 'extern' and type.is_pyobject:
825 error(declarator.pos,
826 "Python object cannot be declared extern")
827 name = name_declarator.name
828 cname = name_declarator.cname
829 if name == '':
830 error(declarator.pos, "Missing name in declaration.")
831 return
832 if type.is_cfunction:
833 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
834 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
835 api = self.api)
836 if entry is not None:
837 entry.directive_locals = self.directive_locals
838 else:
839 if self.directive_locals:
840 s.error("Decorators can only be followed by functions")
841 if self.in_pxd and self.visibility != 'extern':
842 error(self.pos,
843 "Only 'extern' C variable declaration allowed in .pxd file")
844 entry = dest_scope.declare_var(name, type, declarator.pos,
845 cname = cname, visibility = visibility, is_cdef = 1)
846 if need_property:
847 self.need_properties.append(entry)
848 entry.needs_property = 1
851 class CStructOrUnionDefNode(StatNode):
852 # name string
853 # cname string or None
854 # kind "struct" or "union"
855 # typedef_flag boolean
856 # visibility "public" or "private"
857 # in_pxd boolean
858 # attributes [CVarDefNode] or None
859 # entry Entry
860 # packed boolean
862 child_attrs = ["attributes"]
864 def analyse_declarations(self, env):
865 scope = None
866 if self.visibility == 'extern' and self.packed:
867 error(self.pos, "Cannot declare extern struct as 'packed'")
868 if self.attributes is not None:
869 scope = StructOrUnionScope(self.name)
870 self.entry = env.declare_struct_or_union(
871 self.name, self.kind, scope, self.typedef_flag, self.pos,
872 self.cname, visibility = self.visibility, packed = self.packed)
873 if self.attributes is not None:
874 if self.in_pxd and not env.in_cinclude:
875 self.entry.defined_in_pxd = 1
876 for attr in self.attributes:
877 attr.analyse_declarations(env, scope)
878 if self.visibility != 'extern':
879 need_typedef_indirection = False
880 for attr in scope.var_entries:
881 type = attr.type
882 while type.is_array:
883 type = type.base_type
884 if type == self.entry.type:
885 error(attr.pos, "Struct cannot contain itself as a member.")
886 if self.typedef_flag:
887 while type.is_ptr:
888 type = type.base_type
889 if type == self.entry.type:
890 need_typedef_indirection = True
891 if need_typedef_indirection:
892 # C can't handle typedef structs that refer to themselves.
893 struct_entry = self.entry
894 cname = env.new_const_cname()
895 self.entry = env.declare_typedef(self.name, struct_entry.type, self.pos, cname = self.cname, visibility='ignore')
896 struct_entry.type.typedef_flag = False
897 struct_entry.cname = struct_entry.type.cname = env.new_const_cname()
899 def analyse_expressions(self, env):
900 pass
902 def generate_execution_code(self, code):
903 pass
906 class CEnumDefNode(StatNode):
907 # name string or None
908 # cname string or None
909 # items [CEnumDefItemNode]
910 # typedef_flag boolean
911 # visibility "public" or "private"
912 # in_pxd boolean
913 # entry Entry
915 child_attrs = ["items"]
917 def analyse_declarations(self, env):
918 self.entry = env.declare_enum(self.name, self.pos,
919 cname = self.cname, typedef_flag = self.typedef_flag,
920 visibility = self.visibility)
921 if self.items is not None:
922 if self.in_pxd and not env.in_cinclude:
923 self.entry.defined_in_pxd = 1
924 for item in self.items:
925 item.analyse_declarations(env, self.entry)
927 def analyse_expressions(self, env):
928 if self.visibility == 'public':
929 self.temp = env.allocate_temp_pyobject()
930 env.release_temp(self.temp)
932 def generate_execution_code(self, code):
933 if self.visibility == 'public':
934 for item in self.entry.enum_values:
935 code.putln("%s = PyInt_FromLong(%s); %s" % (
936 self.temp,
937 item.cname,
938 code.error_goto_if_null(self.temp, item.pos)))
939 code.put_gotref(self.temp)
940 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
941 Naming.module_cname,
942 item.name,
943 self.temp,
944 code.error_goto(item.pos)))
945 code.put_decref_clear(self.temp, PyrexTypes.py_object_type)
948 class CEnumDefItemNode(StatNode):
949 # name string
950 # cname string or None
951 # value ExprNode or None
953 child_attrs = ["value"]
955 def analyse_declarations(self, env, enum_entry):
956 if self.value:
957 self.value.analyse_const_expression(env)
958 if not self.value.type.is_int:
959 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
960 self.value.analyse_const_expression(env)
961 value = self.value.result()
962 else:
963 value = self.name
964 entry = env.declare_const(self.name, enum_entry.type,
965 value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
966 enum_entry.enum_values.append(entry)
969 class CTypeDefNode(StatNode):
970 # base_type CBaseTypeNode
971 # declarator CDeclaratorNode
972 # visibility "public" or "private"
973 # in_pxd boolean
975 child_attrs = ["base_type", "declarator"]
977 def analyse_declarations(self, env):
978 base = self.base_type.analyse(env)
979 name_declarator, type = self.declarator.analyse(base, env)
980 name = name_declarator.name
981 cname = name_declarator.cname
982 entry = env.declare_typedef(name, type, self.pos,
983 cname = cname, visibility = self.visibility)
984 if self.in_pxd and not env.in_cinclude:
985 entry.defined_in_pxd = 1
987 def analyse_expressions(self, env):
988 pass
989 def generate_execution_code(self, code):
990 pass
993 class FuncDefNode(StatNode, BlockNode):
994 # Base class for function definition nodes.
995 #
996 # return_type PyrexType
997 # #filename string C name of filename string const
998 # entry Symtab.Entry
999 # needs_closure boolean Whether or not this function has inner functions/classes/yield
1000 # directive_locals { string : NameNode } locals defined by cython.locals(...)
1002 py_func = None
1003 assmt = None
1004 needs_closure = False
1006 def analyse_default_values(self, env):
1007 genv = env.global_scope()
1008 for arg in self.args:
1009 if arg.default:
1010 if arg.is_generic:
1011 if not hasattr(arg, 'default_entry'):
1012 arg.default.analyse_types(env)
1013 arg.default = arg.default.coerce_to(arg.type, genv)
1014 if arg.default.is_literal:
1015 arg.default_entry = arg.default
1016 arg.default_result_code = arg.default.calculate_result_code()
1017 if arg.default.type != arg.type and not arg.type.is_int:
1018 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
1019 else:
1020 arg.default.allocate_temps(genv)
1021 arg.default_entry = genv.add_default_value(arg.type)
1022 if arg.type.is_pyobject:
1023 arg.default_entry.init = 0
1024 arg.default_entry.used = 1
1025 arg.default_result_code = arg.default_entry.cname
1026 else:
1027 error(arg.pos,
1028 "This argument cannot have a default value")
1029 arg.default = None
1031 def need_gil_acquisition(self, lenv):
1032 return 0
1034 def create_local_scope(self, env):
1035 genv = env
1036 while env.is_py_class_scope or env.is_c_class_scope:
1037 env = env.outer_scope
1038 if self.needs_closure:
1039 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
1040 else:
1041 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
1042 lenv.return_type = self.return_type
1043 type = self.entry.type
1044 if type.is_cfunction:
1045 lenv.nogil = type.nogil and not type.with_gil
1046 self.local_scope = lenv
1047 lenv.directives = env.directives
1048 return lenv
1050 def generate_function_definitions(self, env, code):
1051 import Buffer
1053 lenv = self.local_scope
1055 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1056 self.entry.scope.is_c_class_scope)
1058 # Generate C code for header and body of function
1059 code.enter_cfunc_scope()
1060 code.return_from_error_cleanup_label = code.new_label()
1062 # ----- Top-level constants used by this function
1063 code.mark_pos(self.pos)
1064 self.generate_interned_num_decls(lenv, code)
1065 self.generate_interned_string_decls(lenv, code)
1066 self.generate_py_string_decls(lenv, code)
1067 self.generate_cached_builtins_decls(lenv, code)
1068 #code.putln("")
1069 #code.put_var_declarations(lenv.const_entries, static = 1)
1070 self.generate_const_definitions(lenv, code)
1071 # ----- Function header
1072 code.putln("")
1073 if self.py_func:
1074 self.py_func.generate_function_header(code,
1075 with_pymethdef = env.is_py_class_scope,
1076 proto_only=True)
1077 self.generate_function_header(code,
1078 with_pymethdef = env.is_py_class_scope)
1079 # ----- Local variable declarations
1080 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
1081 self.generate_argument_declarations(lenv, code)
1082 if self.needs_closure:
1083 code.putln("/* TODO: declare and create scope object */")
1084 code.put_var_declarations(lenv.var_entries)
1085 init = ""
1086 if not self.return_type.is_void:
1087 if self.return_type.is_pyobject:
1088 init = " = NULL"
1089 code.putln(
1090 "%s%s;" %
1091 (self.return_type.declaration_code(
1092 Naming.retval_cname),
1093 init))
1094 tempvardecl_code = code.insertion_point()
1095 self.generate_keyword_list(code)
1096 # ----- Extern library function declarations
1097 lenv.generate_library_function_declarations(code)
1098 # ----- GIL acquisition
1099 acquire_gil = self.need_gil_acquisition(lenv)
1100 if acquire_gil:
1101 env.use_utility_code(force_init_threads_utility_code)
1102 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1103 # ----- Automatic lead-ins for certain special functions
1104 if not lenv.nogil:
1105 code.put_setup_refcount_context(self.entry.name)
1106 if is_getbuffer_slot:
1107 self.getbuffer_init(code)
1108 # ----- Fetch arguments
1109 self.generate_argument_parsing_code(env, code)
1110 # If an argument is assigned to in the body, we must
1111 # incref it to properly keep track of refcounts.
1112 for entry in lenv.arg_entries:
1113 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1114 code.put_var_incref(entry)
1115 # ----- Initialise local variables
1116 for entry in lenv.var_entries:
1117 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1118 code.put_init_var_to_py_none(entry)
1119 # ----- Initialise local buffer auxiliary variables
1120 for entry in lenv.var_entries + lenv.arg_entries:
1121 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1122 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1123 # ----- Check and convert arguments
1124 self.generate_argument_type_tests(code)
1125 # ----- Acquire buffer arguments
1126 for entry in lenv.arg_entries:
1127 if entry.type.is_buffer:
1128 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1129 # ----- Function body
1130 self.body.generate_execution_code(code)
1131 # ----- Default return value
1132 code.putln("")
1133 if self.return_type.is_pyobject:
1134 #if self.return_type.is_extension_type:
1135 # lhs = "(PyObject *)%s" % Naming.retval_cname
1136 #else:
1137 lhs = Naming.retval_cname
1138 code.put_init_to_py_none(lhs, self.return_type)
1139 else:
1140 val = self.return_type.default_value
1141 if val:
1142 code.putln("%s = %s;" % (Naming.retval_cname, val))
1143 # ----- Error cleanup
1144 if code.error_label in code.labels_used:
1145 code.put_goto(code.return_label)
1146 code.put_label(code.error_label)
1147 # cleanup temps the old way
1148 code.put_var_xdecrefs(lenv.temp_entries)
1149 # cleanup temps the new way
1150 for cname, type in code.funcstate.all_managed_temps():
1151 code.put_xdecref(cname, type)
1153 # Clean up buffers -- this calls a Python function
1154 # so need to save and restore error state
1155 buffers_present = len(lenv.buffer_entries) > 0
1156 if buffers_present:
1157 code.globalstate.use_utility_code(restore_exception_utility_code)
1158 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1159 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1160 for entry in lenv.buffer_entries:
1161 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1162 #code.putln("%s = 0;" % entry.cname)
1163 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1165 err_val = self.error_value()
1166 exc_check = self.caller_will_check_exceptions()
1167 if err_val is not None or exc_check:
1168 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1169 else:
1170 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1171 % self.entry.qualified_name, 0)
1172 code.putln(
1173 '__Pyx_WriteUnraisable("%s");' %
1174 self.entry.qualified_name)
1175 env.use_utility_code(unraisable_exception_utility_code)
1176 env.use_utility_code(restore_exception_utility_code)
1177 default_retval = self.return_type.default_value
1178 if err_val is None and default_retval:
1179 err_val = default_retval
1180 if err_val is not None:
1181 code.putln(
1182 "%s = %s;" % (
1183 Naming.retval_cname,
1184 err_val))
1186 if is_getbuffer_slot:
1187 self.getbuffer_error_cleanup(code)
1189 # If we are using the non-error cleanup section we should
1190 # jump past it if we have an error. The if-test below determine
1191 # whether this section is used.
1192 if buffers_present or is_getbuffer_slot:
1193 code.put_goto(code.return_from_error_cleanup_label)
1196 # ----- Non-error return cleanup
1197 # If you add anything here, remember to add a condition to the
1198 # if-test above in the error block (so that it can jump past this
1199 # block).
1200 code.put_label(code.return_label)
1201 for entry in lenv.buffer_entries:
1202 if entry.used:
1203 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1204 if is_getbuffer_slot:
1205 self.getbuffer_normal_cleanup(code)
1206 # ----- Return cleanup for both error and no-error return
1207 code.put_label(code.return_from_error_cleanup_label)
1208 if not Options.init_local_none:
1209 for entry in lenv.var_entries:
1210 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1211 entry.xdecref_cleanup = 1
1212 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1213 # Decref any increfed args
1214 for entry in lenv.arg_entries:
1215 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1216 code.put_var_decref(entry)
1218 # code.putln("/* TODO: decref scope object */")
1219 # ----- Return
1220 # This code is duplicated in ModuleNode.generate_module_init_func
1221 if not lenv.nogil:
1222 default_retval = self.return_type.default_value
1223 err_val = self.error_value()
1224 if err_val is None and default_retval:
1225 err_val = default_retval
1226 if self.return_type.is_pyobject:
1227 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1229 code.put_finish_refcount_context()
1231 if acquire_gil:
1232 code.putln("PyGILState_Release(_save);")
1234 if not self.return_type.is_void:
1235 code.putln("return %s;" % Naming.retval_cname)
1237 code.putln("}")
1238 # ----- Go back and insert temp variable declarations
1239 tempvardecl_code.put_var_declarations(lenv.temp_entries)
1240 tempvardecl_code.put_temp_declarations(code.funcstate)
1241 # ----- Python version
1242 code.exit_cfunc_scope()
1243 if self.py_func:
1244 self.py_func.generate_function_definitions(env, code)
1245 self.generate_wrapper_functions(code)
1247 def declare_argument(self, env, arg):
1248 if arg.type.is_void:
1249 error(arg.pos, "Invalid use of 'void'")
1250 elif not arg.type.is_complete() and not arg.type.is_array:
1251 error(arg.pos,
1252 "Argument type '%s' is incomplete" % arg.type)
1253 return env.declare_arg(arg.name, arg.type, arg.pos)
1255 def generate_wrapper_functions(self, code):
1256 pass
1258 def generate_execution_code(self, code):
1259 # Evaluate and store argument default values
1260 for arg in self.args:
1261 default = arg.default
1262 if default:
1263 if not default.is_literal:
1264 default.generate_evaluation_code(code)
1265 default.make_owned_reference(code)
1266 code.putln(
1267 "%s = %s;" % (
1268 arg.default_entry.cname,
1269 default.result_as(arg.default_entry.type)))
1270 if default.is_temp and default.type.is_pyobject:
1271 code.putln("%s = 0;" % default.result())
1272 default.free_temps(code)
1273 code.put_var_giveref(arg.default_entry)
1274 # For Python class methods, create and store function object
1275 if self.assmt:
1276 self.assmt.generate_execution_code(code)
1278 #
1279 # Special code for the __getbuffer__ function
1280 #
1281 def getbuffer_init(self, code):
1282 info = self.local_scope.arg_entries[1].cname
1283 # Python 3.0 betas have a bug in memoryview which makes it call
1284 # getbuffer with a NULL parameter. For now we work around this;
1285 # the following line should be removed when this bug is fixed.
1286 code.putln("if (%s == NULL) return 0;" % info)
1287 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1288 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1290 def getbuffer_error_cleanup(self, code):
1291 info = self.local_scope.arg_entries[1].cname
1292 code.put_gotref("%s->obj" % info)
1293 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1294 (info, info))
1296 def getbuffer_normal_cleanup(self, code):
1297 info = self.local_scope.arg_entries[1].cname
1298 code.putln("if (%s->obj == Py_None) {" % info)
1299 code.put_gotref("Py_None")
1300 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1301 code.putln("}")
1303 class CFuncDefNode(FuncDefNode):
1304 # C function definition.
1305 #
1306 # modifiers ['inline']
1307 # visibility 'private' or 'public' or 'extern'
1308 # base_type CBaseTypeNode
1309 # declarator CDeclaratorNode
1310 # body StatListNode
1311 # api boolean
1312 # decorators [DecoratorNode] list of decorators
1313 #
1314 # with_gil boolean Acquire GIL around body
1315 # type CFuncType
1316 # py_func wrapper for calling from Python
1317 # overridable whether or not this is a cpdef function
1318 # inline_in_pxd whether this is an inline function in a pxd file
1320 child_attrs = ["base_type", "declarator", "body", "py_func"]
1322 inline_in_pxd = False
1323 decorators = None
1324 directive_locals = {}
1326 def unqualified_name(self):
1327 return self.entry.name
1329 def analyse_declarations(self, env):
1330 directive_locals = self.directive_locals = env.directives['locals']
1331 base_type = self.base_type.analyse(env)
1332 # The 2 here is because we need both function and argument names.
1333 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1334 if not type.is_cfunction:
1335 error(self.pos,
1336 "Suite attached to non-function declaration")
1337 # Remember the actual type according to the function header
1338 # written here, because the type in the symbol table entry
1339 # may be different if we're overriding a C method inherited
1340 # from the base type of an extension type.
1341 self.type = type
1342 type.is_overridable = self.overridable
1343 declarator = self.declarator
1344 while not hasattr(declarator, 'args'):
1345 declarator = declarator.base
1346 self.args = declarator.args
1347 for formal_arg, type_arg in zip(self.args, type.args):
1348 formal_arg.type = type_arg.type
1349 formal_arg.name = type_arg.name
1350 formal_arg.cname = type_arg.cname
1351 name = name_declarator.name
1352 cname = name_declarator.cname
1353 self.entry = env.declare_cfunction(
1354 name, type, self.pos,
1355 cname = cname, visibility = self.visibility,
1356 defining = self.body is not None,
1357 api = self.api, modifiers = self.modifiers)
1358 self.entry.inline_func_in_pxd = self.inline_in_pxd
1359 self.return_type = type.return_type
1361 if self.overridable and not env.is_module_scope:
1362 if len(self.args) < 1 or not self.args[0].type.is_pyobject:
1363 # An error will be produced in the cdef function
1364 self.overridable = False
1366 if self.overridable:
1367 import ExprNodes
1368 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1369 self.py_func = DefNode(pos = self.pos,
1370 name = self.entry.name,
1371 args = self.args,
1372 star_arg = None,
1373 starstar_arg = None,
1374 doc = self.doc,
1375 body = py_func_body,
1376 is_wrapper = 1)
1377 self.py_func.is_module_scope = env.is_module_scope
1378 self.py_func.analyse_declarations(env)
1379 self.entry.as_variable = self.py_func.entry
1380 # Reset scope entry the above cfunction
1381 env.entries[name] = self.entry
1382 self.py_func.interned_attr_cname = env.intern_identifier(
1383 self.py_func.entry.name)
1384 if not env.is_module_scope or Options.lookup_module_cpdef:
1385 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1386 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1388 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1389 import ExprNodes
1390 args = self.type.args
1391 if omit_optional_args:
1392 args = args[:len(args) - self.type.optional_arg_count]
1393 arg_names = [arg.name for arg in args]
1394 if is_module_scope:
1395 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1396 else:
1397 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1398 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1399 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1400 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)
1401 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1403 def declare_arguments(self, env):
1404 for arg in self.type.args:
1405 if not arg.name:
1406 error(arg.pos, "Missing argument name")
1407 self.declare_argument(env, arg)
1409 def need_gil_acquisition(self, lenv):
1410 type = self.type
1411 with_gil = self.type.with_gil
1412 if type.nogil and not with_gil:
1413 if type.return_type.is_pyobject:
1414 error(self.pos,
1415 "Function with Python return type cannot be declared nogil")
1416 for entry in lenv.var_entries + lenv.temp_entries:
1417 if entry.type.is_pyobject:
1418 error(self.pos, "Function declared nogil has Python locals or temporaries")
1419 return with_gil
1421 def analyse_expressions(self, env):
1422 self.local_scope.directives = env.directives
1423 self.analyse_default_values(env)
1424 if self.py_func is not None:
1425 self.py_func.analyse_expressions(env)
1427 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1428 arg_decls = []
1429 type = self.type
1430 visibility = self.entry.visibility
1431 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1432 arg_decls.append(arg.declaration_code())
1433 if with_dispatch and self.overridable:
1434 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1435 if type.optional_arg_count and with_opt_args:
1436 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1437 if type.has_varargs:
1438 arg_decls.append("...")
1439 if not arg_decls:
1440 arg_decls = ["void"]
1441 if cname is None:
1442 cname = self.entry.func_cname
1443 entity = type.function_header_code(cname, ', '.join(arg_decls))
1444 if visibility == 'public':
1445 dll_linkage = "DL_EXPORT"
1446 else:
1447 dll_linkage = None
1448 header = self.return_type.declaration_code(entity,
1449 dll_linkage = dll_linkage)
1450 if visibility == 'extern':
1451 storage_class = "%s " % Naming.extern_c_macro
1452 elif visibility == 'public':
1453 storage_class = ""
1454 else:
1455 storage_class = "static "
1456 code.putln("%s%s %s {" % (
1457 storage_class,
1458 ' '.join(self.modifiers).upper(), # macro forms
1459 header))
1461 def generate_argument_declarations(self, env, code):
1462 for arg in self.args:
1463 if arg.default:
1464 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1466 def generate_keyword_list(self, code):
1467 pass
1469 def generate_argument_parsing_code(self, env, code):
1470 i = 0
1471 if self.type.optional_arg_count:
1472 code.putln('if (%s) {' % Naming.optional_args_cname)
1473 for arg in self.args:
1474 if arg.default:
1475 # FIXME: simple name prefixing doesn't work when
1476 # argument name mangling is in place
1477 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1478 declarator = arg.declarator
1479 while not hasattr(declarator, 'name'):
1480 declarator = declarator.base
1481 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1482 i += 1
1483 for _ in range(self.type.optional_arg_count):
1484 code.putln('}')
1485 code.putln('}')
1487 def generate_argument_conversion_code(self, code):
1488 pass
1490 def generate_argument_type_tests(self, code):
1491 # Generate type tests for args whose type in a parent
1492 # class is a supertype of the declared type.
1493 for arg in self.type.args:
1494 if arg.needs_type_test:
1495 self.generate_arg_type_test(arg, code)
1497 def generate_arg_type_test(self, arg, code):
1498 # Generate type test for one argument.
1499 if arg.type.typeobj_is_available():
1500 typeptr_cname = arg.type.typeptr_cname
1501 arg_code = "((PyObject *)%s)" % arg.cname
1502 code.putln(
1503 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1504 arg_code,
1505 typeptr_cname,
1506 not arg.not_none,
1507 arg.name,
1508 type.is_builtin_type,
1509 code.error_goto(arg.pos)))
1510 else:
1511 error(arg.pos, "Cannot test type of extern C class "
1512 "without type object name specification")
1514 def error_value(self):
1515 if self.return_type.is_pyobject:
1516 return "0"
1517 else:
1518 #return None
1519 return self.entry.type.exception_value
1521 def caller_will_check_exceptions(self):
1522 return self.entry.type.exception_check
1524 def generate_wrapper_functions(self, code):
1525 # If the C signature of a function has changed, we need to generate
1526 # wrappers to put in the slots here.
1527 k = 0
1528 entry = self.entry
1529 func_type = entry.type
1530 while entry.prev_entry is not None:
1531 k += 1
1532 entry = entry.prev_entry
1533 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1534 code.putln()
1535 self.generate_function_header(code,
1536 0,
1537 with_dispatch = entry.type.is_overridable,
1538 with_opt_args = entry.type.optional_arg_count,
1539 cname = entry.func_cname)
1540 if not self.return_type.is_void:
1541 code.put('return ')
1542 args = self.type.args
1543 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1544 if entry.type.is_overridable:
1545 arglist.append(Naming.skip_dispatch_cname)
1546 elif func_type.is_overridable:
1547 arglist.append('0')
1548 if entry.type.optional_arg_count:
1549 arglist.append(Naming.optional_args_cname)
1550 elif func_type.optional_arg_count:
1551 arglist.append('NULL')
1552 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1553 code.putln('}')
1556 class PyArgDeclNode(Node):
1557 # Argument which must be a Python object (used
1558 # for * and ** arguments).
1559 #
1560 # name string
1561 # entry Symtab.Entry
1562 child_attrs = []
1565 class DecoratorNode(Node):
1566 # A decorator
1567 #
1568 # decorator NameNode or CallNode
1569 child_attrs = ['decorator']
1572 class DefNode(FuncDefNode):
1573 # A Python function definition.
1574 #
1575 # name string the Python name of the function
1576 # decorators [DecoratorNode] list of decorators
1577 # args [CArgDeclNode] formal arguments
1578 # star_arg PyArgDeclNode or None * argument
1579 # starstar_arg PyArgDeclNode or None ** argument
1580 # doc EncodedString or None
1581 # body StatListNode
1582 #
1583 # The following subnode is constructed internally
1584 # when the def statement is inside a Python class definition.
1585 #
1586 # assmt AssignmentNode Function construction/assignment
1588 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1590 assmt = None
1591 num_kwonly_args = 0
1592 num_required_kw_args = 0
1593 reqd_kw_flags_cname = "0"
1594 is_wrapper = 0
1595 decorators = None
1596 entry = None
1599 def __init__(self, pos, **kwds):
1600 FuncDefNode.__init__(self, pos, **kwds)
1601 k = rk = r = 0
1602 for arg in self.args:
1603 if arg.kw_only:
1604 k += 1
1605 if not arg.default:
1606 rk += 1
1607 if not arg.default:
1608 r += 1
1609 self.num_kwonly_args = k
1610 self.num_required_kw_args = rk
1611 self.num_required_args = r
1613 def as_cfunction(self, cfunc=None, scope=None):
1614 if self.star_arg:
1615 error(self.star_arg.pos, "cdef function cannot have star argument")
1616 if self.starstar_arg:
1617 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1618 if cfunc is None:
1619 cfunc_args = []
1620 for formal_arg in self.args:
1621 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1622 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1623 cname = None,
1624 type = py_object_type,
1625 pos = formal_arg.pos))
1626 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1627 args = cfunc_args,
1628 has_varargs = False,
1629 exception_value = None,
1630 exception_check = False,
1631 nogil = False,
1632 with_gil = False,
1633 is_overridable = True)
1634 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1635 else:
1636 cfunc_type = cfunc.type
1637 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1638 error(self.pos, "wrong number of arguments")
1639 error(declarator.pos, "previous declaration here")
1640 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1641 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1642 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1643 formal_arg.type = type_arg.type
1644 formal_arg.name_declarator = name_declarator
1645 import ExprNodes
1646 if cfunc_type.exception_value is None:
1647 exception_value = None
1648 else:
1649 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1650 declarator = CFuncDeclaratorNode(self.pos,
1651 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1652 args = self.args,
1653 has_varargs = False,
1654 exception_check = cfunc_type.exception_check,
1655 exception_value = exception_value,
1656 with_gil = cfunc_type.with_gil,
1657 nogil = cfunc_type.nogil)
1658 return CFuncDefNode(self.pos,
1659 modifiers = [],
1660 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1661 declarator = declarator,
1662 body = self.body,
1663 doc = self.doc,
1664 overridable = cfunc_type.is_overridable,
1665 type = cfunc_type,
1666 with_gil = cfunc_type.with_gil,
1667 nogil = cfunc_type.nogil,
1668 visibility = 'private',
1669 api = False,
1670 directive_locals = getattr(cfunc, 'directive_locals', {}))
1672 def analyse_declarations(self, env):
1673 directive_locals = self.directive_locals = env.directives['locals']
1674 for arg in self.args:
1675 if hasattr(arg, 'name'):
1676 type = arg.type
1677 name_declarator = None
1678 else:
1679 base_type = arg.base_type.analyse(env)
1680 name_declarator, type = \
1681 arg.declarator.analyse(base_type, env)
1682 arg.name = name_declarator.name
1683 if arg.name in directive_locals:
1684 type_node = directive_locals[arg.name]
1685 other_type = type_node.analyse_as_type(env)
1686 if other_type is None:
1687 error(type_node.pos, "Not a type")
1688 elif (type is not PyrexTypes.py_object_type
1689 and not type.same_as(other_type)):
1690 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1691 error(type_node.pos, "Previous declaration here")
1692 else:
1693 type = other_type
1694 if name_declarator and name_declarator.cname:
1695 error(self.pos,
1696 "Python function argument cannot have C name specification")
1697 arg.type = type.as_argument_type()
1698 arg.hdr_type = None
1699 arg.needs_conversion = 0
1700 arg.needs_type_test = 0
1701 arg.is_generic = 1
1702 if arg.not_none and not arg.type.is_extension_type:
1703 error(self.pos,
1704 "Only extension type arguments can have 'not None'")
1705 self.declare_pyfunction(env)
1706 self.analyse_signature(env)
1707 self.return_type = self.entry.signature.return_type()
1709 def analyse_signature(self, env):
1710 any_type_tests_needed = 0
1711 if self.entry.is_special:
1712 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1713 elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
1714 # Use the simpler calling signature for zero- and one-argument functions.
1715 if self.entry.signature is TypeSlots.pyfunction_signature:
1716 if len(self.args) == 0:
1717 self.entry.signature = TypeSlots.pyfunction_noargs
1718 elif len(self.args) == 1:
1719 if self.args[0].default is None and not self.args[0].kw_only:
1720 self.entry.signature = TypeSlots.pyfunction_onearg
1721 elif self.entry.signature is TypeSlots.pymethod_signature:
1722 if len(self.args) == 1:
1723 self.entry.signature = TypeSlots.unaryfunc
1724 elif len(self.args) == 2:
1725 if self.args[1].default is None and not self.args[1].kw_only:
1726 self.entry.signature = TypeSlots.ibinaryfunc
1727 sig = self.entry.signature
1728 nfixed = sig.num_fixed_args()
1729 for i in range(nfixed):
1730 if i < len(self.args):
1731 arg = self.args[i]
1732 arg.is_generic = 0
1733 if sig.is_self_arg(i):
1734 arg.is_self_arg = 1
1735 arg.hdr_type = arg.type = env.parent_type
1736 arg.needs_conversion = 0
1737 else:
1738 arg.hdr_type = sig.fixed_arg_type(i)
1739 if not arg.type.same_as(arg.hdr_type):
1740 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1741 arg.needs_type_test = 1
1742 any_type_tests_needed = 1
1743 else:
1744 arg.needs_conversion = 1
1745 if arg.needs_conversion:
1746 arg.hdr_cname = Naming.arg_prefix + arg.name
1747 else:
1748 arg.hdr_cname = Naming.var_prefix + arg.name
1749 else:
1750 self.bad_signature()
1751 return
1752 if nfixed < len(self.args):
1753 if not sig.has_generic_args:
1754 self.bad_signature()
1755 for arg in self.args:
1756 if arg.is_generic and \
1757 (arg.type.is_extension_type or arg.type.is_builtin_type):
1758 arg.needs_type_test = 1
1759 any_type_tests_needed = 1
1760 if any_type_tests_needed:
1761 env.use_utility_code(arg_type_test_utility_code)
1763 def bad_signature(self):
1764 sig = self.entry.signature
1765 expected_str = "%d" % sig.num_fixed_args()
1766 if sig.has_generic_args:
1767 expected_str = expected_str + " or more"
1768 name = self.name
1769 if name.startswith("__") and name.endswith("__"):
1770 desc = "Special method"
1771 else:
1772 desc = "Method"
1773 error(self.pos,
1774 "%s %s has wrong number of arguments "
1775 "(%d declared, %s expected)" % (
1776 desc, self.name, len(self.args), expected_str))
1778 def signature_has_nongeneric_args(self):
1779 argcount = len(self.args)
1780 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1781 return 0
1782 return 1
1784 def signature_has_generic_args(self):
1785 return self.entry.signature.has_generic_args
1787 def declare_pyfunction(self, env):
1788 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1789 name = self.name
1790 entry = env.lookup_here(self.name)
1791 if entry and entry.type.is_cfunction and not self.is_wrapper:
1792 warning(self.pos, "Overriding cdef method with def method.", 5)
1793 entry = env.declare_pyfunction(self.name, self.pos)
1794 self.entry = entry
1795 prefix = env.scope_prefix
1796 entry.func_cname = \
1797 Naming.pyfunc_prefix + prefix + name
1798 entry.pymethdef_cname = \
1799 Naming.pymethdef_prefix + prefix + name
1800 if Options.docstrings:
1801 entry.doc = embed_position(self.pos, self.doc)
1802 entry.doc_cname = \
1803 Naming.funcdoc_prefix + prefix + name
1804 else:
1805 entry.doc = None
1807 def declare_arguments(self, env):
1808 for arg in self.args:
1809 if not arg.name:
1810 error(arg.pos, "Missing argument name")
1811 if arg.needs_conversion:
1812 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1813 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1814 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1815 if arg.type.is_pyobject:
1816 arg.entry.init = "0"
1817 arg.entry.init_to_none = 0
1818 else:
1819 arg.entry = self.declare_argument(env, arg)
1820 arg.entry.used = 1
1821 arg.entry.is_self_arg = arg.is_self_arg
1822 if not arg.is_self_arg:
1823 arg.name_entry = env.get_string_const(
1824 arg.name, identifier = True)
1825 env.add_py_string(arg.name_entry, identifier = True)
1826 if arg.hdr_type:
1827 if arg.is_self_arg or \
1828 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1829 arg.entry.is_declared_generic = 1
1830 self.declare_python_arg(env, self.star_arg)
1831 self.declare_python_arg(env, self.starstar_arg)
1833 def declare_python_arg(self, env, arg):
1834 if arg:
1835 entry = env.declare_var(arg.name,
1836 PyrexTypes.py_object_type, arg.pos)
1837 entry.used = 1
1838 entry.init = "0"
1839 entry.init_to_none = 0
1840 entry.xdecref_cleanup = 1
1841 arg.entry = entry
1842 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1844 def analyse_expressions(self, env):
1845 self.local_scope.directives = env.directives
1846 self.analyse_default_values(env)
1847 if env.is_py_class_scope:
1848 self.synthesize_assignment_node(env)
1850 def synthesize_assignment_node(self, env):
1851 import ExprNodes
1852 self.assmt = SingleAssignmentNode(self.pos,
1853 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1854 rhs = ExprNodes.UnboundMethodNode(self.pos,
1855 class_cname = env.class_obj_cname,
1856 function = ExprNodes.PyCFunctionNode(self.pos,
1857 pymethdef_cname = self.entry.pymethdef_cname)))
1858 self.assmt.analyse_declarations(env)
1859 self.assmt.analyse_expressions(env)
1861 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1862 arg_code_list = []
1863 sig = self.entry.signature
1864 if sig.has_dummy_arg:
1865 arg_code_list.append(
1866 "PyObject *%s" % Naming.self_cname)
1867 for arg in self.args:
1868 if not arg.is_generic:
1869 if arg.is_self_arg:
1870 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1871 else:
1872 arg_code_list.append(
1873 arg.hdr_type.declaration_code(arg.hdr_cname))
1874 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1875 arg_code_list.append("PyObject *unused")
1876 if sig.has_generic_args:
1877 arg_code_list.append(
1878 "PyObject *%s, PyObject *%s"
1879 % (Naming.args_cname, Naming.kwds_cname))
1880 arg_code = ", ".join(arg_code_list)
1881 dc = self.return_type.declaration_code(self.entry.func_cname)
1882 header = "static %s(%s)" % (dc, arg_code)
1883 code.putln("%s; /*proto*/" % header)
1884 if proto_only:
1885 return
1886 if self.entry.doc and Options.docstrings:
1887 docstr = self.entry.doc
1888 if not isinstance(docstr, str):
1889 docstr = docstr.utf8encode()
1890 code.putln(
1891 'static char %s[] = "%s";' % (
1892 self.entry.doc_cname,
1893 split_docstring(escape_byte_string(docstr))))
1894 if with_pymethdef:
1895 code.put(
1896 "static PyMethodDef %s = " %
1897 self.entry.pymethdef_cname)
1898 code.put_pymethoddef(self.entry, ";")
1899 code.putln("%s {" % header)
1901 def generate_argument_declarations(self, env, code):
1902 for arg in self.args:
1903 if arg.is_generic: # or arg.needs_conversion:
1904 if arg.needs_conversion:
1905 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1906 else:
1907 code.put_var_declaration(arg.entry)
1909 def generate_keyword_list(self, code):
1910 if self.signature_has_generic_args() and \
1911 self.signature_has_nongeneric_args():
1912 code.put(
1913 "static PyObject **%s[] = {" %
1914 Naming.pykwdlist_cname)
1915 for arg in self.args:
1916 if arg.is_generic:
1917 code.put('&%s,' % arg.name_entry.pystring_cname)
1918 code.putln("0};")
1920 def generate_argument_parsing_code(self, env, code):
1921 # Generate PyArg_ParseTuple call for generic
1922 # arguments, if any.
1923 if self.entry.signature.has_dummy_arg:
1924 # get rid of unused argument warning
1925 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1927 old_error_label = code.new_error_label()
1928 our_error_label = code.error_label
1929 end_label = code.new_label("argument_unpacking_done")
1931 has_kwonly_args = self.num_kwonly_args > 0
1932 has_star_or_kw_args = self.star_arg is not None \
1933 or self.starstar_arg is not None or has_kwonly_args
1935 for arg in self.args:
1936 if not arg.type.is_pyobject and arg.type.from_py_function is None:
1937 arg.type.create_from_py_utility_code(env)
1939 if not self.signature_has_generic_args():
1940 if has_star_or_kw_args:
1941 error(self.pos, "This method cannot have * or keyword arguments")
1942 self.generate_argument_conversion_code(code)
1944 elif not self.signature_has_nongeneric_args():
1945 # func(*args) or func(**kw) or func(*args, **kw)
1946 self.generate_stararg_copy_code(code)
1948 else:
1949 positional_args = []
1950 kw_only_args = []
1951 default_seen = 0
1952 for arg in self.args:
1953 arg_entry = arg.entry
1954 if arg.is_generic:
1955 if arg.default:
1956 default_seen = 1
1957 if not arg.is_self_arg:
1958 if arg.kw_only:
1959 kw_only_args.append(arg)
1960 else:
1961 positional_args.append(arg)
1962 elif arg.kw_only:
1963 kw_only_args.append(arg)
1964 default_seen = 1
1965 elif default_seen:
1966 error(arg.pos, "Non-default argument following default argument")
1967 elif not arg.is_self_arg:
1968 positional_args.append(arg)
1970 self.generate_tuple_and_keyword_parsing_code(
1971 positional_args, kw_only_args, end_label, code)
1973 code.error_label = old_error_label
1974 if code.label_used(our_error_label):
1975 if not code.label_used(end_label):
1976 code.put_goto(end_label)
1977 code.put_label(our_error_label)
1978 if has_star_or_kw_args:
1979 self.generate_arg_decref(self.star_arg, code)
1980 if self.starstar_arg:
1981 if self.starstar_arg.entry.xdecref_cleanup:
1982 code.put_var_xdecref(self.starstar_arg.entry)
1983 else:
1984 code.put_var_decref(self.starstar_arg.entry)
1985 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1986 code.putln("return %s;" % self.error_value())
1987 if code.label_used(end_label):
1988 code.put_label(end_label)
1990 def generate_arg_assignment(self, arg, item, code):
1991 if arg.type.is_pyobject:
1992 if arg.is_generic:
1993 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1994 code.putln("%s = %s;" % (arg.entry.cname, item))
1995 else:
1996 func = arg.type.from_py_function
1997 if func:
1998 code.putln("%s = %s(%s); %s" % (
1999 arg.entry.cname,
2000 func,
2001 item,
2002 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
2003 else:
2004 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
2006 def generate_arg_xdecref(self, arg, code):
2007 if arg:
2008 code.put_var_xdecref(arg.entry)
2010 def generate_arg_decref(self, arg, code):
2011 if arg:
2012 code.put_var_decref(arg.entry)
2014 def generate_stararg_copy_code(self, code):
2015 if not self.star_arg:
2016 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2017 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
2018 Naming.args_cname)
2019 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2020 self.name.utf8encode(), Naming.args_cname, self.error_value()))
2021 code.putln("}")
2023 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2025 if self.starstar_arg:
2026 if self.star_arg:
2027 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2028 else:
2029 kwarg_check = "%s" % Naming.kwds_cname
2030 else:
2031 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2032 Naming.kwds_cname, Naming.kwds_cname)
2033 code.putln(
2034 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2035 kwarg_check, Naming.kwds_cname, self.name,
2036 bool(self.starstar_arg), self.error_value()))
2038 if self.starstar_arg:
2039 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2040 self.starstar_arg.entry.cname,
2041 Naming.kwds_cname,
2042 Naming.kwds_cname))
2043 code.putln("if (unlikely(!%s)) return %s;" % (
2044 self.starstar_arg.entry.cname, self.error_value()))
2045 self.starstar_arg.entry.xdecref_cleanup = 0
2046 code.put_gotref(self.starstar_arg.entry.cname)
2049 if self.star_arg:
2050 code.put_incref(Naming.args_cname, py_object_type)
2051 code.putln("%s = %s;" % (
2052 self.star_arg.entry.cname,
2053 Naming.args_cname))
2054 self.star_arg.entry.xdecref_cleanup = 0
2056 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2057 kw_only_args, success_label, code):
2058 argtuple_error_label = code.new_label("argtuple_error")
2060 min_positional_args = self.num_required_args - self.num_required_kw_args
2061 if len(self.args) > 0 and self.args[0].is_self_arg:
2062 min_positional_args -= 1
2063 max_positional_args = len(positional_args)
2064 has_fixed_positional_count = not self.star_arg and \
2065 min_positional_args == max_positional_args
2067 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2068 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2069 if self.num_required_kw_args:
2070 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2072 if self.starstar_arg or self.star_arg:
2073 self.generate_stararg_init_code(max_positional_args, code)
2075 # --- optimised code when we receive keyword arguments
2076 if self.num_required_kw_args:
2077 likely_hint = "likely"
2078 else:
2079 likely_hint = "unlikely"
2080 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2081 self.generate_keyword_unpacking_code(
2082 min_positional_args, max_positional_args,
2083 has_fixed_positional_count,
2084 positional_args, kw_only_args, argtuple_error_label, code)
2086 # --- optimised code when we do not receive any keyword arguments
2087 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2088 # Python raises arg tuple related errors first, so we must
2089 # check the length here
2090 if min_positional_args == max_positional_args and not self.star_arg:
2091 compare = '!='
2092 else:
2093 compare = '<'
2094 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2095 Naming.args_cname, compare, min_positional_args))
2096 code.put_goto(argtuple_error_label)
2098 if self.num_required_kw_args:
2099 # pure error case: keywords required but not passed
2100 if max_positional_args > min_positional_args and not self.star_arg:
2101 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2102 Naming.args_cname, max_positional_args))
2103 code.put_goto(argtuple_error_label)
2104 code.putln('} else {')
2105 for i, arg in enumerate(kw_only_args):
2106 if not arg.default:
2107 # required keyword-only argument missing
2108 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2109 self.name.utf8encode(),
2110 arg.name_entry.pystring_cname))
2111 code.putln(code.error_goto(self.pos))
2112 break
2114 elif min_positional_args == max_positional_args:
2115 # parse the exact number of positional arguments from the
2116 # args tuple
2117 code.putln('} else {')
2118 for i, arg in enumerate(positional_args):
2119 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2120 self.generate_arg_assignment(arg, item, code)
2121 self.generate_arg_default_assignments(code)
2123 else:
2124 # parse the positional arguments from the variable length
2125 # args tuple
2126 code.putln('} else {')
2127 self.generate_arg_default_assignments(code)
2128 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2129 if self.star_arg:
2130 code.putln('default:')
2131 reversed_args = list(enumerate(positional_args))[::-1]
2132 for i, arg in reversed_args:
2133 if i >= min_positional_args-1:
2134 if min_positional_args > 1:
2135 code.putln('case %2d:' % (i+1)) # pure code beautification
2136 else:
2137 code.put('case %2d: ' % (i+1))
2138 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2139 self.generate_arg_assignment(arg, item, code)
2140 if min_positional_args == 0:
2141 code.put('case 0: ')
2142 code.putln('break;')
2143 if self.star_arg:
2144 if min_positional_args:
2145 for i in range(min_positional_args-1, -1, -1):
2146 code.putln('case %2d:' % i)
2147 code.put_goto(argtuple_error_label)
2148 else:
2149 code.put('default: ')
2150 code.put_goto(argtuple_error_label)
2151 code.putln('}')
2153 code.putln('}')
2155 if code.label_used(argtuple_error_label):
2156 code.put_goto(success_label)
2157 code.put_label(argtuple_error_label)
2158 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2159 self.name.utf8encode(), has_fixed_positional_count,
2160 min_positional_args, max_positional_args,
2161 Naming.args_cname))
2162 code.putln(code.error_goto(self.pos))
2164 def generate_arg_default_assignments(self, code):
2165 for arg in self.args:
2166 if arg.is_generic and arg.default:
2167 code.putln(
2168 "%s = %s;" % (
2169 arg.entry.cname,
2170 arg.default_result_code))
2172 def generate_stararg_init_code(self, max_positional_args, code):
2173 if self.starstar_arg:
2174 self.starstar_arg.entry.xdecref_cleanup = 0
2175 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2176 self.starstar_arg.entry.cname,
2177 self.starstar_arg.entry.cname,
2178 self.error_value()))
2179 code.put_gotref(self.starstar_arg.entry.cname)
2180 if self.star_arg:
2181 self.star_arg.entry.xdecref_cleanup = 0
2182 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2183 Naming.args_cname,
2184 max_positional_args))
2185 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2186 self.star_arg.entry.cname, Naming.args_cname,
2187 max_positional_args, Naming.args_cname))
2188 code.put_gotref(self.star_arg.entry.cname)
2189 if self.starstar_arg:
2190 code.putln("")
2191 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2192 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2193 code.putln('return %s;' % self.error_value())
2194 code.putln('}')
2195 else:
2196 code.putln("if (unlikely(!%s)) return %s;" % (
2197 self.star_arg.entry.cname, self.error_value()))
2198 code.putln('} else {')
2199 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2200 code.put_incref(Naming.empty_tuple, py_object_type)
2201 code.putln('}')
2203 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2204 has_fixed_positional_count, positional_args,
2205 kw_only_args, argtuple_error_label, code):
2206 all_args = tuple(positional_args) + tuple(kw_only_args)
2207 max_args = len(all_args)
2209 default_args = []
2210 for i, arg in enumerate(all_args):
2211 if arg.default and arg.type.is_pyobject:
2212 default_value = arg.default_result_code
2213 if arg.type is not PyrexTypes.py_object_type:
2214 default_value = "(PyObject*)"+default_value
2215 default_args.append((i, default_value))
2217 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2218 Naming.kwds_cname)
2219 # it looks funny to separate the init-to-0 from setting the
2220 # default value, but C89 needs this
2221 code.putln("PyObject* values[%d] = {%s};" % (
2222 max_args, ','.join(['0']*max_args)))
2223 for i, default_value in default_args:
2224 code.putln('values[%d] = %s;' % (i, default_value))
2226 # parse the tuple and check that it's not too long
2227 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2228 if self.star_arg:
2229 code.putln('default:')
2230 for i in range(max_positional_args-1, -1, -1):
2231 code.put('case %2d: ' % (i+1))
2232 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2233 i, Naming.args_cname, i))
2234 code.putln('case 0: break;')
2235 if not self.star_arg:
2236 code.put('default: ') # more arguments than allowed
2237 code.put_goto(argtuple_error_label)
2238 code.putln('}')
2240 # now fill up the positional/required arguments with values
2241 # from the kw dict
2242 if self.num_required_args or max_positional_args > 0:
2243 last_required_arg = -1
2244 for i, arg in enumerate(all_args):
2245 if not arg.default:
2246 last_required_arg = i
2247 if last_required_arg < max_positional_args:
2248 last_required_arg = max_positional_args-1
2249 num_required_args = self.num_required_args
2250 if max_positional_args > 0:
2251 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2252 for i, arg in enumerate(all_args[:last_required_arg+1]):
2253 if max_positional_args > 0 and i <= max_positional_args:
2254 if self.star_arg and i == max_positional_args:
2255 code.putln('default:')
2256 else:
2257 code.putln('case %2d:' % i)
2258 if arg.default:
2259 if arg.kw_only:
2260 # handled separately below
2261 continue
2262 code.putln('if (kw_args > %d) {' % num_required_args)
2263 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2264 Naming.kwds_cname, arg.name_entry.pystring_cname))
2265 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2266 code.putln('}')
2267 else:
2268 num_required_args -= 1
2269 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2270 i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2271 code.putln('if (likely(values[%d])) kw_args--;' % i);
2272 if i < min_positional_args:
2273 if i == 0:
2274 # special case: we know arg 0 is missing
2275 code.put('else ')
2276 code.put_goto(argtuple_error_label)
2277 else:
2278 # print the correct number of values (args or
2279 # kwargs) that were passed into positional
2280 # arguments up to this point
2281 code.putln('else {')
2282 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2283 self.name.utf8encode(), has_fixed_positional_count,
2284 min_positional_args, max_positional_args, i))
2285 code.putln(code.error_goto(self.pos))
2286 code.putln('}')
2287 elif arg.kw_only:
2288 code.putln('else {')
2289 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2290 self.name.utf8encode(), arg.name_entry.pystring_cname))
2291 code.putln(code.error_goto(self.pos))
2292 code.putln('}')
2293 if max_positional_args > 0:
2294 code.putln('}')
2296 if kw_only_args and not self.starstar_arg:
2297 # unpack optional keyword-only arguments
2298 # checking for interned strings in a dict is faster than iterating
2299 # but it's too likely that we must iterate if we expect **kwargs
2300 optional_args = []
2301 for i, arg in enumerate(all_args[max_positional_args:]):
2302 if not arg.kw_only or not arg.default:
2303 continue
2304 optional_args.append((i+max_positional_args, arg))
2305 if optional_args:
2306 # this mimics an unrolled loop so that we can "break" out of it
2307 code.putln('while (kw_args > 0) {')
2308 code.putln('PyObject* value;')
2309 for i, arg in optional_args:
2310 code.putln(
2311 'value = PyDict_GetItem(%s, %s);' % (
2312 Naming.kwds_cname, arg.name_entry.pystring_cname))
2313 code.putln(
2314 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2315 code.putln('break;')
2316 code.putln('}')
2318 code.putln('if (unlikely(kw_args > 0)) {')
2319 # non-positional/-required kw args left in dict: default args,
2320 # kw-only args, **kwargs or error
2321 #
2322 # This is sort of a catch-all: except for checking required
2323 # arguments, this will always do the right thing for unpacking
2324 # keyword arguments, so that we can concentrate on optimising
2325 # common cases above.
2326 if max_positional_args == 0:
2327 pos_arg_count = "0"
2328 elif self.star_arg:
2329 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2330 Naming.args_cname, max_positional_args,
2331 Naming.args_cname, max_positional_args))
2332 pos_arg_count = "used_pos_args"
2333 else:
2334 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2335 code.globalstate.use_utility_code(parse_keywords_utility_code)
2336 code.put(
2337 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2338 Naming.kwds_cname,
2339 Naming.pykwdlist_cname,
2340 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2341 pos_arg_count,
2342 self.name.utf8encode()))
2343 code.putln(code.error_goto(self.pos))
2344 code.putln('}')
2346 # convert arg values to their final type and assign them
2347 for i, arg in enumerate(all_args):
2348 if arg.default and not arg.type.is_pyobject:
2349 code.putln("if (values[%d]) {" % i)
2350 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2351 if arg.default and not arg.type.is_pyobject:
2352 code.putln('} else {')
2353 code.putln(
2354 "%s = %s;" % (
2355 arg.entry.cname,
2356 arg.default_result_code))
2357 code.putln('}')
2359 def generate_argument_conversion_code(self, code):
2360 # Generate code to convert arguments from
2361 # signature type to declared type, if needed.
2362 for arg in self.args:
2363 if arg.needs_conversion:
2364 self.generate_arg_conversion(arg, code)
2366 def generate_arg_conversion(self, arg, code):
2367 # Generate conversion code for one argument.
2368 old_type = arg.hdr_type
2369 new_type = arg.type
2370 if old_type.is_pyobject:
2371 if arg.default:
2372 code.putln("if (%s) {" % arg.hdr_cname)
2373 else:
2374 code.putln("assert(%s); {" % arg.hdr_cname)
2375 self.generate_arg_conversion_from_pyobject(arg, code)
2376 code.putln("}")
2377 elif new_type.is_pyobject:
2378 self.generate_arg_conversion_to_pyobject(arg, code)
2379 else:
2380 if new_type.assignable_from(old_type):
2381 code.putln(
2382 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2383 else:
2384 error(arg.pos,
2385 "Cannot convert 1 argument from '%s' to '%s'" %
2386 (old_type, new_type))
2388 def generate_arg_conversion_from_pyobject(self, arg, code):
2389 new_type = arg.type
2390 func = new_type.from_py_function
2391 # copied from CoerceFromPyTypeNode
2392 if func:
2393 code.putln("%s = %s(%s); %s" % (
2394 arg.entry.cname,
2395 func,
2396 arg.hdr_cname,
2397 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2398 else:
2399 error(arg.pos,
2400 "Cannot convert Python object argument to type '%s'"
2401 % new_type)
2403 def generate_arg_conversion_to_pyobject(self, arg, code):
2404 old_type = arg.hdr_type
2405 func = old_type.to_py_function
2406 if func:
2407 code.putln("%s = %s(%s); %s" % (
2408 arg.entry.cname,
2409 func,
2410 arg.hdr_cname,
2411 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2412 code.put_var_gotref(arg.entry)
2413 else:
2414 error(arg.pos,
2415 "Cannot convert argument of type '%s' to Python object"
2416 % old_type)
2418 def generate_argument_type_tests(self, code):
2419 # Generate type tests for args whose signature
2420 # type is PyObject * and whose declared type is
2421 # a subtype thereof.
2422 for arg in self.args:
2423 if arg.needs_type_test:
2424 self.generate_arg_type_test(arg, code)
2426 def generate_arg_type_test(self, arg, code):
2427 # Generate type test for one argument.
2428 if arg.type.typeobj_is_available():
2429 typeptr_cname = arg.type.typeptr_cname
2430 arg_code = "((PyObject *)%s)" % arg.entry.cname
2431 code.putln(
2432 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2433 arg_code,
2434 typeptr_cname,
2435 not arg.not_none,
2436 arg.name,
2437 arg.type.is_builtin_type,
2438 code.error_goto(arg.pos)))
2439 else:
2440 error(arg.pos, "Cannot test type of extern C class "
2441 "without type object name specification")
2443 def error_value(self):
2444 return self.entry.signature.error_value
2446 def caller_will_check_exceptions(self):
2447 return 1
2449 class OverrideCheckNode(StatNode):
2450 # A Node for dispatching to the def method if it
2451 # is overriden.
2452 #
2453 # py_func
2454 #
2455 # args
2456 # func_temp
2457 # body
2459 child_attrs = ['body']
2461 body = None
2463 def analyse_expressions(self, env):
2464 self.args = env.arg_entries
2465 if self.py_func.is_module_scope:
2466 first_arg = 0
2467 else:
2468 first_arg = 1
2469 import ExprNodes
2470 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2471 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2472 call_node = ExprNodes.SimpleCallNode(self.pos,
2473 function=self.func_node,
2474 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2475 self.body = ReturnStatNode(self.pos, value=call_node)
2476 self.body.analyse_expressions(env)
2478 def generate_execution_code(self, code):
2479 # Check to see if we are an extension type
2480 if self.py_func.is_module_scope:
2481 self_arg = "((PyObject *)%s)" % Naming.module_cname
2482 else:
2483 self_arg = "((PyObject *)%s)" % self.args[0].cname
2484 code.putln("/* Check if called by wrapper */")
2485 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2486 code.putln("/* Check if overriden in Python */")
2487 if self.py_func.is_module_scope:
2488 code.putln("else {")
2489 else:
2490 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2491 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2492 # need to get attribute manually--scope would return cdef method
2493 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2494 code.put_gotref(self.func_node.py_result())
2495 is_builtin_function_or_method = 'PyCFunction_Check(%s)' % self.func_node.result()
2496 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2497 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2498 self.body.generate_execution_code(code)
2499 code.putln('}')
2500 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2501 code.putln("}")
2503 class ClassDefNode(StatNode, BlockNode):
2504 pass
2506 class PyClassDefNode(ClassDefNode):
2507 # A Python class definition.
2508 #
2509 # name EncodedString Name of the class
2510 # doc string or None
2511 # body StatNode Attribute definition code
2512 # entry Symtab.Entry
2513 # scope PyClassScope
2514 #
2515 # The following subnodes are constructed internally:
2516 #
2517 # dict DictNode Class dictionary
2518 # classobj ClassNode Class object
2519 # target NameNode Variable to assign class object to
2521 child_attrs = ["body", "dict", "classobj", "target"]
2523 def __init__(self, pos, name, bases, doc, body):
2524 StatNode.__init__(self, pos)
2525 self.name = name
2526 self.doc = doc
2527 self.body = body
2528 import ExprNodes
2529 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2530 if self.doc and Options.docstrings:
2531 doc = embed_position(self.pos, self.doc)
2532 doc_node = ExprNodes.StringNode(pos, value = doc)
2533 else:
2534 doc_node = None
2535 self.classobj = ExprNodes.ClassNode(pos, name = name,
2536 bases = bases, dict = self.dict, doc = doc_node)
2537 self.target = ExprNodes.NameNode(pos, name = name)
2539 def as_cclass(self):
2540 """
2541 Return this node as if it were declared as an extension class
2542 """
2543 bases = self.classobj.bases.args
2544 if len(bases) == 0:
2545 base_class_name = None
2546 base_class_module = None
2547 elif len(bases) == 1:
2548 base = bases[0]
2549 path = []
2550 from ExprNodes import AttributeNode, NameNode
2551 while isinstance(base, AttributeNode):
2552 path.insert(0, base.attribute)
2553 base = base.obj
2554 if isinstance(base, NameNode):
2555 path.insert(0, base.name)
2556 base_class_name = path[-1]
2557 if len(path) > 1:
2558 base_class_module = u'.'.join(path[:-1])
2559 else:
2560 base_class_module = None
2561 else:
2562 error(self.classobj.bases.args.pos, "Invalid base class")
2563 else:
2564 error(self.classobj.bases.args.pos, "C class may only have one base class")
2565 return None
2567 return CClassDefNode(self.pos,
2568 visibility = 'private',
2569 module_name = None,
2570 class_name = self.name,
2571 base_class_module = base_class_module,
2572 base_class_name = base_class_name,
2573 body = self.body,
2574 in_pxd = False,
2575 doc = self.doc)
2577 def create_scope(self, env):
2578 genv = env
2579 while env.is_py_class_scope or env.is_c_class_scope:
2580 env = env.outer_scope
2581 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2582 return cenv
2584 def analyse_declarations(self, env):
2585 self.target.analyse_target_declaration(env)
2586 cenv = self.create_scope(env)
2587 cenv.directives = env.directives
2588 cenv.class_obj_cname = self.target.entry.cname
2589 self.body.analyse_declarations(cenv)
2591 def analyse_expressions(self, env):
2592 self.dict.analyse_expressions(env)
2593 self.classobj.analyse_expressions(env)
2594 genv = env.global_scope()
2595 cenv = self.scope
2596 cenv.class_dict_cname = self.dict.result()
2597 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2598 self.body.analyse_expressions(cenv)
2599 self.target.analyse_target_expression(env, self.classobj)
2600 self.dict.release_temp(env)
2601 #self.classobj.release_temp(env)
2602 #self.target.release_target_temp(env)
2604 def generate_function_definitions(self, env, code):
2605 self.generate_py_string_decls(self.scope, code)
2606 self.body.generate_function_definitions(self.scope, code)
2608 def generate_execution_code(self, code):
2609 self.dict.generate_evaluation_code(code)
2610 self.classobj.generate_evaluation_code(code)
2611 self.body.generate_execution_code(code)
2612 self.target.generate_assignment_code(self.classobj, code)
2613 self.dict.generate_disposal_code(code)
2614 self.dict.free_temps(code)
2617 class CClassDefNode(ClassDefNode):
2618 # An extension type definition.
2619 #
2620 # visibility 'private' or 'public' or 'extern'
2621 # typedef_flag boolean
2622 # api boolean
2623 # module_name string or None For import of extern type objects
2624 # class_name string Unqualified name of class
2625 # as_name string or None Name to declare as in this scope
2626 # base_class_module string or None Module containing the base class
2627 # base_class_name string or None Name of the base class
2628 # objstruct_name string or None Specified C name of object struct
2629 # typeobj_name string or None Specified C name of type object
2630 # in_pxd boolean Is in a .pxd file
2631 # doc string or None
2632 # body StatNode or None
2633 # entry Symtab.Entry
2634 # base_type PyExtensionType or None
2635 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2636 # buffer_defaults_pos
2638 child_attrs = ["body"]
2639 buffer_defaults_node = None
2640 buffer_defaults_pos = None
2641 typedef_flag = False
2642 api = False
2643 objstruct_name = None
2644 typeobj_name = None
2646 def analyse_declarations(self, env):
2647 #print "CClassDefNode.analyse_declarations:", self.class_name
2648 #print "...visibility =", self.visibility
2649 #print "...module_name =", self.module_name
2651 import Buffer
2652 if self.buffer_defaults_node:
2653 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2654 env, [], self.buffer_defaults_node,
2655 need_complete=False)
2656 else:
2657 buffer_defaults = None
2659 if env.in_cinclude and not self.objstruct_name:
2660 error(self.pos, "Object struct name specification required for "
2661 "C class defined in 'extern from' block")
2662 self.base_type = None
2663 # Now that module imports are cached, we need to
2664 # import the modules for extern classes.
2665 if self.module_name:
2666 self.module = None
2667 for module in env.cimported_modules:
2668 if module.name == self.module_name:
2669 self.module = module
2670 if self.module is None:
2671 self.module = ModuleScope(self.module_name, None, env.context)
2672 self.module.has_extern_class = 1
2673 env.add_imported_module(self.module)
2675 if self.base_class_name:
2676 if self.base_class_module:
2677 base_class_scope = env.find_module(self.base_class_module, self.pos)
2678 else:
2679 base_class_scope = env
2680 if self.base_class_name == 'object':
2681 # extension classes are special and don't need to inherit from object
2682 if base_class_scope is None or base_class_scope.lookup('object') is None:
2683 self.base_class_name = None
2684 self.base_class_module = None
2685 base_class_scope = None
2686 if base_class_scope:
2687 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2688 if base_class_entry:
2689 if not base_class_entry.is_type:
2690 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2691 elif not base_class_entry.type.is_extension_type:
2692 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2693 elif not base_class_entry.type.is_complete():
2694 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2695 else:
2696 self.base_type = base_class_entry.type
2697 has_body = self.body is not None
2698 if self.module_name and self.visibility != 'extern':
2699 module_path = self.module_name.split(".")
2700 home_scope = env.find_imported_module(module_path, self.pos)
2701 if not home_scope:
2702 return
2703 else:
2704 home_scope = env
2706 if self.visibility == 'extern':
2707 if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
2708 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
2710 self.entry = home_scope.declare_c_class(
2711 name = self.class_name,
2712 pos = self.pos,
2713 defining = has_body and self.in_pxd,
2714 implementing = has_body and not self.in_pxd,
2715 module_name = self.module_name,
2716 base_type = self.base_type,
2717 objstruct_cname = self.objstruct_name,
2718 typeobj_cname = self.typeobj_name,
2719 visibility = self.visibility,
2720 typedef_flag = self.typedef_flag,
2721 api = self.api,
2722 buffer_defaults = buffer_defaults)
2723 if home_scope is not env and self.visibility == 'extern':
2724 env.add_imported_entry(self.class_name, self.entry, pos)
2725 scope = self.entry.type.scope
2726 if scope is not None:
2727 scope.directives = env.directives
2729 if self.doc and Options.docstrings:
2730 scope.doc = embed_position(self.pos, self.doc)
2732 if has_body:
2733 self.body.analyse_declarations(scope)
2734 if self.in_pxd:
2735 scope.defined = 1
2736 else:
2737 scope.implemented = 1
2738 env.allocate_vtable_names(self.entry)
2740 def analyse_expressions(self, env):
2741 if self.body:
2742 scope = self.entry.type.scope
2743 self.body.analyse_expressions(scope)
2745 def generate_function_definitions(self, env, code):
2746 self.generate_py_string_decls(self.entry.type.scope, code)
2747 if self.body:
2748 self.body.generate_function_definitions(
2749 self.entry.type.scope, code)
2751 def generate_execution_code(self, code):
2752 # This is needed to generate evaluation code for
2753 # default values of method arguments.
2754 if self.body:
2755 self.body.generate_execution_code(code)
2757 def annotate(self, code):
2758 if self.body:
2759 self.body.annotate(code)
2762 class PropertyNode(StatNode):
2763 # Definition of a property in an extension type.
2764 #
2765 # name string
2766 # doc EncodedString or None Doc string
2767 # body StatListNode
2769 child_attrs = ["body"]
2771 def analyse_declarations(self, env):
2772 entry = env.declare_property(self.name, self.doc, self.pos)
2773 if entry:
2774 if self.doc and Options.docstrings:
2775 doc_entry = env.get_string_const(
2776 self.doc, identifier = False)
2777 entry.doc_cname = doc_entry.cname
2778 entry.scope.directives = env.directives
2779 self.body.analyse_declarations(entry.scope)
2781 def analyse_expressions(self, env):
2782 self.body.analyse_expressions(env)
2784 def generate_function_definitions(self, env, code):
2785 self.body.generate_function_definitions(env, code)
2787 def generate_execution_code(self, code):
2788 pass
2790 def annotate(self, code):
2791 self.body.annotate(code)
2794 class GlobalNode(StatNode):
2795 # Global variable declaration.
2796 #
2797 # names [string]
2799 child_attrs = []
2801 def analyse_declarations(self, env):
2802 for name in self.names:
2803 env.declare_global(name, self.pos)
2805 def analyse_expressions(self, env):
2806 pass
2808 def generate_execution_code(self, code):
2809 pass
2812 class ExprStatNode(StatNode):
2813 # Expression used as a statement.
2814 #
2815 # expr ExprNode
2817 child_attrs = ["expr"]
2819 def analyse_declarations(self, env):
2820 import ExprNodes
2821 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2822 func = self.expr.function.as_cython_attribute()
2823 if func == u'declare':
2824 args, kwds = self.expr.explicit_args_kwds()
2825 if len(args):
2826 error(self.expr.pos, "Variable names must be specified.")
2827 for var, type_node in kwds.key_value_pairs:
2828 type = type_node.analyse_as_type(env)
2829 if type is None:
2830 error(type_node.pos, "Unknown type")
2831 else:
2832 env.declare_var(var.value, type, var.pos, is_cdef = True)
2833 self.__class__ = PassStatNode
2835 def analyse_expressions(self, env):
2836 self.expr.analyse_expressions(env)
2837 self.expr.release_temp(env)
2839 def generate_execution_code(self, code):
2840 self.expr.generate_evaluation_code(code)
2841 if not self.expr.is_temp and self.expr.result():
2842 code.putln("%s;" % self.expr.result())
2843 self.expr.generate_disposal_code(code)
2844 self.expr.free_temps(code)
2846 def annotate(self, code):
2847 self.expr.annotate(code)
2850 class AssignmentNode(StatNode):
2851 # Abstract base class for assignment nodes.
2852 #
2853 # The analyse_expressions and generate_execution_code
2854 # phases of assignments are split into two sub-phases
2855 # each, to enable all the right hand sides of a
2856 # parallel assignment to be evaluated before assigning
2857 # to any of the left hand sides.
2859 def analyse_expressions(self, env):
2860 self.analyse_types(env)
2861 self.allocate_rhs_temps(env)
2862 self.allocate_lhs_temps(env)
2864 # def analyse_expressions(self, env):
2865 # self.analyse_expressions_1(env)
2866 # self.analyse_expressions_2(env)
2868 def generate_execution_code(self, code):
2869 self.generate_rhs_evaluation_code(code)
2870 self.generate_assignment_code(code)
2873 class SingleAssignmentNode(AssignmentNode):
2874 # The simplest case:
2875 #
2876 # a = b
2877 #
2878 # lhs ExprNode Left hand side
2879 # rhs ExprNode Right hand side
2880 # first bool Is this guaranteed the first assignment to lhs?
2882 child_attrs = ["lhs", "rhs"]
2883 first = False
2884 declaration_only = False
2886 def analyse_declarations(self, env):
2887 import ExprNodes
2889 # handle declarations of the form x = cython.foo()
2890 if isinstance(self.rhs, ExprNodes.CallNode):
2891 func_name = self.rhs.function.as_cython_attribute()
2892 if func_name:
2893 args, kwds = self.rhs.explicit_args_kwds()
2895 if func_name in ['declare', 'typedef']:
2896 if len(args) > 2 or kwds is not None:
2897 error(rhs.pos, "Can only declare one type at a time.")
2898 return
2899 type = args[0].analyse_as_type(env)
2900 if type is None:
2901 error(args[0].pos, "Unknown type")
2902 return
2903 lhs = self.lhs
2904 if func_name == 'declare':
2905 if isinstance(lhs, ExprNodes.NameNode):
2906 vars = [(lhs.name, lhs.pos)]
2907 elif isinstance(lhs, ExprNodes.TupleNode):
2908 vars = [(var.name, var.pos) for var in lhs.args]
2909 else:
2910 error(lhs.pos, "Invalid declaration")
2911 return
2912 for var, pos in vars:
2913 env.declare_var(var, type, pos, is_cdef = True)
2914 if len(args) == 2:
2915 # we have a value
2916 self.rhs = args[1]
2917 else:
2918 self.declaration_only = True
2919 else:
2920 self.declaration_only = True
2921 if not isinstance(lhs, ExprNodes.NameNode):
2922 error(lhs.pos, "Invalid declaration.")
2923 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2925 elif func_name in ['struct', 'union']:
2926 self.declaration_only = True
2927 if len(args) > 0 or kwds is None:
2928 error(rhs.pos, "Struct or union members must be given by name.")
2929 return
2930 members = []
2931 for member, type_node in kwds.key_value_pairs:
2932 type = type_node.analyse_as_type(env)
2933 if type is None:
2934 error(type_node.pos, "Unknown type")
2935 else:
2936 members.append((member.value, type, member.pos))
2937 if len(members) < len(kwds.key_value_pairs):
2938 return
2939 if not isinstance(self.lhs, ExprNodes.NameNode):
2940 error(self.lhs.pos, "Invalid declaration.")
2941 name = self.lhs.name
2942 scope = StructOrUnionScope(name)
2943 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2944 for member, type, pos in members:
2945 scope.declare_var(member, type, pos)
2947 if self.declaration_only:
2948 return
2949 else:
2950 self.lhs.analyse_target_declaration(env)
2952 def analyse_types(self, env, use_temp = 0):
2953 self.rhs.analyse_types(env)
2954 self.lhs.analyse_target_types(env)
2955 self.lhs.gil_assignment_check(env)
2956 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2957 if use_temp:
2958 self.rhs = self.rhs.coerce_to_temp(env)
2960 def allocate_rhs_temps(self, env):
2961 self.rhs.allocate_temps(env)
2963 def allocate_lhs_temps(self, env):
2964 self.lhs.allocate_target_temps(env, self.rhs)
2965 #self.lhs.release_target_temp(env)
2966 #self.rhs.release_temp(env)
2968 def generate_rhs_evaluation_code(self, code):
2969 self.rhs.generate_evaluation_code(code)
2971 def generate_assignment_code(self, code):
2972 self.lhs.generate_assignment_code(self.rhs, code)
2974 def annotate(self, code):
2975 self.lhs.annotate(code)
2976 self.rhs.annotate(code)
2979 class CascadedAssignmentNode(AssignmentNode):
2980 # An assignment with multiple left hand sides:
2981 #
2982 # a = b = c
2983 #
2984 # lhs_list [ExprNode] Left hand sides
2985 # rhs ExprNode Right hand sides
2986 #
2987 # Used internally:
2988 #
2989 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2991 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2992 coerced_rhs_list = None
2994 def analyse_declarations(self, env):
2995 for lhs in self.lhs_list:
2996 lhs.analyse_target_declaration(env)
2998 def analyse_types(self, env, use_temp = 0):
2999 self.rhs.analyse_types(env)
3000 if use_temp:
3001 self.rhs = self.rhs.coerce_to_temp(env)
3002 else:
3003 self.rhs = self.rhs.coerce_to_simple(env)
3004 from ExprNodes import CloneNode
3005 self.coerced_rhs_list = []
3006 for lhs in self.lhs_list:
3007 lhs.analyse_target_types(env)
3008 lhs.gil_assignment_check(env)
3009 rhs = CloneNode(self.rhs)
3010 rhs = rhs.coerce_to(lhs.type, env)
3011 self.coerced_rhs_list.append(rhs)
3013 def allocate_rhs_temps(self, env):
3014 self.rhs.allocate_temps(env)
3016 def allocate_lhs_temps(self, env):
3017 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
3018 rhs.allocate_temps(env)
3019 lhs.allocate_target_temps(env, rhs)
3020 #lhs.release_target_temp(env)
3021 #rhs.release_temp(env)
3022 self.rhs.release_temp(env)
3024 def generate_rhs_evaluation_code(self, code):
3025 self.rhs.generate_evaluation_code(code)
3027 def generate_assignment_code(self, code):
3028 for i in range(len(self.lhs_list)):
3029 lhs = self.lhs_list[i]
3030 rhs = self.coerced_rhs_list[i]
3031 rhs.generate_evaluation_code(code)
3032 lhs.generate_assignment_code(rhs, code)
3033 # Assignment has disposed of the cloned RHS
3034 self.rhs.generate_disposal_code(code)
3035 self.rhs.free_temps(code)
3037 def annotate(self, code):
3038 for i in range(len(self.lhs_list)):
3039 lhs = self.lhs_list[i].annotate(code)
3040 rhs = self.coerced_rhs_list[i].annotate(code)
3041 self.rhs.annotate(code)
3044 class ParallelAssignmentNode(AssignmentNode):
3045 # A combined packing/unpacking assignment:
3046 #
3047 # a, b, c = d, e, f
3048 #
3049 # This has been rearranged by the parser into
3050 #
3051 # a = d ; b = e ; c = f
3052 #
3053 # but we must evaluate all the right hand sides
3054 # before assigning to any of the left hand sides.
3055 #
3056 # stats [AssignmentNode] The constituent assignments
3058 child_attrs = ["stats"]
3060 def analyse_declarations(self, env):
3061 for stat in self.stats:
3062 stat.analyse_declarations(env)
3064 def analyse_expressions(self, env):
3065 for stat in self.stats:
3066 stat.analyse_types(env, use_temp = 1)
3067 stat.allocate_rhs_temps(env)
3068 for stat in self.stats:
3069 stat.allocate_lhs_temps(env)
3071 # def analyse_expressions(self, env):
3072 # for stat in self.stats:
3073 # stat.analyse_expressions_1(env, use_temp = 1)
3074 # for stat in self.stats:
3075 # stat.analyse_expressions_2(env)
3077 def generate_execution_code(self, code):
3078 for stat in self.stats:
3079 stat.generate_rhs_evaluation_code(code)
3080 for stat in self.stats:
3081 stat.generate_assignment_code(code)
3083 def annotate(self, code):
3084 for stat in self.stats:
3085 stat.annotate(code)
3088 class InPlaceAssignmentNode(AssignmentNode):
3089 # An in place arithmatic operand:
3090 #
3091 # a += b
3092 # a -= b
3093 # ...
3094 #
3095 # lhs ExprNode Left hand side
3096 # rhs ExprNode Right hand side
3097 # op char one of "+-*/%^&|"
3098 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3099 #
3100 # This code is a bit tricky because in order to obey Python
3101 # semantics the sub-expressions (e.g. indices) of the lhs must
3102 # not be evaluated twice. So we must re-use the values calculated
3103 # in evaluation phase for the assignment phase as well.
3104 # Fortunately, the type of the lhs node is fairly constrained
3105 # (it must be a NameNode, AttributeNode, or IndexNode).
3107 child_attrs = ["lhs", "rhs"]
3108 dup = None
3110 def analyse_declarations(self, env):
3111 self.lhs.analyse_target_declaration(env)
3113 def analyse_types(self, env):
3114 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3115 self.rhs.analyse_types(env)
3116 self.lhs.analyse_target_types(env)
3117 if Options.incref_local_binop and self.dup.type.is_pyobject:
3118 self.dup = self.dup.coerce_to_temp(env)
3120 def allocate_rhs_temps(self, env):
3121 import ExprNodes
3122 if self.lhs.type.is_pyobject:
3123 self.rhs = self.rhs.coerce_to_pyobject(env)
3124 elif self.rhs.type.is_pyobject:
3125 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3126 if self.lhs.type.is_pyobject:
3127 self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
3128 self.result_value.allocate_temps(env)
3129 # if use_temp:
3130 # self.rhs = self.rhs.coerce_to_temp(env)
3131 self.rhs.allocate_temps(env)
3132 self.dup.allocate_subexpr_temps(env)
3133 self.dup.allocate_temp(env)
3135 def allocate_lhs_temps(self, env):
3136 self.lhs.allocate_target_temps(env, self.rhs)
3137 # self.lhs.release_target_temp(env)
3138 self.dup.release_temp(env)
3139 if self.dup.is_temp:
3140 self.dup.release_subexpr_temps(env)
3141 # self.rhs.release_temp(env)
3142 if self.lhs.type.is_pyobject:
3143 self.result_value.release_temp(env)
3145 def generate_execution_code(self, code):
3146 import ExprNodes
3147 self.rhs.generate_evaluation_code(code)
3148 self.dup.generate_subexpr_evaluation_code(code)
3149 if isinstance(self.dup, ExprNodes.NewTempExprNode):
3150 # This is because we're manually messing with subexpr nodes
3151 if self.dup.is_temp:
3152 self.dup.allocate_temp_result(code)
3153 # self.dup.generate_result_code is run only if it is not buffer access
3154 if self.operator == "**":
3155 extra = ", Py_None"
3156 else:
3157 extra = ""
3158 if self.lhs.type.is_pyobject:
3159 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3160 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3161 self.dup.generate_result_code(code)
3162 code.putln(
3163 "%s = %s(%s, %s%s); %s" % (
3164 self.result_value.result(),
3165 self.py_operation_function(),
3166 self.dup.py_result(),
3167 self.rhs.py_result(),
3168 extra,
3169 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3170 code.put_gotref(self.result_value.py_result())
3171 self.result_value.generate_evaluation_code(code) # May be a type check...
3172 self.rhs.generate_disposal_code(code)
3173 self.rhs.free_temps(code)
3174 self.dup.generate_disposal_code(code)
3175 self.dup.free_temps(code)
3176 self.lhs.generate_assignment_code(self.result_value, code)
3177 else:
3178 c_op = self.operator
3179 if c_op == "//":
3180 c_op = "/"
3181 elif c_op == "**":
3182 error(self.pos, "No C inplace power operator")
3183 elif self.lhs.type.is_complex and not code.globalstate.directives['c99_complex']:
3184 error(self.pos, "Inplace operators not implemented for complex types.")
3186 # have to do assignment directly to avoid side-effects
3187 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3188 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3189 else:
3190 self.dup.generate_result_code(code)
3191 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3192 self.rhs.generate_disposal_code(code)
3193 self.rhs.free_temps(code)
3194 if self.dup.is_temp:
3195 self.dup.generate_subexpr_disposal_code(code)
3196 self.dup.free_subexpr_temps(code)
3198 def create_dup_node(self, env):
3199 import ExprNodes
3200 self.dup = self.lhs
3201 self.dup.analyse_types(env)
3202 if isinstance(self.lhs, ExprNodes.NameNode):
3203 target_lhs = ExprNodes.NameNode(self.dup.pos,
3204 name = self.dup.name,
3205 is_temp = self.dup.is_temp,
3206 entry = self.dup.entry)
3207 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3208 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3209 obj = ExprNodes.CloneNode(self.lhs.obj),
3210 attribute = self.dup.attribute,
3211 is_temp = self.dup.is_temp)
3212 elif isinstance(self.lhs, ExprNodes.IndexNode):
3213 if self.lhs.index:
3214 index = ExprNodes.CloneNode(self.lhs.index)
3215 else:
3216 index = None
3217 if self.lhs.indices:
3218 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3219 else:
3220 indices = []
3221 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3222 base = ExprNodes.CloneNode(self.dup.base),
3223 index = index,
3224 indices = indices,
3225 is_temp = self.dup.is_temp)
3226 else:
3227 assert False
3228 self.lhs = target_lhs
3229 return self.dup
3231 def py_operation_function(self):
3232 return self.py_functions[self.operator]
3234 py_functions = {
3235 "|": "PyNumber_InPlaceOr",
3236 "^": "PyNumber_InPlaceXor",
3237 "&": "PyNumber_InPlaceAnd",
3238 "+": "PyNumber_InPlaceAdd",
3239 "-": "PyNumber_InPlaceSubtract",
3240 "*": "PyNumber_InPlaceMultiply",
3241 "/": "PyNumber_InPlaceDivide",
3242 "%": "PyNumber_InPlaceRemainder",
3243 "<<": "PyNumber_InPlaceLshift",
3244 ">>": "PyNumber_InPlaceRshift",
3245 "**": "PyNumber_InPlacePower",
3246 "//": "PyNumber_InPlaceFloorDivide",
3247 }
3249 def annotate(self, code):
3250 self.lhs.annotate(code)
3251 self.rhs.annotate(code)
3252 self.dup.annotate(code)
3255 class PrintStatNode(StatNode):
3256 # print statement
3257 #
3258 # arg_tuple TupleNode
3259 # append_newline boolean
3261 child_attrs = ["arg_tuple"]
3263 def analyse_expressions(self, env):
3264 self.arg_tuple.analyse_expressions(env)
3265 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3266 self.arg_tuple.release_temp(env)
3267 env.use_utility_code(printing_utility_code)
3268 if len(self.arg_tuple.args) == 1 and self.append_newline:
3269 env.use_utility_code(printing_one_utility_code)
3270 self.gil_check(env)
3272 gil_message = "Python print statement"
3274 def generate_execution_code(self, code):
3275 if len(self.arg_tuple.args) == 1 and self.append_newline:
3276 arg = self.arg_tuple.args[0]
3277 arg.generate_evaluation_code(code)
3279 code.putln(
3280 "if (__Pyx_PrintOne(%s) < 0) %s" % (
3281 arg.py_result(),
3282 code.error_goto(self.pos)))
3283 arg.generate_disposal_code(code)
3284 arg.free_temps(code)
3285 else:
3286 self.arg_tuple.generate_evaluation_code(code)
3287 code.putln(
3288 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3289 self.arg_tuple.py_result(),
3290 self.append_newline,
3291 code.error_goto(self.pos)))
3292 self.arg_tuple.generate_disposal_code(code)
3293 self.arg_tuple.free_temps(code)
3295 def annotate(self, code):
3296 self.arg_tuple.annotate(code)
3299 class ExecStatNode(StatNode):
3300 # exec statement
3301 #
3302 # args [ExprNode]
3304 child_attrs = ["args"]
3306 def analyse_expressions(self, env):
3307 for i, arg in enumerate(self.args):
3308 arg.analyse_expressions(env)
3309 arg = arg.coerce_to_pyobject(env)
3310 arg.release_temp(env)
3311 self.args[i] = arg
3312 self.temp_result = env.allocate_temp_pyobject()
3313 env.release_temp(self.temp_result)
3314 env.use_utility_code(Builtin.pyexec_utility_code)
3315 self.gil_check(env)
3317 gil_message = "Python exec statement"
3319 def generate_execution_code(self, code):
3320 args = []
3321 for arg in self.args:
3322 arg.generate_evaluation_code(code)
3323 args.append( arg.py_result() )
3324 args = tuple(args + ['0', '0'][:3-len(args)])
3325 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3326 (self.temp_result,) + args))
3327 for arg in self.args:
3328 arg.generate_disposal_code(code)
3329 arg.free_temps(code)
3330 code.putln(
3331 code.error_goto_if_null(self.temp_result, self.pos))
3332 code.put_gotref(self.temp_result)
3333 code.put_decref_clear(self.temp_result, py_object_type)
3335 def annotate(self, code):
3336 for arg in self.args:
3337 arg.annotate(code)
3340 class DelStatNode(StatNode):
3341 # del statement
3342 #
3343 # args [ExprNode]
3345 child_attrs = ["args"]
3347 def analyse_declarations(self, env):
3348 for arg in self.args:
3349 arg.analyse_target_declaration(env)
3351 def analyse_expressions(self, env):
3352 for arg in self.args:
3353 arg.analyse_target_expression(env, None)
3354 if arg.type.is_pyobject:
3355 self.gil_check(env)
3356 else:
3357 error(arg.pos, "Deletion of non-Python object")
3358 #arg.release_target_temp(env)
3360 gil_message = "Deleting Python object"
3362 def generate_execution_code(self, code):
3363 for arg in self.args:
3364 if arg.type.is_pyobject:
3365 arg.generate_deletion_code(code)
3366 # else error reported earlier
3368 def annotate(self, code):
3369 for arg in self.args:
3370 arg.annotate(code)
3373 class PassStatNode(StatNode):
3374 # pass statement
3376 child_attrs = []
3378 def analyse_expressions(self, env):
3379 pass
3381 def generate_execution_code(self, code):
3382 pass
3385 class BreakStatNode(StatNode):
3387 child_attrs = []
3389 def analyse_expressions(self, env):
3390 pass
3392 def generate_execution_code(self, code):
3393 if not code.break_label:
3394 error(self.pos, "break statement not inside loop")
3395 else:
3396 code.put_goto(code.break_label)
3399 class ContinueStatNode(StatNode):
3401 child_attrs = []
3403 def analyse_expressions(self, env):
3404 pass
3406 def generate_execution_code(self, code):
3407 if code.funcstate.in_try_finally:
3408 error(self.pos, "continue statement inside try of try...finally")
3409 elif not code.continue_label:
3410 error(self.pos, "continue statement not inside loop")
3411 else:
3412 code.put_goto(code.continue_label)
3415 class ReturnStatNode(StatNode):
3416 # return statement
3417 #
3418 # value ExprNode or None
3419 # return_type PyrexType
3420 # temps_in_use [Entry] Temps in use at time of return
3422 child_attrs = ["value"]
3424 def analyse_expressions(self, env):
3425 return_type = env.return_type
3426 self.return_type = return_type
3427 self.temps_in_use = env.temps_in_use()
3428 if not return_type:
3429 error(self.pos, "Return not inside a function body")
3430 return
3431 if self.value:
3432 self.value.analyse_types(env)
3433 if return_type.is_void or return_type.is_returncode:
3434 error(self.value.pos,
3435 "Return with value in void function")
3436 else:
3437 self.value = self.value.coerce_to(env.return_type, env)
3438 self.value.allocate_temps(env)
3439 self.value.release_temp(env)
3440 else:
3441 if (not return_type.is_void
3442 and not return_type.is_pyobject
3443 and not return_type.is_returncode):
3444 error(self.pos, "Return value required")
3445 if return_type.is_pyobject:
3446 self.gil_check(env)
3448 gil_message = "Returning Python object"
3450 def generate_execution_code(self, code):
3451 code.mark_pos(self.pos)
3452 if not self.return_type:
3453 # error reported earlier
3454 return
3455 if self.return_type.is_pyobject:
3456 code.put_xdecref(Naming.retval_cname,
3457 self.return_type)
3458 if self.value:
3459 self.value.generate_evaluation_code(code)
3460 self.value.make_owned_reference(code)
3461 code.putln(
3462 "%s = %s;" % (
3463 Naming.retval_cname,
3464 self.value.result_as(self.return_type)))
3465 self.value.generate_post_assignment_code(code)
3466 self.value.free_temps(code)
3467 else:
3468 if self.return_type.is_pyobject:
3469 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3470 elif self.return_type.is_returncode:
3471 code.putln(
3472 "%s = %s;" % (
3473 Naming.retval_cname,
3474 self.return_type.default_value))
3475 # free temps the old way
3476 for entry in self.temps_in_use:
3477 code.put_var_decref_clear(entry)
3478 # free temps the new way
3479 for cname, type in code.funcstate.temps_holding_reference():
3480 code.put_decref_clear(cname, type)
3481 #code.putln(
3482 # "goto %s;" %
3483 # code.return_label)
3484 code.put_goto(code.return_label)
3486 def annotate(self, code):
3487 if self.value:
3488 self.value.annotate(code)
3491 class RaiseStatNode(StatNode):
3492 # raise statement
3493 #
3494 # exc_type ExprNode or None
3495 # exc_value ExprNode or None
3496 # exc_tb ExprNode or None
3498 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3500 def analyse_expressions(self, env):
3501 if self.exc_type:
3502 self.exc_type.analyse_types(env)
3503 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3504 self.exc_type.allocate_temps(env)
3505 if self.exc_value:
3506 self.exc_value.analyse_types(env)
3507 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3508 self.exc_value.allocate_temps(env)
3509 if self.exc_tb:
3510 self.exc_tb.analyse_types(env)
3511 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3512 self.exc_tb.allocate_temps(env)
3513 if self.exc_type:
3514 self.exc_type.release_temp(env)
3515 if self.exc_value:
3516 self.exc_value.release_temp(env)
3517 if self.exc_tb:
3518 self.exc_tb.release_temp(env)
3519 env.use_utility_code(raise_utility_code)
3520 env.use_utility_code(restore_exception_utility_code)
3521 self.gil_check(env)
3523 gil_message = "Raising exception"
3525 def generate_execution_code(self, code):
3526 if self.exc_type:
3527 self.exc_type.generate_evaluation_code(code)
3528 type_code = self.exc_type.py_result()
3529 else:
3530 type_code = "0"
3531 if self.exc_value:
3532 self.exc_value.generate_evaluation_code(code)
3533 value_code = self.exc_value.py_result()
3534 else:
3535 value_code = "0"
3536 if self.exc_tb:
3537 self.exc_tb.generate_evaluation_code(code)
3538 tb_code = self.exc_tb.py_result()
3539 else:
3540 tb_code = "0"
3541 if self.exc_type or self.exc_value or self.exc_tb:
3542 code.putln(
3543 "__Pyx_Raise(%s, %s, %s);" % (
3544 type_code,
3545 value_code,
3546 tb_code))
3547 else:
3548 code.putln(
3549 "__Pyx_ReRaise();")
3550 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3551 if obj:
3552 obj.generate_disposal_code(code)
3553 obj.free_temps(code)
3554 code.putln(
3555 code.error_goto(self.pos))
3557 def annotate(self, code):
3558 if self.exc_type:
3559 self.exc_type.annotate(code)
3560 if self.exc_value:
3561 self.exc_value.annotate(code)
3562 if self.exc_tb:
3563 self.exc_tb.annotate(code)
3566 class ReraiseStatNode(StatNode):
3568 child_attrs = []
3570 def analyse_expressions(self, env):
3571 self.gil_check(env)
3572 env.use_utility_code(raise_utility_code)
3573 env.use_utility_code(restore_exception_utility_code)
3575 gil_message = "Raising exception"
3577 def generate_execution_code(self, code):
3578 vars = code.funcstate.exc_vars
3579 if vars:
3580 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3581 code.putln(code.error_goto(self.pos))
3582 else:
3583 error(self.pos, "Reraise not inside except clause")
3586 class AssertStatNode(StatNode):
3587 # assert statement
3588 #
3589 # cond ExprNode
3590 # value ExprNode or None
3592 child_attrs = ["cond", "value"]
3594 def analyse_expressions(self, env):
3595 self.cond = self.cond.analyse_boolean_expression(env)
3596 if self.value:
3597 self.value.analyse_types(env)
3598 self.value = self.value.coerce_to_pyobject(env)
3599 self.value.allocate_temps(env)
3600 self.cond.release_temp(env)
3601 if self.value:
3602 self.value.release_temp(env)
3603 self.gil_check(env)
3604 #env.recycle_pending_temps() # TEMPORARY
3606 gil_message = "Raising exception"
3608 def generate_execution_code(self, code):
3609 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3610 self.cond.generate_evaluation_code(code)
3611 code.putln(
3612 "if (unlikely(!%s)) {" %
3613 self.cond.result())
3614 if self.value:
3615 self.value.generate_evaluation_code(code)
3616 code.putln(
3617 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3618 self.value.py_result())
3619 self.value.generate_disposal_code(code)
3620 self.value.free_temps(code)
3621 else:
3622 code.putln(
3623 "PyErr_SetNone(PyExc_AssertionError);")
3624 code.putln(
3625 code.error_goto(self.pos))
3626 code.putln(
3627 "}")
3628 self.cond.generate_disposal_code(code)
3629 self.cond.free_temps(code)
3630 code.putln("#endif")
3632 def annotate(self, code):
3633 self.cond.annotate(code)
3634 if self.value:
3635 self.value.annotate(code)
3638 class IfStatNode(StatNode):
3639 # if statement
3640 #
3641 # if_clauses [IfClauseNode]
3642 # else_clause StatNode or None
3644 child_attrs = ["if_clauses", "else_clause"]
3646 def analyse_control_flow(self, env):
3647 env.start_branching(self.pos)
3648 for if_clause in self.if_clauses:
3649 if_clause.analyse_control_flow(env)
3650 env.next_branch(if_clause.end_pos())
3651 if self.else_clause:
3652 self.else_clause.analyse_control_flow(env)
3653 env.finish_branching(self.end_pos())
3655 def analyse_declarations(self, env):
3656 for if_clause in self.if_clauses:
3657 if_clause.analyse_declarations(env)
3658 if self.else_clause:
3659 self.else_clause.analyse_declarations(env)
3661 def analyse_expressions(self, env):
3662 for if_clause in self.if_clauses:
3663 if_clause.analyse_expressions(env)
3664 if self.else_clause:
3665 self.else_clause.analyse_expressions(env)
3667 def generate_execution_code(self, code):
3668 code.mark_pos(self.pos)
3669 end_label = code.new_label()
3670 for if_clause in self.if_clauses:
3671 if_clause.generate_execution_code(code, end_label)
3672 if self.else_clause:
3673 code.putln("/*else*/ {")
3674 self.else_clause.generate_execution_code(code)
3675 code.putln("}")
3676 code.put_label(end_label)
3678 def annotate(self, code):
3679 for if_clause in self.if_clauses:
3680 if_clause.annotate(code)
3681 if self.else_clause:
3682 self.else_clause.annotate(code)
3685 class IfClauseNode(Node):
3686 # if or elif clause in an if statement
3687 #
3688 # condition ExprNode
3689 # body StatNode
3691 child_attrs = ["condition", "body"]
3693 def analyse_control_flow(self, env):
3694 self.body.analyse_control_flow(env)
3696 def analyse_declarations(self, env):
3697 self.condition.analyse_declarations(env)
3698 self.body.analyse_declarations(env)
3700 def analyse_expressions(self, env):
3701 self.condition = \
3702 self.condition.analyse_temp_boolean_expression(env)
3703 self.condition.release_temp(env)
3704 self.body.analyse_expressions(env)
3706 def generate_execution_code(self, code, end_label):
3707 self.condition.generate_evaluation_code(code)
3708 code.putln(
3709 "if (%s) {" %
3710 self.condition.result())
3711 self.condition.generate_disposal_code(code)
3712 self.condition.free_temps(code)
3713 self.body.generate_execution_code(code)
3714 #code.putln(
3715 # "goto %s;" %
3716 # end_label)
3717 code.put_goto(end_label)
3718 code.putln("}")
3720 def annotate(self, code):
3721 self.condition.annotate(code)
3722 self.body.annotate(code)
3725 class SwitchCaseNode(StatNode):
3726 # Generated in the optimization of an if-elif-else node
3727 #
3728 # conditions [ExprNode]
3729 # body StatNode
3731 child_attrs = ['conditions', 'body']
3733 def generate_execution_code(self, code):
3734 for cond in self.conditions:
3735 code.mark_pos(cond.pos)
3736 code.putln("case %s:" % cond.calculate_result_code())
3737 self.body.generate_execution_code(code)
3738 code.putln("break;")
3740 def annotate(self, code):
3741 for cond in self.conditions:
3742 cond.annotate(code)
3743 self.body.annotate(code)
3745 class SwitchStatNode(StatNode):
3746 # Generated in the optimization of an if-elif-else node
3747 #
3748 # test ExprNode
3749 # cases [SwitchCaseNode]
3750 # else_clause StatNode or None
3752 child_attrs = ['test', 'cases', 'else_clause']
3754 def generate_execution_code(self, code):
3755 code.putln("switch (%s) {" % self.test.calculate_result_code())
3756 for case in self.cases:
3757 case.generate_execution_code(code)
3758 if self.else_clause is not None:
3759 code.putln("default:")
3760 self.else_clause.generate_execution_code(code)
3761 code.putln("break;")
3762 code.putln("}")
3764 def annotate(self, code):
3765 self.test.annotate(code)
3766 for case in self.cases:
3767 case.annotate(code)
3768 if self.else_clause is not None:
3769 self.else_clause.annotate(code)
3771 class LoopNode(object):
3773 def analyse_control_flow(self, env):
3774 env.start_branching(self.pos)
3775 self.body.analyse_control_flow(env)
3776 env.next_branch(self.body.end_pos())
3777 if self.else_clause:
3778 self.else_clause.analyse_control_flow(env)
3779 env.finish_branching(self.end_pos())
3782 class WhileStatNode(LoopNode, StatNode):
3783 # while statement
3784 #
3785 # condition ExprNode
3786 # body StatNode
3787 # else_clause StatNode
3789 child_attrs = ["condition", "body", "else_clause"]
3791 def analyse_declarations(self, env):
3792 self.body.analyse_declarations(env)
3793 if self.else_clause:
3794 self.else_clause.analyse_declarations(env)
3796 def analyse_expressions(self, env):
3797 self.condition = \
3798 self.condition.analyse_temp_boolean_expression(env)
3799 self.condition.release_temp(env)
3800 #env.recycle_pending_temps() # TEMPORARY
3801 self.body.analyse_expressions(env)
3802 if self.else_clause:
3803 self.else_clause.analyse_expressions(env)
3805 def generate_execution_code(self, code):
3806 old_loop_labels = code.new_loop_labels()
3807 code.putln(
3808 "while (1) {")
3809 self.condition.generate_evaluation_code(code)
3810 self.condition.generate_disposal_code(code)
3811 code.putln(
3812 "if (!%s) break;" %
3813 self.condition.result())
3814 self.condition.free_temps(code)
3815 self.body.generate_execution_code(code)
3816 code.put_label(code.continue_label)
3817 code.putln("}")
3818 break_label = code.break_label
3819 code.set_loop_labels(old_loop_labels)
3820 if self.else_clause:
3821 code.putln("/*else*/ {")
3822 self.else_clause.generate_execution_code(code)
3823 code.putln("}")
3824 code.put_label(break_label)
3826 def annotate(self, code):
3827 self.condition.annotate(code)
3828 self.body.annotate(code)
3829 if self.else_clause:
3830 self.else_clause.annotate(code)
3833 def ForStatNode(pos, **kw):
3834 if 'iterator' in kw:
3835 return ForInStatNode(pos, **kw)
3836 else:
3837 return ForFromStatNode(pos, **kw)
3839 class ForInStatNode(LoopNode, StatNode):
3840 # for statement
3841 #
3842 # target ExprNode
3843 # iterator IteratorNode
3844 # body StatNode
3845 # else_clause StatNode
3846 # item NextNode used internally
3848 child_attrs = ["target", "iterator", "body", "else_clause"]
3849 item = None
3851 def analyse_declarations(self, env):
3852 self.target.analyse_target_declaration(env)
3853 self.body.analyse_declarations(env)
3854 if self.else_clause:
3855 self.else_clause.analyse_declarations(env)
3857 def analyse_expressions(self, env):
3858 import ExprNodes
3859 self.target.analyse_target_types(env)
3860 self.iterator.analyse_expressions(env)
3861 self.item = ExprNodes.NextNode(self.iterator, env)
3862 self.item = self.item.coerce_to(self.target.type, env)
3863 self.item.allocate_temps(env)
3864 self.target.allocate_target_temps(env, self.item)
3865 #self.item.release_temp(env)
3866 #self.target.release_target_temp(env)
3867 self.body.analyse_expressions(env)
3868 if self.else_clause:
3869 self.else_clause.analyse_expressions(env)
3870 self.iterator.release_temp(env)
3872 def generate_execution_code(self, code):
3873 old_loop_labels = code.new_loop_labels()
3874 self.iterator.allocate_counter_temp(code)
3875 self.iterator.generate_evaluation_code(code)
3876 code.putln(
3877 "for (;;) {")
3878 self.item.generate_evaluation_code(code)
3879 self.target.generate_assignment_code(self.item, code)
3880 self.body.generate_execution_code(code)
3881 code.put_label(code.continue_label)
3882 code.putln(
3883 "}")
3884 break_label = code.break_label
3885 code.set_loop_labels(old_loop_labels)
3886 if self.else_clause:
3887 code.putln("/*else*/ {")
3888 self.else_clause.generate_execution_code(code)
3889 code.putln("}")
3890 code.put_label(break_label)
3891 self.iterator.release_counter_temp(code)
3892 self.iterator.generate_disposal_code(code)
3893 self.iterator.free_temps(code)
3895 def annotate(self, code):
3896 self.target.annotate(code)
3897 self.iterator.annotate(code)
3898 self.body.annotate(code)
3899 if self.else_clause:
3900 self.else_clause.annotate(code)
3901 self.item.annotate(code)
3904 class ForFromStatNode(LoopNode, StatNode):
3905 # for name from expr rel name rel expr
3906 #
3907 # target NameNode
3908 # bound1 ExprNode
3909 # relation1 string
3910 # relation2 string
3911 # bound2 ExprNode
3912 # step ExprNode or None
3913 # body StatNode
3914 # else_clause StatNode or None
3915 #
3916 # Used internally:
3917 #
3918 # from_range bool
3919 # is_py_target bool
3920 # loopvar_node ExprNode (usually a NameNode or temp node)
3921 # py_loopvar_node PyTempNode or None
3922 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3924 is_py_target = False
3925 loopvar_node = None
3926 py_loopvar_node = None
3927 from_range = False
3929 def analyse_declarations(self, env):
3930 self.target.analyse_target_declaration(env)
3931 self.body.analyse_declarations(env)
3932 if self.else_clause:
3933 self.else_clause.analyse_declarations(env)
3935 def analyse_expressions(self, env):
3936 import ExprNodes
3937 self.target.analyse_target_types(env)
3938 self.bound1.analyse_types(env)
3939 self.bound2.analyse_types(env)
3940 if self.step is not None:
3941 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3942 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3943 self.step.analyse_types(env)
3945 target_type = self.target.type
3946 if self.target.type.is_numeric:
3947 loop_type = self.target.type
3948 else:
3949 loop_type = PyrexTypes.c_int_type
3950 if not self.bound1.type.is_pyobject:
3951 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
3952 if not self.bound2.type.is_pyobject:
3953 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
3954 if self.step is not None and not self.step.type.is_pyobject:
3955 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
3956 self.bound1 = self.bound1.coerce_to(loop_type, env)
3957 self.bound2 = self.bound2.coerce_to(loop_type, env)
3958 if not self.bound2.is_literal:
3959 self.bound2 = self.bound2.coerce_to_temp(env)
3960 if self.step is not None:
3961 self.step = self.step.coerce_to(loop_type, env)
3962 if not self.step.is_literal:
3963 self.step = self.step.coerce_to_temp(env)
3965 target_type = self.target.type
3966 if not (target_type.is_pyobject or target_type.is_numeric):
3967 error(self.target.pos,
3968 "for-from loop variable must be c numeric type or Python object")
3969 if target_type.is_numeric:
3970 self.is_py_target = False
3971 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3972 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3973 self.loopvar_node = self.target
3974 self.py_loopvar_node = None
3975 else:
3976 self.is_py_target = True
3977 c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
3978 c_loopvar_node.allocate_temps(env)
3979 self.loopvar_node = c_loopvar_node
3980 self.py_loopvar_node = \
3981 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3982 self.bound1.allocate_temps(env)
3983 self.bound2.allocate_temps(env)
3984 if self.step is not None:
3985 self.step.allocate_temps(env)
3986 if self.is_py_target:
3987 self.py_loopvar_node.allocate_temps(env)
3988 self.target.allocate_target_temps(env, self.py_loopvar_node)
3989 #self.target.release_target_temp(env)
3990 #self.py_loopvar_node.release_temp(env)
3991 self.body.analyse_expressions(env)
3992 if self.is_py_target:
3993 c_loopvar_node.release_temp(env)
3994 if self.else_clause:
3995 self.else_clause.analyse_expressions(env)
3996 self.bound1.release_temp(env)
3997 self.bound2.release_temp(env)
3998 if self.step is not None:
3999 self.step.release_temp(env)
4001 def generate_execution_code(self, code):
4002 old_loop_labels = code.new_loop_labels()
4003 from_range = self.from_range
4004 self.bound1.generate_evaluation_code(code)
4005 self.bound2.generate_evaluation_code(code)
4006 offset, incop = self.relation_table[self.relation1]
4007 if self.step is not None:
4008 self.step.generate_evaluation_code(code)
4009 step = self.step.result()
4010 incop = "%s=%s" % (incop[0], step)
4011 if from_range:
4012 loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
4013 else:
4014 loopvar_name = self.loopvar_node.result()
4015 code.putln(
4016 "for (%s = %s%s; %s %s %s; %s%s) {" % (
4017 loopvar_name,
4018 self.bound1.result(), offset,
4019 loopvar_name, self.relation2, self.bound2.result(),
4020 loopvar_name, incop))
4021 if self.py_loopvar_node:
4022 self.py_loopvar_node.generate_evaluation_code(code)
4023 self.target.generate_assignment_code(self.py_loopvar_node, code)
4024 elif from_range:
4025 code.putln("%s = %s;" % (
4026 self.target.result(), loopvar_name))
4027 self.body.generate_execution_code(code)
4028 code.put_label(code.continue_label)
4029 if self.py_loopvar_node:
4030 # This mess is to make for..from loops with python targets behave
4031 # exactly like those with C targets with regards to re-assignment
4032 # of the loop variable.
4033 import ExprNodes
4034 if self.target.entry.is_pyglobal:
4035 # We know target is a NameNode, this is the only ugly case.
4036 target_node = ExprNodes.PyTempNode(self.target.pos, None)
4037 target_node.result_code = code.funcstate.allocate_temp(py_object_type, False)
4038 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
4039 target_node.result_code,
4040 Naming.module_cname,
4041 self.target.entry.interned_cname,
4042 code.error_goto_if_null(target_node.result_code, self.target.pos)))
4043 code.put_gotref(target_node.result_code)
4044 else:
4045 target_node = self.target
4046 from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
4047 from_py_node.temp_code = loopvar_name
4048 from_py_node.generate_result_code(code)
4049 if self.target.entry.is_pyglobal:
4050 code.put_decref_clear(target_node.result_code, py_object_type)
4051 code.funcstate.release_temp(target_node.result_code)
4052 code.putln("}")
4053 if self.py_loopvar_node:
4054 # This is potentially wasteful, but we don't want the semantics to
4055 # depend on whether or not the loop is a python type.
4056 self.py_loopvar_node.generate_evaluation_code(code)
4057 self.target.generate_assignment_code(self.py_loopvar_node, code)
4058 break_label = code.break_label
4059 code.set_loop_labels(old_loop_labels)
4060 if self.else_clause:
4061 code.putln("/*else*/ {")
4062 self.else_clause.generate_execution_code(code)
4063 code.putln("}")
4064 code.put_label(break_label)
4065 self.bound1.generate_disposal_code(code)
4066 self.bound1.free_temps(code)
4067 self.bound2.generate_disposal_code(code)
4068 self.bound2.free_temps(code)
4069 if self.step is not None:
4070 self.step.generate_disposal_code(code)
4071 self.step.free_temps(code)
4072 if from_range:
4073 code.funcstate.release_temp(loopvar_name)
4075 relation_table = {
4076 # {relop : (initial offset, increment op)}
4077 '<=': ("", "++"),
4078 '<' : ("+1", "++"),
4079 '>=': ("", "--"),
4080 '>' : ("-1", "--")
4081 }
4083 def annotate(self, code):
4084 self.target.annotate(code)
4085 self.bound1.annotate(code)
4086 self.bound2.annotate(code)
4087 if self.step:
4088 self.bound2.annotate(code)
4089 self.body.annotate(code)
4090 if self.else_clause:
4091 self.else_clause.annotate(code)
4094 class WithStatNode(StatNode):
4095 """
4096 Represents a Python with statement.
4098 This is only used at parse tree level; and is not present in
4099 analysis or generation phases.
4100 """
4101 # manager The with statement manager object
4102 # target Node (lhs expression)
4103 # body StatNode
4104 child_attrs = ["manager", "target", "body"]
4106 class TryExceptStatNode(StatNode):
4107 # try .. except statement
4108 #
4109 # body StatNode
4110 # except_clauses [ExceptClauseNode]
4111 # else_clause StatNode or None
4112 # cleanup_list [Entry] old style temps to clean up on error
4114 child_attrs = ["body", "except_clauses", "else_clause"]
4116 def analyse_control_flow(self, env):
4117 env.start_branching(self.pos)
4118 self.body.analyse_control_flow(env)
4119 successful_try = env.control_flow # grab this for later
4120 env.next_branch(self.body.end_pos())
4121 env.finish_branching(self.body.end_pos())
4123 env.start_branching(self.except_clauses[0].pos)
4124 for except_clause in self.except_clauses:
4125 except_clause.analyse_control_flow(env)
4126 env.next_branch(except_clause.end_pos())
4128 # the else cause it executed only when the try clause finishes
4129 env.control_flow.incoming = successful_try
4130 if self.else_clause:
4131 self.else_clause.analyse_control_flow(env)
4132 env.finish_branching(self.end_pos())
4134 def analyse_declarations(self, env):
4135 self.body.analyse_declarations(env)
4136 for except_clause in self.except_clauses:
4137 except_clause.analyse_declarations(env)
4138 if self.else_clause:
4139 self.else_clause.analyse_declarations(env)
4140 self.gil_check(env)
4141 env.use_utility_code(reset_exception_utility_code)
4143 def analyse_expressions(self, env):
4144 self.body.analyse_expressions(env)
4145 self.cleanup_list = env.free_temp_entries[:]
4146 default_clause_seen = 0
4147 for except_clause in self.except_clauses:
4148 except_clause.analyse_expressions(env)
4149 if default_clause_seen:
4150 error(except_clause.pos, "default 'except:' must be last")
4151 if not except_clause.pattern:
4152 default_clause_seen = 1
4153 self.has_default_clause = default_clause_seen
4154 if self.else_clause:
4155 self.else_clause.analyse_expressions(env)
4156 self.gil_check(env)
4158 gil_message = "Try-except statement"
4160 def generate_execution_code(self, code):
4161 old_return_label = code.return_label
4162 old_break_label = code.break_label
4163 old_continue_label = code.continue_label
4164 old_error_label = code.new_error_label()
4165 our_error_label = code.error_label
4166 except_end_label = code.new_label('exception_handled')
4167 except_error_label = code.new_label('except_error')
4168 except_return_label = code.new_label('except_return')
4169 try_return_label = code.new_label('try_return')
4170 try_break_label = code.new_label('try_break')
4171 try_continue_label = code.new_label('try_continue')
4172 try_end_label = code.new_label('try_end')
4174 code.putln("{")
4175 code.putln("PyObject %s;" %
4176 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4177 code.putln("__Pyx_ExceptionSave(%s);" %
4178 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4179 for var in Naming.exc_save_vars:
4180 code.put_xgotref(var)
4181 code.putln(
4182 "/*try:*/ {")
4183 code.return_label = try_return_label
4184 code.break_label = try_break_label
4185 code.continue_label = try_continue_label
4186 self.body.generate_execution_code(code)
4187 code.putln(
4188 "}")
4189 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4190 code.error_label = except_error_label
4191 code.return_label = except_return_label
4192 if self.else_clause:
4193 code.putln(
4194 "/*else:*/ {")
4195 self.else_clause.generate_execution_code(code)
4196 code.putln(
4197 "}")
4198 for var in Naming.exc_save_vars:
4199 code.put_xdecref_clear(var, py_object_type)
4200 code.put_goto(try_end_label)
4201 if code.label_used(try_return_label):
4202 code.put_label(try_return_label)
4203 for var in Naming.exc_save_vars:
4204 code.put_xdecref_clear(var, py_object_type)
4205 code.put_goto(old_return_label)
4206 code.put_label(our_error_label)
4207 code.put_var_xdecrefs_clear(self.cleanup_list)
4208 for temp_name, type in temps_to_clean_up:
4209 code.put_xdecref_clear(temp_name, type)
4210 for except_clause in self.except_clauses:
4211 except_clause.generate_handling_code(code, except_end_label)
4213 error_label_used = code.label_used(except_error_label)
4214 if error_label_used or not self.has_default_clause:
4215 if error_label_used:
4216 code.put_label(except_error_label)
4217 for var in Naming.exc_save_vars:
4218 code.put_xdecref(var, py_object_type)
4219 code.put_goto(old_error_label)
4221 if code.label_used(try_break_label):
4222 code.put_label(try_break_label)
4223 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4224 code.putln("__Pyx_ExceptionReset(%s);" %
4225 ', '.join(Naming.exc_save_vars))
4226 code.put_goto(old_break_label)
4228 if code.label_used(try_continue_label):
4229 code.put_label(try_continue_label)
4230 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4231 code.putln("__Pyx_ExceptionReset(%s);" %
4232 ', '.join(Naming.exc_save_vars))
4233 code.put_goto(old_continue_label)
4235 if code.label_used(except_return_label):
4236 code.put_label(except_return_label)
4237 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4238 code.putln("__Pyx_ExceptionReset(%s);" %
4239 ', '.join(Naming.exc_save_vars))
4240 code.put_goto(old_return_label)
4242 if code.label_used(except_end_label):
4243 code.put_label(except_end_label)
4244 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4245 code.putln("__Pyx_ExceptionReset(%s);" %
4246 ', '.join(Naming.exc_save_vars))
4247 code.put_label(try_end_label)
4248 code.putln("}")
4250 code.return_label = old_return_label
4251 code.break_label = old_break_label
4252 code.continue_label = old_continue_label
4253 code.error_label = old_error_label
4255 def annotate(self, code):
4256 self.body.annotate(code)
4257 for except_node in self.except_clauses:
4258 except_node.annotate(code)
4259 if self.else_clause:
4260 self.else_clause.annotate(code)
4263 class ExceptClauseNode(Node):
4264 # Part of try ... except statement.
4265 #
4266 # pattern ExprNode
4267 # target ExprNode or None
4268 # body StatNode
4269 # excinfo_target NameNode or None optional target for exception info
4270 # match_flag string result of exception match
4271 # exc_value ExcValueNode used internally
4272 # function_name string qualified name of enclosing function
4273 # exc_vars (string * 3) local exception variables
4275 # excinfo_target is never set by the parser, but can be set by a transform
4276 # in order to extract more extensive information about the exception as a
4277 # sys.exc_info()-style tuple into a target variable
4279 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4281 exc_value = None
4282 excinfo_target = None
4284 def analyse_declarations(self, env):
4285 if self.target:
4286 self.target.analyse_target_declaration(env)
4287 if self.excinfo_target is not None:
4288 self.excinfo_target.analyse_target_declaration(env)
4289 self.body.analyse_declarations(env)
4291 def analyse_expressions(self, env):
4292 import ExprNodes
4293 genv = env.global_scope()
4294 self.function_name = env.qualified_name
4295 if self.pattern:
4296 self.pattern.analyse_expressions(env)
4297 self.pattern = self.pattern.coerce_to_pyobject(env)
4298 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
4299 self.pattern.release_temp(env)
4300 env.release_temp(self.match_flag)
4302 if self.target or self.excinfo_target:
4303 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
4304 else:
4305 self.exc_vars = None
4307 if self.target:
4308 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
4309 self.exc_value.allocate_temps(env)
4310 self.target.analyse_target_expression(env, self.exc_value)
4311 if self.excinfo_target is not None:
4312 import ExprNodes
4313 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4314 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
4315 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
4316 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
4317 ])
4318 self.excinfo_tuple.analyse_expressions(env)
4319 self.excinfo_tuple.allocate_temps(env)
4320 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4322 self.body.analyse_expressions(env)
4324 if self.exc_vars:
4325 for var in self.exc_vars:
4326 env.release_temp(var)
4328 def generate_handling_code(self, code, end_label):
4329 code.mark_pos(self.pos)
4330 if self.pattern:
4331 self.pattern.generate_evaluation_code(code)
4332 code.putln(
4333 "%s = PyErr_ExceptionMatches(%s);" % (
4334 self.match_flag,
4335 self.pattern.py_result()))
4336 self.pattern.generate_disposal_code(code)
4337 self.pattern.free_temps(code)
4338 code.putln(
4339 "if (%s) {" %
4340 self.match_flag)
4341 else:
4342 code.putln("/*except:*/ {")
4344 if self.exc_vars:
4345 exc_vars = self.exc_vars
4346 elif not getattr(self.body, 'stats', True):
4347 # most simple case: no exception variable, empty body (pass)
4348 # => reset the exception state, done
4349 code.putln("PyErr_Restore(0,0,0);")
4350 code.put_goto(end_label)
4351 code.putln("}")
4352 return
4353 else:
4354 # during type analysis, we didn't know if we need the
4355 # exception value, but apparently, we do
4356 exc_vars = [code.funcstate.allocate_temp(py_object_type,
4357 manage_ref=True)
4358 for i in xrange(3)]
4360 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4361 # We always have to fetch the exception value even if
4362 # there is no target, because this also normalises the
4363 # exception and stores it in the thread state.
4364 code.globalstate.use_utility_code(get_exception_utility_code)
4365 exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4366 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4367 code.error_goto(self.pos)))
4368 for x in exc_vars:
4369 code.put_gotref(x)
4370 if self.target:
4371 self.exc_value.generate_evaluation_code(code)
4372 self.target.generate_assignment_code(self.exc_value, code)
4373 if self.excinfo_target is not None:
4374 self.excinfo_tuple.generate_evaluation_code(code)
4375 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4378 old_break_label, old_continue_label = code.break_label, code.continue_label
4379 code.break_label = code.new_label('except_break')
4380 code.continue_label = code.new_label('except_continue')
4382 old_exc_vars = code.funcstate.exc_vars
4383 code.funcstate.exc_vars = exc_vars
4384 self.body.generate_execution_code(code)
4385 code.funcstate.exc_vars = old_exc_vars
4386 for var in exc_vars:
4387 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4388 code.put_goto(end_label)
4390 if code.label_used(code.break_label):
4391 code.put_label(code.break_label)
4392 for var in exc_vars:
4393 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4394 code.put_goto(old_break_label)
4395 code.break_label = old_break_label
4397 if code.label_used(code.continue_label):
4398 code.put_label(code.continue_label)
4399 for var in exc_vars:
4400 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4401 code.put_goto(old_continue_label)
4402 code.continue_label = old_continue_label
4404 if not self.exc_vars:
4405 # clean up locally allocated temps
4406 for temp in exc_vars:
4407 code.funcstate.release_temp(temp)
4409 code.putln(
4410 "}")
4412 def annotate(self, code):
4413 if self.pattern:
4414 self.pattern.annotate(code)
4415 if self.target:
4416 self.target.annotate(code)
4417 self.body.annotate(code)
4420 class TryFinallyStatNode(StatNode):
4421 # try ... finally statement
4422 #
4423 # body StatNode
4424 # finally_clause StatNode
4425 #
4426 # cleanup_list [Entry] old_style temps to clean up on error
4427 #
4428 # The plan is that we funnel all continue, break
4429 # return and error gotos into the beginning of the
4430 # finally block, setting a variable to remember which
4431 # one we're doing. At the end of the finally block, we
4432 # switch on the variable to figure out where to go.
4433 # In addition, if we're doing an error, we save the
4434 # exception on entry to the finally block and restore
4435 # it on exit.
4437 child_attrs = ["body", "finally_clause"]
4439 preserve_exception = 1
4441 disallow_continue_in_try_finally = 0
4442 # There doesn't seem to be any point in disallowing
4443 # continue in the try block, since we have no problem
4444 # handling it.
4446 def create_analysed(pos, env, body, finally_clause):
4447 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4448 node.cleanup_list = []
4449 return node
4450 create_analysed = staticmethod(create_analysed)
4452 def analyse_control_flow(self, env):
4453 env.start_branching(self.pos)
4454 self.body.analyse_control_flow(env)
4455 env.next_branch(self.body.end_pos())
4456 env.finish_branching(self.body.end_pos())
4457 self.finally_clause.analyse_control_flow(env)
4459 def analyse_declarations(self, env):
4460 self.body.analyse_declarations(env)
4461 self.finally_clause.analyse_declarations(env)
4463 def analyse_expressions(self, env):
4464 self.body.analyse_expressions(env)
4465 self.cleanup_list = env.free_temp_entries[:]
4466 self.finally_clause.analyse_expressions(env)
4467 self.gil_check(env)
4469 gil_message = "Try-finally statement"
4471 def generate_execution_code(self, code):
4472 old_error_label = code.error_label
4473 old_labels = code.all_new_labels()
4474 new_labels = code.get_all_labels()
4475 new_error_label = code.error_label
4476 catch_label = code.new_label()
4477 code.putln(
4478 "/*try:*/ {")
4479 if self.disallow_continue_in_try_finally:
4480 was_in_try_finally = code.funcstate.in_try_finally
4481 code.funcstate.in_try_finally = 1
4482 self.body.generate_execution_code(code)
4483 if self.disallow_continue_in_try_finally:
4484 code.funcstate.in_try_finally = was_in_try_finally
4485 code.putln(
4486 "}")
4487 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4488 code.putln(
4489 "/*finally:*/ {")
4490 cases_used = []
4491 error_label_used = 0
4492 for i, new_label in enumerate(new_labels):
4493 if new_label in code.labels_used:
4494 cases_used.append(i)
4495 if new_label == new_error_label:
4496 error_label_used = 1
4497 error_label_case = i
4498 if cases_used:
4499 code.putln(
4500 "int __pyx_why;")
4501 if error_label_used and self.preserve_exception:
4502 code.putln(
4503 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4504 code.putln(
4505 "int %s;" % Naming.exc_lineno_name)
4506 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4507 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4508 code.putln(exc_var_init_zero)
4509 else:
4510 exc_var_init_zero = None
4511 code.use_label(catch_label)
4512 code.putln(
4513 "__pyx_why = 0; goto %s;" % catch_label)
4514 for i in cases_used:
4515 new_label = new_labels[i]
4516 #if new_label and new_label != "<try>":
4517 if new_label == new_error_label and self.preserve_exception:
4518 self.put_error_catcher(code,
4519 new_error_label, i+1, catch_label, temps_to_clean_up)
4520 else:
4521 code.put('%s: ' % new_label)
4522 if exc_var_init_zero:
4523 code.putln(exc_var_init_zero)
4524 code.putln("__pyx_why = %s; goto %s;" % (
4525 i+1,
4526 catch_label))
4527 code.put_label(catch_label)
4528 code.set_all_labels(old_labels)
4529 if error_label_used:
4530 code.new_error_label()
4531 finally_error_label = code.error_label
4532 self.finally_clause.generate_execution_code(code)
4533 if error_label_used:
4534 if finally_error_label in code.labels_used and self.preserve_exception:
4535 over_label = code.new_label()
4536 code.put_goto(over_label);
4537 code.put_label(finally_error_label)
4538 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4539 for var in Naming.exc_vars:
4540 code.putln("Py_XDECREF(%s);" % var)
4541 code.putln("}")
4542 code.put_goto(old_error_label)
4543 code.put_label(over_label)
4544 code.error_label = old_error_label
4545 if cases_used:
4546 code.putln(
4547 "switch (__pyx_why) {")
4548 for i in cases_used:
4549 old_label = old_labels[i]
4550 if old_label == old_error_label and self.preserve_exception:
4551 self.put_error_uncatcher(code, i+1, old_error_label)
4552 else:
4553 code.use_label(old_label)
4554 code.putln(
4555 "case %s: goto %s;" % (
4556 i+1,
4557 old_label))
4558 code.putln(
4559 "}")
4560 code.putln(
4561 "}")
4563 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4564 code.globalstate.use_utility_code(restore_exception_utility_code)
4565 code.putln(
4566 "%s: {" %
4567 error_label)
4568 code.putln(
4569 "__pyx_why = %s;" %
4570 i)
4571 code.put_var_xdecrefs_clear(self.cleanup_list)
4572 for temp_name, type in temps_to_clean_up:
4573 code.put_xdecref_clear(temp_name, type)
4574 code.putln(
4575 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4576 Naming.exc_vars)
4577 code.putln(
4578 "%s = %s;" % (
4579 Naming.exc_lineno_name, Naming.lineno_cname))
4580 #code.putln(
4581 # "goto %s;" %
4582 # catch_label)
4583 code.put_goto(catch_label)
4584 code.putln(
4585 "}")
4587 def put_error_uncatcher(self, code, i, error_label):
4588 code.globalstate.use_utility_code(restore_exception_utility_code)
4589 code.putln(
4590 "case %s: {" %
4591 i)
4592 code.putln(
4593 "__Pyx_ErrRestore(%s, %s, %s);" %
4594 Naming.exc_vars)
4595 code.putln(
4596 "%s = %s;" % (
4597 Naming.lineno_cname, Naming.exc_lineno_name))
4598 for var in Naming.exc_vars:
4599 code.putln(
4600 "%s = 0;" %
4601 var)
4602 code.put_goto(error_label)
4603 code.putln(
4604 "}")
4606 def annotate(self, code):
4607 self.body.annotate(code)
4608 self.finally_clause.annotate(code)
4611 class GILStatNode(TryFinallyStatNode):
4612 # 'with gil' or 'with nogil' statement
4613 #
4614 # state string 'gil' or 'nogil'
4616 child_attrs = []
4618 preserve_exception = 0
4620 def __init__(self, pos, state, body):
4621 self.state = state
4622 TryFinallyStatNode.__init__(self, pos,
4623 body = body,
4624 finally_clause = GILExitNode(pos, state = state))
4626 def analyse_expressions(self, env):
4627 env.use_utility_code(force_init_threads_utility_code)
4628 was_nogil = env.nogil
4629 env.nogil = 1
4630 TryFinallyStatNode.analyse_expressions(self, env)
4631 env.nogil = was_nogil
4633 def gil_check(self, env):
4634 pass
4636 def generate_execution_code(self, code):
4637 code.mark_pos(self.pos)
4638 if self.state == 'gil':
4639 code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4640 else:
4641 code.putln("{ PyThreadState *_save;")
4642 code.putln("Py_UNBLOCK_THREADS")
4643 TryFinallyStatNode.generate_execution_code(self, code)
4644 code.putln("}")
4647 class GILExitNode(StatNode):
4648 # Used as the 'finally' block in a GILStatNode
4649 #
4650 # state string 'gil' or 'nogil'
4652 child_attrs = []
4654 def analyse_expressions(self, env):
4655 pass
4657 def generate_execution_code(self, code):
4658 if self.state == 'gil':
4659 code.putln("PyGILState_Release();")
4660 else:
4661 code.putln("Py_BLOCK_THREADS")
4664 class CImportStatNode(StatNode):
4665 # cimport statement
4666 #
4667 # module_name string Qualified name of module being imported
4668 # as_name string or None Name specified in "as" clause, if any
4670 child_attrs = []
4672 def analyse_declarations(self, env):
4673 if not env.is_module_scope:
4674 error(self.pos, "cimport only allowed at module level")
4675 return
4676 module_scope = env.find_module(self.module_name, self.pos)
4677 if "." in self.module_name:
4678 names = [EncodedString(name) for name in self.module_name.split(".")]
4679 top_name = names[0]
4680 top_module_scope = env.context.find_submodule(top_name)
4681 module_scope = top_module_scope
4682 for name in names[1:]:
4683 submodule_scope = module_scope.find_submodule(name)
4684 module_scope.declare_module(name, submodule_scope, self.pos)
4685 module_scope = submodule_scope
4686 if self.as_name:
4687 env.declare_module(self.as_name, module_scope, self.pos)
4688 else:
4689 env.declare_module(top_name, top_module_scope, self.pos)
4690 else:
4691 name = self.as_name or self.module_name
4692 env.declare_module(name, module_scope, self.pos)
4694 def analyse_expressions(self, env):
4695 pass
4697 def generate_execution_code(self, code):
4698 pass
4701 class FromCImportStatNode(StatNode):
4702 # from ... cimport statement
4703 #
4704 # module_name string Qualified name of module
4705 # imported_names [(pos, name, as_name, kind)] Names to be imported
4707 child_attrs = []
4709 def analyse_declarations(self, env):
4710 if not env.is_module_scope:
4711 error(self.pos, "cimport only allowed at module level")
4712 return
4713 module_scope = env.find_module(self.module_name, self.pos)
4714 env.add_imported_module(module_scope)
4715 for pos, name, as_name, kind in self.imported_names:
4716 if name == "*":
4717 for local_name, entry in module_scope.entries.items():
4718 env.add_imported_entry(local_name, entry, pos)
4719 else:
4720 entry = module_scope.lookup(name)
4721 if entry:
4722 if kind and not self.declaration_matches(entry, kind):
4723 entry.redeclared(pos)
4724 else:
4725 if kind == 'struct' or kind == 'union':
4726 entry = module_scope.declare_struct_or_union(name,
4727 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4728 elif kind == 'class':
4729 entry = module_scope.declare_c_class(name, pos = pos,
4730 module_name = self.module_name)
4731 else:
4732 submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
4733 if submodule_scope.parent_module is module_scope:
4734 env.declare_module(as_name or name, submodule_scope, self.pos)
4735 else:
4736 error(pos, "Name '%s' not declared in module '%s'"
4737 % (name, self.module_name))
4739 if entry:
4740 local_name = as_name or name
4741 env.add_imported_entry(local_name, entry, pos)
4743 def declaration_matches(self, entry, kind):
4744 if not entry.is_type:
4745 return 0
4746 type = entry.type
4747 if kind == 'class':
4748 if not type.is_extension_type:
4749 return 0
4750 else:
4751 if not type.is_struct_or_union:
4752 return 0
4753 if kind != type.kind:
4754 return 0
4755 return 1
4757 def analyse_expressions(self, env):
4758 pass
4760 def generate_execution_code(self, code):
4761 pass
4764 class FromImportStatNode(StatNode):
4765 # from ... import statement
4766 #
4767 # module ImportNode
4768 # items [(string, NameNode)]
4769 # interned_items [(string, NameNode, ExprNode)]
4770 # item PyTempNode used internally
4771 # import_star boolean used internally
4773 child_attrs = ["module"]
4774 import_star = 0
4776 def analyse_declarations(self, env):
4777 for name, target in self.items:
4778 if name == "*":
4779 if not env.is_module_scope:
4780 error(self.pos, "import * only allowed at module level")
4781 return
4782 env.has_import_star = 1
4783 self.import_star = 1
4784 else:
4785 target.analyse_target_declaration(env)
4787 def analyse_expressions(self, env):
4788 import ExprNodes
4789 self.module.analyse_expressions(env)
4790 self.item = ExprNodes.PyTempNode(self.pos, env)
4791 self.item.allocate_temp(env)
4792 self.interned_items = []
4793 for name, target in self.items:
4794 if name == '*':
4795 for _, entry in env.entries.items():
4796 if not entry.is_type and entry.type.is_extension_type:
4797 env.use_utility_code(ExprNodes.type_test_utility_code)
4798 break
4799 else:
4800 entry = env.lookup(target.name)
4801 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4802 continue # already cimported
4803 target.analyse_target_expression(env, None)
4804 if target.type is py_object_type:
4805 coerced_item = None
4806 else:
4807 coerced_item = self.item.coerce_to(target.type, env)
4808 self.interned_items.append(
4809 (env.intern_identifier(name), target, coerced_item))
4810 #target.release_target_temp(env) # was release_temp ?!?
4811 self.module.release_temp(env)
4812 self.item.release_temp(env)
4814 def generate_execution_code(self, code):
4815 self.module.generate_evaluation_code(code)
4816 if self.import_star:
4817 code.putln(
4818 'if (%s(%s) < 0) %s;' % (
4819 Naming.import_star,
4820 self.module.py_result(),
4821 code.error_goto(self.pos)))
4822 for cname, target, coerced_item in self.interned_items:
4823 code.putln(
4824 '%s = PyObject_GetAttr(%s, %s); %s' % (
4825 self.item.result(),
4826 self.module.py_result(),
4827 cname,
4828 code.error_goto_if_null(self.item.result(), self.pos)))
4829 code.put_gotref(self.item.py_result())
4830 if coerced_item is None:
4831 target.generate_assignment_code(self.item, code)
4832 else:
4833 coerced_item.allocate_temp_result(code)
4834 coerced_item.generate_result_code(code)
4835 target.generate_assignment_code(coerced_item, code)
4836 if self.item.result() != coerced_item.result():
4837 code.put_decref_clear(self.item.result(), self.item.type)
4838 self.module.generate_disposal_code(code)
4839 self.module.free_temps(code)
4843 #------------------------------------------------------------------------------------
4844 #
4845 # Runtime support code
4846 #
4847 #------------------------------------------------------------------------------------
4849 utility_function_predeclarations = \
4850 """
4851 #ifdef __GNUC__
4852 #define INLINE __inline__
4853 #elif _WIN32
4854 #define INLINE __inline
4855 #else
4856 #define INLINE
4857 #endif
4859 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4861 """ + """
4863 static int %(skip_dispatch_cname)s = 0;
4865 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4867 if Options.gcc_branch_hints:
4868 branch_prediction_macros = \
4869 """
4870 #ifdef __GNUC__
4871 /* Test for GCC > 2.95 */
4872 #if __GNUC__ > 2 || \
4873 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4874 #define likely(x) __builtin_expect(!!(x), 1)
4875 #define unlikely(x) __builtin_expect(!!(x), 0)
4876 #else /* __GNUC__ > 2 ... */
4877 #define likely(x) (x)
4878 #define unlikely(x) (x)
4879 #endif /* __GNUC__ > 2 ... */
4880 #else /* __GNUC__ */
4881 #define likely(x) (x)
4882 #define unlikely(x) (x)
4883 #endif /* __GNUC__ */
4884 """
4885 else:
4886 branch_prediction_macros = \
4887 """
4888 #define likely(x) (x)
4889 #define unlikely(x) (x)
4890 """
4892 #get_name_predeclaration = \
4893 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4895 #get_name_interned_predeclaration = \
4896 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4898 #------------------------------------------------------------------------------------
4900 printing_utility_code = UtilityCode(
4901 proto = """
4902 static int __Pyx_Print(PyObject *, int); /*proto*/
4903 #if PY_MAJOR_VERSION >= 3
4904 static PyObject* %s = 0;
4905 static PyObject* %s = 0;
4906 #endif
4907 """ % (Naming.print_function, Naming.print_function_kwargs),
4908 impl = r"""
4909 #if PY_MAJOR_VERSION < 3
4910 static PyObject *__Pyx_GetStdout(void) {
4911 PyObject *f = PySys_GetObject((char *)"stdout");
4912 if (!f) {
4913 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4914 }
4915 return f;
4916 }
4918 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4919 PyObject *f;
4920 PyObject* v;
4921 int i;
4923 if (!(f = __Pyx_GetStdout()))
4924 return -1;
4925 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4926 if (PyFile_SoftSpace(f, 1)) {
4927 if (PyFile_WriteString(" ", f) < 0)
4928 return -1;
4929 }
4930 v = PyTuple_GET_ITEM(arg_tuple, i);
4931 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4932 return -1;
4933 if (PyString_Check(v)) {
4934 char *s = PyString_AsString(v);
4935 Py_ssize_t len = PyString_Size(v);
4936 if (len > 0 &&
4937 isspace(Py_CHARMASK(s[len-1])) &&
4938 s[len-1] != ' ')
4939 PyFile_SoftSpace(f, 0);
4940 }
4941 }
4942 if (newline) {
4943 if (PyFile_WriteString("\n", f) < 0)
4944 return -1;
4945 PyFile_SoftSpace(f, 0);
4946 }
4947 return 0;
4948 }
4950 #else /* Python 3 has a print function */
4952 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4953 PyObject* kwargs = 0;
4954 PyObject* result = 0;
4955 PyObject* end_string;
4956 if (!%(PRINT_FUNCTION)s) {
4957 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4958 if (!%(PRINT_FUNCTION)s)
4959 return -1;
4960 }
4961 if (!newline) {
4962 if (!%(PRINT_KWARGS)s) {
4963 %(PRINT_KWARGS)s = PyDict_New();
4964 if (!%(PRINT_KWARGS)s)
4965 return -1;
4966 end_string = PyUnicode_FromStringAndSize(" ", 1);
4967 if (!end_string)
4968 return -1;
4969 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4970 Py_DECREF(end_string);
4971 return -1;
4972 }
4973 Py_DECREF(end_string);
4974 }
4975 kwargs = %(PRINT_KWARGS)s;
4976 }
4977 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4978 if (!result)
4979 return -1;
4980 Py_DECREF(result);
4981 return 0;
4982 }
4984 #endif
4985 """ % {'BUILTINS' : Naming.builtins_cname,
4986 'PRINT_FUNCTION' : Naming.print_function,
4987 'PRINT_KWARGS' : Naming.print_function_kwargs}
4988 )
4991 printing_one_utility_code = UtilityCode(
4992 proto = """
4993 static int __Pyx_PrintOne(PyObject *o); /*proto*/
4994 """,
4995 impl = r"""
4996 #if PY_MAJOR_VERSION < 3
4998 static int __Pyx_PrintOne(PyObject *o) {
4999 PyObject *f;
5000 if (!(f = __Pyx_GetStdout()))
5001 return -1;
5002 if (PyFile_SoftSpace(f, 0)) {
5003 if (PyFile_WriteString(" ", f) < 0)
5004 return -1;
5005 }
5006 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
5007 return -1;
5008 if (PyFile_WriteString("\n", f) < 0)
5009 return -1;
5010 return 0;
5011 /* the line below is just to avoid compiler
5012 * compiler warnings about unused functions */
5013 return __Pyx_Print(NULL, 0);
5014 }
5016 #else /* Python 3 has a print function */
5018 static int __Pyx_PrintOne(PyObject *o) {
5019 int res;
5020 PyObject* arg_tuple = PyTuple_New(1);
5021 if (unlikely(!arg_tuple))
5022 return -1;
5023 Py_INCREF(o);
5024 PyTuple_SET_ITEM(arg_tuple, 0, o);
5025 res = __Pyx_Print(arg_tuple, 1);
5026 Py_DECREF(arg_tuple);
5027 return res;
5028 }
5030 #endif
5031 """,
5032 requires=[printing_utility_code])
5036 #------------------------------------------------------------------------------------
5038 # The following function is based on do_raise() from ceval.c.
5040 raise_utility_code = UtilityCode(
5041 proto = """
5042 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5043 """,
5044 impl = """
5045 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5046 Py_XINCREF(type);
5047 Py_XINCREF(value);
5048 Py_XINCREF(tb);
5049 /* First, check the traceback argument, replacing None with NULL. */
5050 if (tb == Py_None) {
5051 Py_DECREF(tb);
5052 tb = 0;
5053 }
5054 else if (tb != NULL && !PyTraceBack_Check(tb)) {
5055 PyErr_SetString(PyExc_TypeError,
5056 "raise: arg 3 must be a traceback or None");
5057 goto raise_error;
5058 }
5059 /* Next, replace a missing value with None */
5060 if (value == NULL) {
5061 value = Py_None;
5062 Py_INCREF(value);
5063 }
5064 #if PY_VERSION_HEX < 0x02050000
5065 if (!PyClass_Check(type))
5066 #else
5067 if (!PyType_Check(type))
5068 #endif
5069 {
5070 /* Raising an instance. The value should be a dummy. */
5071 if (value != Py_None) {
5072 PyErr_SetString(PyExc_TypeError,
5073 "instance exception may not have a separate value");
5074 goto raise_error;
5075 }
5076 /* Normalize to raise <class>, <instance> */
5077 Py_DECREF(value);
5078 value = type;
5079 #if PY_VERSION_HEX < 0x02050000
5080 if (PyInstance_Check(type)) {
5081 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
5082 Py_INCREF(type);
5083 }
5084 else {
5085 type = 0;
5086 PyErr_SetString(PyExc_TypeError,
5087 "raise: exception must be an old-style class or instance");
5088 goto raise_error;
5089 }
5090 #else
5091 type = (PyObject*) Py_TYPE(type);
5092 Py_INCREF(type);
5093 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
5094 PyErr_SetString(PyExc_TypeError,
5095 "raise: exception class must be a subclass of BaseException");
5096 goto raise_error;
5097 }
5098 #endif
5099 }
5100 __Pyx_ErrRestore(type, value, tb);
5101 return;
5102 raise_error:
5103 Py_XDECREF(value);
5104 Py_XDECREF(type);
5105 Py_XDECREF(tb);
5106 return;
5107 }
5108 """)
5110 #------------------------------------------------------------------------------------
5112 reraise_utility_code = UtilityCode(
5113 proto = """
5114 static void __Pyx_ReRaise(void); /*proto*/
5115 """,
5116 impl = """
5117 static void __Pyx_ReRaise(void) {
5118 PyThreadState *tstate = PyThreadState_GET();
5119 PyObject* tmp_type = tstate->curexc_type;
5120 PyObject* tmp_value = tstate->curexc_value;
5121 PyObject* tmp_tb = tstate->curexc_traceback;
5122 tstate->curexc_type = tstate->exc_type;
5123 tstate->curexc_value = tstate->exc_value;
5124 tstate->curexc_traceback = tstate->exc_traceback;
5125 tstate->exc_type = 0;
5126 tstate->exc_value = 0;
5127 tstate->exc_traceback = 0;
5128 Py_XDECREF(tmp_type);
5129 Py_XDECREF(tmp_value);
5130 Py_XDECREF(tmp_tb);
5131 }
5132 """)
5134 #------------------------------------------------------------------------------------
5136 arg_type_test_utility_code = UtilityCode(
5137 proto = """
5138 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5139 const char *name, int exact); /*proto*/
5140 """,
5141 impl = """
5142 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5143 const char *name, int exact)
5144 {
5145 if (!type) {
5146 PyErr_Format(PyExc_SystemError, "Missing type object");
5147 return 0;
5148 }
5149 if (none_allowed && obj == Py_None) return 1;
5150 else if (exact) {
5151 if (Py_TYPE(obj) == type) return 1;
5152 }
5153 else {
5154 if (PyObject_TypeCheck(obj, type)) return 1;
5155 }
5156 PyErr_Format(PyExc_TypeError,
5157 "Argument '%s' has incorrect type (expected %s, got %s)",
5158 name, type->tp_name, Py_TYPE(obj)->tp_name);
5159 return 0;
5160 }
5161 """)
5163 #------------------------------------------------------------------------------------
5164 #
5165 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5166 # many or too few positional arguments were found. This handles
5167 # Py_ssize_t formatting correctly.
5169 raise_argtuple_invalid_utility_code = UtilityCode(
5170 proto = """
5171 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5172 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5173 """,
5174 impl = """
5175 static void __Pyx_RaiseArgtupleInvalid(
5176 const char* func_name,
5177 int exact,
5178 Py_ssize_t num_min,
5179 Py_ssize_t num_max,
5180 Py_ssize_t num_found)
5181 {
5182 Py_ssize_t num_expected;
5183 const char *number, *more_or_less;
5185 if (num_found < num_min) {
5186 num_expected = num_min;
5187 more_or_less = "at least";
5188 } else {
5189 num_expected = num_max;
5190 more_or_less = "at most";
5191 }
5192 if (exact) {
5193 more_or_less = "exactly";
5194 }
5195 number = (num_expected == 1) ? "" : "s";
5196 PyErr_Format(PyExc_TypeError,
5197 #if PY_VERSION_HEX < 0x02050000
5198 "%s() takes %s %d positional argument%s (%d given)",
5199 #else
5200 "%s() takes %s %zd positional argument%s (%zd given)",
5201 #endif
5202 func_name, more_or_less, num_expected, number, num_found);
5203 }
5204 """)
5206 raise_keyword_required_utility_code = UtilityCode(
5207 proto = """
5208 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5209 """,
5210 impl = """
5211 static INLINE void __Pyx_RaiseKeywordRequired(
5212 const char* func_name,
5213 PyObject* kw_name)
5214 {
5215 PyErr_Format(PyExc_TypeError,
5216 #if PY_MAJOR_VERSION >= 3
5217 "%s() needs keyword-only argument %U", func_name, kw_name);
5218 #else
5219 "%s() needs keyword-only argument %s", func_name,
5220 PyString_AS_STRING(kw_name));
5221 #endif
5222 }
5223 """)
5225 raise_double_keywords_utility_code = UtilityCode(
5226 proto = """
5227 static void __Pyx_RaiseDoubleKeywordsError(
5228 const char* func_name, PyObject* kw_name); /*proto*/
5229 """,
5230 impl = """
5231 static void __Pyx_RaiseDoubleKeywordsError(
5232 const char* func_name,
5233 PyObject* kw_name)
5234 {
5235 PyErr_Format(PyExc_TypeError,
5236 #if PY_MAJOR_VERSION >= 3
5237 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5238 #else
5239 "%s() got multiple values for keyword argument '%s'", func_name,
5240 PyString_AS_STRING(kw_name));
5241 #endif
5242 }
5243 """)
5245 #------------------------------------------------------------------------------------
5246 #
5247 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5248 # were passed to a function, or if any keywords were passed to a
5249 # function that does not accept them.
5251 keyword_string_check_utility_code = UtilityCode(
5252 proto = """
5253 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5254 const char* function_name, int kw_allowed); /*proto*/
5255 """,
5256 impl = """
5257 static INLINE int __Pyx_CheckKeywordStrings(
5258 PyObject *kwdict,
5259 const char* function_name,
5260 int kw_allowed)
5261 {
5262 PyObject* key = 0;
5263 Py_ssize_t pos = 0;
5264 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5265 #if PY_MAJOR_VERSION < 3
5266 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5267 #else
5268 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5269 #endif
5270 goto invalid_keyword_type;
5271 }
5272 if ((!kw_allowed) && unlikely(key))
5273 goto invalid_keyword;
5274 return 1;
5275 invalid_keyword_type:
5276 PyErr_Format(PyExc_TypeError,
5277 "%s() keywords must be strings", function_name);
5278 return 0;
5279 invalid_keyword:
5280 PyErr_Format(PyExc_TypeError,
5281 #if PY_MAJOR_VERSION < 3
5282 "%s() got an unexpected keyword argument '%s'",
5283 function_name, PyString_AsString(key));
5284 #else
5285 "%s() got an unexpected keyword argument '%U'",
5286 function_name, key);
5287 #endif
5288 return 0;
5289 }
5290 """)
5292 #------------------------------------------------------------------------------------
5293 #
5294 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5295 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5296 # keywords will raise an invalid keyword error.
5297 #
5298 # Three kinds of errors are checked: 1) non-string keywords, 2)
5299 # unexpected keywords and 3) overlap with positional arguments.
5300 #
5301 # If num_posargs is greater 0, it denotes the number of positional
5302 # arguments that were passed and that must therefore not appear
5303 # amongst the keywords as well.
5304 #
5305 # This method does not check for required keyword arguments.
5306 #
5308 parse_keywords_utility_code = UtilityCode(
5309 proto = """
5310 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5311 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5312 const char* function_name); /*proto*/
5313 """,
5314 impl = """
5315 static int __Pyx_ParseOptionalKeywords(
5316 PyObject *kwds,
5317 PyObject **argnames[],
5318 PyObject *kwds2,
5319 PyObject *values[],
5320 Py_ssize_t num_pos_args,
5321 const char* function_name)
5322 {
5323 PyObject *key = 0, *value = 0;
5324 Py_ssize_t pos = 0;
5325 PyObject*** name;
5326 PyObject*** first_kw_arg = argnames + num_pos_args;
5328 while (PyDict_Next(kwds, &pos, &key, &value)) {
5329 name = first_kw_arg;
5330 while (*name && (**name != key)) name++;
5331 if (*name) {
5332 values[name-argnames] = value;
5333 } else {
5334 #if PY_MAJOR_VERSION < 3
5335 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5336 #else
5337 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5338 #endif
5339 goto invalid_keyword_type;
5340 } else {
5341 for (name = first_kw_arg; *name; name++) {
5342 #if PY_MAJOR_VERSION >= 3
5343 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5344 PyUnicode_Compare(**name, key) == 0) break;
5345 #else
5346 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5347 _PyString_Eq(**name, key)) break;
5348 #endif
5349 }
5350 if (*name) {
5351 values[name-argnames] = value;
5352 } else {
5353 /* unexpected keyword found */
5354 for (name=argnames; name != first_kw_arg; name++) {
5355 if (**name == key) goto arg_passed_twice;
5356 #if PY_MAJOR_VERSION >= 3
5357 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5358 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5359 #else
5360 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5361 _PyString_Eq(**name, key)) goto arg_passed_twice;
5362 #endif
5363 }
5364 if (kwds2) {
5365 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5366 } else {
5367 goto invalid_keyword;
5368 }
5369 }
5370 }
5371 }
5372 }
5373 return 0;
5374 arg_passed_twice:
5375 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5376 goto bad;
5377 invalid_keyword_type:
5378 PyErr_Format(PyExc_TypeError,
5379 "%s() keywords must be strings", function_name);
5380 goto bad;
5381 invalid_keyword:
5382 PyErr_Format(PyExc_TypeError,
5383 #if PY_MAJOR_VERSION < 3
5384 "%s() got an unexpected keyword argument '%s'",
5385 function_name, PyString_AsString(key));
5386 #else
5387 "%s() got an unexpected keyword argument '%U'",
5388 function_name, key);
5389 #endif
5390 bad:
5391 return -1;
5392 }
5393 """)
5395 #------------------------------------------------------------------------------------
5397 traceback_utility_code = UtilityCode(
5398 proto = """
5399 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5400 """,
5401 impl = """
5402 #include "compile.h"
5403 #include "frameobject.h"
5404 #include "traceback.h"
5406 static void __Pyx_AddTraceback(const char *funcname) {
5407 PyObject *py_srcfile = 0;
5408 PyObject *py_funcname = 0;
5409 PyObject *py_globals = 0;
5410 PyObject *empty_string = 0;
5411 PyCodeObject *py_code = 0;
5412 PyFrameObject *py_frame = 0;
5414 #if PY_MAJOR_VERSION < 3
5415 py_srcfile = PyString_FromString(%(FILENAME)s);
5416 #else
5417 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5418 #endif
5419 if (!py_srcfile) goto bad;
5420 if (%(CLINENO)s) {
5421 #if PY_MAJOR_VERSION < 3
5422 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5423 #else
5424 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5425 #endif
5426 }
5427 else {
5428 #if PY_MAJOR_VERSION < 3
5429 py_funcname = PyString_FromString(funcname);
5430 #else
5431 py_funcname = PyUnicode_FromString(funcname);
5432 #endif
5433 }
5434 if (!py_funcname) goto bad;
5435 py_globals = PyModule_GetDict(%(GLOBALS)s);
5436 if (!py_globals) goto bad;
5437 #if PY_MAJOR_VERSION < 3
5438 empty_string = PyString_FromStringAndSize("", 0);
5439 #else
5440 empty_string = PyBytes_FromStringAndSize("", 0);
5441 #endif
5442 if (!empty_string) goto bad;
5443 py_code = PyCode_New(
5444 0, /*int argcount,*/
5445 #if PY_MAJOR_VERSION >= 3
5446 0, /*int kwonlyargcount,*/
5447 #endif
5448 0, /*int nlocals,*/
5449 0, /*int stacksize,*/
5450 0, /*int flags,*/
5451 empty_string, /*PyObject *code,*/
5452 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5453 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5454 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5455 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5456 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5457 py_srcfile, /*PyObject *filename,*/
5458 py_funcname, /*PyObject *name,*/
5459 %(LINENO)s, /*int firstlineno,*/
5460 empty_string /*PyObject *lnotab*/
5461 );
5462 if (!py_code) goto bad;
5463 py_frame = PyFrame_New(
5464 PyThreadState_GET(), /*PyThreadState *tstate,*/
5465 py_code, /*PyCodeObject *code,*/
5466 py_globals, /*PyObject *globals,*/
5467 0 /*PyObject *locals*/
5468 );
5469 if (!py_frame) goto bad;
5470 py_frame->f_lineno = %(LINENO)s;
5471 PyTraceBack_Here(py_frame);
5472 bad:
5473 Py_XDECREF(py_srcfile);
5474 Py_XDECREF(py_funcname);
5475 Py_XDECREF(empty_string);
5476 Py_XDECREF(py_code);
5477 Py_XDECREF(py_frame);
5478 }
5479 """ % {
5480 'FILENAME': Naming.filename_cname,
5481 'LINENO': Naming.lineno_cname,
5482 'CFILENAME': Naming.cfilenm_cname,
5483 'CLINENO': Naming.clineno_cname,
5484 'GLOBALS': Naming.module_cname,
5485 'EMPTY_TUPLE' : Naming.empty_tuple,
5486 })
5488 restore_exception_utility_code = UtilityCode(
5489 proto = """
5490 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5491 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5492 """,
5493 impl = """
5494 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5495 PyObject *tmp_type, *tmp_value, *tmp_tb;
5496 PyThreadState *tstate = PyThreadState_GET();
5498 #if PY_MAJOR_VERSION >= 3
5499 /* Note: this is a temporary work-around to prevent crashes in Python 3.0 */
5500 if ((tstate->exc_type != NULL) & (tstate->exc_type != Py_None)) {
5501 tmp_type = tstate->exc_type;
5502 tmp_value = tstate->exc_value;
5503 tmp_tb = tstate->exc_traceback;
5504 PyErr_NormalizeException(&type, &value, &tb);
5505 PyErr_NormalizeException(&tmp_type, &tmp_value, &tmp_tb);
5506 tstate->exc_type = 0;
5507 tstate->exc_value = 0;
5508 tstate->exc_traceback = 0;
5509 PyException_SetContext(value, tmp_value);
5510 Py_DECREF(tmp_type);
5511 Py_XDECREF(tmp_tb);
5512 }
5513 #endif
5515 tmp_type = tstate->curexc_type;
5516 tmp_value = tstate->curexc_value;
5517 tmp_tb = tstate->curexc_traceback;
5518 tstate->curexc_type = type;
5519 tstate->curexc_value = value;
5520 tstate->curexc_traceback = tb;
5521 Py_XDECREF(tmp_type);
5522 Py_XDECREF(tmp_value);
5523 Py_XDECREF(tmp_tb);
5524 }
5526 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5527 PyThreadState *tstate = PyThreadState_GET();
5528 *type = tstate->curexc_type;
5529 *value = tstate->curexc_value;
5530 *tb = tstate->curexc_traceback;
5532 tstate->curexc_type = 0;
5533 tstate->curexc_value = 0;
5534 tstate->curexc_traceback = 0;
5535 }
5537 """)
5539 #------------------------------------------------------------------------------------
5541 unraisable_exception_utility_code = UtilityCode(
5542 proto = """
5543 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5544 """,
5545 impl = """
5546 static void __Pyx_WriteUnraisable(const char *name) {
5547 PyObject *old_exc, *old_val, *old_tb;
5548 PyObject *ctx;
5549 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5550 #if PY_MAJOR_VERSION < 3
5551 ctx = PyString_FromString(name);
5552 #else
5553 ctx = PyUnicode_FromString(name);
5554 #endif
5555 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5556 if (!ctx) {
5557 PyErr_WriteUnraisable(Py_None);
5558 } else {
5559 PyErr_WriteUnraisable(ctx);
5560 Py_DECREF(ctx);
5561 }
5562 }
5563 """,
5564 requires=[restore_exception_utility_code])
5566 #------------------------------------------------------------------------------------
5568 set_vtable_utility_code = UtilityCode(
5569 proto = """
5570 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5571 """,
5572 impl = """
5573 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5574 PyObject *pycobj = 0;
5575 int result;
5577 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5578 if (!pycobj)
5579 goto bad;
5580 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5581 goto bad;
5582 result = 0;
5583 goto done;
5585 bad:
5586 result = -1;
5587 done:
5588 Py_XDECREF(pycobj);
5589 return result;
5590 }
5591 """)
5593 #------------------------------------------------------------------------------------
5595 get_vtable_utility_code = UtilityCode(
5596 proto = """
5597 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5598 """,
5599 impl = r"""
5600 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5601 int result;
5602 PyObject *pycobj;
5604 pycobj = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5605 if (!pycobj)
5606 goto bad;
5607 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5608 if (!*(void **)vtabptr)
5609 goto bad;
5610 result = 0;
5611 goto done;
5613 bad:
5614 result = -1;
5615 done:
5616 Py_XDECREF(pycobj);
5617 return result;
5618 }
5619 """)
5621 #------------------------------------------------------------------------------------
5623 init_string_tab_utility_code = UtilityCode(
5624 proto = """
5625 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5626 """,
5627 impl = """
5628 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5629 while (t->p) {
5630 #if PY_MAJOR_VERSION < 3
5631 if (t->is_unicode && (!t->is_identifier)) {
5632 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5633 } else if (t->intern) {
5634 *t->p = PyString_InternFromString(t->s);
5635 } else {
5636 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5637 }
5638 #else /* Python 3+ has unicode identifiers */
5639 if (t->is_identifier || (t->is_unicode && t->intern)) {
5640 *t->p = PyUnicode_InternFromString(t->s);
5641 } else if (t->is_unicode) {
5642 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5643 } else {
5644 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5645 }
5646 #endif
5647 if (!*t->p)
5648 return -1;
5649 ++t;
5650 }
5651 return 0;
5652 }
5653 """)
5655 #------------------------------------------------------------------------------------
5657 get_exception_utility_code = UtilityCode(
5658 proto = """
5659 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5660 """,
5661 impl = """
5662 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5663 PyObject *tmp_type, *tmp_value, *tmp_tb;
5664 PyThreadState *tstate = PyThreadState_GET();
5665 *type = tstate->curexc_type;
5666 *value = tstate->curexc_value;
5667 *tb = tstate->curexc_traceback;
5668 tstate->curexc_type = 0;
5669 tstate->curexc_value = 0;
5670 tstate->curexc_traceback = 0;
5671 PyErr_NormalizeException(type, value, tb);
5672 if (PyErr_Occurred())
5673 goto bad;
5674 Py_INCREF(*type);
5675 Py_INCREF(*value);
5676 Py_INCREF(*tb);
5677 tmp_type = tstate->exc_type;
5678 tmp_value = tstate->exc_value;
5679 tmp_tb = tstate->exc_traceback;
5680 tstate->exc_type = *type;
5681 tstate->exc_value = *value;
5682 tstate->exc_traceback = *tb;
5683 /* Make sure tstate is in a consistent state when we XDECREF
5684 these objects (XDECREF may run arbitrary code). */
5685 Py_XDECREF(tmp_type);
5686 Py_XDECREF(tmp_value);
5687 Py_XDECREF(tmp_tb);
5688 return 0;
5689 bad:
5690 Py_XDECREF(*type);
5691 Py_XDECREF(*value);
5692 Py_XDECREF(*tb);
5693 return -1;
5694 }
5696 """)
5698 #------------------------------------------------------------------------------------
5700 reset_exception_utility_code = UtilityCode(
5701 proto = """
5702 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5703 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5704 """,
5705 impl = """
5706 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5707 PyThreadState *tstate = PyThreadState_GET();
5708 *type = tstate->exc_type;
5709 *value = tstate->exc_value;
5710 *tb = tstate->exc_traceback;
5711 Py_XINCREF(*type);
5712 Py_XINCREF(*value);
5713 Py_XINCREF(*tb);
5714 }
5716 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5717 PyObject *tmp_type, *tmp_value, *tmp_tb;
5718 PyThreadState *tstate = PyThreadState_GET();
5719 tmp_type = tstate->exc_type;
5720 tmp_value = tstate->exc_value;
5721 tmp_tb = tstate->exc_traceback;
5722 tstate->exc_type = type;
5723 tstate->exc_value = value;
5724 tstate->exc_traceback = tb;
5725 Py_XDECREF(tmp_type);
5726 Py_XDECREF(tmp_value);
5727 Py_XDECREF(tmp_tb);
5728 }
5729 """)
5731 #------------------------------------------------------------------------------------
5733 force_init_threads_utility_code = UtilityCode(
5734 proto="""
5735 #ifndef __PYX_FORCE_INIT_THREADS
5736 #if PY_VERSION_HEX < 0x02040200
5737 #define __PYX_FORCE_INIT_THREADS 1
5738 #else
5739 #define __PYX_FORCE_INIT_THREADS 0
5740 #endif
5741 #endif
5742 """)
5744 #------------------------------------------------------------------------------------
