Cython has moved to github.
cython-devel
view Cython/Compiler/Nodes.py @ 1863:51b79d9aca35
Fix #156, missing self in cpdef method.
| author | Robert Bradshaw <robertwb@math.washington.edu> |
|---|---|
| date | Sat Mar 14 22:45:55 2009 -0700 (3 years ago) |
| parents | 620326b14c3f |
| children | b1bdbb05d78c |
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 from DebugFlags import debug_disposal_code
24 absolute_path_length = 0
26 def relative_position(pos):
27 """
28 We embed the relative filename in the generated C file, since we
29 don't want to have to regnerate and compile all the source code
30 whenever the Python install directory moves (which could happen,
31 e.g,. when distributing binaries.)
33 INPUT:
34 a position tuple -- (absolute filename, line number column position)
36 OUTPUT:
37 relative filename
38 line number
40 AUTHOR: William Stein
41 """
42 global absolute_path_length
43 if absolute_path_length==0:
44 absolute_path_length = len(os.path.abspath(os.getcwd()))
45 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
47 def embed_position(pos, docstring):
48 if not Options.embed_pos_in_docstring:
49 return docstring
50 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
51 if docstring is None:
52 # unicode string
53 return EncodedString(pos_line)
55 # make sure we can encode the filename in the docstring encoding
56 # otherwise make the docstring a unicode string
57 encoding = docstring.encoding
58 if encoding is not None:
59 try:
60 encoded_bytes = pos_line.encode(encoding)
61 except UnicodeEncodeError:
62 encoding = None
64 if not docstring:
65 # reuse the string encoding of the original docstring
66 doc = EncodedString(pos_line)
67 else:
68 doc = EncodedString(pos_line + u'\n' + docstring)
69 doc.encoding = encoding
70 return doc
73 from Code import CCodeWriter
74 from types import FunctionType
76 def write_func_call(func):
77 def f(*args, **kwds):
78 if len(args) > 1 and isinstance(args[1], CCodeWriter):
79 # here we annotate the code with this function call
80 # but only if new code is generated
81 node, code = args[:2]
82 marker = ' /* %s -> %s.%s %s */' % (
83 ' ' * code.call_level,
84 node.__class__.__name__,
85 func.__name__,
86 node.pos[1:])
87 pristine = code.buffer.stream.tell()
88 code.putln(marker)
89 start = code.buffer.stream.tell()
90 code.call_level += 4
91 res = func(*args, **kwds)
92 code.call_level -= 4
93 if start == code.buffer.stream.tell():
94 code.buffer.stream.seek(pristine)
95 else:
96 marker = marker.replace('->', '<-')
97 code.putln(marker)
98 return res
99 else:
100 return func(*args, **kwds)
101 return f
103 class VerboseCodeWriter(type):
104 # Set this as a metaclass to trace function calls in code.
105 # This slows down code generation and makes much larger files.
106 def __new__(cls, name, bases, attrs):
107 attrs = dict(attrs)
108 for mname, m in attrs.items():
109 if isinstance(m, FunctionType):
110 attrs[mname] = write_func_call(m)
111 return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
114 class Node(object):
115 # pos (string, int, int) Source file position
116 # is_name boolean Is a NameNode
117 # is_literal boolean Is a ConstNode
119 # Uncomment this for debugging.
120 # __metaclass__ = VerboseCodeWriter
122 is_name = 0
123 is_literal = 0
124 temps = None
126 # All descandants should set child_attrs to a list of the attributes
127 # containing nodes considered "children" in the tree. Each such attribute
128 # can either contain a single node or a list of nodes. See Visitor.py.
129 child_attrs = None
131 def __init__(self, pos, **kw):
132 self.pos = pos
133 self.__dict__.update(kw)
135 gil_message = "Operation"
137 def gil_check(self, env):
138 if env.nogil:
139 self.gil_error()
141 def gil_error(self):
142 error(self.pos, "%s not allowed without gil" % self.gil_message)
144 def clone_node(self):
145 """Clone the node. This is defined as a shallow copy, except for member lists
146 amongst the child attributes (from get_child_accessors) which are also
147 copied. Lists containing child nodes are thus seen as a way for the node
148 to hold multiple children directly; the list is not treated as a seperate
149 level in the tree."""
150 result = copy.copy(self)
151 for attrname in result.child_attrs:
152 value = getattr(result, attrname)
153 if isinstance(value, list):
154 setattr(result, attrname, [x for x in value])
155 return result
158 #
159 # There are 4 phases of parse tree processing, applied in order to
160 # all the statements in a given scope-block:
161 #
162 # (0) analyse_control_flow
163 # Create the control flow tree into which state can be asserted and
164 # queried.
165 #
166 # (1) analyse_declarations
167 # Make symbol table entries for all declarations at the current
168 # level, both explicit (def, cdef, etc.) and implicit (assignment
169 # to an otherwise undeclared name).
170 #
171 # (2) analyse_expressions
172 # Determine the result types of expressions and fill in the
173 # 'type' attribute of each ExprNode. Insert coercion nodes into the
174 # tree where needed to convert to and from Python objects.
175 # Allocate temporary locals for intermediate results. Fill
176 # in the 'result_code' attribute of each ExprNode with a C code
177 # fragment.
178 #
179 # (3) generate_code
180 # Emit C code for all declarations, statements and expressions.
181 # Recursively applies the 3 processing phases to the bodies of
182 # functions.
183 #
185 def analyse_control_flow(self, env):
186 pass
188 def analyse_declarations(self, env):
189 pass
191 def analyse_expressions(self, env):
192 raise InternalError("analyse_expressions not implemented for %s" % \
193 self.__class__.__name__)
195 def generate_code(self, code):
196 raise InternalError("generate_code not implemented for %s" % \
197 self.__class__.__name__)
199 def annotate(self, code):
200 # mro does the wrong thing
201 if isinstance(self, BlockNode):
202 self.body.annotate(code)
204 def end_pos(self):
205 try:
206 return self._end_pos
207 except AttributeError:
208 pos = self.pos
209 if not self.child_attrs:
210 self._end_pos = pos
211 return pos
212 for attr in self.child_attrs:
213 child = getattr(self, attr)
214 # Sometimes lists, sometimes nodes
215 if child is None:
216 pass
217 elif isinstance(child, list):
218 for c in child:
219 pos = max(pos, c.end_pos())
220 else:
221 pos = max(pos, child.end_pos())
222 self._end_pos = pos
223 return pos
225 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
226 if cutoff == 0:
227 return "<...nesting level cutoff...>"
228 if encountered is None:
229 encountered = set()
230 if id(self) in encountered:
231 return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
232 encountered.add(id(self))
234 def dump_child(x, level):
235 if isinstance(x, Node):
236 return x.dump(level, filter_out, cutoff-1, encountered)
237 elif isinstance(x, list):
238 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
239 else:
240 return repr(x)
243 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
244 if len(attrs) == 0:
245 return "<%s (%d)>" % (self.__class__.__name__, id(self))
246 else:
247 indent = " " * level
248 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
249 for key, value in attrs:
250 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
251 res += "%s>" % indent
252 return res
254 class CompilerDirectivesNode(Node):
255 """
256 Sets compiler directives for the children nodes
257 """
258 # directives {string:value} A dictionary holding the right value for
259 # *all* possible directives.
260 # body Node
261 child_attrs = ["body"]
263 def analyse_control_flow(self, env):
264 old = env.directives
265 env.directives = self.directives
266 self.body.analyse_control_flow(env)
267 env.directives = old
269 def analyse_declarations(self, env):
270 old = env.directives
271 env.directives = self.directives
272 self.body.analyse_declarations(env)
273 env.directives = old
275 def analyse_expressions(self, env):
276 old = env.directives
277 env.directives = self.directives
278 self.body.analyse_expressions(env)
279 env.directives = old
281 def generate_function_definitions(self, env, code):
282 env_old = env.directives
283 code_old = code.globalstate.directives
284 code.globalstate.directives = self.directives
285 self.body.generate_function_definitions(env, code)
286 env.directives = env_old
287 code.globalstate.directives = code_old
289 def generate_execution_code(self, code):
290 old = code.globalstate.directives
291 code.globalstate.directives = self.directives
292 self.body.generate_execution_code(code)
293 code.globalstate.directives = old
295 def annotate(self, code):
296 old = code.globalstate.directives
297 code.globalstate.directives = self.directives
298 self.body.annotate(code)
299 code.globalstate.directives = old
301 class BlockNode(object):
302 # Mixin class for nodes representing a declaration block.
304 def generate_const_definitions(self, env, code):
305 if env.const_entries:
306 for entry in env.const_entries:
307 if not entry.is_interned:
308 code.globalstate.add_const_definition(entry)
310 def generate_interned_string_decls(self, env, code):
311 entries = env.global_scope().new_interned_string_entries
312 if entries:
313 for entry in entries:
314 code.globalstate.add_interned_string_decl(entry)
315 del entries[:]
317 def generate_py_string_decls(self, env, code):
318 if env is None:
319 return # earlier error
320 entries = env.pystring_entries
321 if entries:
322 for entry in entries:
323 if not entry.is_interned:
324 code.globalstate.add_py_string_decl(entry)
326 def generate_interned_num_decls(self, env, code):
327 # Flush accumulated interned nums from the global scope
328 # and generate declarations for them.
329 genv = env.global_scope()
330 entries = genv.interned_nums
331 if entries:
332 for entry in entries:
333 code.globalstate.add_interned_num_decl(entry)
334 del entries[:]
336 def generate_cached_builtins_decls(self, env, code):
337 entries = env.global_scope().undeclared_cached_builtins
338 for entry in entries:
339 code.globalstate.add_cached_builtin_decl(entry)
340 del entries[:]
343 class StatListNode(Node):
344 # stats a list of StatNode
346 child_attrs = ["stats"]
348 def create_analysed(pos, env, *args, **kw):
349 node = StatListNode(pos, *args, **kw)
350 return node # No node-specific analysis necesarry
351 create_analysed = staticmethod(create_analysed)
353 def analyse_control_flow(self, env):
354 for stat in self.stats:
355 stat.analyse_control_flow(env)
357 def analyse_declarations(self, env):
358 #print "StatListNode.analyse_declarations" ###
359 for stat in self.stats:
360 stat.analyse_declarations(env)
362 def analyse_expressions(self, env):
363 #print "StatListNode.analyse_expressions" ###
364 for stat in self.stats:
365 stat.analyse_expressions(env)
367 def generate_function_definitions(self, env, code):
368 #print "StatListNode.generate_function_definitions" ###
369 for stat in self.stats:
370 stat.generate_function_definitions(env, code)
372 def generate_execution_code(self, code):
373 #print "StatListNode.generate_execution_code" ###
374 for stat in self.stats:
375 code.mark_pos(stat.pos)
376 stat.generate_execution_code(code)
378 def annotate(self, code):
379 for stat in self.stats:
380 stat.annotate(code)
383 class StatNode(Node):
384 #
385 # Code generation for statements is split into the following subphases:
386 #
387 # (1) generate_function_definitions
388 # Emit C code for the definitions of any structs,
389 # unions, enums and functions defined in the current
390 # scope-block.
391 #
392 # (2) generate_execution_code
393 # Emit C code for executable statements.
394 #
396 def generate_function_definitions(self, env, code):
397 pass
399 def generate_execution_code(self, code):
400 raise InternalError("generate_execution_code not implemented for %s" % \
401 self.__class__.__name__)
404 class CDefExternNode(StatNode):
405 # include_file string or None
406 # body StatNode
408 child_attrs = ["body"]
410 def analyse_declarations(self, env):
411 if self.include_file:
412 env.add_include_file(self.include_file)
413 old_cinclude_flag = env.in_cinclude
414 env.in_cinclude = 1
415 self.body.analyse_declarations(env)
416 env.in_cinclude = old_cinclude_flag
418 def analyse_expressions(self, env):
419 pass
421 def generate_execution_code(self, code):
422 pass
424 def annotate(self, code):
425 self.body.annotate(code)
428 class CDeclaratorNode(Node):
429 # Part of a C declaration.
430 #
431 # Processing during analyse_declarations phase:
432 #
433 # analyse
434 # Returns (name, type) pair where name is the
435 # CNameDeclaratorNode of the name being declared
436 # and type is the type it is being declared as.
437 #
438 # calling_convention string Calling convention of CFuncDeclaratorNode
439 # for which this is a base
441 child_attrs = []
443 calling_convention = ""
446 class CNameDeclaratorNode(CDeclaratorNode):
447 # name string The Pyrex name being declared
448 # cname string or None C name, if specified
449 # default ExprNode or None the value assigned on declaration
451 child_attrs = ['default']
453 default = None
455 def analyse(self, base_type, env, nonempty = 0):
456 if nonempty and self.name == '':
457 # May have mistaken the name for the type.
458 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
459 error(self.pos, "Missing argument name")
460 elif base_type.is_void:
461 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
462 else:
463 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
464 base_type = py_object_type
465 self.type = base_type
466 return self, base_type
468 class CPtrDeclaratorNode(CDeclaratorNode):
469 # base CDeclaratorNode
471 child_attrs = ["base"]
473 def analyse(self, base_type, env, nonempty = 0):
474 if base_type.is_pyobject:
475 error(self.pos,
476 "Pointer base type cannot be a Python object")
477 ptr_type = PyrexTypes.c_ptr_type(base_type)
478 return self.base.analyse(ptr_type, env, nonempty = nonempty)
480 class CArrayDeclaratorNode(CDeclaratorNode):
481 # base CDeclaratorNode
482 # dimension ExprNode
484 child_attrs = ["base", "dimension"]
486 def analyse(self, base_type, env, nonempty = 0):
487 if self.dimension:
488 self.dimension.analyse_const_expression(env)
489 if not self.dimension.type.is_int:
490 error(self.dimension.pos, "Array dimension not integer")
491 size = self.dimension.result()
492 try:
493 size = int(size)
494 except ValueError:
495 # runtime constant?
496 pass
497 else:
498 size = None
499 if not base_type.is_complete():
500 error(self.pos,
501 "Array element type '%s' is incomplete" % base_type)
502 if base_type.is_pyobject:
503 error(self.pos,
504 "Array element cannot be a Python object")
505 if base_type.is_cfunction:
506 error(self.pos,
507 "Array element cannot be a function")
508 array_type = PyrexTypes.c_array_type(base_type, size)
509 return self.base.analyse(array_type, env, nonempty = nonempty)
512 class CFuncDeclaratorNode(CDeclaratorNode):
513 # base CDeclaratorNode
514 # args [CArgDeclNode]
515 # has_varargs boolean
516 # exception_value ConstNode
517 # exception_check boolean True if PyErr_Occurred check needed
518 # nogil boolean Can be called without gil
519 # with_gil boolean Acquire gil around function body
521 child_attrs = ["base", "args", "exception_value"]
523 overridable = 0
524 optional_arg_count = 0
526 def analyse(self, return_type, env, nonempty = 0):
527 if nonempty:
528 nonempty -= 1
529 func_type_args = []
530 for arg_node in self.args:
531 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
532 name = name_declarator.name
533 if name_declarator.cname:
534 error(self.pos,
535 "Function argument cannot have C name specification")
536 # Turn *[] argument into **
537 if type.is_array:
538 type = PyrexTypes.c_ptr_type(type.base_type)
539 # Catch attempted C-style func(void) decl
540 if type.is_void:
541 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
542 # if type.is_pyobject and self.nogil:
543 # error(self.pos,
544 # "Function with Python argument cannot be declared nogil")
545 func_type_args.append(
546 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
547 if arg_node.default:
548 self.optional_arg_count += 1
549 elif self.optional_arg_count:
550 error(self.pos, "Non-default argument follows default argument")
552 if self.optional_arg_count:
553 scope = StructOrUnionScope()
554 scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
555 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
556 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
557 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
558 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
559 kind = 'struct',
560 scope = scope,
561 typedef_flag = 0,
562 pos = self.pos,
563 cname = struct_cname)
564 self.op_args_struct.defined_in_pxd = 1
565 self.op_args_struct.used = 1
567 exc_val = None
568 exc_check = 0
569 if return_type.is_pyobject \
570 and (self.exception_value or self.exception_check) \
571 and self.exception_check != '+':
572 error(self.pos,
573 "Exception clause not allowed for function returning Python object")
574 else:
575 if self.exception_value:
576 self.exception_value.analyse_const_expression(env)
577 if self.exception_check == '+':
578 exc_val_type = self.exception_value.type
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 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1079 # ----- Automatic lead-ins for certain special functions
1080 if not lenv.nogil:
1081 code.put_setup_refcount_context(self.entry.name)
1082 if is_getbuffer_slot:
1083 self.getbuffer_init(code)
1084 # ----- Fetch arguments
1085 self.generate_argument_parsing_code(env, code)
1086 # If an argument is assigned to in the body, we must
1087 # incref it to properly keep track of refcounts.
1088 for entry in lenv.arg_entries:
1089 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1090 code.put_var_incref(entry)
1091 # ----- Initialise local variables
1092 for entry in lenv.var_entries:
1093 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1094 code.put_init_var_to_py_none(entry)
1095 # ----- Initialise local buffer auxiliary variables
1096 for entry in lenv.var_entries + lenv.arg_entries:
1097 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1098 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1099 # ----- Check and convert arguments
1100 self.generate_argument_type_tests(code)
1101 # ----- Acquire buffer arguments
1102 for entry in lenv.arg_entries:
1103 if entry.type.is_buffer:
1104 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1105 # ----- Function body
1106 self.body.generate_execution_code(code)
1107 # ----- Default return value
1108 code.putln("")
1109 if self.return_type.is_pyobject:
1110 #if self.return_type.is_extension_type:
1111 # lhs = "(PyObject *)%s" % Naming.retval_cname
1112 #else:
1113 lhs = Naming.retval_cname
1114 code.put_init_to_py_none(lhs, self.return_type)
1115 else:
1116 val = self.return_type.default_value
1117 if val:
1118 code.putln("%s = %s;" % (Naming.retval_cname, val))
1119 # ----- Error cleanup
1120 if code.error_label in code.labels_used:
1121 code.put_goto(code.return_label)
1122 code.put_label(code.error_label)
1123 # cleanup temps the old way
1124 code.put_var_xdecrefs(lenv.temp_entries)
1125 # cleanup temps the new way
1126 for cname, type in code.funcstate.all_managed_temps():
1127 code.put_xdecref(cname, type)
1129 # Clean up buffers -- this calls a Python function
1130 # so need to save and restore error state
1131 buffers_present = len(lenv.buffer_entries) > 0
1132 if buffers_present:
1133 code.globalstate.use_utility_code(restore_exception_utility_code)
1134 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1135 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1136 for entry in lenv.buffer_entries:
1137 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1138 #code.putln("%s = 0;" % entry.cname)
1139 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1141 err_val = self.error_value()
1142 exc_check = self.caller_will_check_exceptions()
1143 if err_val is not None or exc_check:
1144 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1145 else:
1146 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1147 % self.entry.qualified_name, 0)
1148 code.putln(
1149 '__Pyx_WriteUnraisable("%s");' %
1150 self.entry.qualified_name)
1151 env.use_utility_code(unraisable_exception_utility_code)
1152 env.use_utility_code(restore_exception_utility_code)
1153 default_retval = self.return_type.default_value
1154 if err_val is None and default_retval:
1155 err_val = default_retval
1156 if err_val is not None:
1157 code.putln(
1158 "%s = %s;" % (
1159 Naming.retval_cname,
1160 err_val))
1162 if is_getbuffer_slot:
1163 self.getbuffer_error_cleanup(code)
1165 # If we are using the non-error cleanup section we should
1166 # jump past it if we have an error. The if-test below determine
1167 # whether this section is used.
1168 if buffers_present or is_getbuffer_slot:
1169 code.put_goto(code.return_from_error_cleanup_label)
1172 # ----- Non-error return cleanup
1173 # If you add anything here, remember to add a condition to the
1174 # if-test above in the error block (so that it can jump past this
1175 # block).
1176 code.put_label(code.return_label)
1177 for entry in lenv.buffer_entries:
1178 if entry.used:
1179 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1180 if is_getbuffer_slot:
1181 self.getbuffer_normal_cleanup(code)
1182 # ----- Return cleanup for both error and no-error return
1183 code.put_label(code.return_from_error_cleanup_label)
1184 if not Options.init_local_none:
1185 for entry in lenv.var_entries:
1186 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1187 entry.xdecref_cleanup = 1
1188 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1189 # Decref any increfed args
1190 for entry in lenv.arg_entries:
1191 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1192 code.put_var_decref(entry)
1194 # code.putln("/* TODO: decref scope object */")
1195 # ----- Return
1196 # This code is duplicated in ModuleNode.generate_module_init_func
1197 if not lenv.nogil:
1198 default_retval = self.return_type.default_value
1199 err_val = self.error_value()
1200 if err_val is None and default_retval:
1201 err_val = default_retval
1202 if self.return_type.is_pyobject:
1203 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1205 code.put_finish_refcount_context()
1207 if acquire_gil:
1208 code.putln("PyGILState_Release(_save);")
1210 if not self.return_type.is_void:
1211 code.putln("return %s;" % Naming.retval_cname)
1213 code.putln("}")
1214 # ----- Go back and insert temp variable declarations
1215 tempvardecl_code.put_var_declarations(lenv.temp_entries)
1216 tempvardecl_code.put_temp_declarations(code.funcstate)
1217 # ----- Python version
1218 code.exit_cfunc_scope()
1219 if self.py_func:
1220 self.py_func.generate_function_definitions(env, code)
1221 self.generate_wrapper_functions(code)
1223 def declare_argument(self, env, arg):
1224 if arg.type.is_void:
1225 error(arg.pos, "Invalid use of 'void'")
1226 elif not arg.type.is_complete() and not arg.type.is_array:
1227 error(arg.pos,
1228 "Argument type '%s' is incomplete" % arg.type)
1229 return env.declare_arg(arg.name, arg.type, arg.pos)
1231 def generate_wrapper_functions(self, code):
1232 pass
1234 def generate_execution_code(self, code):
1235 # Evaluate and store argument default values
1236 for arg in self.args:
1237 default = arg.default
1238 if default:
1239 if not default.is_literal:
1240 default.generate_evaluation_code(code)
1241 default.make_owned_reference(code)
1242 code.putln(
1243 "%s = %s;" % (
1244 arg.default_entry.cname,
1245 default.result_as(arg.default_entry.type)))
1246 if default.is_temp and default.type.is_pyobject:
1247 code.putln("%s = 0;" % default.result())
1248 default.free_temps(code)
1249 code.put_var_giveref(arg.default_entry)
1250 # For Python class methods, create and store function object
1251 if self.assmt:
1252 self.assmt.generate_execution_code(code)
1254 #
1255 # Special code for the __getbuffer__ function
1256 #
1257 def getbuffer_init(self, code):
1258 info = self.local_scope.arg_entries[1].cname
1259 # Python 3.0 betas have a bug in memoryview which makes it call
1260 # getbuffer with a NULL parameter. For now we work around this;
1261 # the following line should be removed when this bug is fixed.
1262 code.putln("if (%s == NULL) return 0;" % info)
1263 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1264 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1266 def getbuffer_error_cleanup(self, code):
1267 info = self.local_scope.arg_entries[1].cname
1268 code.put_gotref("%s->obj" % info)
1269 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1270 (info, info))
1272 def getbuffer_normal_cleanup(self, code):
1273 info = self.local_scope.arg_entries[1].cname
1274 code.putln("if (%s->obj == Py_None) {" % info)
1275 code.put_gotref("Py_None")
1276 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1277 code.putln("}")
1279 class CFuncDefNode(FuncDefNode):
1280 # C function definition.
1281 #
1282 # modifiers ['inline']
1283 # visibility 'private' or 'public' or 'extern'
1284 # base_type CBaseTypeNode
1285 # declarator CDeclaratorNode
1286 # body StatListNode
1287 # api boolean
1288 # decorators [DecoratorNode] list of decorators
1289 #
1290 # with_gil boolean Acquire GIL around body
1291 # type CFuncType
1292 # py_func wrapper for calling from Python
1293 # overridable whether or not this is a cpdef function
1294 # inline_in_pxd whether this is an inline function in a pxd file
1296 child_attrs = ["base_type", "declarator", "body", "py_func"]
1298 inline_in_pxd = False
1299 decorators = None
1300 directive_locals = {}
1302 def unqualified_name(self):
1303 return self.entry.name
1305 def analyse_declarations(self, env):
1306 if 'locals' in env.directives and env.directives['locals']:
1307 self.directive_locals = env.directives['locals']
1308 directive_locals = self.directive_locals
1309 base_type = self.base_type.analyse(env)
1310 # The 2 here is because we need both function and argument names.
1311 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1312 if not type.is_cfunction:
1313 error(self.pos,
1314 "Suite attached to non-function declaration")
1315 # Remember the actual type according to the function header
1316 # written here, because the type in the symbol table entry
1317 # may be different if we're overriding a C method inherited
1318 # from the base type of an extension type.
1319 self.type = type
1320 type.is_overridable = self.overridable
1321 declarator = self.declarator
1322 while not hasattr(declarator, 'args'):
1323 declarator = declarator.base
1324 self.args = declarator.args
1325 for formal_arg, type_arg in zip(self.args, type.args):
1326 formal_arg.type = type_arg.type
1327 formal_arg.name = type_arg.name
1328 formal_arg.cname = type_arg.cname
1329 name = name_declarator.name
1330 cname = name_declarator.cname
1331 self.entry = env.declare_cfunction(
1332 name, type, self.pos,
1333 cname = cname, visibility = self.visibility,
1334 defining = self.body is not None,
1335 api = self.api, modifiers = self.modifiers)
1336 self.entry.inline_func_in_pxd = self.inline_in_pxd
1337 self.return_type = type.return_type
1339 if self.overridable and len(self.args) > 0:
1340 import ExprNodes
1341 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1342 self.py_func = DefNode(pos = self.pos,
1343 name = self.entry.name,
1344 args = self.args,
1345 star_arg = None,
1346 starstar_arg = None,
1347 doc = self.doc,
1348 body = py_func_body,
1349 is_wrapper = 1)
1350 self.py_func.is_module_scope = env.is_module_scope
1351 self.py_func.analyse_declarations(env)
1352 self.entry.as_variable = self.py_func.entry
1353 # Reset scope entry the above cfunction
1354 env.entries[name] = self.entry
1355 self.py_func.interned_attr_cname = env.intern_identifier(
1356 self.py_func.entry.name)
1357 if not env.is_module_scope or Options.lookup_module_cpdef:
1358 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1359 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1361 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1362 import ExprNodes
1363 args = self.type.args
1364 if omit_optional_args:
1365 args = args[:len(args) - self.type.optional_arg_count]
1366 arg_names = [arg.name for arg in args]
1367 if is_module_scope:
1368 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1369 else:
1370 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1371 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1372 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1373 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)
1374 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1376 def declare_arguments(self, env):
1377 for arg in self.type.args:
1378 if not arg.name:
1379 error(arg.pos, "Missing argument name")
1380 self.declare_argument(env, arg)
1382 def need_gil_acquisition(self, lenv):
1383 type = self.type
1384 with_gil = self.type.with_gil
1385 if type.nogil and not with_gil:
1386 if type.return_type.is_pyobject:
1387 error(self.pos,
1388 "Function with Python return type cannot be declared nogil")
1389 for entry in lenv.var_entries + lenv.temp_entries:
1390 if entry.type.is_pyobject:
1391 error(self.pos, "Function declared nogil has Python locals or temporaries")
1392 return with_gil
1394 def analyse_expressions(self, env):
1395 self.analyse_default_values(env)
1396 if self.py_func is not None:
1397 self.py_func.analyse_expressions(env)
1399 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1400 arg_decls = []
1401 type = self.type
1402 visibility = self.entry.visibility
1403 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1404 arg_decls.append(arg.declaration_code())
1405 if with_dispatch and self.overridable:
1406 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1407 if type.optional_arg_count and with_opt_args:
1408 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1409 if type.has_varargs:
1410 arg_decls.append("...")
1411 if not arg_decls:
1412 arg_decls = ["void"]
1413 if cname is None:
1414 cname = self.entry.func_cname
1415 entity = type.function_header_code(cname, ', '.join(arg_decls))
1416 if visibility == 'public':
1417 dll_linkage = "DL_EXPORT"
1418 else:
1419 dll_linkage = None
1420 header = self.return_type.declaration_code(entity,
1421 dll_linkage = dll_linkage)
1422 if visibility == 'extern':
1423 storage_class = "%s " % Naming.extern_c_macro
1424 elif visibility == 'public':
1425 storage_class = ""
1426 else:
1427 storage_class = "static "
1428 code.putln("%s%s %s {" % (
1429 storage_class,
1430 ' '.join(self.modifiers).upper(), # macro forms
1431 header))
1433 def generate_argument_declarations(self, env, code):
1434 for arg in self.args:
1435 if arg.default:
1436 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1438 def generate_keyword_list(self, code):
1439 pass
1441 def generate_argument_parsing_code(self, env, code):
1442 i = 0
1443 if self.type.optional_arg_count:
1444 code.putln('if (%s) {' % Naming.optional_args_cname)
1445 for arg in self.args:
1446 if arg.default:
1447 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1448 declarator = arg.declarator
1449 while not hasattr(declarator, 'name'):
1450 declarator = declarator.base
1451 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1452 i += 1
1453 for _ in range(self.type.optional_arg_count):
1454 code.putln('}')
1455 code.putln('}')
1457 def generate_argument_conversion_code(self, code):
1458 pass
1460 def generate_argument_type_tests(self, code):
1461 # Generate type tests for args whose type in a parent
1462 # class is a supertype of the declared type.
1463 for arg in self.type.args:
1464 if arg.needs_type_test:
1465 self.generate_arg_type_test(arg, code)
1467 def generate_arg_type_test(self, arg, code):
1468 # Generate type test for one argument.
1469 if arg.type.typeobj_is_available():
1470 typeptr_cname = arg.type.typeptr_cname
1471 arg_code = "((PyObject *)%s)" % arg.cname
1472 code.putln(
1473 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1474 arg_code,
1475 typeptr_cname,
1476 not arg.not_none,
1477 arg.name,
1478 type.is_builtin_type,
1479 code.error_goto(arg.pos)))
1480 else:
1481 error(arg.pos, "Cannot test type of extern C class "
1482 "without type object name specification")
1484 def error_value(self):
1485 if self.return_type.is_pyobject:
1486 return "0"
1487 else:
1488 #return None
1489 return self.entry.type.exception_value
1491 def caller_will_check_exceptions(self):
1492 return self.entry.type.exception_check
1494 def generate_wrapper_functions(self, code):
1495 # If the C signature of a function has changed, we need to generate
1496 # wrappers to put in the slots here.
1497 k = 0
1498 entry = self.entry
1499 func_type = entry.type
1500 while entry.prev_entry is not None:
1501 k += 1
1502 entry = entry.prev_entry
1503 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1504 code.putln()
1505 self.generate_function_header(code,
1506 0,
1507 with_dispatch = entry.type.is_overridable,
1508 with_opt_args = entry.type.optional_arg_count,
1509 cname = entry.func_cname)
1510 if not self.return_type.is_void:
1511 code.put('return ')
1512 args = self.type.args
1513 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1514 if entry.type.is_overridable:
1515 arglist.append(Naming.skip_dispatch_cname)
1516 elif func_type.is_overridable:
1517 arglist.append('0')
1518 if entry.type.optional_arg_count:
1519 arglist.append(Naming.optional_args_cname)
1520 elif func_type.optional_arg_count:
1521 arglist.append('NULL')
1522 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1523 code.putln('}')
1526 class PyArgDeclNode(Node):
1527 # Argument which must be a Python object (used
1528 # for * and ** arguments).
1529 #
1530 # name string
1531 # entry Symtab.Entry
1532 child_attrs = []
1535 class DecoratorNode(Node):
1536 # A decorator
1537 #
1538 # decorator NameNode or CallNode
1539 child_attrs = ['decorator']
1542 class DefNode(FuncDefNode):
1543 # A Python function definition.
1544 #
1545 # name string the Python name of the function
1546 # decorators [DecoratorNode] list of decorators
1547 # args [CArgDeclNode] formal arguments
1548 # star_arg PyArgDeclNode or None * argument
1549 # starstar_arg PyArgDeclNode or None ** argument
1550 # doc EncodedString or None
1551 # body StatListNode
1552 #
1553 # The following subnode is constructed internally
1554 # when the def statement is inside a Python class definition.
1555 #
1556 # assmt AssignmentNode Function construction/assignment
1558 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1560 assmt = None
1561 num_kwonly_args = 0
1562 num_required_kw_args = 0
1563 reqd_kw_flags_cname = "0"
1564 is_wrapper = 0
1565 decorators = None
1566 entry = None
1569 def __init__(self, pos, **kwds):
1570 FuncDefNode.__init__(self, pos, **kwds)
1571 k = rk = r = 0
1572 for arg in self.args:
1573 if arg.kw_only:
1574 k += 1
1575 if not arg.default:
1576 rk += 1
1577 if not arg.default:
1578 r += 1
1579 self.num_kwonly_args = k
1580 self.num_required_kw_args = rk
1581 self.num_required_args = r
1583 def as_cfunction(self, cfunc=None, scope=None):
1584 if self.star_arg:
1585 error(self.star_arg.pos, "cdef function cannot have star argument")
1586 if self.starstar_arg:
1587 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1588 if cfunc is None:
1589 cfunc_args = []
1590 for formal_arg in self.args:
1591 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1592 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1593 cname = None,
1594 type = py_object_type,
1595 pos = formal_arg.pos))
1596 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1597 args = cfunc_args,
1598 has_varargs = False,
1599 exception_value = None,
1600 exception_check = False,
1601 nogil = False,
1602 with_gil = False,
1603 is_overridable = True)
1604 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1605 else:
1606 cfunc_type = cfunc.type
1607 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1608 error(self.pos, "wrong number of arguments")
1609 error(declarator.pos, "previous declaration here")
1610 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1611 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1612 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1613 formal_arg.type = type_arg.type
1614 formal_arg.name_declarator = name_declarator
1615 import ExprNodes
1616 if cfunc_type.exception_value is None:
1617 exception_value = None
1618 else:
1619 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1620 declarator = CFuncDeclaratorNode(self.pos,
1621 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1622 args = self.args,
1623 has_varargs = False,
1624 exception_check = cfunc_type.exception_check,
1625 exception_value = exception_value,
1626 with_gil = cfunc_type.with_gil,
1627 nogil = cfunc_type.nogil)
1628 return CFuncDefNode(self.pos,
1629 modifiers = [],
1630 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1631 declarator = declarator,
1632 body = self.body,
1633 doc = self.doc,
1634 overridable = cfunc_type.is_overridable,
1635 type = cfunc_type,
1636 with_gil = cfunc_type.with_gil,
1637 nogil = cfunc_type.nogil,
1638 visibility = 'private',
1639 api = False,
1640 directive_locals = cfunc.directive_locals)
1642 def analyse_declarations(self, env):
1643 if 'locals' in env.directives:
1644 directive_locals = env.directives['locals']
1645 else:
1646 directive_locals = {}
1647 self.directive_locals = directive_locals
1648 for arg in self.args:
1649 if hasattr(arg, 'name'):
1650 type = arg.type
1651 name_declarator = None
1652 else:
1653 base_type = arg.base_type.analyse(env)
1654 name_declarator, type = \
1655 arg.declarator.analyse(base_type, env)
1656 arg.name = name_declarator.name
1657 if arg.name in directive_locals:
1658 type_node = directive_locals[arg.name]
1659 other_type = type_node.analyse_as_type(env)
1660 if other_type is None:
1661 error(type_node.pos, "Not a type")
1662 elif (type is not PyrexTypes.py_object_type
1663 and not type.same_as(other_type)):
1664 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1665 error(type_node.pos, "Previous declaration here")
1666 else:
1667 type = other_type
1668 if name_declarator and name_declarator.cname:
1669 error(self.pos,
1670 "Python function argument cannot have C name specification")
1671 arg.type = type.as_argument_type()
1672 arg.hdr_type = None
1673 arg.needs_conversion = 0
1674 arg.needs_type_test = 0
1675 arg.is_generic = 1
1676 if arg.not_none and not arg.type.is_extension_type:
1677 error(self.pos,
1678 "Only extension type arguments can have 'not None'")
1679 self.declare_pyfunction(env)
1680 self.analyse_signature(env)
1681 self.return_type = self.entry.signature.return_type()
1683 def analyse_signature(self, env):
1684 any_type_tests_needed = 0
1685 # Use the simpler calling signature for zero- and one-argument functions.
1686 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1687 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1688 if len(self.args) == 0:
1689 self.entry.signature = TypeSlots.pyfunction_noargs
1690 elif len(self.args) == 1:
1691 if self.args[0].default is None and not self.args[0].kw_only:
1692 self.entry.signature = TypeSlots.pyfunction_onearg
1693 elif self.entry.signature is TypeSlots.pymethod_signature:
1694 if len(self.args) == 1:
1695 self.entry.signature = TypeSlots.unaryfunc
1696 elif len(self.args) == 2:
1697 if self.args[1].default is None and not self.args[1].kw_only:
1698 self.entry.signature = TypeSlots.ibinaryfunc
1699 elif self.entry.is_special:
1700 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1701 sig = self.entry.signature
1702 nfixed = sig.num_fixed_args()
1703 for i in range(nfixed):
1704 if i < len(self.args):
1705 arg = self.args[i]
1706 arg.is_generic = 0
1707 if sig.is_self_arg(i):
1708 arg.is_self_arg = 1
1709 arg.hdr_type = arg.type = env.parent_type
1710 arg.needs_conversion = 0
1711 else:
1712 arg.hdr_type = sig.fixed_arg_type(i)
1713 if not arg.type.same_as(arg.hdr_type):
1714 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1715 arg.needs_type_test = 1
1716 any_type_tests_needed = 1
1717 else:
1718 arg.needs_conversion = 1
1719 if arg.needs_conversion:
1720 arg.hdr_cname = Naming.arg_prefix + arg.name
1721 else:
1722 arg.hdr_cname = Naming.var_prefix + arg.name
1723 else:
1724 self.bad_signature()
1725 return
1726 if nfixed < len(self.args):
1727 if not sig.has_generic_args:
1728 self.bad_signature()
1729 for arg in self.args:
1730 if arg.is_generic and \
1731 (arg.type.is_extension_type or arg.type.is_builtin_type):
1732 arg.needs_type_test = 1
1733 any_type_tests_needed = 1
1734 if any_type_tests_needed:
1735 env.use_utility_code(arg_type_test_utility_code)
1737 def bad_signature(self):
1738 sig = self.entry.signature
1739 expected_str = "%d" % sig.num_fixed_args()
1740 if sig.has_generic_args:
1741 expected_str = expected_str + " or more"
1742 name = self.name
1743 if name.startswith("__") and name.endswith("__"):
1744 desc = "Special method"
1745 else:
1746 desc = "Method"
1747 error(self.pos,
1748 "%s %s has wrong number of arguments "
1749 "(%d declared, %s expected)" % (
1750 desc, self.name, len(self.args), expected_str))
1752 def signature_has_nongeneric_args(self):
1753 argcount = len(self.args)
1754 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1755 return 0
1756 return 1
1758 def signature_has_generic_args(self):
1759 return self.entry.signature.has_generic_args
1761 def declare_pyfunction(self, env):
1762 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1763 name = self.name
1764 entry = env.lookup_here(self.name)
1765 if entry and entry.type.is_cfunction and not self.is_wrapper:
1766 warning(self.pos, "Overriding cdef method with def method.", 5)
1767 entry = env.declare_pyfunction(self.name, self.pos)
1768 self.entry = entry
1769 prefix = env.scope_prefix
1770 entry.func_cname = \
1771 Naming.pyfunc_prefix + prefix + name
1772 entry.pymethdef_cname = \
1773 Naming.pymethdef_prefix + prefix + name
1774 if Options.docstrings:
1775 entry.doc = embed_position(self.pos, self.doc)
1776 entry.doc_cname = \
1777 Naming.funcdoc_prefix + prefix + name
1778 else:
1779 entry.doc = None
1781 def declare_arguments(self, env):
1782 for arg in self.args:
1783 if not arg.name:
1784 error(arg.pos, "Missing argument name")
1785 if arg.needs_conversion:
1786 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1787 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1788 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1789 if arg.type.is_pyobject:
1790 arg.entry.init = "0"
1791 arg.entry.init_to_none = 0
1792 else:
1793 arg.entry = self.declare_argument(env, arg)
1794 arg.entry.used = 1
1795 arg.entry.is_self_arg = arg.is_self_arg
1796 if not arg.is_self_arg:
1797 arg.name_entry = env.get_string_const(
1798 arg.name, identifier = True)
1799 env.add_py_string(arg.name_entry, identifier = True)
1800 if arg.hdr_type:
1801 if arg.is_self_arg or \
1802 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1803 arg.entry.is_declared_generic = 1
1804 self.declare_python_arg(env, self.star_arg)
1805 self.declare_python_arg(env, self.starstar_arg)
1807 def declare_python_arg(self, env, arg):
1808 if arg:
1809 entry = env.declare_var(arg.name,
1810 PyrexTypes.py_object_type, arg.pos)
1811 entry.used = 1
1812 entry.init = "0"
1813 entry.init_to_none = 0
1814 entry.xdecref_cleanup = 1
1815 arg.entry = entry
1816 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1818 def analyse_expressions(self, env):
1819 self.analyse_default_values(env)
1820 if env.is_py_class_scope:
1821 self.synthesize_assignment_node(env)
1823 def synthesize_assignment_node(self, env):
1824 import ExprNodes
1825 self.assmt = SingleAssignmentNode(self.pos,
1826 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1827 rhs = ExprNodes.UnboundMethodNode(self.pos,
1828 class_cname = env.class_obj_cname,
1829 function = ExprNodes.PyCFunctionNode(self.pos,
1830 pymethdef_cname = self.entry.pymethdef_cname)))
1831 self.assmt.analyse_declarations(env)
1832 self.assmt.analyse_expressions(env)
1834 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1835 arg_code_list = []
1836 sig = self.entry.signature
1837 if sig.has_dummy_arg:
1838 arg_code_list.append(
1839 "PyObject *%s" % Naming.self_cname)
1840 for arg in self.args:
1841 if not arg.is_generic:
1842 if arg.is_self_arg:
1843 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1844 else:
1845 arg_code_list.append(
1846 arg.hdr_type.declaration_code(arg.hdr_cname))
1847 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1848 arg_code_list.append("PyObject *unused")
1849 if sig.has_generic_args:
1850 arg_code_list.append(
1851 "PyObject *%s, PyObject *%s"
1852 % (Naming.args_cname, Naming.kwds_cname))
1853 arg_code = ", ".join(arg_code_list)
1854 dc = self.return_type.declaration_code(self.entry.func_cname)
1855 header = "static %s(%s)" % (dc, arg_code)
1856 code.putln("%s; /*proto*/" % header)
1857 if proto_only:
1858 return
1859 if self.entry.doc and Options.docstrings:
1860 docstr = self.entry.doc
1861 if not isinstance(docstr, str):
1862 docstr = docstr.utf8encode()
1863 code.putln(
1864 'static char %s[] = "%s";' % (
1865 self.entry.doc_cname,
1866 split_docstring(escape_byte_string(docstr))))
1867 if with_pymethdef:
1868 code.put(
1869 "static PyMethodDef %s = " %
1870 self.entry.pymethdef_cname)
1871 code.put_pymethoddef(self.entry, ";")
1872 code.putln("%s {" % header)
1874 def generate_argument_declarations(self, env, code):
1875 for arg in self.args:
1876 if arg.is_generic: # or arg.needs_conversion:
1877 if arg.needs_conversion:
1878 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1879 else:
1880 code.put_var_declaration(arg.entry)
1882 def generate_keyword_list(self, code):
1883 if self.signature_has_generic_args() and \
1884 self.signature_has_nongeneric_args():
1885 code.put(
1886 "static PyObject **%s[] = {" %
1887 Naming.pykwdlist_cname)
1888 for arg in self.args:
1889 if arg.is_generic:
1890 code.put('&%s,' % arg.name_entry.pystring_cname)
1891 code.putln("0};")
1893 def generate_argument_parsing_code(self, env, code):
1894 # Generate PyArg_ParseTuple call for generic
1895 # arguments, if any.
1896 if self.entry.signature.has_dummy_arg:
1897 # get rid of unused argument warning
1898 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1900 old_error_label = code.new_error_label()
1901 our_error_label = code.error_label
1902 end_label = code.new_label("argument_unpacking_done")
1904 has_kwonly_args = self.num_kwonly_args > 0
1905 has_star_or_kw_args = self.star_arg is not None \
1906 or self.starstar_arg is not None or has_kwonly_args
1908 if not self.signature_has_generic_args():
1909 if has_star_or_kw_args:
1910 error(self.pos, "This method cannot have * or keyword arguments")
1911 self.generate_argument_conversion_code(code)
1913 elif not self.signature_has_nongeneric_args():
1914 # func(*args) or func(**kw) or func(*args, **kw)
1915 self.generate_stararg_copy_code(code)
1917 else:
1918 positional_args = []
1919 kw_only_args = []
1920 default_seen = 0
1921 for arg in self.args:
1922 arg_entry = arg.entry
1923 if arg.is_generic:
1924 if arg.default:
1925 default_seen = 1
1926 if not arg.is_self_arg:
1927 if arg.kw_only:
1928 kw_only_args.append(arg)
1929 else:
1930 positional_args.append(arg)
1931 elif arg.kw_only:
1932 kw_only_args.append(arg)
1933 default_seen = 1
1934 elif default_seen:
1935 error(arg.pos, "Non-default argument following default argument")
1936 elif not arg.is_self_arg:
1937 positional_args.append(arg)
1939 self.generate_tuple_and_keyword_parsing_code(
1940 positional_args, kw_only_args, end_label, code)
1942 code.error_label = old_error_label
1943 if code.label_used(our_error_label):
1944 if not code.label_used(end_label):
1945 code.put_goto(end_label)
1946 code.put_label(our_error_label)
1947 if has_star_or_kw_args:
1948 self.generate_arg_decref(self.star_arg, code)
1949 if self.starstar_arg:
1950 if self.starstar_arg.entry.xdecref_cleanup:
1951 code.put_var_xdecref(self.starstar_arg.entry)
1952 else:
1953 code.put_var_decref(self.starstar_arg.entry)
1954 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1955 code.putln("return %s;" % self.error_value())
1956 if code.label_used(end_label):
1957 code.put_label(end_label)
1959 def generate_arg_assignment(self, arg, item, code):
1960 if arg.type.is_pyobject:
1961 if arg.is_generic:
1962 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1963 code.putln("%s = %s;" % (arg.entry.cname, item))
1964 else:
1965 func = arg.type.from_py_function
1966 if func:
1967 code.putln("%s = %s(%s); %s" % (
1968 arg.entry.cname,
1969 func,
1970 item,
1971 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1972 else:
1973 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1975 def generate_arg_xdecref(self, arg, code):
1976 if arg:
1977 code.put_var_xdecref(arg.entry)
1979 def generate_arg_decref(self, arg, code):
1980 if arg:
1981 code.put_var_decref(arg.entry)
1983 def generate_stararg_copy_code(self, code):
1984 if not self.star_arg:
1985 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1986 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1987 Naming.args_cname)
1988 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
1989 self.name.utf8encode(), Naming.args_cname, self.error_value()))
1990 code.putln("}")
1992 code.globalstate.use_utility_code(keyword_string_check_utility_code)
1994 if self.starstar_arg:
1995 if self.star_arg:
1996 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
1997 else:
1998 kwarg_check = "%s" % Naming.kwds_cname
1999 else:
2000 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2001 Naming.kwds_cname, Naming.kwds_cname)
2002 code.putln(
2003 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2004 kwarg_check, Naming.kwds_cname, self.name,
2005 bool(self.starstar_arg), self.error_value()))
2007 if self.starstar_arg:
2008 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2009 self.starstar_arg.entry.cname,
2010 Naming.kwds_cname,
2011 Naming.kwds_cname))
2012 code.putln("if (unlikely(!%s)) return %s;" % (
2013 self.starstar_arg.entry.cname, self.error_value()))
2014 self.starstar_arg.entry.xdecref_cleanup = 0
2015 code.put_gotref(self.starstar_arg.entry.cname)
2018 if self.star_arg:
2019 code.put_incref(Naming.args_cname, py_object_type)
2020 code.putln("%s = %s;" % (
2021 self.star_arg.entry.cname,
2022 Naming.args_cname))
2023 self.star_arg.entry.xdecref_cleanup = 0
2025 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2026 kw_only_args, success_label, code):
2027 argtuple_error_label = code.new_label("argtuple_error")
2029 min_positional_args = self.num_required_args - self.num_required_kw_args
2030 if len(self.args) > 0 and self.args[0].is_self_arg:
2031 min_positional_args -= 1
2032 max_positional_args = len(positional_args)
2033 has_fixed_positional_count = not self.star_arg and \
2034 min_positional_args == max_positional_args
2036 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2037 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2038 if self.num_required_kw_args:
2039 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2041 if self.starstar_arg or self.star_arg:
2042 self.generate_stararg_init_code(max_positional_args, code)
2044 # --- optimised code when we receive keyword arguments
2045 if self.num_required_kw_args:
2046 likely_hint = "likely"
2047 else:
2048 likely_hint = "unlikely"
2049 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2050 self.generate_keyword_unpacking_code(
2051 min_positional_args, max_positional_args,
2052 has_fixed_positional_count,
2053 positional_args, kw_only_args, argtuple_error_label, code)
2055 # --- optimised code when we do not receive any keyword arguments
2056 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2057 # Python raises arg tuple related errors first, so we must
2058 # check the length here
2059 if min_positional_args == max_positional_args and not self.star_arg:
2060 compare = '!='
2061 else:
2062 compare = '<'
2063 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2064 Naming.args_cname, compare, min_positional_args))
2065 code.put_goto(argtuple_error_label)
2067 if self.num_required_kw_args:
2068 # pure error case: keywords required but not passed
2069 if max_positional_args > min_positional_args and not self.star_arg:
2070 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2071 Naming.args_cname, max_positional_args))
2072 code.put_goto(argtuple_error_label)
2073 code.putln('} else {')
2074 for i, arg in enumerate(kw_only_args):
2075 if not arg.default:
2076 # required keyword-only argument missing
2077 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2078 self.name.utf8encode(),
2079 arg.name_entry.pystring_cname))
2080 code.putln(code.error_goto(self.pos))
2081 break
2083 elif min_positional_args == max_positional_args:
2084 # parse the exact number of positional arguments from the
2085 # args tuple
2086 code.putln('} else {')
2087 for i, arg in enumerate(positional_args):
2088 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2089 self.generate_arg_assignment(arg, item, code)
2090 self.generate_arg_default_assignments(code)
2092 else:
2093 # parse the positional arguments from the variable length
2094 # args tuple
2095 code.putln('} else {')
2096 self.generate_arg_default_assignments(code)
2097 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2098 if self.star_arg:
2099 code.putln('default:')
2100 reversed_args = list(enumerate(positional_args))[::-1]
2101 for i, arg in reversed_args:
2102 if i >= min_positional_args-1:
2103 if min_positional_args > 1:
2104 code.putln('case %2d:' % (i+1)) # pure code beautification
2105 else:
2106 code.put('case %2d: ' % (i+1))
2107 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2108 self.generate_arg_assignment(arg, item, code)
2109 if min_positional_args == 0:
2110 code.put('case 0: ')
2111 code.putln('break;')
2112 if self.star_arg:
2113 if min_positional_args:
2114 for i in range(min_positional_args-1, -1, -1):
2115 code.putln('case %2d:' % i)
2116 code.put_goto(argtuple_error_label)
2117 else:
2118 code.put('default: ')
2119 code.put_goto(argtuple_error_label)
2120 code.putln('}')
2122 code.putln('}')
2124 if code.label_used(argtuple_error_label):
2125 code.put_goto(success_label)
2126 code.put_label(argtuple_error_label)
2127 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2128 self.name.utf8encode(), has_fixed_positional_count,
2129 min_positional_args, max_positional_args,
2130 Naming.args_cname))
2131 code.putln(code.error_goto(self.pos))
2133 def generate_arg_default_assignments(self, code):
2134 for arg in self.args:
2135 if arg.is_generic and arg.default:
2136 code.putln(
2137 "%s = %s;" % (
2138 arg.entry.cname,
2139 arg.default_result_code))
2141 def generate_stararg_init_code(self, max_positional_args, code):
2142 if self.starstar_arg:
2143 self.starstar_arg.entry.xdecref_cleanup = 0
2144 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2145 self.starstar_arg.entry.cname,
2146 self.starstar_arg.entry.cname,
2147 self.error_value()))
2148 code.put_gotref(self.starstar_arg.entry.cname)
2149 if self.star_arg:
2150 self.star_arg.entry.xdecref_cleanup = 0
2151 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2152 Naming.args_cname,
2153 max_positional_args))
2154 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2155 self.star_arg.entry.cname, Naming.args_cname,
2156 max_positional_args, Naming.args_cname))
2157 code.put_gotref(self.star_arg.entry.cname)
2158 if self.starstar_arg:
2159 code.putln("")
2160 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2161 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2162 code.putln('return %s;' % self.error_value())
2163 code.putln('}')
2164 else:
2165 code.putln("if (unlikely(!%s)) return %s;" % (
2166 self.star_arg.entry.cname, self.error_value()))
2167 code.putln('} else {')
2168 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2169 code.put_incref(Naming.empty_tuple, py_object_type)
2170 code.putln('}')
2172 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2173 has_fixed_positional_count, positional_args,
2174 kw_only_args, argtuple_error_label, code):
2175 all_args = tuple(positional_args) + tuple(kw_only_args)
2176 max_args = len(all_args)
2178 default_args = []
2179 for i, arg in enumerate(all_args):
2180 if arg.default and arg.type.is_pyobject:
2181 default_value = arg.default_result_code
2182 if arg.type is not PyrexTypes.py_object_type:
2183 default_value = "(PyObject*)"+default_value
2184 default_args.append((i, default_value))
2186 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2187 Naming.kwds_cname)
2188 # it looks funny to separate the init-to-0 from setting the
2189 # default value, but C89 needs this
2190 code.putln("PyObject* values[%d] = {%s};" % (
2191 max_args, ','.join(['0']*max_args)))
2192 for i, default_value in default_args:
2193 code.putln('values[%d] = %s;' % (i, default_value))
2195 # parse the tuple and check that it's not too long
2196 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2197 if self.star_arg:
2198 code.putln('default:')
2199 for i in range(max_positional_args-1, -1, -1):
2200 code.put('case %2d: ' % (i+1))
2201 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2202 i, Naming.args_cname, i))
2203 code.putln('case 0: break;')
2204 if not self.star_arg:
2205 code.put('default: ') # more arguments than allowed
2206 code.put_goto(argtuple_error_label)
2207 code.putln('}')
2209 # now fill up the positional/required arguments with values
2210 # from the kw dict
2211 if self.num_required_args or max_positional_args > 0:
2212 last_required_arg = -1
2213 for i, arg in enumerate(all_args):
2214 if not arg.default:
2215 last_required_arg = i
2216 if last_required_arg < max_positional_args:
2217 last_required_arg = max_positional_args-1
2218 num_required_args = self.num_required_args
2219 if max_positional_args > 0:
2220 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2221 for i, arg in enumerate(all_args[:last_required_arg+1]):
2222 if max_positional_args > 0 and i <= max_positional_args:
2223 if self.star_arg and i == max_positional_args:
2224 code.putln('default:')
2225 else:
2226 code.putln('case %2d:' % i)
2227 if arg.default:
2228 if arg.kw_only:
2229 # handled separately below
2230 continue
2231 code.putln('if (kw_args > %d) {' % num_required_args)
2232 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2233 Naming.kwds_cname, arg.name_entry.pystring_cname))
2234 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2235 code.putln('}')
2236 else:
2237 num_required_args -= 1
2238 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2239 i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2240 code.putln('if (likely(values[%d])) kw_args--;' % i);
2241 if i < min_positional_args:
2242 if i == 0:
2243 # special case: we know arg 0 is missing
2244 code.put('else ')
2245 code.put_goto(argtuple_error_label)
2246 else:
2247 # print the correct number of values (args or
2248 # kwargs) that were passed into positional
2249 # arguments up to this point
2250 code.putln('else {')
2251 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2252 self.name.utf8encode(), has_fixed_positional_count,
2253 min_positional_args, max_positional_args, i))
2254 code.putln(code.error_goto(self.pos))
2255 code.putln('}')
2256 elif arg.kw_only:
2257 code.putln('else {')
2258 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2259 self.name.utf8encode(), arg.name_entry.pystring_cname))
2260 code.putln(code.error_goto(self.pos))
2261 code.putln('}')
2262 if max_positional_args > 0:
2263 code.putln('}')
2265 if kw_only_args and not self.starstar_arg:
2266 # unpack optional keyword-only arguments
2267 # checking for interned strings in a dict is faster than iterating
2268 # but it's too likely that we must iterate if we expect **kwargs
2269 optional_args = []
2270 for i, arg in enumerate(all_args[max_positional_args:]):
2271 if not arg.kw_only or not arg.default:
2272 continue
2273 optional_args.append((i+max_positional_args, arg))
2274 if optional_args:
2275 # this mimics an unrolled loop so that we can "break" out of it
2276 code.putln('while (kw_args > 0) {')
2277 code.putln('PyObject* value;')
2278 for i, arg in optional_args:
2279 code.putln(
2280 'value = PyDict_GetItem(%s, %s);' % (
2281 Naming.kwds_cname, arg.name_entry.pystring_cname))
2282 code.putln(
2283 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2284 code.putln('break;')
2285 code.putln('}')
2287 code.putln('if (unlikely(kw_args > 0)) {')
2288 # non-positional/-required kw args left in dict: default args,
2289 # kw-only args, **kwargs or error
2290 #
2291 # This is sort of a catch-all: except for checking required
2292 # arguments, this will always do the right thing for unpacking
2293 # keyword arguments, so that we can concentrate on optimising
2294 # common cases above.
2295 if max_positional_args == 0:
2296 pos_arg_count = "0"
2297 elif self.star_arg:
2298 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2299 Naming.args_cname, max_positional_args,
2300 Naming.args_cname, max_positional_args))
2301 pos_arg_count = "used_pos_args"
2302 else:
2303 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2304 code.globalstate.use_utility_code(parse_keywords_utility_code)
2305 code.put(
2306 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2307 Naming.kwds_cname,
2308 Naming.pykwdlist_cname,
2309 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2310 pos_arg_count,
2311 self.name.utf8encode()))
2312 code.putln(code.error_goto(self.pos))
2313 code.putln('}')
2315 # convert arg values to their final type and assign them
2316 for i, arg in enumerate(all_args):
2317 if arg.default and not arg.type.is_pyobject:
2318 code.putln("if (values[%d]) {" % i)
2319 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2320 if arg.default and not arg.type.is_pyobject:
2321 code.putln('} else {')
2322 code.putln(
2323 "%s = %s;" % (
2324 arg.entry.cname,
2325 arg.default_result_code))
2326 code.putln('}')
2328 def generate_argument_conversion_code(self, code):
2329 # Generate code to convert arguments from
2330 # signature type to declared type, if needed.
2331 for arg in self.args:
2332 if arg.needs_conversion:
2333 self.generate_arg_conversion(arg, code)
2335 def generate_arg_conversion(self, arg, code):
2336 # Generate conversion code for one argument.
2337 old_type = arg.hdr_type
2338 new_type = arg.type
2339 if old_type.is_pyobject:
2340 if arg.default:
2341 code.putln("if (%s) {" % arg.hdr_cname)
2342 else:
2343 code.putln("assert(%s); {" % arg.hdr_cname)
2344 self.generate_arg_conversion_from_pyobject(arg, code)
2345 code.putln("}")
2346 elif new_type.is_pyobject:
2347 self.generate_arg_conversion_to_pyobject(arg, code)
2348 else:
2349 if new_type.assignable_from(old_type):
2350 code.putln(
2351 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2352 else:
2353 error(arg.pos,
2354 "Cannot convert 1 argument from '%s' to '%s'" %
2355 (old_type, new_type))
2357 def generate_arg_conversion_from_pyobject(self, arg, code):
2358 new_type = arg.type
2359 func = new_type.from_py_function
2360 # copied from CoerceFromPyTypeNode
2361 if func:
2362 code.putln("%s = %s(%s); %s" % (
2363 arg.entry.cname,
2364 func,
2365 arg.hdr_cname,
2366 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2367 else:
2368 error(arg.pos,
2369 "Cannot convert Python object argument to type '%s'"
2370 % new_type)
2372 def generate_arg_conversion_to_pyobject(self, arg, code):
2373 old_type = arg.hdr_type
2374 func = old_type.to_py_function
2375 if func:
2376 code.putln("%s = %s(%s); %s" % (
2377 arg.entry.cname,
2378 func,
2379 arg.hdr_cname,
2380 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2381 code.put_var_gotref(arg.entry)
2382 else:
2383 error(arg.pos,
2384 "Cannot convert argument of type '%s' to Python object"
2385 % old_type)
2387 def generate_argument_type_tests(self, code):
2388 # Generate type tests for args whose signature
2389 # type is PyObject * and whose declared type is
2390 # a subtype thereof.
2391 for arg in self.args:
2392 if arg.needs_type_test:
2393 self.generate_arg_type_test(arg, code)
2395 def generate_arg_type_test(self, arg, code):
2396 # Generate type test for one argument.
2397 if arg.type.typeobj_is_available():
2398 typeptr_cname = arg.type.typeptr_cname
2399 arg_code = "((PyObject *)%s)" % arg.entry.cname
2400 code.putln(
2401 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2402 arg_code,
2403 typeptr_cname,
2404 not arg.not_none,
2405 arg.name,
2406 arg.type.is_builtin_type,
2407 code.error_goto(arg.pos)))
2408 else:
2409 error(arg.pos, "Cannot test type of extern C class "
2410 "without type object name specification")
2412 def error_value(self):
2413 return self.entry.signature.error_value
2415 def caller_will_check_exceptions(self):
2416 return 1
2418 class OverrideCheckNode(StatNode):
2419 # A Node for dispatching to the def method if it
2420 # is overriden.
2421 #
2422 # py_func
2423 #
2424 # args
2425 # func_temp
2426 # body
2428 child_attrs = ['body']
2430 body = None
2432 def analyse_expressions(self, env):
2433 self.args = env.arg_entries
2434 if self.py_func.is_module_scope:
2435 first_arg = 0
2436 else:
2437 first_arg = 1
2438 import ExprNodes
2439 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2440 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2441 call_node = ExprNodes.SimpleCallNode(self.pos,
2442 function=self.func_node,
2443 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2444 self.body = ReturnStatNode(self.pos, value=call_node)
2445 self.body.analyse_expressions(env)
2447 def generate_execution_code(self, code):
2448 # Check to see if we are an extension type
2449 if self.py_func.is_module_scope:
2450 self_arg = "((PyObject *)%s)" % Naming.module_cname
2451 else:
2452 self_arg = "((PyObject *)%s)" % self.args[0].cname
2453 code.putln("/* Check if called by wrapper */")
2454 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2455 code.putln("/* Check if overriden in Python */")
2456 if self.py_func.is_module_scope:
2457 code.putln("else {")
2458 else:
2459 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2460 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2461 # need to get attribute manually--scope would return cdef method
2462 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2463 code.put_gotref(self.func_node.py_result())
2464 is_builtin_function_or_method = 'PyCFunction_Check(%s)' % self.func_node.result()
2465 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2466 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2467 self.body.generate_execution_code(code)
2468 code.putln('}')
2469 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2470 code.putln("}")
2472 class ClassDefNode(StatNode, BlockNode):
2473 pass
2475 class PyClassDefNode(ClassDefNode):
2476 # A Python class definition.
2477 #
2478 # name EncodedString Name of the class
2479 # doc string or None
2480 # body StatNode Attribute definition code
2481 # entry Symtab.Entry
2482 # scope PyClassScope
2483 #
2484 # The following subnodes are constructed internally:
2485 #
2486 # dict DictNode Class dictionary
2487 # classobj ClassNode Class object
2488 # target NameNode Variable to assign class object to
2490 child_attrs = ["body", "dict", "classobj", "target"]
2492 def __init__(self, pos, name, bases, doc, body):
2493 StatNode.__init__(self, pos)
2494 self.name = name
2495 self.doc = doc
2496 self.body = body
2497 import ExprNodes
2498 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2499 if self.doc and Options.docstrings:
2500 doc = embed_position(self.pos, self.doc)
2501 doc_node = ExprNodes.StringNode(pos, value = doc)
2502 else:
2503 doc_node = None
2504 self.classobj = ExprNodes.ClassNode(pos, name = name,
2505 bases = bases, dict = self.dict, doc = doc_node)
2506 self.target = ExprNodes.NameNode(pos, name = name)
2508 def as_cclass(self):
2509 """
2510 Return this node as if it were declared as an extension class
2511 """
2512 bases = self.classobj.bases.args
2513 if len(bases) == 0:
2514 base_class_name = None
2515 base_class_module = None
2516 elif len(bases) == 1:
2517 base = bases[0]
2518 path = []
2519 from ExprNodes import AttributeNode, NameNode
2520 while isinstance(base, AttributeNode):
2521 path.insert(0, base.attribute)
2522 base = base.obj
2523 if isinstance(base, NameNode):
2524 path.insert(0, base.name)
2525 base_class_name = path[-1]
2526 if len(path) > 1:
2527 base_class_module = u'.'.join(path[:-1])
2528 else:
2529 base_class_module = None
2530 else:
2531 error(self.classobj.bases.args.pos, "Invalid base class")
2532 else:
2533 error(self.classobj.bases.args.pos, "C class may only have one base class")
2534 return None
2536 return CClassDefNode(self.pos,
2537 visibility = 'private',
2538 module_name = None,
2539 class_name = self.name,
2540 base_class_module = base_class_module,
2541 base_class_name = base_class_name,
2542 body = self.body,
2543 in_pxd = False,
2544 doc = self.doc)
2546 def create_scope(self, env):
2547 genv = env
2548 while env.is_py_class_scope or env.is_c_class_scope:
2549 env = env.outer_scope
2550 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2551 return cenv
2553 def analyse_declarations(self, env):
2554 self.target.analyse_target_declaration(env)
2555 cenv = self.create_scope(env)
2556 cenv.class_obj_cname = self.target.entry.cname
2557 self.body.analyse_declarations(cenv)
2559 def analyse_expressions(self, env):
2560 self.dict.analyse_expressions(env)
2561 self.classobj.analyse_expressions(env)
2562 genv = env.global_scope()
2563 cenv = self.scope
2564 cenv.class_dict_cname = self.dict.result()
2565 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2566 self.body.analyse_expressions(cenv)
2567 self.target.analyse_target_expression(env, self.classobj)
2568 self.dict.release_temp(env)
2569 #self.classobj.release_temp(env)
2570 #self.target.release_target_temp(env)
2572 def generate_function_definitions(self, env, code):
2573 self.generate_py_string_decls(self.scope, code)
2574 self.body.generate_function_definitions(self.scope, code)
2576 def generate_execution_code(self, code):
2577 self.dict.generate_evaluation_code(code)
2578 self.classobj.generate_evaluation_code(code)
2579 self.body.generate_execution_code(code)
2580 self.target.generate_assignment_code(self.classobj, code)
2581 self.dict.generate_disposal_code(code)
2582 self.dict.free_temps(code)
2585 class CClassDefNode(ClassDefNode):
2586 # An extension type definition.
2587 #
2588 # visibility 'private' or 'public' or 'extern'
2589 # typedef_flag boolean
2590 # api boolean
2591 # module_name string or None For import of extern type objects
2592 # class_name string Unqualified name of class
2593 # as_name string or None Name to declare as in this scope
2594 # base_class_module string or None Module containing the base class
2595 # base_class_name string or None Name of the base class
2596 # objstruct_name string or None Specified C name of object struct
2597 # typeobj_name string or None Specified C name of type object
2598 # in_pxd boolean Is in a .pxd file
2599 # doc string or None
2600 # body StatNode or None
2601 # entry Symtab.Entry
2602 # base_type PyExtensionType or None
2603 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2604 # buffer_defaults_pos
2606 child_attrs = ["body"]
2607 buffer_defaults_node = None
2608 buffer_defaults_pos = None
2609 typedef_flag = False
2610 api = False
2611 objstruct_name = None
2612 typeobj_name = None
2614 def analyse_declarations(self, env):
2615 #print "CClassDefNode.analyse_declarations:", self.class_name
2616 #print "...visibility =", self.visibility
2617 #print "...module_name =", self.module_name
2619 import Buffer
2620 if self.buffer_defaults_node:
2621 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2622 env, [], self.buffer_defaults_node,
2623 need_complete=False)
2624 else:
2625 buffer_defaults = None
2627 if env.in_cinclude and not self.objstruct_name:
2628 error(self.pos, "Object struct name specification required for "
2629 "C class defined in 'extern from' block")
2630 self.base_type = None
2631 # Now that module imports are cached, we need to
2632 # import the modules for extern classes.
2633 if self.module_name:
2634 self.module = None
2635 for module in env.cimported_modules:
2636 if module.name == self.module_name:
2637 self.module = module
2638 if self.module is None:
2639 self.module = ModuleScope(self.module_name, None, env.context)
2640 self.module.has_extern_class = 1
2641 env.add_imported_module(self.module)
2643 if self.base_class_name:
2644 if self.base_class_module:
2645 base_class_scope = env.find_module(self.base_class_module, self.pos)
2646 else:
2647 base_class_scope = env
2648 if self.base_class_name == 'object':
2649 # extension classes are special and don't need to inherit from object
2650 if base_class_scope is None or base_class_scope.lookup('object') is None:
2651 self.base_class_name = None
2652 self.base_class_module = None
2653 base_class_scope = None
2654 if base_class_scope:
2655 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2656 if base_class_entry:
2657 if not base_class_entry.is_type:
2658 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2659 elif not base_class_entry.type.is_extension_type:
2660 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2661 elif not base_class_entry.type.is_complete():
2662 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2663 else:
2664 self.base_type = base_class_entry.type
2665 has_body = self.body is not None
2666 if self.module_name and self.visibility != 'extern':
2667 module_path = self.module_name.split(".")
2668 home_scope = env.find_imported_module(module_path, self.pos)
2669 if not home_scope:
2670 return
2671 else:
2672 home_scope = env
2673 self.entry = home_scope.declare_c_class(
2674 name = self.class_name,
2675 pos = self.pos,
2676 defining = has_body and self.in_pxd,
2677 implementing = has_body and not self.in_pxd,
2678 module_name = self.module_name,
2679 base_type = self.base_type,
2680 objstruct_cname = self.objstruct_name,
2681 typeobj_cname = self.typeobj_name,
2682 visibility = self.visibility,
2683 typedef_flag = self.typedef_flag,
2684 api = self.api,
2685 buffer_defaults = buffer_defaults)
2686 if home_scope is not env and self.visibility == 'extern':
2687 env.add_imported_entry(self.class_name, self.entry, pos)
2688 scope = self.entry.type.scope
2690 if self.doc and Options.docstrings:
2691 scope.doc = embed_position(self.pos, self.doc)
2693 if has_body:
2694 self.body.analyse_declarations(scope)
2695 if self.in_pxd:
2696 scope.defined = 1
2697 else:
2698 scope.implemented = 1
2699 env.allocate_vtable_names(self.entry)
2701 def analyse_expressions(self, env):
2702 if self.body:
2703 scope = self.entry.type.scope
2704 self.body.analyse_expressions(scope)
2706 def generate_function_definitions(self, env, code):
2707 self.generate_py_string_decls(self.entry.type.scope, code)
2708 if self.body:
2709 self.body.generate_function_definitions(
2710 self.entry.type.scope, code)
2712 def generate_execution_code(self, code):
2713 # This is needed to generate evaluation code for
2714 # default values of method arguments.
2715 if self.body:
2716 self.body.generate_execution_code(code)
2718 def annotate(self, code):
2719 if self.body:
2720 self.body.annotate(code)
2723 class PropertyNode(StatNode):
2724 # Definition of a property in an extension type.
2725 #
2726 # name string
2727 # doc EncodedString or None Doc string
2728 # body StatListNode
2730 child_attrs = ["body"]
2732 def analyse_declarations(self, env):
2733 entry = env.declare_property(self.name, self.doc, self.pos)
2734 if entry:
2735 if self.doc and Options.docstrings:
2736 doc_entry = env.get_string_const(
2737 self.doc, identifier = False)
2738 entry.doc_cname = doc_entry.cname
2739 self.body.analyse_declarations(entry.scope)
2741 def analyse_expressions(self, env):
2742 self.body.analyse_expressions(env)
2744 def generate_function_definitions(self, env, code):
2745 self.body.generate_function_definitions(env, code)
2747 def generate_execution_code(self, code):
2748 pass
2750 def annotate(self, code):
2751 self.body.annotate(code)
2754 class GlobalNode(StatNode):
2755 # Global variable declaration.
2756 #
2757 # names [string]
2759 child_attrs = []
2761 def analyse_declarations(self, env):
2762 for name in self.names:
2763 env.declare_global(name, self.pos)
2765 def analyse_expressions(self, env):
2766 pass
2768 def generate_execution_code(self, code):
2769 pass
2772 class ExprStatNode(StatNode):
2773 # Expression used as a statement.
2774 #
2775 # expr ExprNode
2777 child_attrs = ["expr"]
2779 def analyse_declarations(self, env):
2780 import ExprNodes
2781 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2782 func = self.expr.function.as_cython_attribute()
2783 if func == u'declare':
2784 args, kwds = self.expr.explicit_args_kwds()
2785 if len(args):
2786 error(self.expr.pos, "Variable names must be specified.")
2787 for var, type_node in kwds.key_value_pairs:
2788 type = type_node.analyse_as_type(env)
2789 if type is None:
2790 error(type_node.pos, "Unknown type")
2791 else:
2792 env.declare_var(var.value, type, var.pos, is_cdef = True)
2793 self.__class__ = PassStatNode
2795 def analyse_expressions(self, env):
2796 self.expr.analyse_expressions(env)
2797 self.expr.release_temp(env)
2799 def generate_execution_code(self, code):
2800 self.expr.generate_evaluation_code(code)
2801 if not self.expr.is_temp and self.expr.result():
2802 code.putln("%s;" % self.expr.result())
2803 self.expr.generate_disposal_code(code)
2804 self.expr.free_temps(code)
2806 def annotate(self, code):
2807 self.expr.annotate(code)
2810 class AssignmentNode(StatNode):
2811 # Abstract base class for assignment nodes.
2812 #
2813 # The analyse_expressions and generate_execution_code
2814 # phases of assignments are split into two sub-phases
2815 # each, to enable all the right hand sides of a
2816 # parallel assignment to be evaluated before assigning
2817 # to any of the left hand sides.
2819 def analyse_expressions(self, env):
2820 self.analyse_types(env)
2821 self.allocate_rhs_temps(env)
2822 self.allocate_lhs_temps(env)
2824 # def analyse_expressions(self, env):
2825 # self.analyse_expressions_1(env)
2826 # self.analyse_expressions_2(env)
2828 def generate_execution_code(self, code):
2829 self.generate_rhs_evaluation_code(code)
2830 self.generate_assignment_code(code)
2833 class SingleAssignmentNode(AssignmentNode):
2834 # The simplest case:
2835 #
2836 # a = b
2837 #
2838 # lhs ExprNode Left hand side
2839 # rhs ExprNode Right hand side
2840 # first bool Is this guaranteed the first assignment to lhs?
2842 child_attrs = ["lhs", "rhs"]
2843 first = False
2844 declaration_only = False
2846 def analyse_declarations(self, env):
2847 import ExprNodes
2849 # handle declarations of the form x = cython.foo()
2850 if isinstance(self.rhs, ExprNodes.CallNode):
2851 func_name = self.rhs.function.as_cython_attribute()
2852 if func_name:
2853 args, kwds = self.rhs.explicit_args_kwds()
2855 if func_name in ['declare', 'typedef']:
2856 if len(args) > 2 or kwds is not None:
2857 error(rhs.pos, "Can only declare one type at a time.")
2858 return
2859 type = args[0].analyse_as_type(env)
2860 if type is None:
2861 error(args[0].pos, "Unknown type")
2862 return
2863 lhs = self.lhs
2864 if func_name == 'declare':
2865 if isinstance(lhs, ExprNodes.NameNode):
2866 vars = [(lhs.name, lhs.pos)]
2867 elif isinstance(lhs, ExprNodes.TupleNode):
2868 vars = [(var.name, var.pos) for var in lhs.args]
2869 else:
2870 error(lhs.pos, "Invalid declaration")
2871 return
2872 for var, pos in vars:
2873 env.declare_var(var, type, pos, is_cdef = True)
2874 if len(args) == 2:
2875 # we have a value
2876 self.rhs = args[1]
2877 else:
2878 self.declaration_only = True
2879 else:
2880 self.declaration_only = True
2881 if not isinstance(lhs, ExprNodes.NameNode):
2882 error(lhs.pos, "Invalid declaration.")
2883 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2885 elif func_name in ['struct', 'union']:
2886 self.declaration_only = True
2887 if len(args) > 0 or kwds is None:
2888 error(rhs.pos, "Struct or union members must be given by name.")
2889 return
2890 members = []
2891 for member, type_node in kwds.key_value_pairs:
2892 type = type_node.analyse_as_type(env)
2893 if type is None:
2894 error(type_node.pos, "Unknown type")
2895 else:
2896 members.append((member.value, type, member.pos))
2897 if len(members) < len(kwds.key_value_pairs):
2898 return
2899 if not isinstance(self.lhs, ExprNodes.NameNode):
2900 error(self.lhs.pos, "Invalid declaration.")
2901 name = self.lhs.name
2902 scope = StructOrUnionScope(name)
2903 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2904 for member, type, pos in members:
2905 scope.declare_var(member, type, pos)
2907 if self.declaration_only:
2908 return
2909 else:
2910 self.lhs.analyse_target_declaration(env)
2912 def analyse_types(self, env, use_temp = 0):
2913 self.rhs.analyse_types(env)
2914 self.lhs.analyse_target_types(env)
2915 self.lhs.gil_assignment_check(env)
2916 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2917 if use_temp:
2918 self.rhs = self.rhs.coerce_to_temp(env)
2920 def allocate_rhs_temps(self, env):
2921 self.rhs.allocate_temps(env)
2923 def allocate_lhs_temps(self, env):
2924 self.lhs.allocate_target_temps(env, self.rhs)
2925 #self.lhs.release_target_temp(env)
2926 #self.rhs.release_temp(env)
2928 def generate_rhs_evaluation_code(self, code):
2929 self.rhs.generate_evaluation_code(code)
2931 def generate_assignment_code(self, code):
2932 self.lhs.generate_assignment_code(self.rhs, code)
2934 def annotate(self, code):
2935 self.lhs.annotate(code)
2936 self.rhs.annotate(code)
2939 class CascadedAssignmentNode(AssignmentNode):
2940 # An assignment with multiple left hand sides:
2941 #
2942 # a = b = c
2943 #
2944 # lhs_list [ExprNode] Left hand sides
2945 # rhs ExprNode Right hand sides
2946 #
2947 # Used internally:
2948 #
2949 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2951 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2952 coerced_rhs_list = None
2954 def analyse_declarations(self, env):
2955 for lhs in self.lhs_list:
2956 lhs.analyse_target_declaration(env)
2958 def analyse_types(self, env, use_temp = 0):
2959 self.rhs.analyse_types(env)
2960 if use_temp:
2961 self.rhs = self.rhs.coerce_to_temp(env)
2962 else:
2963 self.rhs = self.rhs.coerce_to_simple(env)
2964 from ExprNodes import CloneNode
2965 self.coerced_rhs_list = []
2966 for lhs in self.lhs_list:
2967 lhs.analyse_target_types(env)
2968 lhs.gil_assignment_check(env)
2969 rhs = CloneNode(self.rhs)
2970 rhs = rhs.coerce_to(lhs.type, env)
2971 self.coerced_rhs_list.append(rhs)
2973 def allocate_rhs_temps(self, env):
2974 self.rhs.allocate_temps(env)
2976 def allocate_lhs_temps(self, env):
2977 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2978 rhs.allocate_temps(env)
2979 lhs.allocate_target_temps(env, rhs)
2980 #lhs.release_target_temp(env)
2981 #rhs.release_temp(env)
2982 self.rhs.release_temp(env)
2984 def generate_rhs_evaluation_code(self, code):
2985 self.rhs.generate_evaluation_code(code)
2987 def generate_assignment_code(self, code):
2988 for i in range(len(self.lhs_list)):
2989 lhs = self.lhs_list[i]
2990 rhs = self.coerced_rhs_list[i]
2991 rhs.generate_evaluation_code(code)
2992 lhs.generate_assignment_code(rhs, code)
2993 # Assignment has disposed of the cloned RHS
2994 self.rhs.generate_disposal_code(code)
2995 self.rhs.free_temps(code)
2997 def annotate(self, code):
2998 for i in range(len(self.lhs_list)):
2999 lhs = self.lhs_list[i].annotate(code)
3000 rhs = self.coerced_rhs_list[i].annotate(code)
3001 self.rhs.annotate(code)
3004 class ParallelAssignmentNode(AssignmentNode):
3005 # A combined packing/unpacking assignment:
3006 #
3007 # a, b, c = d, e, f
3008 #
3009 # This has been rearranged by the parser into
3010 #
3011 # a = d ; b = e ; c = f
3012 #
3013 # but we must evaluate all the right hand sides
3014 # before assigning to any of the left hand sides.
3015 #
3016 # stats [AssignmentNode] The constituent assignments
3018 child_attrs = ["stats"]
3020 def analyse_declarations(self, env):
3021 for stat in self.stats:
3022 stat.analyse_declarations(env)
3024 def analyse_expressions(self, env):
3025 for stat in self.stats:
3026 stat.analyse_types(env, use_temp = 1)
3027 stat.allocate_rhs_temps(env)
3028 for stat in self.stats:
3029 stat.allocate_lhs_temps(env)
3031 # def analyse_expressions(self, env):
3032 # for stat in self.stats:
3033 # stat.analyse_expressions_1(env, use_temp = 1)
3034 # for stat in self.stats:
3035 # stat.analyse_expressions_2(env)
3037 def generate_execution_code(self, code):
3038 for stat in self.stats:
3039 stat.generate_rhs_evaluation_code(code)
3040 for stat in self.stats:
3041 stat.generate_assignment_code(code)
3043 def annotate(self, code):
3044 for stat in self.stats:
3045 stat.annotate(code)
3048 class InPlaceAssignmentNode(AssignmentNode):
3049 # An in place arithmatic operand:
3050 #
3051 # a += b
3052 # a -= b
3053 # ...
3054 #
3055 # lhs ExprNode Left hand side
3056 # rhs ExprNode Right hand side
3057 # op char one of "+-*/%^&|"
3058 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3059 #
3060 # This code is a bit tricky because in order to obey Python
3061 # semantics the sub-expressions (e.g. indices) of the lhs must
3062 # not be evaluated twice. So we must re-use the values calculated
3063 # in evaluation phase for the assignment phase as well.
3064 # Fortunately, the type of the lhs node is fairly constrained
3065 # (it must be a NameNode, AttributeNode, or IndexNode).
3067 child_attrs = ["lhs", "rhs"]
3068 dup = None
3070 def analyse_declarations(self, env):
3071 self.lhs.analyse_target_declaration(env)
3073 def analyse_types(self, env):
3074 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3075 self.rhs.analyse_types(env)
3076 self.lhs.analyse_target_types(env)
3077 if Options.incref_local_binop and self.dup.type.is_pyobject:
3078 self.dup = self.dup.coerce_to_temp(env)
3080 def allocate_rhs_temps(self, env):
3081 import ExprNodes
3082 if self.lhs.type.is_pyobject:
3083 self.rhs = self.rhs.coerce_to_pyobject(env)
3084 elif self.rhs.type.is_pyobject:
3085 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3086 if self.lhs.type.is_pyobject:
3087 self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
3088 self.result_value.allocate_temps(env)
3089 # if use_temp:
3090 # self.rhs = self.rhs.coerce_to_temp(env)
3091 self.rhs.allocate_temps(env)
3092 self.dup.allocate_subexpr_temps(env)
3093 self.dup.allocate_temp(env)
3095 def allocate_lhs_temps(self, env):
3096 self.lhs.allocate_target_temps(env, self.rhs)
3097 # self.lhs.release_target_temp(env)
3098 self.dup.release_temp(env)
3099 if self.dup.is_temp:
3100 self.dup.release_subexpr_temps(env)
3101 # self.rhs.release_temp(env)
3102 if self.lhs.type.is_pyobject:
3103 self.result_value.release_temp(env)
3105 def generate_execution_code(self, code):
3106 import ExprNodes
3107 self.rhs.generate_evaluation_code(code)
3108 self.dup.generate_subexpr_evaluation_code(code)
3109 if isinstance(self.dup, ExprNodes.NewTempExprNode):
3110 # This is because we're manually messing with subexpr nodes
3111 if self.dup.is_temp:
3112 self.dup.allocate_temp_result(code)
3113 # self.dup.generate_result_code is run only if it is not buffer access
3114 if self.operator == "**":
3115 extra = ", Py_None"
3116 else:
3117 extra = ""
3118 if self.lhs.type.is_pyobject:
3119 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3120 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3121 self.dup.generate_result_code(code)
3122 code.putln(
3123 "%s = %s(%s, %s%s); %s" % (
3124 self.result_value.result(),
3125 self.py_operation_function(),
3126 self.dup.py_result(),
3127 self.rhs.py_result(),
3128 extra,
3129 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3130 code.put_gotref(self.result_value.py_result())
3131 self.result_value.generate_evaluation_code(code) # May be a type check...
3132 self.rhs.generate_disposal_code(code)
3133 self.rhs.free_temps(code)
3134 self.dup.generate_disposal_code(code)
3135 self.dup.free_temps(code)
3136 self.lhs.generate_assignment_code(self.result_value, code)
3137 else:
3138 c_op = self.operator
3139 if c_op == "//":
3140 c_op = "/"
3141 elif c_op == "**":
3142 if self.lhs.type.is_int and self.rhs.type.is_int:
3143 error(self.pos, "** with two C int types is ambiguous")
3144 else:
3145 error(self.pos, "No C inplace power operator")
3146 # have to do assignment directly to avoid side-effects
3147 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3148 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3149 else:
3150 self.dup.generate_result_code(code)
3151 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3152 self.rhs.generate_disposal_code(code)
3153 self.rhs.free_temps(code)
3154 if self.dup.is_temp:
3155 self.dup.generate_subexpr_disposal_code(code)
3156 self.dup.free_subexpr_temps(code)
3158 def create_dup_node(self, env):
3159 import ExprNodes
3160 self.dup = self.lhs
3161 self.dup.analyse_types(env)
3162 if isinstance(self.lhs, ExprNodes.NameNode):
3163 target_lhs = ExprNodes.NameNode(self.dup.pos,
3164 name = self.dup.name,
3165 is_temp = self.dup.is_temp,
3166 entry = self.dup.entry)
3167 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3168 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3169 obj = ExprNodes.CloneNode(self.lhs.obj),
3170 attribute = self.dup.attribute,
3171 is_temp = self.dup.is_temp)
3172 elif isinstance(self.lhs, ExprNodes.IndexNode):
3173 if self.lhs.index:
3174 index = ExprNodes.CloneNode(self.lhs.index)
3175 else:
3176 index = None
3177 if self.lhs.indices:
3178 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3179 else:
3180 indices = []
3181 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3182 base = ExprNodes.CloneNode(self.dup.base),
3183 index = index,
3184 indices = indices,
3185 is_temp = self.dup.is_temp)
3186 else:
3187 assert False
3188 self.lhs = target_lhs
3189 return self.dup
3191 def py_operation_function(self):
3192 return self.py_functions[self.operator]
3194 py_functions = {
3195 "|": "PyNumber_InPlaceOr",
3196 "^": "PyNumber_InPlaceXor",
3197 "&": "PyNumber_InPlaceAnd",
3198 "+": "PyNumber_InPlaceAdd",
3199 "-": "PyNumber_InPlaceSubtract",
3200 "*": "PyNumber_InPlaceMultiply",
3201 "/": "PyNumber_InPlaceDivide",
3202 "%": "PyNumber_InPlaceRemainder",
3203 "<<": "PyNumber_InPlaceLshift",
3204 ">>": "PyNumber_InPlaceRshift",
3205 "**": "PyNumber_InPlacePower",
3206 "//": "PyNumber_InPlaceFloorDivide",
3207 }
3209 def annotate(self, code):
3210 self.lhs.annotate(code)
3211 self.rhs.annotate(code)
3212 self.dup.annotate(code)
3215 class PrintStatNode(StatNode):
3216 # print statement
3217 #
3218 # arg_tuple TupleNode
3219 # append_newline boolean
3221 child_attrs = ["arg_tuple"]
3223 def analyse_expressions(self, env):
3224 self.arg_tuple.analyse_expressions(env)
3225 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3226 self.arg_tuple.release_temp(env)
3227 env.use_utility_code(printing_utility_code)
3228 if len(self.arg_tuple.args) == 1 and self.append_newline:
3229 env.use_utility_code(printing_one_utility_code)
3230 self.gil_check(env)
3232 gil_message = "Python print statement"
3234 def generate_execution_code(self, code):
3235 if len(self.arg_tuple.args) == 1 and self.append_newline:
3236 arg = self.arg_tuple.args[0]
3237 arg.generate_evaluation_code(code)
3239 code.putln(
3240 "if (__Pyx_PrintOne(%s) < 0) %s" % (
3241 arg.py_result(),
3242 code.error_goto(self.pos)))
3243 arg.generate_disposal_code(code)
3244 arg.free_temps(code)
3245 else:
3246 self.arg_tuple.generate_evaluation_code(code)
3247 code.putln(
3248 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3249 self.arg_tuple.py_result(),
3250 self.append_newline,
3251 code.error_goto(self.pos)))
3252 self.arg_tuple.generate_disposal_code(code)
3253 self.arg_tuple.free_temps(code)
3255 def annotate(self, code):
3256 self.arg_tuple.annotate(code)
3259 class ExecStatNode(StatNode):
3260 # exec statement
3261 #
3262 # args [ExprNode]
3264 child_attrs = ["args"]
3266 def analyse_expressions(self, env):
3267 for i, arg in enumerate(self.args):
3268 arg.analyse_expressions(env)
3269 arg = arg.coerce_to_pyobject(env)
3270 arg.release_temp(env)
3271 self.args[i] = arg
3272 self.temp_result = env.allocate_temp_pyobject()
3273 env.release_temp(self.temp_result)
3274 env.use_utility_code(Builtin.pyexec_utility_code)
3275 self.gil_check(env)
3277 gil_message = "Python exec statement"
3279 def generate_execution_code(self, code):
3280 args = []
3281 for arg in self.args:
3282 arg.generate_evaluation_code(code)
3283 args.append( arg.py_result() )
3284 args = tuple(args + ['0', '0'][:3-len(args)])
3285 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3286 (self.temp_result,) + args))
3287 for arg in self.args:
3288 arg.generate_disposal_code(code)
3289 arg.free_temps(code)
3290 code.putln(
3291 code.error_goto_if_null(self.temp_result, self.pos))
3292 code.put_gotref(self.temp_result)
3293 code.put_decref_clear(self.temp_result, py_object_type)
3295 def annotate(self, code):
3296 for arg in self.args:
3297 arg.annotate(code)
3300 class DelStatNode(StatNode):
3301 # del statement
3302 #
3303 # args [ExprNode]
3305 child_attrs = ["args"]
3307 def analyse_declarations(self, env):
3308 for arg in self.args:
3309 arg.analyse_target_declaration(env)
3311 def analyse_expressions(self, env):
3312 for arg in self.args:
3313 arg.analyse_target_expression(env, None)
3314 if arg.type.is_pyobject:
3315 self.gil_check(env)
3316 else:
3317 error(arg.pos, "Deletion of non-Python object")
3318 #arg.release_target_temp(env)
3320 gil_message = "Deleting Python object"
3322 def generate_execution_code(self, code):
3323 for arg in self.args:
3324 if arg.type.is_pyobject:
3325 arg.generate_deletion_code(code)
3326 # else error reported earlier
3328 def annotate(self, code):
3329 for arg in self.args:
3330 arg.annotate(code)
3333 class PassStatNode(StatNode):
3334 # pass statement
3336 child_attrs = []
3338 def analyse_expressions(self, env):
3339 pass
3341 def generate_execution_code(self, code):
3342 pass
3345 class BreakStatNode(StatNode):
3347 child_attrs = []
3349 def analyse_expressions(self, env):
3350 pass
3352 def generate_execution_code(self, code):
3353 if not code.break_label:
3354 error(self.pos, "break statement not inside loop")
3355 else:
3356 code.put_goto(code.break_label)
3359 class ContinueStatNode(StatNode):
3361 child_attrs = []
3363 def analyse_expressions(self, env):
3364 pass
3366 def generate_execution_code(self, code):
3367 if code.funcstate.in_try_finally:
3368 error(self.pos, "continue statement inside try of try...finally")
3369 elif not code.continue_label:
3370 error(self.pos, "continue statement not inside loop")
3371 else:
3372 code.put_goto(code.continue_label)
3375 class ReturnStatNode(StatNode):
3376 # return statement
3377 #
3378 # value ExprNode or None
3379 # return_type PyrexType
3380 # temps_in_use [Entry] Temps in use at time of return
3382 child_attrs = ["value"]
3384 def analyse_expressions(self, env):
3385 return_type = env.return_type
3386 self.return_type = return_type
3387 self.temps_in_use = env.temps_in_use()
3388 if not return_type:
3389 error(self.pos, "Return not inside a function body")
3390 return
3391 if self.value:
3392 self.value.analyse_types(env)
3393 if return_type.is_void or return_type.is_returncode:
3394 error(self.value.pos,
3395 "Return with value in void function")
3396 else:
3397 self.value = self.value.coerce_to(env.return_type, env)
3398 self.value.allocate_temps(env)
3399 self.value.release_temp(env)
3400 else:
3401 if (not return_type.is_void
3402 and not return_type.is_pyobject
3403 and not return_type.is_returncode):
3404 error(self.pos, "Return value required")
3405 if return_type.is_pyobject:
3406 self.gil_check(env)
3408 gil_message = "Returning Python object"
3410 def generate_execution_code(self, code):
3411 code.mark_pos(self.pos)
3412 if not self.return_type:
3413 # error reported earlier
3414 return
3415 if self.return_type.is_pyobject:
3416 code.put_xdecref(Naming.retval_cname,
3417 self.return_type)
3418 if self.value:
3419 self.value.generate_evaluation_code(code)
3420 self.value.make_owned_reference(code)
3421 code.putln(
3422 "%s = %s;" % (
3423 Naming.retval_cname,
3424 self.value.result_as(self.return_type)))
3425 self.value.generate_post_assignment_code(code)
3426 self.value.free_temps(code)
3427 else:
3428 if self.return_type.is_pyobject:
3429 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3430 elif self.return_type.is_returncode:
3431 code.putln(
3432 "%s = %s;" % (
3433 Naming.retval_cname,
3434 self.return_type.default_value))
3435 # free temps the old way
3436 for entry in self.temps_in_use:
3437 code.put_var_decref_clear(entry)
3438 # free temps the new way
3439 for cname, type in code.funcstate.temps_holding_reference():
3440 code.put_decref_clear(cname, type)
3441 #code.putln(
3442 # "goto %s;" %
3443 # code.return_label)
3444 code.put_goto(code.return_label)
3446 def annotate(self, code):
3447 if self.value:
3448 self.value.annotate(code)
3451 class RaiseStatNode(StatNode):
3452 # raise statement
3453 #
3454 # exc_type ExprNode or None
3455 # exc_value ExprNode or None
3456 # exc_tb ExprNode or None
3458 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3460 def analyse_expressions(self, env):
3461 if self.exc_type:
3462 self.exc_type.analyse_types(env)
3463 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3464 self.exc_type.allocate_temps(env)
3465 if self.exc_value:
3466 self.exc_value.analyse_types(env)
3467 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3468 self.exc_value.allocate_temps(env)
3469 if self.exc_tb:
3470 self.exc_tb.analyse_types(env)
3471 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3472 self.exc_tb.allocate_temps(env)
3473 if self.exc_type:
3474 self.exc_type.release_temp(env)
3475 if self.exc_value:
3476 self.exc_value.release_temp(env)
3477 if self.exc_tb:
3478 self.exc_tb.release_temp(env)
3479 env.use_utility_code(raise_utility_code)
3480 env.use_utility_code(restore_exception_utility_code)
3481 self.gil_check(env)
3483 gil_message = "Raising exception"
3485 def generate_execution_code(self, code):
3486 if self.exc_type:
3487 self.exc_type.generate_evaluation_code(code)
3488 type_code = self.exc_type.py_result()
3489 else:
3490 type_code = "0"
3491 if self.exc_value:
3492 self.exc_value.generate_evaluation_code(code)
3493 value_code = self.exc_value.py_result()
3494 else:
3495 value_code = "0"
3496 if self.exc_tb:
3497 self.exc_tb.generate_evaluation_code(code)
3498 tb_code = self.exc_tb.py_result()
3499 else:
3500 tb_code = "0"
3501 if self.exc_type or self.exc_value or self.exc_tb:
3502 code.putln(
3503 "__Pyx_Raise(%s, %s, %s);" % (
3504 type_code,
3505 value_code,
3506 tb_code))
3507 else:
3508 code.putln(
3509 "__Pyx_ReRaise();")
3510 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3511 if obj:
3512 obj.generate_disposal_code(code)
3513 obj.free_temps(code)
3514 code.putln(
3515 code.error_goto(self.pos))
3517 def annotate(self, code):
3518 if self.exc_type:
3519 self.exc_type.annotate(code)
3520 if self.exc_value:
3521 self.exc_value.annotate(code)
3522 if self.exc_tb:
3523 self.exc_tb.annotate(code)
3526 class ReraiseStatNode(StatNode):
3528 child_attrs = []
3530 def analyse_expressions(self, env):
3531 self.gil_check(env)
3532 env.use_utility_code(raise_utility_code)
3533 env.use_utility_code(restore_exception_utility_code)
3535 gil_message = "Raising exception"
3537 def generate_execution_code(self, code):
3538 vars = code.funcstate.exc_vars
3539 if vars:
3540 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3541 code.putln(code.error_goto(self.pos))
3542 else:
3543 error(self.pos, "Reraise not inside except clause")
3546 class AssertStatNode(StatNode):
3547 # assert statement
3548 #
3549 # cond ExprNode
3550 # value ExprNode or None
3552 child_attrs = ["cond", "value"]
3554 def analyse_expressions(self, env):
3555 self.cond = self.cond.analyse_boolean_expression(env)
3556 if self.value:
3557 self.value.analyse_types(env)
3558 self.value = self.value.coerce_to_pyobject(env)
3559 self.value.allocate_temps(env)
3560 self.cond.release_temp(env)
3561 if self.value:
3562 self.value.release_temp(env)
3563 self.gil_check(env)
3564 #env.recycle_pending_temps() # TEMPORARY
3566 gil_message = "Raising exception"
3568 def generate_execution_code(self, code):
3569 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3570 self.cond.generate_evaluation_code(code)
3571 code.putln(
3572 "if (unlikely(!%s)) {" %
3573 self.cond.result())
3574 if self.value:
3575 self.value.generate_evaluation_code(code)
3576 code.putln(
3577 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3578 self.value.py_result())
3579 self.value.generate_disposal_code(code)
3580 self.value.free_temps(code)
3581 else:
3582 code.putln(
3583 "PyErr_SetNone(PyExc_AssertionError);")
3584 code.putln(
3585 code.error_goto(self.pos))
3586 code.putln(
3587 "}")
3588 self.cond.generate_disposal_code(code)
3589 self.cond.free_temps(code)
3590 code.putln("#endif")
3592 def annotate(self, code):
3593 self.cond.annotate(code)
3594 if self.value:
3595 self.value.annotate(code)
3598 class IfStatNode(StatNode):
3599 # if statement
3600 #
3601 # if_clauses [IfClauseNode]
3602 # else_clause StatNode or None
3604 child_attrs = ["if_clauses", "else_clause"]
3606 def analyse_control_flow(self, env):
3607 env.start_branching(self.pos)
3608 for if_clause in self.if_clauses:
3609 if_clause.analyse_control_flow(env)
3610 env.next_branch(if_clause.end_pos())
3611 if self.else_clause:
3612 self.else_clause.analyse_control_flow(env)
3613 env.finish_branching(self.end_pos())
3615 def analyse_declarations(self, env):
3616 for if_clause in self.if_clauses:
3617 if_clause.analyse_declarations(env)
3618 if self.else_clause:
3619 self.else_clause.analyse_declarations(env)
3621 def analyse_expressions(self, env):
3622 for if_clause in self.if_clauses:
3623 if_clause.analyse_expressions(env)
3624 if self.else_clause:
3625 self.else_clause.analyse_expressions(env)
3627 def generate_execution_code(self, code):
3628 code.mark_pos(self.pos)
3629 end_label = code.new_label()
3630 for if_clause in self.if_clauses:
3631 if_clause.generate_execution_code(code, end_label)
3632 if self.else_clause:
3633 code.putln("/*else*/ {")
3634 self.else_clause.generate_execution_code(code)
3635 code.putln("}")
3636 code.put_label(end_label)
3638 def annotate(self, code):
3639 for if_clause in self.if_clauses:
3640 if_clause.annotate(code)
3641 if self.else_clause:
3642 self.else_clause.annotate(code)
3645 class IfClauseNode(Node):
3646 # if or elif clause in an if statement
3647 #
3648 # condition ExprNode
3649 # body StatNode
3651 child_attrs = ["condition", "body"]
3653 def analyse_control_flow(self, env):
3654 self.body.analyse_control_flow(env)
3656 def analyse_declarations(self, env):
3657 self.condition.analyse_declarations(env)
3658 self.body.analyse_declarations(env)
3660 def analyse_expressions(self, env):
3661 self.condition = \
3662 self.condition.analyse_temp_boolean_expression(env)
3663 self.condition.release_temp(env)
3664 self.body.analyse_expressions(env)
3666 def generate_execution_code(self, code, end_label):
3667 self.condition.generate_evaluation_code(code)
3668 code.putln(
3669 "if (%s) {" %
3670 self.condition.result())
3671 self.condition.generate_disposal_code(code)
3672 self.condition.free_temps(code)
3673 self.body.generate_execution_code(code)
3674 #code.putln(
3675 # "goto %s;" %
3676 # end_label)
3677 code.put_goto(end_label)
3678 code.putln("}")
3680 def annotate(self, code):
3681 self.condition.annotate(code)
3682 self.body.annotate(code)
3685 class SwitchCaseNode(StatNode):
3686 # Generated in the optimization of an if-elif-else node
3687 #
3688 # conditions [ExprNode]
3689 # body StatNode
3691 child_attrs = ['conditions', 'body']
3693 def generate_execution_code(self, code):
3694 for cond in self.conditions:
3695 code.mark_pos(cond.pos)
3696 code.putln("case %s:" % cond.calculate_result_code())
3697 self.body.generate_execution_code(code)
3698 code.putln("break;")
3700 def annotate(self, code):
3701 for cond in self.conditions:
3702 cond.annotate(code)
3703 self.body.annotate(code)
3705 class SwitchStatNode(StatNode):
3706 # Generated in the optimization of an if-elif-else node
3707 #
3708 # test ExprNode
3709 # cases [SwitchCaseNode]
3710 # else_clause StatNode or None
3712 child_attrs = ['test', 'cases', 'else_clause']
3714 def generate_execution_code(self, code):
3715 code.putln("switch (%s) {" % self.test.calculate_result_code())
3716 for case in self.cases:
3717 case.generate_execution_code(code)
3718 if self.else_clause is not None:
3719 code.putln("default:")
3720 self.else_clause.generate_execution_code(code)
3721 code.putln("break;")
3722 code.putln("}")
3724 def annotate(self, code):
3725 self.test.annotate(code)
3726 for case in self.cases:
3727 case.annotate(code)
3728 if self.else_clause is not None:
3729 self.else_clause.annotate(code)
3731 class LoopNode(object):
3733 def analyse_control_flow(self, env):
3734 env.start_branching(self.pos)
3735 self.body.analyse_control_flow(env)
3736 env.next_branch(self.body.end_pos())
3737 if self.else_clause:
3738 self.else_clause.analyse_control_flow(env)
3739 env.finish_branching(self.end_pos())
3742 class WhileStatNode(LoopNode, StatNode):
3743 # while statement
3744 #
3745 # condition ExprNode
3746 # body StatNode
3747 # else_clause StatNode
3749 child_attrs = ["condition", "body", "else_clause"]
3751 def analyse_declarations(self, env):
3752 self.body.analyse_declarations(env)
3753 if self.else_clause:
3754 self.else_clause.analyse_declarations(env)
3756 def analyse_expressions(self, env):
3757 self.condition = \
3758 self.condition.analyse_temp_boolean_expression(env)
3759 self.condition.release_temp(env)
3760 #env.recycle_pending_temps() # TEMPORARY
3761 self.body.analyse_expressions(env)
3762 if self.else_clause:
3763 self.else_clause.analyse_expressions(env)
3765 def generate_execution_code(self, code):
3766 old_loop_labels = code.new_loop_labels()
3767 code.putln(
3768 "while (1) {")
3769 self.condition.generate_evaluation_code(code)
3770 self.condition.generate_disposal_code(code)
3771 code.putln(
3772 "if (!%s) break;" %
3773 self.condition.result())
3774 self.condition.free_temps(code)
3775 self.body.generate_execution_code(code)
3776 code.put_label(code.continue_label)
3777 code.putln("}")
3778 break_label = code.break_label
3779 code.set_loop_labels(old_loop_labels)
3780 if self.else_clause:
3781 code.putln("/*else*/ {")
3782 self.else_clause.generate_execution_code(code)
3783 code.putln("}")
3784 code.put_label(break_label)
3786 def annotate(self, code):
3787 self.condition.annotate(code)
3788 self.body.annotate(code)
3789 if self.else_clause:
3790 self.else_clause.annotate(code)
3793 def ForStatNode(pos, **kw):
3794 if 'iterator' in kw:
3795 return ForInStatNode(pos, **kw)
3796 else:
3797 return ForFromStatNode(pos, **kw)
3799 class ForInStatNode(LoopNode, StatNode):
3800 # for statement
3801 #
3802 # target ExprNode
3803 # iterator IteratorNode
3804 # body StatNode
3805 # else_clause StatNode
3806 # item NextNode used internally
3808 child_attrs = ["target", "iterator", "body", "else_clause"]
3809 item = None
3811 def analyse_declarations(self, env):
3812 self.target.analyse_target_declaration(env)
3813 self.body.analyse_declarations(env)
3814 if self.else_clause:
3815 self.else_clause.analyse_declarations(env)
3817 def analyse_expressions(self, env):
3818 import ExprNodes
3819 self.target.analyse_target_types(env)
3820 self.iterator.analyse_expressions(env)
3821 self.item = ExprNodes.NextNode(self.iterator, env)
3822 self.item = self.item.coerce_to(self.target.type, env)
3823 self.item.allocate_temps(env)
3824 self.target.allocate_target_temps(env, self.item)
3825 #self.item.release_temp(env)
3826 #self.target.release_target_temp(env)
3827 self.body.analyse_expressions(env)
3828 if self.else_clause:
3829 self.else_clause.analyse_expressions(env)
3830 self.iterator.release_temp(env)
3832 def generate_execution_code(self, code):
3833 old_loop_labels = code.new_loop_labels()
3834 self.iterator.allocate_counter_temp(code)
3835 self.iterator.generate_evaluation_code(code)
3836 code.putln(
3837 "for (;;) {")
3838 self.item.generate_evaluation_code(code)
3839 self.target.generate_assignment_code(self.item, code)
3840 self.body.generate_execution_code(code)
3841 code.put_label(code.continue_label)
3842 code.putln(
3843 "}")
3844 break_label = code.break_label
3845 code.set_loop_labels(old_loop_labels)
3846 if self.else_clause:
3847 code.putln("/*else*/ {")
3848 self.else_clause.generate_execution_code(code)
3849 code.putln("}")
3850 code.put_label(break_label)
3851 self.iterator.release_counter_temp(code)
3852 self.iterator.generate_disposal_code(code)
3853 self.iterator.free_temps(code)
3855 def annotate(self, code):
3856 self.target.annotate(code)
3857 self.iterator.annotate(code)
3858 self.body.annotate(code)
3859 if self.else_clause:
3860 self.else_clause.annotate(code)
3861 self.item.annotate(code)
3864 class ForFromStatNode(LoopNode, StatNode):
3865 # for name from expr rel name rel expr
3866 #
3867 # target NameNode
3868 # bound1 ExprNode
3869 # relation1 string
3870 # relation2 string
3871 # bound2 ExprNode
3872 # step ExprNode or None
3873 # body StatNode
3874 # else_clause StatNode or None
3875 #
3876 # Used internally:
3877 #
3878 # is_py_target bool
3879 # loopvar_node ExprNode (usually a NameNode or temp node)
3880 # py_loopvar_node PyTempNode or None
3881 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3883 is_py_target = False
3884 loopvar_node = None
3885 py_loopvar_node = None
3887 def analyse_declarations(self, env):
3888 self.target.analyse_target_declaration(env)
3889 self.body.analyse_declarations(env)
3890 if self.else_clause:
3891 self.else_clause.analyse_declarations(env)
3893 def analyse_expressions(self, env):
3894 import ExprNodes
3895 self.target.analyse_target_types(env)
3896 self.bound1.analyse_types(env)
3897 self.bound2.analyse_types(env)
3898 if self.target.type.is_numeric:
3899 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3900 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3901 else:
3902 self.bound1 = self.bound1.coerce_to_integer(env)
3903 self.bound2 = self.bound2.coerce_to_integer(env)
3904 if self.step is not None:
3905 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3906 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3907 self.step.analyse_types(env)
3908 self.step = self.step.coerce_to_integer(env)
3909 if not (self.bound2.is_name or self.bound2.is_literal):
3910 self.bound2 = self.bound2.coerce_to_temp(env)
3911 target_type = self.target.type
3912 if not (target_type.is_pyobject or target_type.is_numeric):
3913 error(self.target.pos,
3914 "Integer for-loop variable must be of type int or Python object")
3915 #if not (target_type.is_pyobject
3916 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3917 # error(self.target.pos,
3918 # "Cannot assign integer to variable of type '%s'" % target_type)
3919 if target_type.is_numeric:
3920 self.is_py_target = 0
3921 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3922 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3923 self.loopvar_node = self.target
3924 self.py_loopvar_node = None
3925 else:
3926 self.is_py_target = 1
3927 c_loopvar_node = ExprNodes.TempNode(self.pos,
3928 PyrexTypes.c_long_type, env)
3929 c_loopvar_node.allocate_temps(env)
3930 self.loopvar_node = c_loopvar_node
3931 self.py_loopvar_node = \
3932 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3933 self.bound1.allocate_temps(env)
3934 self.bound2.allocate_temps(env)
3935 if self.step is not None:
3936 self.step.allocate_temps(env)
3937 if self.is_py_target:
3938 self.py_loopvar_node.allocate_temps(env)
3939 self.target.allocate_target_temps(env, self.py_loopvar_node)
3940 #self.target.release_target_temp(env)
3941 #self.py_loopvar_node.release_temp(env)
3942 self.body.analyse_expressions(env)
3943 if self.is_py_target:
3944 c_loopvar_node.release_temp(env)
3945 if self.else_clause:
3946 self.else_clause.analyse_expressions(env)
3947 self.bound1.release_temp(env)
3948 self.bound2.release_temp(env)
3949 if self.step is not None:
3950 self.step.release_temp(env)
3952 def generate_execution_code(self, code):
3953 old_loop_labels = code.new_loop_labels()
3954 from_range = getattr(self, "from_range", False)
3955 self.bound1.generate_evaluation_code(code)
3956 self.bound2.generate_evaluation_code(code)
3957 offset, incop = self.relation_table[self.relation1]
3958 if incop == "++":
3959 decop = "--"
3960 else:
3961 decop = "++"
3962 if self.step is not None:
3963 self.step.generate_evaluation_code(code)
3964 step = self.step.result()
3965 incop = "%s=%s" % (incop[0], step)
3966 decop = "%s=%s" % (decop[0], step)
3967 loopvar_name = self.loopvar_node.result()
3968 if from_range:
3969 # Skip the loop entirely (and avoid assigning to the loopvar) if
3970 # the loop is empty:
3971 code.putln("if (%s%s %s %s) {" % (
3972 self.bound1.result(), offset, self.relation2, self.bound2.result()
3973 ))
3974 code.putln(
3975 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3976 loopvar_name,
3977 self.bound1.result(), offset,
3978 loopvar_name, self.relation2, self.bound2.result(),
3979 loopvar_name, incop))
3980 if self.py_loopvar_node:
3981 self.py_loopvar_node.generate_evaluation_code(code)
3982 self.target.generate_assignment_code(self.py_loopvar_node, code)
3983 self.body.generate_execution_code(code)
3984 code.put_label(code.continue_label)
3985 if from_range:
3986 # Undo last increment to maintain Python semantics:
3987 code.putln("} %s%s;" % (loopvar_name, decop))
3988 # End the outer if statement:
3989 code.putln("} /* end if */")
3990 else:
3991 code.putln("}")
3992 break_label = code.break_label
3993 code.set_loop_labels(old_loop_labels)
3994 if self.else_clause:
3995 code.putln("/*else*/ {")
3996 self.else_clause.generate_execution_code(code)
3997 code.putln("}")
3998 code.put_label(break_label)
3999 self.bound1.generate_disposal_code(code)
4000 self.bound1.free_temps(code)
4001 self.bound2.generate_disposal_code(code)
4002 self.bound2.free_temps(code)
4003 if self.step is not None:
4004 self.step.generate_disposal_code(code)
4005 self.step.free_temps(code)
4007 relation_table = {
4008 # {relop : (initial offset, increment op)}
4009 '<=': ("", "++"),
4010 '<' : ("+1", "++"),
4011 '>=': ("", "--"),
4012 '>' : ("-1", "--")
4013 }
4015 def annotate(self, code):
4016 self.target.annotate(code)
4017 self.bound1.annotate(code)
4018 self.bound2.annotate(code)
4019 if self.step:
4020 self.bound2.annotate(code)
4021 self.body.annotate(code)
4022 if self.else_clause:
4023 self.else_clause.annotate(code)
4026 class WithStatNode(StatNode):
4027 """
4028 Represents a Python with statement.
4030 This is only used at parse tree level; and is not present in
4031 analysis or generation phases.
4032 """
4033 # manager The with statement manager object
4034 # target Node (lhs expression)
4035 # body StatNode
4036 child_attrs = ["manager", "target", "body"]
4038 class TryExceptStatNode(StatNode):
4039 # try .. except statement
4040 #
4041 # body StatNode
4042 # except_clauses [ExceptClauseNode]
4043 # else_clause StatNode or None
4044 # cleanup_list [Entry] old style temps to clean up on error
4046 child_attrs = ["body", "except_clauses", "else_clause"]
4048 def analyse_control_flow(self, env):
4049 env.start_branching(self.pos)
4050 self.body.analyse_control_flow(env)
4051 successful_try = env.control_flow # grab this for later
4052 env.next_branch(self.body.end_pos())
4053 env.finish_branching(self.body.end_pos())
4055 env.start_branching(self.except_clauses[0].pos)
4056 for except_clause in self.except_clauses:
4057 except_clause.analyse_control_flow(env)
4058 env.next_branch(except_clause.end_pos())
4060 # the else cause it executed only when the try clause finishes
4061 env.control_flow.incoming = successful_try
4062 if self.else_clause:
4063 self.else_clause.analyse_control_flow(env)
4064 env.finish_branching(self.end_pos())
4066 def analyse_declarations(self, env):
4067 self.body.analyse_declarations(env)
4068 for except_clause in self.except_clauses:
4069 except_clause.analyse_declarations(env)
4070 if self.else_clause:
4071 self.else_clause.analyse_declarations(env)
4072 self.gil_check(env)
4073 env.use_utility_code(reset_exception_utility_code)
4075 def analyse_expressions(self, env):
4076 self.body.analyse_expressions(env)
4077 self.cleanup_list = env.free_temp_entries[:]
4078 default_clause_seen = 0
4079 for except_clause in self.except_clauses:
4080 except_clause.analyse_expressions(env)
4081 if default_clause_seen:
4082 error(except_clause.pos, "default 'except:' must be last")
4083 if not except_clause.pattern:
4084 default_clause_seen = 1
4085 self.has_default_clause = default_clause_seen
4086 if self.else_clause:
4087 self.else_clause.analyse_expressions(env)
4088 self.gil_check(env)
4090 gil_message = "Try-except statement"
4092 def generate_execution_code(self, code):
4093 old_return_label = code.return_label
4094 old_break_label = code.break_label
4095 old_continue_label = code.continue_label
4096 old_error_label = code.new_error_label()
4097 our_error_label = code.error_label
4098 except_end_label = code.new_label('exception_handled')
4099 except_error_label = code.new_label('except_error')
4100 except_return_label = code.new_label('except_return')
4101 try_return_label = code.new_label('try_return')
4102 try_break_label = code.new_label('try_break')
4103 try_continue_label = code.new_label('try_continue')
4104 try_end_label = code.new_label('try_end')
4106 code.putln("{")
4107 code.putln("PyObject %s;" %
4108 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4109 code.putln("__Pyx_ExceptionSave(%s);" %
4110 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4111 for var in Naming.exc_save_vars:
4112 code.put_xgotref(var)
4113 code.putln(
4114 "/*try:*/ {")
4115 code.return_label = try_return_label
4116 code.break_label = try_break_label
4117 code.continue_label = try_continue_label
4118 self.body.generate_execution_code(code)
4119 code.putln(
4120 "}")
4121 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4122 code.error_label = except_error_label
4123 code.return_label = except_return_label
4124 if self.else_clause:
4125 code.putln(
4126 "/*else:*/ {")
4127 self.else_clause.generate_execution_code(code)
4128 code.putln(
4129 "}")
4130 for var in Naming.exc_save_vars:
4131 code.put_xdecref_clear(var, py_object_type)
4132 code.put_goto(try_end_label)
4133 if code.label_used(try_return_label):
4134 code.put_label(try_return_label)
4135 for var in Naming.exc_save_vars:
4136 code.put_xdecref_clear(var, py_object_type)
4137 code.put_goto(old_return_label)
4138 code.put_label(our_error_label)
4139 code.put_var_xdecrefs_clear(self.cleanup_list)
4140 for temp_name, type in temps_to_clean_up:
4141 code.put_xdecref_clear(temp_name, type)
4142 for except_clause in self.except_clauses:
4143 except_clause.generate_handling_code(code, except_end_label)
4145 error_label_used = code.label_used(except_error_label)
4146 if error_label_used or not self.has_default_clause:
4147 if error_label_used:
4148 code.put_label(except_error_label)
4149 for var in Naming.exc_save_vars:
4150 code.put_xdecref(var, py_object_type)
4151 code.put_goto(old_error_label)
4153 if code.label_used(try_break_label):
4154 code.put_label(try_break_label)
4155 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4156 code.putln("__Pyx_ExceptionReset(%s);" %
4157 ', '.join(Naming.exc_save_vars))
4158 code.put_goto(old_break_label)
4160 if code.label_used(try_continue_label):
4161 code.put_label(try_continue_label)
4162 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4163 code.putln("__Pyx_ExceptionReset(%s);" %
4164 ', '.join(Naming.exc_save_vars))
4165 code.put_goto(old_continue_label)
4167 if code.label_used(except_return_label):
4168 code.put_label(except_return_label)
4169 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4170 code.putln("__Pyx_ExceptionReset(%s);" %
4171 ', '.join(Naming.exc_save_vars))
4172 code.put_goto(old_return_label)
4174 if code.label_used(except_end_label):
4175 code.put_label(except_end_label)
4176 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4177 code.putln("__Pyx_ExceptionReset(%s);" %
4178 ', '.join(Naming.exc_save_vars))
4179 code.put_label(try_end_label)
4180 code.putln("}")
4182 code.return_label = old_return_label
4183 code.break_label = old_break_label
4184 code.continue_label = old_continue_label
4185 code.error_label = old_error_label
4187 def annotate(self, code):
4188 self.body.annotate(code)
4189 for except_node in self.except_clauses:
4190 except_node.annotate(code)
4191 if self.else_clause:
4192 self.else_clause.annotate(code)
4195 class ExceptClauseNode(Node):
4196 # Part of try ... except statement.
4197 #
4198 # pattern ExprNode
4199 # target ExprNode or None
4200 # body StatNode
4201 # excinfo_target NameNode or None optional target for exception info
4202 # match_flag string result of exception match
4203 # exc_value ExcValueNode used internally
4204 # function_name string qualified name of enclosing function
4205 # exc_vars (string * 3) local exception variables
4207 # excinfo_target is never set by the parser, but can be set by a transform
4208 # in order to extract more extensive information about the exception as a
4209 # sys.exc_info()-style tuple into a target variable
4211 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4213 exc_value = None
4214 excinfo_target = None
4216 def analyse_declarations(self, env):
4217 if self.target:
4218 self.target.analyse_target_declaration(env)
4219 if self.excinfo_target is not None:
4220 self.excinfo_target.analyse_target_declaration(env)
4221 self.body.analyse_declarations(env)
4223 def analyse_expressions(self, env):
4224 import ExprNodes
4225 genv = env.global_scope()
4226 self.function_name = env.qualified_name
4227 if self.pattern:
4228 self.pattern.analyse_expressions(env)
4229 self.pattern = self.pattern.coerce_to_pyobject(env)
4230 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
4231 self.pattern.release_temp(env)
4232 env.release_temp(self.match_flag)
4233 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
4234 if self.target:
4235 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
4236 self.exc_value.allocate_temps(env)
4237 self.target.analyse_target_expression(env, self.exc_value)
4238 if self.excinfo_target is not None:
4239 import ExprNodes
4240 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4241 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
4242 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
4243 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
4244 ])
4245 self.excinfo_tuple.analyse_expressions(env)
4246 self.excinfo_tuple.allocate_temps(env)
4247 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4249 self.body.analyse_expressions(env)
4250 for var in self.exc_vars:
4251 env.release_temp(var)
4252 env.use_utility_code(get_exception_utility_code)
4253 env.use_utility_code(restore_exception_utility_code)
4255 def generate_handling_code(self, code, end_label):
4256 code.mark_pos(self.pos)
4257 if self.pattern:
4258 self.pattern.generate_evaluation_code(code)
4259 code.putln(
4260 "%s = PyErr_ExceptionMatches(%s);" % (
4261 self.match_flag,
4262 self.pattern.py_result()))
4263 self.pattern.generate_disposal_code(code)
4264 self.pattern.free_temps(code)
4265 code.putln(
4266 "if (%s) {" %
4267 self.match_flag)
4268 else:
4269 code.putln("/*except:*/ {")
4270 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4271 # We always have to fetch the exception value even if
4272 # there is no target, because this also normalises the
4273 # exception and stores it in the thread state.
4274 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
4275 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4276 code.error_goto(self.pos)))
4277 for x in self.exc_vars:
4278 code.put_gotref(x)
4279 if self.target:
4280 self.exc_value.generate_evaluation_code(code)
4281 self.target.generate_assignment_code(self.exc_value, code)
4282 if self.excinfo_target is not None:
4283 self.excinfo_tuple.generate_evaluation_code(code)
4284 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4287 old_break_label, old_continue_label = code.break_label, code.continue_label
4288 code.break_label = code.new_label('except_break')
4289 code.continue_label = code.new_label('except_continue')
4291 old_exc_vars = code.funcstate.exc_vars
4292 code.funcstate.exc_vars = self.exc_vars
4293 self.body.generate_execution_code(code)
4294 code.funcstate.exc_vars = old_exc_vars
4295 for var in self.exc_vars:
4296 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4297 code.put_goto(end_label)
4299 if code.label_used(code.break_label):
4300 code.put_label(code.break_label)
4301 for var in self.exc_vars:
4302 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4303 code.put_goto(old_break_label)
4304 code.break_label = old_break_label
4306 if code.label_used(code.continue_label):
4307 code.put_label(code.continue_label)
4308 for var in self.exc_vars:
4309 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4310 code.put_goto(old_continue_label)
4311 code.continue_label = old_continue_label
4313 code.putln(
4314 "}")
4316 def annotate(self, code):
4317 if self.pattern:
4318 self.pattern.annotate(code)
4319 if self.target:
4320 self.target.annotate(code)
4321 self.body.annotate(code)
4324 class TryFinallyStatNode(StatNode):
4325 # try ... finally statement
4326 #
4327 # body StatNode
4328 # finally_clause StatNode
4329 #
4330 # cleanup_list [Entry] old_style temps to clean up on error
4331 #
4332 # The plan is that we funnel all continue, break
4333 # return and error gotos into the beginning of the
4334 # finally block, setting a variable to remember which
4335 # one we're doing. At the end of the finally block, we
4336 # switch on the variable to figure out where to go.
4337 # In addition, if we're doing an error, we save the
4338 # exception on entry to the finally block and restore
4339 # it on exit.
4341 child_attrs = ["body", "finally_clause"]
4343 preserve_exception = 1
4345 disallow_continue_in_try_finally = 0
4346 # There doesn't seem to be any point in disallowing
4347 # continue in the try block, since we have no problem
4348 # handling it.
4350 def create_analysed(pos, env, body, finally_clause):
4351 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4352 node.cleanup_list = []
4353 return node
4354 create_analysed = staticmethod(create_analysed)
4356 def analyse_control_flow(self, env):
4357 env.start_branching(self.pos)
4358 self.body.analyse_control_flow(env)
4359 env.next_branch(self.body.end_pos())
4360 env.finish_branching(self.body.end_pos())
4361 self.finally_clause.analyse_control_flow(env)
4363 def analyse_declarations(self, env):
4364 self.body.analyse_declarations(env)
4365 self.finally_clause.analyse_declarations(env)
4367 def analyse_expressions(self, env):
4368 self.body.analyse_expressions(env)
4369 self.cleanup_list = env.free_temp_entries[:]
4370 self.finally_clause.analyse_expressions(env)
4371 self.gil_check(env)
4373 gil_message = "Try-finally statement"
4375 def generate_execution_code(self, code):
4376 old_error_label = code.error_label
4377 old_labels = code.all_new_labels()
4378 new_labels = code.get_all_labels()
4379 new_error_label = code.error_label
4380 catch_label = code.new_label()
4381 code.putln(
4382 "/*try:*/ {")
4383 if self.disallow_continue_in_try_finally:
4384 was_in_try_finally = code.funcstate.in_try_finally
4385 code.funcstate.in_try_finally = 1
4386 self.body.generate_execution_code(code)
4387 if self.disallow_continue_in_try_finally:
4388 code.funcstate.in_try_finally = was_in_try_finally
4389 code.putln(
4390 "}")
4391 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4392 code.putln(
4393 "/*finally:*/ {")
4394 cases_used = []
4395 error_label_used = 0
4396 for i, new_label in enumerate(new_labels):
4397 if new_label in code.labels_used:
4398 cases_used.append(i)
4399 if new_label == new_error_label:
4400 error_label_used = 1
4401 error_label_case = i
4402 if cases_used:
4403 code.putln(
4404 "int __pyx_why;")
4405 if error_label_used and self.preserve_exception:
4406 code.putln(
4407 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4408 code.putln(
4409 "int %s;" % Naming.exc_lineno_name)
4410 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4411 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4412 code.putln(exc_var_init_zero)
4413 else:
4414 exc_var_init_zero = None
4415 code.use_label(catch_label)
4416 code.putln(
4417 "__pyx_why = 0; goto %s;" % catch_label)
4418 for i in cases_used:
4419 new_label = new_labels[i]
4420 #if new_label and new_label != "<try>":
4421 if new_label == new_error_label and self.preserve_exception:
4422 self.put_error_catcher(code,
4423 new_error_label, i+1, catch_label, temps_to_clean_up)
4424 else:
4425 code.put('%s: ' % new_label)
4426 if exc_var_init_zero:
4427 code.putln(exc_var_init_zero)
4428 code.putln("__pyx_why = %s; goto %s;" % (
4429 i+1,
4430 catch_label))
4431 code.put_label(catch_label)
4432 code.set_all_labels(old_labels)
4433 if error_label_used:
4434 code.new_error_label()
4435 finally_error_label = code.error_label
4436 self.finally_clause.generate_execution_code(code)
4437 if error_label_used:
4438 if finally_error_label in code.labels_used and self.preserve_exception:
4439 over_label = code.new_label()
4440 code.put_goto(over_label);
4441 code.put_label(finally_error_label)
4442 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4443 for var in Naming.exc_vars:
4444 code.putln("Py_XDECREF(%s);" % var)
4445 code.putln("}")
4446 code.put_goto(old_error_label)
4447 code.put_label(over_label)
4448 code.error_label = old_error_label
4449 if cases_used:
4450 code.putln(
4451 "switch (__pyx_why) {")
4452 for i in cases_used:
4453 old_label = old_labels[i]
4454 if old_label == old_error_label and self.preserve_exception:
4455 self.put_error_uncatcher(code, i+1, old_error_label)
4456 else:
4457 code.use_label(old_label)
4458 code.putln(
4459 "case %s: goto %s;" % (
4460 i+1,
4461 old_label))
4462 code.putln(
4463 "}")
4464 code.putln(
4465 "}")
4467 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4468 code.globalstate.use_utility_code(restore_exception_utility_code)
4469 code.putln(
4470 "%s: {" %
4471 error_label)
4472 code.putln(
4473 "__pyx_why = %s;" %
4474 i)
4475 code.put_var_xdecrefs_clear(self.cleanup_list)
4476 for temp_name, type in temps_to_clean_up:
4477 code.put_xdecref_clear(temp_name, type)
4478 code.putln(
4479 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4480 Naming.exc_vars)
4481 code.putln(
4482 "%s = %s;" % (
4483 Naming.exc_lineno_name, Naming.lineno_cname))
4484 #code.putln(
4485 # "goto %s;" %
4486 # catch_label)
4487 code.put_goto(catch_label)
4488 code.putln(
4489 "}")
4491 def put_error_uncatcher(self, code, i, error_label):
4492 code.globalstate.use_utility_code(restore_exception_utility_code)
4493 code.putln(
4494 "case %s: {" %
4495 i)
4496 code.putln(
4497 "__Pyx_ErrRestore(%s, %s, %s);" %
4498 Naming.exc_vars)
4499 code.putln(
4500 "%s = %s;" % (
4501 Naming.lineno_cname, Naming.exc_lineno_name))
4502 for var in Naming.exc_vars:
4503 code.putln(
4504 "%s = 0;" %
4505 var)
4506 code.put_goto(error_label)
4507 code.putln(
4508 "}")
4510 def annotate(self, code):
4511 self.body.annotate(code)
4512 self.finally_clause.annotate(code)
4515 class GILStatNode(TryFinallyStatNode):
4516 # 'with gil' or 'with nogil' statement
4517 #
4518 # state string 'gil' or 'nogil'
4520 child_attrs = []
4522 preserve_exception = 0
4524 def __init__(self, pos, state, body):
4525 self.state = state
4526 TryFinallyStatNode.__init__(self, pos,
4527 body = body,
4528 finally_clause = GILExitNode(pos, state = state))
4530 def analyse_expressions(self, env):
4531 was_nogil = env.nogil
4532 env.nogil = 1
4533 TryFinallyStatNode.analyse_expressions(self, env)
4534 env.nogil = was_nogil
4536 def gil_check(self, env):
4537 pass
4539 def generate_execution_code(self, code):
4540 code.putln("/*with %s:*/ {" % self.state)
4541 if self.state == 'gil':
4542 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
4543 else:
4544 code.putln("PyThreadState *_save;")
4545 code.putln("Py_UNBLOCK_THREADS")
4546 TryFinallyStatNode.generate_execution_code(self, code)
4547 code.putln("}")
4550 class GILExitNode(StatNode):
4551 # Used as the 'finally' block in a GILStatNode
4552 #
4553 # state string 'gil' or 'nogil'
4555 child_attrs = []
4557 def analyse_expressions(self, env):
4558 pass
4560 def generate_execution_code(self, code):
4561 if self.state == 'gil':
4562 code.putln("PyGILState_Release();")
4563 else:
4564 code.putln("Py_BLOCK_THREADS")
4567 class CImportStatNode(StatNode):
4568 # cimport statement
4569 #
4570 # module_name string Qualified name of module being imported
4571 # as_name string or None Name specified in "as" clause, if any
4573 child_attrs = []
4575 def analyse_declarations(self, env):
4576 if not env.is_module_scope:
4577 error(self.pos, "cimport only allowed at module level")
4578 return
4579 module_scope = env.find_module(self.module_name, self.pos)
4580 if "." in self.module_name:
4581 names = [EncodedString(name) for name in self.module_name.split(".")]
4582 top_name = names[0]
4583 top_module_scope = env.context.find_submodule(top_name)
4584 module_scope = top_module_scope
4585 for name in names[1:]:
4586 submodule_scope = module_scope.find_submodule(name)
4587 module_scope.declare_module(name, submodule_scope, self.pos)
4588 module_scope = submodule_scope
4589 if self.as_name:
4590 env.declare_module(self.as_name, module_scope, self.pos)
4591 else:
4592 env.declare_module(top_name, top_module_scope, self.pos)
4593 else:
4594 name = self.as_name or self.module_name
4595 env.declare_module(name, module_scope, self.pos)
4597 def analyse_expressions(self, env):
4598 pass
4600 def generate_execution_code(self, code):
4601 pass
4604 class FromCImportStatNode(StatNode):
4605 # from ... cimport statement
4606 #
4607 # module_name string Qualified name of module
4608 # imported_names [(pos, name, as_name, kind)] Names to be imported
4610 child_attrs = []
4612 def analyse_declarations(self, env):
4613 if not env.is_module_scope:
4614 error(self.pos, "cimport only allowed at module level")
4615 return
4616 module_scope = env.find_module(self.module_name, self.pos)
4617 env.add_imported_module(module_scope)
4618 for pos, name, as_name, kind in self.imported_names:
4619 if name == "*":
4620 for local_name, entry in module_scope.entries.items():
4621 env.add_imported_entry(local_name, entry, pos)
4622 else:
4623 entry = module_scope.lookup(name)
4624 if entry:
4625 if kind and not self.declaration_matches(entry, kind):
4626 entry.redeclared(pos)
4627 else:
4628 if kind == 'struct' or kind == 'union':
4629 entry = module_scope.declare_struct_or_union(name,
4630 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4631 elif kind == 'class':
4632 entry = module_scope.declare_c_class(name, pos = pos,
4633 module_name = self.module_name)
4634 else:
4635 error(pos, "Name '%s' not declared in module '%s'"
4636 % (name, self.module_name))
4638 if entry:
4639 local_name = as_name or name
4640 env.add_imported_entry(local_name, entry, pos)
4642 def declaration_matches(self, entry, kind):
4643 if not entry.is_type:
4644 return 0
4645 type = entry.type
4646 if kind == 'class':
4647 if not type.is_extension_type:
4648 return 0
4649 else:
4650 if not type.is_struct_or_union:
4651 return 0
4652 if kind != type.kind:
4653 return 0
4654 return 1
4656 def analyse_expressions(self, env):
4657 pass
4659 def generate_execution_code(self, code):
4660 pass
4663 class FromImportStatNode(StatNode):
4664 # from ... import statement
4665 #
4666 # module ImportNode
4667 # items [(string, NameNode)]
4668 # interned_items [(string, NameNode, ExprNode)]
4669 # item PyTempNode used internally
4670 # import_star boolean used internally
4672 child_attrs = ["module"]
4673 import_star = 0
4675 def analyse_declarations(self, env):
4676 for name, target in self.items:
4677 if name == "*":
4678 if not env.is_module_scope:
4679 error(self.pos, "import * only allowed at module level")
4680 return
4681 env.has_import_star = 1
4682 self.import_star = 1
4683 else:
4684 target.analyse_target_declaration(env)
4686 def analyse_expressions(self, env):
4687 import ExprNodes
4688 self.module.analyse_expressions(env)
4689 self.item = ExprNodes.PyTempNode(self.pos, env)
4690 self.item.allocate_temp(env)
4691 self.interned_items = []
4692 for name, target in self.items:
4693 if name == '*':
4694 for _, entry in env.entries.items():
4695 if not entry.is_type and entry.type.is_extension_type:
4696 env.use_utility_code(ExprNodes.type_test_utility_code)
4697 break
4698 else:
4699 entry = env.lookup(target.name)
4700 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4701 continue # already cimported
4702 target.analyse_target_expression(env, None)
4703 if target.type is py_object_type:
4704 coerced_item = None
4705 else:
4706 coerced_item = self.item.coerce_to(target.type, env)
4707 self.interned_items.append(
4708 (env.intern_identifier(name), target, coerced_item))
4709 #target.release_target_temp(env) # was release_temp ?!?
4710 self.module.release_temp(env)
4711 self.item.release_temp(env)
4713 def generate_execution_code(self, code):
4714 self.module.generate_evaluation_code(code)
4715 if self.import_star:
4716 code.putln(
4717 'if (%s(%s) < 0) %s;' % (
4718 Naming.import_star,
4719 self.module.py_result(),
4720 code.error_goto(self.pos)))
4721 for cname, target, coerced_item in self.interned_items:
4722 code.putln(
4723 '%s = PyObject_GetAttr(%s, %s); %s' % (
4724 self.item.result(),
4725 self.module.py_result(),
4726 cname,
4727 code.error_goto_if_null(self.item.result(), self.pos)))
4728 code.put_gotref(self.item.py_result())
4729 if coerced_item is None:
4730 target.generate_assignment_code(self.item, code)
4731 else:
4732 coerced_item.allocate_temp_result(code)
4733 coerced_item.generate_result_code(code)
4734 target.generate_assignment_code(coerced_item, code)
4735 if self.item.result() != coerced_item.result():
4736 code.put_decref_clear(self.item.result(), self.item.type)
4737 self.module.generate_disposal_code(code)
4738 self.module.free_temps(code)
4742 #------------------------------------------------------------------------------------
4743 #
4744 # Runtime support code
4745 #
4746 #------------------------------------------------------------------------------------
4748 utility_function_predeclarations = \
4749 """
4750 #ifdef __GNUC__
4751 #define INLINE __inline__
4752 #elif _WIN32
4753 #define INLINE __inline
4754 #else
4755 #define INLINE
4756 #endif
4758 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4760 """ + """
4762 static int %(skip_dispatch_cname)s = 0;
4764 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4766 if Options.gcc_branch_hints:
4767 branch_prediction_macros = \
4768 """
4769 #ifdef __GNUC__
4770 /* Test for GCC > 2.95 */
4771 #if __GNUC__ > 2 || \
4772 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4773 #define likely(x) __builtin_expect(!!(x), 1)
4774 #define unlikely(x) __builtin_expect(!!(x), 0)
4775 #else /* __GNUC__ > 2 ... */
4776 #define likely(x) (x)
4777 #define unlikely(x) (x)
4778 #endif /* __GNUC__ > 2 ... */
4779 #else /* __GNUC__ */
4780 #define likely(x) (x)
4781 #define unlikely(x) (x)
4782 #endif /* __GNUC__ */
4783 """
4784 else:
4785 branch_prediction_macros = \
4786 """
4787 #define likely(x) (x)
4788 #define unlikely(x) (x)
4789 """
4791 #get_name_predeclaration = \
4792 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4794 #get_name_interned_predeclaration = \
4795 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4797 #------------------------------------------------------------------------------------
4799 printing_utility_code = UtilityCode(
4800 proto = """
4801 static int __Pyx_Print(PyObject *, int); /*proto*/
4802 #if PY_MAJOR_VERSION >= 3
4803 static PyObject* %s = 0;
4804 static PyObject* %s = 0;
4805 #endif
4806 """ % (Naming.print_function, Naming.print_function_kwargs),
4807 impl = r"""
4808 #if PY_MAJOR_VERSION < 3
4809 static PyObject *__Pyx_GetStdout(void) {
4810 PyObject *f = PySys_GetObject((char *)"stdout");
4811 if (!f) {
4812 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4813 }
4814 return f;
4815 }
4817 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4818 PyObject *f;
4819 PyObject* v;
4820 int i;
4822 if (!(f = __Pyx_GetStdout()))
4823 return -1;
4824 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4825 if (PyFile_SoftSpace(f, 1)) {
4826 if (PyFile_WriteString(" ", f) < 0)
4827 return -1;
4828 }
4829 v = PyTuple_GET_ITEM(arg_tuple, i);
4830 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4831 return -1;
4832 if (PyString_Check(v)) {
4833 char *s = PyString_AsString(v);
4834 Py_ssize_t len = PyString_Size(v);
4835 if (len > 0 &&
4836 isspace(Py_CHARMASK(s[len-1])) &&
4837 s[len-1] != ' ')
4838 PyFile_SoftSpace(f, 0);
4839 }
4840 }
4841 if (newline) {
4842 if (PyFile_WriteString("\n", f) < 0)
4843 return -1;
4844 PyFile_SoftSpace(f, 0);
4845 }
4846 return 0;
4847 }
4849 #else /* Python 3 has a print function */
4851 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4852 PyObject* kwargs = 0;
4853 PyObject* result = 0;
4854 PyObject* end_string;
4855 if (!%(PRINT_FUNCTION)s) {
4856 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4857 if (!%(PRINT_FUNCTION)s)
4858 return -1;
4859 }
4860 if (!newline) {
4861 if (!%(PRINT_KWARGS)s) {
4862 %(PRINT_KWARGS)s = PyDict_New();
4863 if (!%(PRINT_KWARGS)s)
4864 return -1;
4865 end_string = PyUnicode_FromStringAndSize(" ", 1);
4866 if (!end_string)
4867 return -1;
4868 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4869 Py_DECREF(end_string);
4870 return -1;
4871 }
4872 Py_DECREF(end_string);
4873 }
4874 kwargs = %(PRINT_KWARGS)s;
4875 }
4876 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4877 if (!result)
4878 return -1;
4879 Py_DECREF(result);
4880 return 0;
4881 }
4883 #endif
4884 """ % {'BUILTINS' : Naming.builtins_cname,
4885 'PRINT_FUNCTION' : Naming.print_function,
4886 'PRINT_KWARGS' : Naming.print_function_kwargs}
4887 )
4890 printing_one_utility_code = UtilityCode(
4891 proto = """
4892 static int __Pyx_PrintOne(PyObject *o); /*proto*/
4893 """,
4894 impl = r"""
4895 #if PY_MAJOR_VERSION < 3
4897 static int __Pyx_PrintOne(PyObject *o) {
4898 PyObject *f;
4899 if (!(f = __Pyx_GetStdout()))
4900 return -1;
4901 if (PyFile_SoftSpace(f, 0)) {
4902 if (PyFile_WriteString(" ", f) < 0)
4903 return -1;
4904 }
4905 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
4906 return -1;
4907 if (PyFile_WriteString("\n", f) < 0)
4908 return -1;
4909 return 0;
4910 /* the line below is just to avoid compiler
4911 * compiler warnings about unused functions */
4912 return __Pyx_Print(NULL, 0);
4913 }
4915 #else /* Python 3 has a print function */
4917 static int __Pyx_PrintOne(PyObject *o) {
4918 int res;
4919 PyObject* arg_tuple = PyTuple_New(1);
4920 if (unlikely(!arg_tuple))
4921 return -1;
4922 Py_INCREF(o);
4923 PyTuple_SET_ITEM(arg_tuple, 0, o);
4924 res = __Pyx_Print(arg_tuple, 1);
4925 Py_DECREF(arg_tuple);
4926 return res;
4927 }
4929 #endif
4930 """)
4934 #------------------------------------------------------------------------------------
4936 # The following function is based on do_raise() from ceval.c.
4938 raise_utility_code = UtilityCode(
4939 proto = """
4940 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4941 """,
4942 impl = """
4943 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4944 Py_XINCREF(type);
4945 Py_XINCREF(value);
4946 Py_XINCREF(tb);
4947 /* First, check the traceback argument, replacing None with NULL. */
4948 if (tb == Py_None) {
4949 Py_DECREF(tb);
4950 tb = 0;
4951 }
4952 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4953 PyErr_SetString(PyExc_TypeError,
4954 "raise: arg 3 must be a traceback or None");
4955 goto raise_error;
4956 }
4957 /* Next, replace a missing value with None */
4958 if (value == NULL) {
4959 value = Py_None;
4960 Py_INCREF(value);
4961 }
4962 #if PY_VERSION_HEX < 0x02050000
4963 if (!PyClass_Check(type))
4964 #else
4965 if (!PyType_Check(type))
4966 #endif
4967 {
4968 /* Raising an instance. The value should be a dummy. */
4969 if (value != Py_None) {
4970 PyErr_SetString(PyExc_TypeError,
4971 "instance exception may not have a separate value");
4972 goto raise_error;
4973 }
4974 /* Normalize to raise <class>, <instance> */
4975 Py_DECREF(value);
4976 value = type;
4977 #if PY_VERSION_HEX < 0x02050000
4978 if (PyInstance_Check(type)) {
4979 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4980 Py_INCREF(type);
4981 }
4982 else {
4983 type = 0;
4984 PyErr_SetString(PyExc_TypeError,
4985 "raise: exception must be an old-style class or instance");
4986 goto raise_error;
4987 }
4988 #else
4989 type = (PyObject*) Py_TYPE(type);
4990 Py_INCREF(type);
4991 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4992 PyErr_SetString(PyExc_TypeError,
4993 "raise: exception class must be a subclass of BaseException");
4994 goto raise_error;
4995 }
4996 #endif
4997 }
4998 __Pyx_ErrRestore(type, value, tb);
4999 return;
5000 raise_error:
5001 Py_XDECREF(value);
5002 Py_XDECREF(type);
5003 Py_XDECREF(tb);
5004 return;
5005 }
5006 """)
5008 #------------------------------------------------------------------------------------
5010 reraise_utility_code = UtilityCode(
5011 proto = """
5012 static void __Pyx_ReRaise(void); /*proto*/
5013 """,
5014 impl = """
5015 static void __Pyx_ReRaise(void) {
5016 PyThreadState *tstate = PyThreadState_GET();
5017 PyObject* tmp_type = tstate->curexc_type;
5018 PyObject* tmp_value = tstate->curexc_value;
5019 PyObject* tmp_tb = tstate->curexc_traceback;
5020 tstate->curexc_type = tstate->exc_type;
5021 tstate->curexc_value = tstate->exc_value;
5022 tstate->curexc_traceback = tstate->exc_traceback;
5023 tstate->exc_type = 0;
5024 tstate->exc_value = 0;
5025 tstate->exc_traceback = 0;
5026 Py_XDECREF(tmp_type);
5027 Py_XDECREF(tmp_value);
5028 Py_XDECREF(tmp_tb);
5029 }
5030 """)
5032 #------------------------------------------------------------------------------------
5034 arg_type_test_utility_code = UtilityCode(
5035 proto = """
5036 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5037 const char *name, int exact); /*proto*/
5038 """,
5039 impl = """
5040 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5041 const char *name, int exact)
5042 {
5043 if (!type) {
5044 PyErr_Format(PyExc_SystemError, "Missing type object");
5045 return 0;
5046 }
5047 if (none_allowed && obj == Py_None) return 1;
5048 else if (exact) {
5049 if (Py_TYPE(obj) == type) return 1;
5050 }
5051 else {
5052 if (PyObject_TypeCheck(obj, type)) return 1;
5053 }
5054 PyErr_Format(PyExc_TypeError,
5055 "Argument '%s' has incorrect type (expected %s, got %s)",
5056 name, type->tp_name, Py_TYPE(obj)->tp_name);
5057 return 0;
5058 }
5059 """)
5061 #------------------------------------------------------------------------------------
5062 #
5063 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5064 # many or too few positional arguments were found. This handles
5065 # Py_ssize_t formatting correctly.
5067 raise_argtuple_invalid_utility_code = UtilityCode(
5068 proto = """
5069 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5070 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5071 """,
5072 impl = """
5073 static void __Pyx_RaiseArgtupleInvalid(
5074 const char* func_name,
5075 int exact,
5076 Py_ssize_t num_min,
5077 Py_ssize_t num_max,
5078 Py_ssize_t num_found)
5079 {
5080 Py_ssize_t num_expected;
5081 const char *number, *more_or_less;
5083 if (num_found < num_min) {
5084 num_expected = num_min;
5085 more_or_less = "at least";
5086 } else {
5087 num_expected = num_max;
5088 more_or_less = "at most";
5089 }
5090 if (exact) {
5091 more_or_less = "exactly";
5092 }
5093 number = (num_expected == 1) ? "" : "s";
5094 PyErr_Format(PyExc_TypeError,
5095 #if PY_VERSION_HEX < 0x02050000
5096 "%s() takes %s %d positional argument%s (%d given)",
5097 #else
5098 "%s() takes %s %zd positional argument%s (%zd given)",
5099 #endif
5100 func_name, more_or_less, num_expected, number, num_found);
5101 }
5102 """)
5104 raise_keyword_required_utility_code = UtilityCode(
5105 proto = """
5106 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5107 """,
5108 impl = """
5109 static INLINE void __Pyx_RaiseKeywordRequired(
5110 const char* func_name,
5111 PyObject* kw_name)
5112 {
5113 PyErr_Format(PyExc_TypeError,
5114 #if PY_MAJOR_VERSION >= 3
5115 "%s() needs keyword-only argument %U", func_name, kw_name);
5116 #else
5117 "%s() needs keyword-only argument %s", func_name,
5118 PyString_AS_STRING(kw_name));
5119 #endif
5120 }
5121 """)
5123 raise_double_keywords_utility_code = UtilityCode(
5124 proto = """
5125 static void __Pyx_RaiseDoubleKeywordsError(
5126 const char* func_name, PyObject* kw_name); /*proto*/
5127 """,
5128 impl = """
5129 static void __Pyx_RaiseDoubleKeywordsError(
5130 const char* func_name,
5131 PyObject* kw_name)
5132 {
5133 PyErr_Format(PyExc_TypeError,
5134 #if PY_MAJOR_VERSION >= 3
5135 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5136 #else
5137 "%s() got multiple values for keyword argument '%s'", func_name,
5138 PyString_AS_STRING(kw_name));
5139 #endif
5140 }
5141 """)
5143 #------------------------------------------------------------------------------------
5144 #
5145 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5146 # were passed to a function, or if any keywords were passed to a
5147 # function that does not accept them.
5149 keyword_string_check_utility_code = UtilityCode(
5150 proto = """
5151 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5152 const char* function_name, int kw_allowed); /*proto*/
5153 """,
5154 impl = """
5155 static INLINE int __Pyx_CheckKeywordStrings(
5156 PyObject *kwdict,
5157 const char* function_name,
5158 int kw_allowed)
5159 {
5160 PyObject* key = 0;
5161 Py_ssize_t pos = 0;
5162 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5163 #if PY_MAJOR_VERSION < 3
5164 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5165 #else
5166 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5167 #endif
5168 goto invalid_keyword_type;
5169 }
5170 if ((!kw_allowed) && unlikely(key))
5171 goto invalid_keyword;
5172 return 1;
5173 invalid_keyword_type:
5174 PyErr_Format(PyExc_TypeError,
5175 "%s() keywords must be strings", function_name);
5176 return 0;
5177 invalid_keyword:
5178 PyErr_Format(PyExc_TypeError,
5179 #if PY_MAJOR_VERSION < 3
5180 "%s() got an unexpected keyword argument '%s'",
5181 function_name, PyString_AsString(key));
5182 #else
5183 "%s() got an unexpected keyword argument '%U'",
5184 function_name, key);
5185 #endif
5186 return 0;
5187 }
5188 """)
5190 #------------------------------------------------------------------------------------
5191 #
5192 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5193 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5194 # keywords will raise an invalid keyword error.
5195 #
5196 # Three kinds of errors are checked: 1) non-string keywords, 2)
5197 # unexpected keywords and 3) overlap with positional arguments.
5198 #
5199 # If num_posargs is greater 0, it denotes the number of positional
5200 # arguments that were passed and that must therefore not appear
5201 # amongst the keywords as well.
5202 #
5203 # This method does not check for required keyword arguments.
5204 #
5206 parse_keywords_utility_code = UtilityCode(
5207 proto = """
5208 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5209 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5210 const char* function_name); /*proto*/
5211 """,
5212 impl = """
5213 static int __Pyx_ParseOptionalKeywords(
5214 PyObject *kwds,
5215 PyObject **argnames[],
5216 PyObject *kwds2,
5217 PyObject *values[],
5218 Py_ssize_t num_pos_args,
5219 const char* function_name)
5220 {
5221 PyObject *key = 0, *value = 0;
5222 Py_ssize_t pos = 0;
5223 PyObject*** name;
5224 PyObject*** first_kw_arg = argnames + num_pos_args;
5226 while (PyDict_Next(kwds, &pos, &key, &value)) {
5227 name = first_kw_arg;
5228 while (*name && (**name != key)) name++;
5229 if (*name) {
5230 values[name-argnames] = value;
5231 } else {
5232 #if PY_MAJOR_VERSION < 3
5233 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5234 #else
5235 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5236 #endif
5237 goto invalid_keyword_type;
5238 } else {
5239 for (name = first_kw_arg; *name; name++) {
5240 #if PY_MAJOR_VERSION >= 3
5241 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5242 PyUnicode_Compare(**name, key) == 0) break;
5243 #else
5244 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5245 _PyString_Eq(**name, key)) break;
5246 #endif
5247 }
5248 if (*name) {
5249 values[name-argnames] = value;
5250 } else {
5251 /* unexpected keyword found */
5252 for (name=argnames; name != first_kw_arg; name++) {
5253 if (**name == key) goto arg_passed_twice;
5254 #if PY_MAJOR_VERSION >= 3
5255 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5256 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5257 #else
5258 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5259 _PyString_Eq(**name, key)) goto arg_passed_twice;
5260 #endif
5261 }
5262 if (kwds2) {
5263 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5264 } else {
5265 goto invalid_keyword;
5266 }
5267 }
5268 }
5269 }
5270 }
5271 return 0;
5272 arg_passed_twice:
5273 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5274 goto bad;
5275 invalid_keyword_type:
5276 PyErr_Format(PyExc_TypeError,
5277 "%s() keywords must be strings", function_name);
5278 goto bad;
5279 invalid_keyword:
5280 PyErr_Format(PyExc_TypeError,
5281 #if PY_MAJOR_VERSION < 3
5282 "%s() got an unexpected keyword argument '%s'",
5283 function_name, PyString_AsString(key));
5284 #else
5285 "%s() got an unexpected keyword argument '%U'",
5286 function_name, key);
5287 #endif
5288 bad:
5289 return -1;
5290 }
5291 """)
5293 #------------------------------------------------------------------------------------
5295 unraisable_exception_utility_code = UtilityCode(
5296 proto = """
5297 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5298 """,
5299 impl = """
5300 static void __Pyx_WriteUnraisable(const char *name) {
5301 PyObject *old_exc, *old_val, *old_tb;
5302 PyObject *ctx;
5303 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5304 #if PY_MAJOR_VERSION < 3
5305 ctx = PyString_FromString(name);
5306 #else
5307 ctx = PyUnicode_FromString(name);
5308 #endif
5309 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5310 if (!ctx) {
5311 PyErr_WriteUnraisable(Py_None);
5312 } else {
5313 PyErr_WriteUnraisable(ctx);
5314 Py_DECREF(ctx);
5315 }
5316 }
5317 """)
5319 #------------------------------------------------------------------------------------
5321 traceback_utility_code = UtilityCode(
5322 proto = """
5323 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5324 """,
5325 impl = """
5326 #include "compile.h"
5327 #include "frameobject.h"
5328 #include "traceback.h"
5330 static void __Pyx_AddTraceback(const char *funcname) {
5331 PyObject *py_srcfile = 0;
5332 PyObject *py_funcname = 0;
5333 PyObject *py_globals = 0;
5334 PyObject *empty_string = 0;
5335 PyCodeObject *py_code = 0;
5336 PyFrameObject *py_frame = 0;
5338 #if PY_MAJOR_VERSION < 3
5339 py_srcfile = PyString_FromString(%(FILENAME)s);
5340 #else
5341 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5342 #endif
5343 if (!py_srcfile) goto bad;
5344 if (%(CLINENO)s) {
5345 #if PY_MAJOR_VERSION < 3
5346 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5347 #else
5348 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5349 #endif
5350 }
5351 else {
5352 #if PY_MAJOR_VERSION < 3
5353 py_funcname = PyString_FromString(funcname);
5354 #else
5355 py_funcname = PyUnicode_FromString(funcname);
5356 #endif
5357 }
5358 if (!py_funcname) goto bad;
5359 py_globals = PyModule_GetDict(%(GLOBALS)s);
5360 if (!py_globals) goto bad;
5361 #if PY_MAJOR_VERSION < 3
5362 empty_string = PyString_FromStringAndSize("", 0);
5363 #else
5364 empty_string = PyBytes_FromStringAndSize("", 0);
5365 #endif
5366 if (!empty_string) goto bad;
5367 py_code = PyCode_New(
5368 0, /*int argcount,*/
5369 #if PY_MAJOR_VERSION >= 3
5370 0, /*int kwonlyargcount,*/
5371 #endif
5372 0, /*int nlocals,*/
5373 0, /*int stacksize,*/
5374 0, /*int flags,*/
5375 empty_string, /*PyObject *code,*/
5376 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5377 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5378 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5379 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5380 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5381 py_srcfile, /*PyObject *filename,*/
5382 py_funcname, /*PyObject *name,*/
5383 %(LINENO)s, /*int firstlineno,*/
5384 empty_string /*PyObject *lnotab*/
5385 );
5386 if (!py_code) goto bad;
5387 py_frame = PyFrame_New(
5388 PyThreadState_GET(), /*PyThreadState *tstate,*/
5389 py_code, /*PyCodeObject *code,*/
5390 py_globals, /*PyObject *globals,*/
5391 0 /*PyObject *locals*/
5392 );
5393 if (!py_frame) goto bad;
5394 py_frame->f_lineno = %(LINENO)s;
5395 PyTraceBack_Here(py_frame);
5396 bad:
5397 Py_XDECREF(py_srcfile);
5398 Py_XDECREF(py_funcname);
5399 Py_XDECREF(empty_string);
5400 Py_XDECREF(py_code);
5401 Py_XDECREF(py_frame);
5402 }
5403 """ % {
5404 'FILENAME': Naming.filename_cname,
5405 'LINENO': Naming.lineno_cname,
5406 'CFILENAME': Naming.cfilenm_cname,
5407 'CLINENO': Naming.clineno_cname,
5408 'GLOBALS': Naming.module_cname,
5409 'EMPTY_TUPLE' : Naming.empty_tuple,
5410 })
5412 restore_exception_utility_code = UtilityCode(
5413 proto = """
5414 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5415 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5416 """,
5417 impl = """
5418 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5419 PyObject *tmp_type, *tmp_value, *tmp_tb;
5420 PyThreadState *tstate = PyThreadState_GET();
5422 #if PY_MAJOR_VERSION >= 3
5423 /* Note: this is a temporary work-around to prevent crashes in Python 3.0 */
5424 if ((tstate->exc_type != NULL) & (tstate->exc_type != Py_None)) {
5425 tmp_type = tstate->exc_type;
5426 tmp_value = tstate->exc_value;
5427 tmp_tb = tstate->exc_traceback;
5428 PyErr_NormalizeException(&type, &value, &tb);
5429 PyErr_NormalizeException(&tmp_type, &tmp_value, &tmp_tb);
5430 tstate->exc_type = 0;
5431 tstate->exc_value = 0;
5432 tstate->exc_traceback = 0;
5433 PyException_SetContext(value, tmp_value);
5434 Py_DECREF(tmp_type);
5435 Py_XDECREF(tmp_tb);
5436 }
5437 #endif
5439 tmp_type = tstate->curexc_type;
5440 tmp_value = tstate->curexc_value;
5441 tmp_tb = tstate->curexc_traceback;
5442 tstate->curexc_type = type;
5443 tstate->curexc_value = value;
5444 tstate->curexc_traceback = tb;
5445 Py_XDECREF(tmp_type);
5446 Py_XDECREF(tmp_value);
5447 Py_XDECREF(tmp_tb);
5448 }
5450 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5451 PyThreadState *tstate = PyThreadState_GET();
5452 *type = tstate->curexc_type;
5453 *value = tstate->curexc_value;
5454 *tb = tstate->curexc_traceback;
5456 tstate->curexc_type = 0;
5457 tstate->curexc_value = 0;
5458 tstate->curexc_traceback = 0;
5459 }
5461 """)
5463 #------------------------------------------------------------------------------------
5465 set_vtable_utility_code = UtilityCode(
5466 proto = """
5467 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5468 """,
5469 impl = """
5470 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5471 PyObject *pycobj = 0;
5472 int result;
5474 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5475 if (!pycobj)
5476 goto bad;
5477 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5478 goto bad;
5479 result = 0;
5480 goto done;
5482 bad:
5483 result = -1;
5484 done:
5485 Py_XDECREF(pycobj);
5486 return result;
5487 }
5488 """)
5490 #------------------------------------------------------------------------------------
5492 get_vtable_utility_code = UtilityCode(
5493 proto = """
5494 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5495 """,
5496 impl = r"""
5497 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5498 int result;
5499 PyObject *pycobj;
5501 pycobj = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5502 if (!pycobj)
5503 goto bad;
5504 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5505 if (!*(void **)vtabptr)
5506 goto bad;
5507 result = 0;
5508 goto done;
5510 bad:
5511 result = -1;
5512 done:
5513 Py_XDECREF(pycobj);
5514 return result;
5515 }
5516 """)
5518 #------------------------------------------------------------------------------------
5520 init_string_tab_utility_code = UtilityCode(
5521 proto = """
5522 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5523 """,
5524 impl = """
5525 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5526 while (t->p) {
5527 #if PY_MAJOR_VERSION < 3
5528 if (t->is_unicode && (!t->is_identifier)) {
5529 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5530 } else if (t->intern) {
5531 *t->p = PyString_InternFromString(t->s);
5532 } else {
5533 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5534 }
5535 #else /* Python 3+ has unicode identifiers */
5536 if (t->is_identifier || (t->is_unicode && t->intern)) {
5537 *t->p = PyUnicode_InternFromString(t->s);
5538 } else if (t->is_unicode) {
5539 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5540 } else {
5541 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5542 }
5543 #endif
5544 if (!*t->p)
5545 return -1;
5546 ++t;
5547 }
5548 return 0;
5549 }
5550 """)
5552 #------------------------------------------------------------------------------------
5554 get_exception_utility_code = UtilityCode(
5555 proto = """
5556 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5557 """,
5558 impl = """
5559 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5560 PyObject *tmp_type, *tmp_value, *tmp_tb;
5561 PyThreadState *tstate = PyThreadState_GET();
5562 __Pyx_ErrFetch(type, value, tb);
5563 PyErr_NormalizeException(type, value, tb);
5564 if (PyErr_Occurred())
5565 goto bad;
5566 Py_INCREF(*type);
5567 Py_INCREF(*value);
5568 Py_INCREF(*tb);
5569 tmp_type = tstate->exc_type;
5570 tmp_value = tstate->exc_value;
5571 tmp_tb = tstate->exc_traceback;
5572 tstate->exc_type = *type;
5573 tstate->exc_value = *value;
5574 tstate->exc_traceback = *tb;
5575 /* Make sure tstate is in a consistent state when we XDECREF
5576 these objects (XDECREF may run arbitrary code). */
5577 Py_XDECREF(tmp_type);
5578 Py_XDECREF(tmp_value);
5579 Py_XDECREF(tmp_tb);
5580 return 0;
5581 bad:
5582 Py_XDECREF(*type);
5583 Py_XDECREF(*value);
5584 Py_XDECREF(*tb);
5585 return -1;
5586 }
5588 """)
5590 #------------------------------------------------------------------------------------
5592 reset_exception_utility_code = UtilityCode(
5593 proto = """
5594 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5595 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5596 """,
5597 impl = """
5598 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5599 PyThreadState *tstate = PyThreadState_GET();
5600 *type = tstate->exc_type;
5601 *value = tstate->exc_value;
5602 *tb = tstate->exc_traceback;
5603 Py_XINCREF(*type);
5604 Py_XINCREF(*value);
5605 Py_XINCREF(*tb);
5606 }
5608 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5609 PyObject *tmp_type, *tmp_value, *tmp_tb;
5610 PyThreadState *tstate = PyThreadState_GET();
5611 tmp_type = tstate->exc_type;
5612 tmp_value = tstate->exc_value;
5613 tmp_tb = tstate->exc_traceback;
5614 tstate->exc_type = type;
5615 tstate->exc_value = value;
5616 tstate->exc_traceback = tb;
5617 Py_XDECREF(tmp_type);
5618 Py_XDECREF(tmp_value);
5619 Py_XDECREF(tmp_tb);
5620 }
5621 """)
5623 #------------------------------------------------------------------------------------
