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