Cython has moved to github.
cython-devel
view Cython/Compiler/Nodes.py @ 1302:1f4f07a63dba
conservative fix for empty switch statements
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Fri Nov 07 06:55:37 2008 +0100 (3 years ago) |
| parents | 393a919e3f46 |
| children | baa0e6f48f15 |
line source
1 #
2 # Pyrex - Parse tree nodes
3 #
5 import string, sys, os, time, copy
7 import Code
8 from Errors import error, warning, InternalError
9 import Naming
10 import PyrexTypes
11 import TypeSlots
12 from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType
13 from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
14 StructOrUnionScope, PyClassScope, CClassScope
15 from Cython.Utils import open_new_file, replace_suffix, UtilityCode
16 from StringEncoding import EncodedString, escape_byte_string, split_docstring
17 import Options
18 import ControlFlow
20 from DebugFlags import debug_disposal_code
22 absolute_path_length = 0
24 def relative_position(pos):
25 """
26 We embed the relative filename in the generated C file, since we
27 don't want to have to regnerate and compile all the source code
28 whenever the Python install directory moves (which could happen,
29 e.g,. when distributing binaries.)
31 INPUT:
32 a position tuple -- (absolute filename, line number column position)
34 OUTPUT:
35 relative filename
36 line number
38 AUTHOR: William Stein
39 """
40 global absolute_path_length
41 if absolute_path_length==0:
42 absolute_path_length = len(os.path.abspath(os.getcwd()))
43 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
45 def embed_position(pos, docstring):
46 if not Options.embed_pos_in_docstring:
47 return docstring
48 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
49 if docstring is None:
50 # unicode string
51 return EncodedString(pos_line)
53 # make sure we can encode the filename in the docstring encoding
54 # otherwise make the docstring a unicode string
55 encoding = docstring.encoding
56 if encoding is not None:
57 try:
58 encoded_bytes = pos_line.encode(encoding)
59 except UnicodeEncodeError:
60 encoding = None
62 if not docstring:
63 # reuse the string encoding of the original docstring
64 doc = EncodedString(pos_line)
65 else:
66 doc = EncodedString(pos_line + u'\n' + docstring)
67 doc.encoding = encoding
68 return doc
70 class Node(object):
71 # pos (string, int, int) Source file position
72 # is_name boolean Is a NameNode
73 # is_literal boolean Is a ConstNode
75 is_name = 0
76 is_literal = 0
77 temps = None
79 # All descandants should set child_attrs to a list of the attributes
80 # containing nodes considered "children" in the tree. Each such attribute
81 # can either contain a single node or a list of nodes. See Visitor.py.
82 child_attrs = None
84 def __init__(self, pos, **kw):
85 self.pos = pos
86 self.__dict__.update(kw)
88 gil_message = "Operation"
90 def gil_check(self, env):
91 if env.nogil:
92 self.gil_error()
94 def gil_error(self):
95 error(self.pos, "%s not allowed without gil" % self.gil_message)
97 def clone_node(self):
98 """Clone the node. This is defined as a shallow copy, except for member lists
99 amongst the child attributes (from get_child_accessors) which are also
100 copied. Lists containing child nodes are thus seen as a way for the node
101 to hold multiple children directly; the list is not treated as a seperate
102 level in the tree."""
103 result = copy.copy(self)
104 for attrname in result.child_attrs:
105 value = getattr(result, attrname)
106 if isinstance(value, list):
107 setattr(result, attrname, [x for x in value])
108 return result
111 #
112 # There are 4 phases of parse tree processing, applied in order to
113 # all the statements in a given scope-block:
114 #
115 # (0) analyse_control_flow
116 # Create the control flow tree into which state can be asserted and
117 # queried.
118 #
119 # (1) analyse_declarations
120 # Make symbol table entries for all declarations at the current
121 # level, both explicit (def, cdef, etc.) and implicit (assignment
122 # to an otherwise undeclared name).
123 #
124 # (2) analyse_expressions
125 # Determine the result types of expressions and fill in the
126 # 'type' attribute of each ExprNode. Insert coercion nodes into the
127 # tree where needed to convert to and from Python objects.
128 # Allocate temporary locals for intermediate results. Fill
129 # in the 'result_code' attribute of each ExprNode with a C code
130 # fragment.
131 #
132 # (3) generate_code
133 # Emit C code for all declarations, statements and expressions.
134 # Recursively applies the 3 processing phases to the bodies of
135 # functions.
136 #
138 def analyse_control_flow(self, env):
139 pass
141 def analyse_declarations(self, env):
142 pass
144 def analyse_expressions(self, env):
145 raise InternalError("analyse_expressions not implemented for %s" % \
146 self.__class__.__name__)
148 def generate_code(self, code):
149 raise InternalError("generate_code not implemented for %s" % \
150 self.__class__.__name__)
152 def annotate(self, code):
153 # mro does the wrong thing
154 if isinstance(self, BlockNode):
155 self.body.annotate(code)
157 def end_pos(self):
158 if not self.child_attrs:
159 return self.pos
160 try:
161 return self._end_pos
162 except AttributeError:
163 pos = self.pos
164 for attr in self.child_attrs:
165 child = getattr(self, attr)
166 # Sometimes lists, sometimes nodes
167 if child is None:
168 pass
169 elif isinstance(child, list):
170 for c in child:
171 pos = max(pos, c.end_pos())
172 else:
173 pos = max(pos, child.end_pos())
174 self._end_pos = pos
175 return pos
177 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
178 if cutoff == 0:
179 return "<...nesting level cutoff...>"
180 if encountered is None:
181 encountered = set()
182 if id(self) in encountered:
183 return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
184 encountered.add(id(self))
186 def dump_child(x, level):
187 if isinstance(x, Node):
188 return x.dump(level, filter_out, cutoff-1, encountered)
189 elif isinstance(x, list):
190 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
191 else:
192 return repr(x)
195 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
196 if len(attrs) == 0:
197 return "<%s (%d)>" % (self.__class__.__name__, id(self))
198 else:
199 indent = " " * level
200 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
201 for key, value in attrs:
202 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
203 res += "%s>" % indent
204 return res
206 class CompilerDirectivesNode(Node):
207 """
208 Sets compiler directives for the children nodes
209 """
210 # directives {string:value} A dictionary holding the right value for
211 # *all* possible directives.
212 # body Node
213 child_attrs = ["body"]
215 def analyse_control_flow(self, env):
216 old = env.directives
217 env.directives = self.directives
218 self.body.analyse_control_flow(env)
219 env.directives = old
221 def analyse_declarations(self, env):
222 old = env.directives
223 env.directives = self.directives
224 self.body.analyse_declarations(env)
225 env.directives = old
227 def analyse_expressions(self, env):
228 old = env.directives
229 env.directives = self.directives
230 self.body.analyse_expressions(env)
231 env.directives = old
233 def generate_function_definitions(self, env, code):
234 env_old = env.directives
235 code_old = code.globalstate.directives
236 code.globalstate.directives = self.directives
237 self.body.generate_function_definitions(env, code)
238 env.directives = env_old
239 code.globalstate.directives = code_old
241 def generate_execution_code(self, code):
242 old = code.globalstate.directives
243 code.globalstate.directives = self.directives
244 self.body.generate_execution_code(code)
245 code.globalstate.directives = old
247 def annotate(self, code):
248 old = code.globalstate.directives
249 code.globalstate.directives = self.directives
250 self.body.annotate(code)
251 code.globalstate.directives = old
253 class BlockNode:
254 # Mixin class for nodes representing a declaration block.
256 def generate_const_definitions(self, env, code):
257 if env.const_entries:
258 for entry in env.const_entries:
259 if not entry.is_interned:
260 code.globalstate.add_const_definition(entry)
262 def generate_interned_string_decls(self, env, code):
263 entries = env.global_scope().new_interned_string_entries
264 if entries:
265 for entry in entries:
266 code.globalstate.add_interned_string_decl(entry)
267 del entries[:]
269 def generate_py_string_decls(self, env, code):
270 if env is None:
271 return # earlier error
272 entries = env.pystring_entries
273 if entries:
274 for entry in entries:
275 if not entry.is_interned:
276 code.globalstate.add_py_string_decl(entry)
278 def generate_interned_num_decls(self, env, code):
279 # Flush accumulated interned nums from the global scope
280 # and generate declarations for them.
281 genv = env.global_scope()
282 entries = genv.interned_nums
283 if entries:
284 for entry in entries:
285 code.globalstate.add_interned_num_decl(entry)
286 del entries[:]
288 def generate_cached_builtins_decls(self, env, code):
289 entries = env.global_scope().undeclared_cached_builtins
290 for entry in entries:
291 code.globalstate.add_cached_builtin_decl(entry)
292 del entries[:]
295 class StatListNode(Node):
296 # stats a list of StatNode
298 child_attrs = ["stats"]
300 def create_analysed(pos, env, *args, **kw):
301 node = StatListNode(pos, *args, **kw)
302 return node # No node-specific analysis necesarry
303 create_analysed = staticmethod(create_analysed)
305 def analyse_control_flow(self, env):
306 for stat in self.stats:
307 stat.analyse_control_flow(env)
309 def analyse_declarations(self, env):
310 #print "StatListNode.analyse_declarations" ###
311 for stat in self.stats:
312 stat.analyse_declarations(env)
314 def analyse_expressions(self, env):
315 #print "StatListNode.analyse_expressions" ###
316 for stat in self.stats:
317 stat.analyse_expressions(env)
319 def generate_function_definitions(self, env, code):
320 #print "StatListNode.generate_function_definitions" ###
321 for stat in self.stats:
322 stat.generate_function_definitions(env, code)
324 def generate_execution_code(self, code):
325 #print "StatListNode.generate_execution_code" ###
326 for stat in self.stats:
327 code.mark_pos(stat.pos)
328 stat.generate_execution_code(code)
330 def annotate(self, code):
331 for stat in self.stats:
332 stat.annotate(code)
335 class StatNode(Node):
336 #
337 # Code generation for statements is split into the following subphases:
338 #
339 # (1) generate_function_definitions
340 # Emit C code for the definitions of any structs,
341 # unions, enums and functions defined in the current
342 # scope-block.
343 #
344 # (2) generate_execution_code
345 # Emit C code for executable statements.
346 #
348 def generate_function_definitions(self, env, code):
349 pass
351 def generate_execution_code(self, code):
352 raise InternalError("generate_execution_code not implemented for %s" % \
353 self.__class__.__name__)
356 class CDefExternNode(StatNode):
357 # include_file string or None
358 # body StatNode
360 child_attrs = ["body"]
362 def analyse_declarations(self, env):
363 if self.include_file:
364 env.add_include_file(self.include_file)
365 old_cinclude_flag = env.in_cinclude
366 env.in_cinclude = 1
367 self.body.analyse_declarations(env)
368 env.in_cinclude = old_cinclude_flag
370 def analyse_expressions(self, env):
371 pass
373 def generate_execution_code(self, code):
374 pass
376 def annotate(self, code):
377 self.body.annotate(code)
380 class CDeclaratorNode(Node):
381 # Part of a C declaration.
382 #
383 # Processing during analyse_declarations phase:
384 #
385 # analyse
386 # Returns (name, type) pair where name is the
387 # CNameDeclaratorNode of the name being declared
388 # and type is the type it is being declared as.
389 #
390 # calling_convention string Calling convention of CFuncDeclaratorNode
391 # for which this is a base
393 child_attrs = []
395 calling_convention = ""
398 class CNameDeclaratorNode(CDeclaratorNode):
399 # name string The Pyrex name being declared
400 # cname string or None C name, if specified
401 # default ExprNode or None the value assigned on declaration
403 child_attrs = ['default']
405 default = None
407 def analyse(self, base_type, env, nonempty = 0):
408 if nonempty and self.name == '':
409 # May have mistaken the name for the type.
410 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
411 error(self.pos, "Missing argument name")
412 elif base_type.is_void:
413 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
414 else:
415 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
416 base_type = py_object_type
417 self.type = base_type
418 return self, base_type
420 class CPtrDeclaratorNode(CDeclaratorNode):
421 # base CDeclaratorNode
423 child_attrs = ["base"]
425 def analyse(self, base_type, env, nonempty = 0):
426 if base_type.is_pyobject:
427 error(self.pos,
428 "Pointer base type cannot be a Python object")
429 ptr_type = PyrexTypes.c_ptr_type(base_type)
430 return self.base.analyse(ptr_type, env, nonempty = nonempty)
432 class CArrayDeclaratorNode(CDeclaratorNode):
433 # base CDeclaratorNode
434 # dimension ExprNode
436 child_attrs = ["base", "dimension"]
438 def analyse(self, base_type, env, nonempty = 0):
439 if self.dimension:
440 self.dimension.analyse_const_expression(env)
441 if not self.dimension.type.is_int:
442 error(self.dimension.pos, "Array dimension not integer")
443 size = self.dimension.result()
444 else:
445 size = None
446 if not base_type.is_complete():
447 error(self.pos,
448 "Array element type '%s' is incomplete" % base_type)
449 if base_type.is_pyobject:
450 error(self.pos,
451 "Array element cannot be a Python object")
452 if base_type.is_cfunction:
453 error(self.pos,
454 "Array element cannot be a function")
455 array_type = PyrexTypes.c_array_type(base_type, size)
456 return self.base.analyse(array_type, env, nonempty = nonempty)
459 class CFuncDeclaratorNode(CDeclaratorNode):
460 # base CDeclaratorNode
461 # args [CArgDeclNode]
462 # has_varargs boolean
463 # exception_value ConstNode
464 # exception_check boolean True if PyErr_Occurred check needed
465 # nogil boolean Can be called without gil
466 # with_gil boolean Acquire gil around function body
468 child_attrs = ["base", "args", "exception_value"]
470 overridable = 0
471 optional_arg_count = 0
473 def analyse(self, return_type, env, nonempty = 0):
474 if nonempty:
475 nonempty -= 1
476 func_type_args = []
477 for arg_node in self.args:
478 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
479 name = name_declarator.name
480 if name_declarator.cname:
481 error(self.pos,
482 "Function argument cannot have C name specification")
483 # Turn *[] argument into **
484 if type.is_array:
485 type = PyrexTypes.c_ptr_type(type.base_type)
486 # Catch attempted C-style func(void) decl
487 if type.is_void:
488 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
489 # if type.is_pyobject and self.nogil:
490 # error(self.pos,
491 # "Function with Python argument cannot be declared nogil")
492 func_type_args.append(
493 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
494 if arg_node.default:
495 self.optional_arg_count += 1
496 elif self.optional_arg_count:
497 error(self.pos, "Non-default argument follows default argument")
499 if self.optional_arg_count:
500 scope = StructOrUnionScope()
501 scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
502 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
503 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
504 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
505 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
506 kind = 'struct',
507 scope = scope,
508 typedef_flag = 0,
509 pos = self.pos,
510 cname = struct_cname)
511 self.op_args_struct.defined_in_pxd = 1
512 self.op_args_struct.used = 1
514 exc_val = None
515 exc_check = 0
516 if return_type.is_pyobject \
517 and (self.exception_value or self.exception_check) \
518 and self.exception_check != '+':
519 error(self.pos,
520 "Exception clause not allowed for function returning Python object")
521 else:
522 if self.exception_value:
523 self.exception_value.analyse_const_expression(env)
524 if self.exception_check == '+':
525 exc_val_type = self.exception_value.type
526 if not exc_val_type.is_error and \
527 not exc_val_type.is_pyobject and \
528 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
529 error(self.exception_value.pos,
530 "Exception value must be a Python exception or cdef function with no arguments.")
531 exc_val = self.exception_value
532 else:
533 exc_val = self.exception_value.result()
534 if not return_type.assignable_from(self.exception_value.type):
535 error(self.exception_value.pos,
536 "Exception value incompatible with function return type")
537 exc_check = self.exception_check
538 if return_type.is_array:
539 error(self.pos,
540 "Function cannot return an array")
541 if return_type.is_cfunction:
542 error(self.pos,
543 "Function cannot return a function")
544 func_type = PyrexTypes.CFuncType(
545 return_type, func_type_args, self.has_varargs,
546 optional_arg_count = self.optional_arg_count,
547 exception_value = exc_val, exception_check = exc_check,
548 calling_convention = self.base.calling_convention,
549 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
550 if self.optional_arg_count:
551 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
552 return self.base.analyse(func_type, env)
555 class CArgDeclNode(Node):
556 # Item in a function declaration argument list.
557 #
558 # base_type CBaseTypeNode
559 # declarator CDeclaratorNode
560 # not_none boolean Tagged with 'not None'
561 # default ExprNode or None
562 # default_entry Symtab.Entry Entry for the variable holding the default value
563 # default_result_code string cname or code fragment for default value
564 # is_self_arg boolean Is the "self" arg of an extension type method
565 # is_kw_only boolean Is a keyword-only argument
567 child_attrs = ["base_type", "declarator", "default"]
569 is_self_arg = 0
570 is_generic = 1
571 type = None
572 name_declarator = None
574 def analyse(self, env, nonempty = 0):
575 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
576 if self.type is None:
577 # The parser may missinterpret names as types...
578 # We fix that here.
579 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
580 if nonempty:
581 self.declarator.name = self.base_type.name
582 self.base_type.name = None
583 self.base_type.is_basic_c_type = False
584 could_be_name = True
585 else:
586 could_be_name = False
587 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
588 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
589 self.declarator.name = self.base_type.arg_name
590 return self.declarator.analyse(base_type, env, nonempty = nonempty)
591 else:
592 return self.name_declarator, self.type
594 def annotate(self, code):
595 if self.default:
596 self.default.annotate(code)
599 class CBaseTypeNode(Node):
600 # Abstract base class for C base type nodes.
601 #
602 # Processing during analyse_declarations phase:
603 #
604 # analyse
605 # Returns the type.
607 pass
609 class CAnalysedBaseTypeNode(Node):
610 # type type
612 child_attrs = []
614 def analyse(self, env, could_be_name = False):
615 return self.type
617 class CSimpleBaseTypeNode(CBaseTypeNode):
618 # name string
619 # module_path [string] Qualifying name components
620 # is_basic_c_type boolean
621 # signed boolean
622 # longness integer
623 # is_self_arg boolean Is self argument of C method
625 child_attrs = []
626 arg_name = None # in case the argument name was interpreted as a type
628 def analyse(self, env, could_be_name = False):
629 # Return type descriptor.
630 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
631 type = None
632 if self.is_basic_c_type:
633 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
634 if not type:
635 error(self.pos, "Unrecognised type modifier combination")
636 elif self.name == "object" and not self.module_path:
637 type = py_object_type
638 elif self.name is None:
639 if self.is_self_arg and env.is_c_class_scope:
640 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
641 type = env.parent_type
642 else:
643 type = py_object_type
644 else:
645 if self.module_path:
646 scope = env.find_imported_module(self.module_path, self.pos)
647 else:
648 scope = env
649 if scope:
650 if scope.is_c_class_scope:
651 scope = scope.global_scope()
652 entry = scope.lookup(self.name)
653 if entry and entry.is_type:
654 type = entry.type
655 elif could_be_name:
656 if self.is_self_arg and env.is_c_class_scope:
657 type = env.parent_type
658 else:
659 type = py_object_type
660 self.arg_name = self.name
661 else:
662 error(self.pos, "'%s' is not a type identifier" % self.name)
663 if type:
664 return type
665 else:
666 return PyrexTypes.error_type
668 class CBufferAccessTypeNode(CBaseTypeNode):
669 # After parsing:
670 # positional_args [ExprNode] List of positional arguments
671 # keyword_args DictNode Keyword arguments
672 # base_type_node CBaseTypeNode
674 # After analysis:
675 # type PyrexType.BufferType ...containing the right options
678 child_attrs = ["base_type_node", "positional_args",
679 "keyword_args", "dtype_node"]
681 dtype_node = None
683 def analyse(self, env, could_be_name = False):
684 base_type = self.base_type_node.analyse(env)
685 if base_type.is_error: return base_type
686 import Buffer
688 options = Buffer.analyse_buffer_options(
689 self.pos,
690 env,
691 self.positional_args,
692 self.keyword_args,
693 base_type.buffer_defaults)
695 self.type = PyrexTypes.BufferType(base_type, **options)
696 return self.type
698 class CComplexBaseTypeNode(CBaseTypeNode):
699 # base_type CBaseTypeNode
700 # declarator CDeclaratorNode
702 child_attrs = ["base_type", "declarator"]
704 def analyse(self, env, could_be_name = False):
705 base = self.base_type.analyse(env, could_be_name)
706 _, type = self.declarator.analyse(base, env)
707 return type
710 class CVarDefNode(StatNode):
711 # C variable definition or forward/extern function declaration.
712 #
713 # visibility 'private' or 'public' or 'extern'
714 # base_type CBaseTypeNode
715 # declarators [CDeclaratorNode]
716 # in_pxd boolean
717 # api boolean
718 # need_properties [entry]
720 child_attrs = ["base_type", "declarators"]
721 need_properties = ()
723 def analyse_declarations(self, env, dest_scope = None):
724 if not dest_scope:
725 dest_scope = env
726 self.dest_scope = dest_scope
727 base_type = self.base_type.analyse(env)
728 if (dest_scope.is_c_class_scope
729 and self.visibility == 'public'
730 and base_type.is_pyobject
731 and (base_type.is_builtin_type or base_type.is_extension_type)):
732 self.need_properties = []
733 need_property = True
734 visibility = 'private'
735 else:
736 need_property = False
737 visibility = self.visibility
739 for declarator in self.declarators:
740 name_declarator, type = declarator.analyse(base_type, env)
741 if not type.is_complete():
742 if not (self.visibility == 'extern' and type.is_array):
743 error(declarator.pos,
744 "Variable type '%s' is incomplete" % type)
745 if self.visibility == 'extern' and type.is_pyobject:
746 error(declarator.pos,
747 "Python object cannot be declared extern")
748 name = name_declarator.name
749 cname = name_declarator.cname
750 if name == '':
751 error(declarator.pos, "Missing name in declaration.")
752 return
753 if type.is_cfunction:
754 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
755 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
756 api = self.api)
757 else:
758 if self.in_pxd and self.visibility != 'extern':
759 error(self.pos,
760 "Only 'extern' C variable declaration allowed in .pxd file")
761 entry = dest_scope.declare_var(name, type, declarator.pos,
762 cname = cname, visibility = visibility, is_cdef = 1)
763 if need_property:
764 self.need_properties.append(entry)
765 entry.needs_property = 1
768 class CStructOrUnionDefNode(StatNode):
769 # name string
770 # cname string or None
771 # kind "struct" or "union"
772 # typedef_flag boolean
773 # visibility "public" or "private"
774 # in_pxd boolean
775 # attributes [CVarDefNode] or None
776 # entry Entry
778 child_attrs = ["attributes"]
780 def analyse_declarations(self, env):
781 scope = None
782 if self.attributes is not None:
783 scope = StructOrUnionScope(self.name)
784 self.entry = env.declare_struct_or_union(
785 self.name, self.kind, scope, self.typedef_flag, self.pos,
786 self.cname, visibility = self.visibility)
787 if self.attributes is not None:
788 if self.in_pxd and not env.in_cinclude:
789 self.entry.defined_in_pxd = 1
790 for attr in self.attributes:
791 attr.analyse_declarations(env, scope)
793 def analyse_expressions(self, env):
794 pass
796 def generate_execution_code(self, code):
797 pass
800 class CEnumDefNode(StatNode):
801 # name string or None
802 # cname string or None
803 # items [CEnumDefItemNode]
804 # typedef_flag boolean
805 # visibility "public" or "private"
806 # in_pxd boolean
807 # entry Entry
809 child_attrs = ["items"]
811 def analyse_declarations(self, env):
812 self.entry = env.declare_enum(self.name, self.pos,
813 cname = self.cname, typedef_flag = self.typedef_flag,
814 visibility = self.visibility)
815 if self.items is not None:
816 if self.in_pxd and not env.in_cinclude:
817 self.entry.defined_in_pxd = 1
818 for item in self.items:
819 item.analyse_declarations(env, self.entry)
821 def analyse_expressions(self, env):
822 if self.visibility == 'public':
823 self.temp = env.allocate_temp_pyobject()
824 env.release_temp(self.temp)
826 def generate_execution_code(self, code):
827 if self.visibility == 'public':
828 for item in self.entry.enum_values:
829 code.putln("%s = PyInt_FromLong(%s); %s" % (
830 self.temp,
831 item.cname,
832 code.error_goto_if_null(self.temp, item.pos)))
833 code.putln('if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
834 Naming.module_cname,
835 item.name,
836 self.temp,
837 code.error_goto(item.pos)))
838 code.putln("%s = 0;" % self.temp)
841 class CEnumDefItemNode(StatNode):
842 # name string
843 # cname string or None
844 # value ExprNode or None
846 child_attrs = ["value"]
848 def analyse_declarations(self, env, enum_entry):
849 if self.value:
850 self.value.analyse_const_expression(env)
851 if not self.value.type.is_int:
852 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
853 self.value.analyse_const_expression(env)
854 value = self.value.result()
855 else:
856 value = self.name
857 entry = env.declare_const(self.name, enum_entry.type,
858 value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
859 enum_entry.enum_values.append(entry)
862 class CTypeDefNode(StatNode):
863 # base_type CBaseTypeNode
864 # declarator CDeclaratorNode
865 # visibility "public" or "private"
866 # in_pxd boolean
868 child_attrs = ["base_type", "declarator"]
870 def analyse_declarations(self, env):
871 base = self.base_type.analyse(env)
872 name_declarator, type = self.declarator.analyse(base, env)
873 name = name_declarator.name
874 cname = name_declarator.cname
875 entry = env.declare_typedef(name, type, self.pos,
876 cname = cname, visibility = self.visibility)
877 if self.in_pxd and not env.in_cinclude:
878 entry.defined_in_pxd = 1
880 def analyse_expressions(self, env):
881 pass
882 def generate_execution_code(self, code):
883 pass
886 class FuncDefNode(StatNode, BlockNode):
887 # Base class for function definition nodes.
888 #
889 # return_type PyrexType
890 # #filename string C name of filename string const
891 # entry Symtab.Entry
892 # needs_closure boolean Whether or not this function has inner functions/classes/yield
894 py_func = None
895 assmt = None
896 needs_closure = False
898 def analyse_default_values(self, env):
899 genv = env.global_scope()
900 for arg in self.args:
901 if arg.default:
902 if arg.is_generic:
903 if not hasattr(arg, 'default_entry'):
904 arg.default.analyse_types(env)
905 arg.default = arg.default.coerce_to(arg.type, genv)
906 if arg.default.is_literal:
907 arg.default_entry = arg.default
908 arg.default_result_code = arg.default.calculate_result_code()
909 if arg.default.type != arg.type and not arg.type.is_int:
910 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
911 else:
912 arg.default.allocate_temps(genv)
913 arg.default_entry = genv.add_default_value(arg.type)
914 arg.default_entry.used = 1
915 arg.default_result_code = arg.default_entry.cname
916 else:
917 error(arg.pos,
918 "This argument cannot have a default value")
919 arg.default = None
921 def need_gil_acquisition(self, lenv):
922 return 0
924 def create_local_scope(self, env):
925 genv = env
926 while env.is_py_class_scope or env.is_c_class_scope:
927 env = env.outer_scope
928 if self.needs_closure:
929 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
930 else:
931 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
932 lenv.return_type = self.return_type
933 type = self.entry.type
934 if type.is_cfunction:
935 lenv.nogil = type.nogil and not type.with_gil
936 self.local_scope = lenv
937 return lenv
939 def generate_function_definitions(self, env, code):
940 import Buffer
942 lenv = self.local_scope
944 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
945 self.entry.scope.is_c_class_scope)
947 # Generate C code for header and body of function
948 code.enter_cfunc_scope()
949 code.return_from_error_cleanup_label = code.new_label()
951 # ----- Top-level constants used by this function
952 code.mark_pos(self.pos)
953 self.generate_interned_num_decls(lenv, code)
954 self.generate_interned_string_decls(lenv, code)
955 self.generate_py_string_decls(lenv, code)
956 self.generate_cached_builtins_decls(lenv, code)
957 #code.putln("")
958 #code.put_var_declarations(lenv.const_entries, static = 1)
959 self.generate_const_definitions(lenv, code)
960 # ----- Function header
961 code.putln("")
962 if self.py_func:
963 self.py_func.generate_function_header(code,
964 with_pymethdef = env.is_py_class_scope,
965 proto_only=True)
966 self.generate_function_header(code,
967 with_pymethdef = env.is_py_class_scope)
968 # ----- Local variable declarations
969 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
970 self.generate_argument_declarations(lenv, code)
971 if self.needs_closure:
972 code.putln("/* TODO: declare and create scope object */")
973 code.put_var_declarations(lenv.var_entries)
974 init = ""
975 if not self.return_type.is_void:
976 code.putln(
977 "%s%s;" %
978 (self.return_type.declaration_code(
979 Naming.retval_cname),
980 init))
981 tempvardecl_code = code.insertion_point()
982 self.generate_keyword_list(code)
983 # ----- Extern library function declarations
984 lenv.generate_library_function_declarations(code)
985 # ----- GIL acquisition
986 acquire_gil = self.need_gil_acquisition(lenv)
987 if acquire_gil:
988 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
989 # ----- Automatic lead-ins for certain special functions
990 if is_getbuffer_slot:
991 self.getbuffer_init(code)
992 # ----- Fetch arguments
993 self.generate_argument_parsing_code(env, code)
994 # If an argument is assigned to in the body, we must
995 # incref it to properly keep track of refcounts.
996 for entry in lenv.arg_entries:
997 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
998 code.put_var_incref(entry)
999 # ----- Initialise local variables
1000 for entry in lenv.var_entries:
1001 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1002 code.put_init_var_to_py_none(entry)
1003 # ----- Initialise local buffer auxiliary variables
1004 for entry in lenv.var_entries + lenv.arg_entries:
1005 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1006 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1007 # ----- Check and convert arguments
1008 self.generate_argument_type_tests(code)
1009 # ----- Acquire buffer arguments
1010 for entry in lenv.arg_entries:
1011 if entry.type.is_buffer:
1012 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1013 # ----- Function body
1014 self.body.generate_execution_code(code)
1015 # ----- Default return value
1016 code.putln("")
1017 if self.return_type.is_pyobject:
1018 #if self.return_type.is_extension_type:
1019 # lhs = "(PyObject *)%s" % Naming.retval_cname
1020 #else:
1021 lhs = Naming.retval_cname
1022 code.put_init_to_py_none(lhs, self.return_type)
1023 else:
1024 val = self.return_type.default_value
1025 if val:
1026 code.putln("%s = %s;" % (Naming.retval_cname, val))
1027 # ----- Error cleanup
1028 if code.error_label in code.labels_used:
1029 code.put_goto(code.return_label)
1030 code.put_label(code.error_label)
1031 code.put_var_xdecrefs(lenv.temp_entries)
1033 # Clean up buffers -- this calls a Python function
1034 # so need to save and restore error state
1035 buffers_present = len(lenv.buffer_entries) > 0
1036 if buffers_present:
1037 code.globalstate.use_utility_code(restore_exception_utility_code)
1038 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1039 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1040 for entry in lenv.buffer_entries:
1041 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1042 #code.putln("%s = 0;" % entry.cname)
1043 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1045 err_val = self.error_value()
1046 exc_check = self.caller_will_check_exceptions()
1047 if err_val is not None or exc_check:
1048 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1049 else:
1050 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1051 % self.entry.qualified_name, 0)
1052 code.putln(
1053 '__Pyx_WriteUnraisable("%s");' %
1054 self.entry.qualified_name)
1055 env.use_utility_code(unraisable_exception_utility_code)
1056 env.use_utility_code(restore_exception_utility_code)
1057 default_retval = self.return_type.default_value
1058 if err_val is None and default_retval:
1059 err_val = default_retval
1060 if err_val is not None:
1061 code.putln(
1062 "%s = %s;" % (
1063 Naming.retval_cname,
1064 err_val))
1066 if is_getbuffer_slot:
1067 self.getbuffer_error_cleanup(code)
1069 # If we are using the non-error cleanup section we should
1070 # jump past it if we have an error. The if-test below determine
1071 # whether this section is used.
1072 if buffers_present or is_getbuffer_slot:
1073 code.put_goto(code.return_from_error_cleanup_label)
1076 # ----- Non-error return cleanup
1077 # If you add anything here, remember to add a condition to the
1078 # if-test above in the error block (so that it can jump past this
1079 # block).
1080 code.put_label(code.return_label)
1081 for entry in lenv.buffer_entries:
1082 if entry.used:
1083 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1084 if is_getbuffer_slot:
1085 self.getbuffer_normal_cleanup(code)
1086 # ----- Return cleanup for both error and no-error return
1087 code.put_label(code.return_from_error_cleanup_label)
1088 if not Options.init_local_none:
1089 for entry in lenv.var_entries:
1090 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1091 entry.xdecref_cleanup = 1
1092 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1093 # Decref any increfed args
1094 for entry in lenv.arg_entries:
1095 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1096 code.put_var_decref(entry)
1097 if acquire_gil:
1098 code.putln("PyGILState_Release(_save);")
1099 # code.putln("/* TODO: decref scope object */")
1100 # ----- Return
1101 if not self.return_type.is_void:
1102 code.putln("return %s;" % Naming.retval_cname)
1103 code.putln("}")
1104 # ----- Go back and insert temp variable declarations
1105 tempvardecl_code.put_var_declarations(lenv.temp_entries)
1106 tempvardecl_code.put_temp_declarations(code.funcstate)
1107 # ----- Python version
1108 code.exit_cfunc_scope()
1109 if self.py_func:
1110 self.py_func.generate_function_definitions(env, code)
1111 self.generate_wrapper_functions(code)
1113 def declare_argument(self, env, arg):
1114 if arg.type.is_void:
1115 error(arg.pos, "Invalid use of 'void'")
1116 elif not arg.type.is_complete() and not arg.type.is_array:
1117 error(arg.pos,
1118 "Argument type '%s' is incomplete" % arg.type)
1119 return env.declare_arg(arg.name, arg.type, arg.pos)
1121 def generate_wrapper_functions(self, code):
1122 pass
1124 def generate_execution_code(self, code):
1125 # Evaluate and store argument default values
1126 for arg in self.args:
1127 default = arg.default
1128 if default:
1129 if not default.is_literal:
1130 default.generate_evaluation_code(code)
1131 default.make_owned_reference(code)
1132 code.putln(
1133 "%s = %s;" % (
1134 arg.default_entry.cname,
1135 default.result_as(arg.default_entry.type)))
1136 if default.is_temp and default.type.is_pyobject:
1137 code.putln(
1138 "%s = 0;" %
1139 default.result())
1140 # For Python class methods, create and store function object
1141 if self.assmt:
1142 self.assmt.generate_execution_code(code)
1144 #
1145 # Special code for the __getbuffer__ function
1146 #
1147 def getbuffer_init(self, code):
1148 info = self.local_scope.arg_entries[1].cname
1149 # Python 3.0 betas have a bug in memoryview which makes it call
1150 # getbuffer with a NULL parameter. For now we work around this;
1151 # the following line should be removed when this bug is fixed.
1152 code.putln("if (%s == NULL) return 0;" % info)
1153 code.putln("%s->obj = Py_None; Py_INCREF(Py_None);" % info)
1155 def getbuffer_error_cleanup(self, code):
1156 info = self.local_scope.arg_entries[1].cname
1157 code.putln("Py_DECREF(%s->obj); %s->obj = NULL;" %
1158 (info, info))
1160 def getbuffer_normal_cleanup(self, code):
1161 info = self.local_scope.arg_entries[1].cname
1162 code.putln("if (%s->obj == Py_None) { Py_DECREF(Py_None); %s->obj = NULL; }" %
1163 (info, info))
1165 class CFuncDefNode(FuncDefNode):
1166 # C function definition.
1167 #
1168 # modifiers ['inline']
1169 # visibility 'private' or 'public' or 'extern'
1170 # base_type CBaseTypeNode
1171 # declarator CDeclaratorNode
1172 # body StatListNode
1173 # api boolean
1174 #
1175 # with_gil boolean Acquire GIL around body
1176 # type CFuncType
1177 # py_func wrapper for calling from Python
1178 # overridable whether or not this is a cpdef function
1180 child_attrs = ["base_type", "declarator", "body", "py_func"]
1182 def unqualified_name(self):
1183 return self.entry.name
1185 def analyse_declarations(self, env):
1186 if 'locals' in env.directives:
1187 directive_locals = env.directives['locals']
1188 else:
1189 directive_locals = {}
1190 self.directive_locals = directive_locals
1191 base_type = self.base_type.analyse(env)
1192 # The 2 here is because we need both function and argument names.
1193 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1194 if not type.is_cfunction:
1195 error(self.pos,
1196 "Suite attached to non-function declaration")
1197 # Remember the actual type according to the function header
1198 # written here, because the type in the symbol table entry
1199 # may be different if we're overriding a C method inherited
1200 # from the base type of an extension type.
1201 self.type = type
1202 type.is_overridable = self.overridable
1203 declarator = self.declarator
1204 while not hasattr(declarator, 'args'):
1205 declarator = declarator.base
1206 self.args = declarator.args
1207 for formal_arg, type_arg in zip(self.args, type.args):
1208 formal_arg.type = type_arg.type
1209 formal_arg.cname = type_arg.cname
1210 name = name_declarator.name
1211 cname = name_declarator.cname
1212 self.entry = env.declare_cfunction(
1213 name, type, self.pos,
1214 cname = cname, visibility = self.visibility,
1215 defining = self.body is not None,
1216 api = self.api)
1217 self.return_type = type.return_type
1219 if self.overridable:
1220 import ExprNodes
1221 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1222 self.py_func = DefNode(pos = self.pos,
1223 name = self.entry.name,
1224 args = self.args,
1225 star_arg = None,
1226 starstar_arg = None,
1227 doc = self.doc,
1228 body = py_func_body,
1229 is_wrapper = 1)
1230 self.py_func.is_module_scope = env.is_module_scope
1231 self.py_func.analyse_declarations(env)
1232 self.entry.as_variable = self.py_func.entry
1233 # Reset scope entry the above cfunction
1234 env.entries[name] = self.entry
1235 self.py_func.interned_attr_cname = env.intern_identifier(
1236 self.py_func.entry.name)
1237 if not env.is_module_scope or Options.lookup_module_cpdef:
1238 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1239 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1241 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1242 import ExprNodes
1243 args = self.type.args
1244 if omit_optional_args:
1245 args = args[:len(args) - self.type.optional_arg_count]
1246 arg_names = [arg.name for arg in args]
1247 if is_module_scope:
1248 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1249 else:
1250 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1251 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1252 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1253 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)
1254 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1256 def declare_arguments(self, env):
1257 for arg in self.type.args:
1258 if not arg.name:
1259 error(arg.pos, "Missing argument name")
1260 self.declare_argument(env, arg)
1262 def need_gil_acquisition(self, lenv):
1263 type = self.type
1264 with_gil = self.type.with_gil
1265 if type.nogil and not with_gil:
1266 if type.return_type.is_pyobject:
1267 error(self.pos,
1268 "Function with Python return type cannot be declared nogil")
1269 for entry in lenv.var_entries + lenv.temp_entries:
1270 if entry.type.is_pyobject:
1271 error(self.pos, "Function declared nogil has Python locals or temporaries")
1272 return with_gil
1274 def analyse_expressions(self, env):
1275 self.analyse_default_values(env)
1276 if self.overridable:
1277 self.py_func.analyse_expressions(env)
1279 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1280 arg_decls = []
1281 type = self.type
1282 visibility = self.entry.visibility
1283 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1284 arg_decls.append(arg.declaration_code())
1285 if with_dispatch and self.overridable:
1286 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1287 if type.optional_arg_count and with_opt_args:
1288 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1289 if type.has_varargs:
1290 arg_decls.append("...")
1291 if not arg_decls:
1292 arg_decls = ["void"]
1293 if cname is None:
1294 cname = self.entry.func_cname
1295 entity = type.function_header_code(cname, string.join(arg_decls, ", "))
1296 if visibility == 'public':
1297 dll_linkage = "DL_EXPORT"
1298 else:
1299 dll_linkage = None
1300 header = self.return_type.declaration_code(entity,
1301 dll_linkage = dll_linkage)
1302 if visibility == 'extern':
1303 storage_class = "%s " % Naming.extern_c_macro
1304 elif visibility == 'public':
1305 storage_class = ""
1306 else:
1307 storage_class = "static "
1308 code.putln("%s%s %s {" % (
1309 storage_class,
1310 ' '.join(self.modifiers).upper(), # macro forms
1311 header))
1313 def generate_argument_declarations(self, env, code):
1314 for arg in self.args:
1315 if arg.default:
1316 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1318 def generate_keyword_list(self, code):
1319 pass
1321 def generate_argument_parsing_code(self, env, code):
1322 i = 0
1323 if self.type.optional_arg_count:
1324 code.putln('if (%s) {' % Naming.optional_args_cname)
1325 for arg in self.args:
1326 if arg.default:
1327 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1328 declarator = arg.declarator
1329 while not hasattr(declarator, 'name'):
1330 declarator = declarator.base
1331 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1332 i += 1
1333 for _ in range(self.type.optional_arg_count):
1334 code.putln('}')
1335 code.putln('}')
1337 def generate_argument_conversion_code(self, code):
1338 pass
1340 def generate_argument_type_tests(self, code):
1341 # Generate type tests for args whose type in a parent
1342 # class is a supertype of the declared type.
1343 for arg in self.type.args:
1344 if arg.needs_type_test:
1345 self.generate_arg_type_test(arg, code)
1347 def generate_arg_type_test(self, arg, code):
1348 # Generate type test for one argument.
1349 if arg.type.typeobj_is_available():
1350 typeptr_cname = arg.type.typeptr_cname
1351 arg_code = "((PyObject *)%s)" % arg.cname
1352 code.putln(
1353 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1354 arg_code,
1355 typeptr_cname,
1356 not arg.not_none,
1357 arg.name,
1358 type.is_builtin_type,
1359 code.error_goto(arg.pos)))
1360 else:
1361 error(arg.pos, "Cannot test type of extern C class "
1362 "without type object name specification")
1364 def error_value(self):
1365 if self.return_type.is_pyobject:
1366 return "0"
1367 else:
1368 #return None
1369 return self.entry.type.exception_value
1371 def caller_will_check_exceptions(self):
1372 return self.entry.type.exception_check
1374 def generate_wrapper_functions(self, code):
1375 # If the C signature of a function has changed, we need to generate
1376 # wrappers to put in the slots here.
1377 k = 0
1378 entry = self.entry
1379 func_type = entry.type
1380 while entry.prev_entry is not None:
1381 k += 1
1382 entry = entry.prev_entry
1383 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1384 code.putln()
1385 self.generate_function_header(code,
1386 0,
1387 with_dispatch = entry.type.is_overridable,
1388 with_opt_args = entry.type.optional_arg_count,
1389 cname = entry.func_cname)
1390 if not self.return_type.is_void:
1391 code.put('return ')
1392 args = self.type.args
1393 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1394 if entry.type.is_overridable:
1395 arglist.append(Naming.skip_dispatch_cname)
1396 elif func_type.is_overridable:
1397 arglist.append('0')
1398 if entry.type.optional_arg_count:
1399 arglist.append(Naming.optional_args_cname)
1400 elif func_type.optional_arg_count:
1401 arglist.append('NULL')
1402 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1403 code.putln('}')
1406 class PyArgDeclNode(Node):
1407 # Argument which must be a Python object (used
1408 # for * and ** arguments).
1409 #
1410 # name string
1411 # entry Symtab.Entry
1412 child_attrs = []
1415 class DecoratorNode(Node):
1416 # A decorator
1417 #
1418 # decorator NameNode or CallNode
1419 child_attrs = ['decorator']
1422 class DefNode(FuncDefNode):
1423 # A Python function definition.
1424 #
1425 # name string the Python name of the function
1426 # decorators [DecoratorNode] list of decorators
1427 # args [CArgDeclNode] formal arguments
1428 # star_arg PyArgDeclNode or None * argument
1429 # starstar_arg PyArgDeclNode or None ** argument
1430 # doc EncodedString or None
1431 # body StatListNode
1432 #
1433 # The following subnode is constructed internally
1434 # when the def statement is inside a Python class definition.
1435 #
1436 # assmt AssignmentNode Function construction/assignment
1438 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1440 assmt = None
1441 num_kwonly_args = 0
1442 num_required_kw_args = 0
1443 reqd_kw_flags_cname = "0"
1444 is_wrapper = 0
1445 decorators = None
1446 entry = None
1449 def __init__(self, pos, **kwds):
1450 FuncDefNode.__init__(self, pos, **kwds)
1451 k = rk = r = 0
1452 for arg in self.args:
1453 if arg.kw_only:
1454 k += 1
1455 if not arg.default:
1456 rk += 1
1457 if not arg.default:
1458 r += 1
1459 self.num_kwonly_args = k
1460 self.num_required_kw_args = rk
1461 self.num_required_args = r
1463 def as_cfunction(self, cfunc):
1464 if self.star_arg:
1465 error(self.star_arg.pos, "cdef function cannot have star argument")
1466 if self.starstar_arg:
1467 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1468 if len(self.args) != len(cfunc.type.args) or cfunc.type.has_varargs:
1469 error(self.pos, "wrong number of arguments")
1470 error(declarator.pos, "previous declaration here")
1471 for formal_arg, type_arg in zip(self.args, cfunc.type.args):
1472 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1473 if type is PyrexTypes.py_object_type or formal_arg.is_self:
1474 formal_arg.type = type_arg.type
1475 formal_arg.name_declarator = name_declarator
1476 import ExprNodes
1477 if cfunc.type.exception_value is None:
1478 exception_value = None
1479 else:
1480 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc.type.exception_value, type=cfunc.type.return_type)
1481 declarator = CFuncDeclaratorNode(self.pos,
1482 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1483 args = self.args,
1484 has_varargs = False,
1485 exception_check = cfunc.type.exception_check,
1486 exception_value = exception_value,
1487 with_gil = cfunc.type.with_gil,
1488 nogil = cfunc.type.nogil)
1489 return CFuncDefNode(self.pos,
1490 modifiers = [],
1491 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc.type.return_type),
1492 declarator = declarator,
1493 body = self.body,
1494 doc = self.doc,
1495 overridable = cfunc.type.is_overridable,
1496 type = cfunc.type,
1497 with_gil = cfunc.type.with_gil,
1498 nogil = cfunc.type.nogil,
1499 visibility = 'private',
1500 api = False)
1502 def analyse_declarations(self, env):
1503 if 'locals' in env.directives:
1504 directive_locals = env.directives['locals']
1505 else:
1506 directive_locals = {}
1507 self.directive_locals = directive_locals
1508 for arg in self.args:
1509 base_type = arg.base_type.analyse(env)
1510 name_declarator, type = \
1511 arg.declarator.analyse(base_type, env)
1512 arg.name = name_declarator.name
1513 if arg.name in directive_locals:
1514 type_node = directive_locals[arg.name]
1515 other_type = type_node.analyse_as_type(env)
1516 if other_type is None:
1517 error(type_node.pos, "Not a type")
1518 elif (type is not PyrexTypes.py_object_type
1519 and not type.same_as(other_type)):
1520 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1521 error(type_node.pos, "Previous declaration here")
1522 else:
1523 type = other_type
1524 if name_declarator.cname:
1525 error(self.pos,
1526 "Python function argument cannot have C name specification")
1527 arg.type = type.as_argument_type()
1528 arg.hdr_type = None
1529 arg.needs_conversion = 0
1530 arg.needs_type_test = 0
1531 arg.is_generic = 1
1532 if arg.not_none and not arg.type.is_extension_type:
1533 error(self.pos,
1534 "Only extension type arguments can have 'not None'")
1535 self.declare_pyfunction(env)
1536 self.analyse_signature(env)
1537 self.return_type = self.entry.signature.return_type()
1539 def analyse_signature(self, env):
1540 any_type_tests_needed = 0
1541 # Use the simpler calling signature for zero- and one-argument functions.
1542 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1543 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1544 if len(self.args) == 0:
1545 self.entry.signature = TypeSlots.pyfunction_noargs
1546 elif len(self.args) == 1:
1547 if self.args[0].default is None and not self.args[0].kw_only:
1548 self.entry.signature = TypeSlots.pyfunction_onearg
1549 elif self.entry.signature is TypeSlots.pymethod_signature:
1550 if len(self.args) == 1:
1551 self.entry.signature = TypeSlots.unaryfunc
1552 elif len(self.args) == 2:
1553 if self.args[1].default is None and not self.args[1].kw_only:
1554 self.entry.signature = TypeSlots.ibinaryfunc
1555 elif self.entry.is_special:
1556 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1557 sig = self.entry.signature
1558 nfixed = sig.num_fixed_args()
1559 for i in range(nfixed):
1560 if i < len(self.args):
1561 arg = self.args[i]
1562 arg.is_generic = 0
1563 if sig.is_self_arg(i):
1564 arg.is_self_arg = 1
1565 arg.hdr_type = arg.type = env.parent_type
1566 arg.needs_conversion = 0
1567 else:
1568 arg.hdr_type = sig.fixed_arg_type(i)
1569 if not arg.type.same_as(arg.hdr_type):
1570 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1571 arg.needs_type_test = 1
1572 any_type_tests_needed = 1
1573 else:
1574 arg.needs_conversion = 1
1575 if arg.needs_conversion:
1576 arg.hdr_cname = Naming.arg_prefix + arg.name
1577 else:
1578 arg.hdr_cname = Naming.var_prefix + arg.name
1579 else:
1580 self.bad_signature()
1581 return
1582 if nfixed < len(self.args):
1583 if not sig.has_generic_args:
1584 self.bad_signature()
1585 for arg in self.args:
1586 if arg.is_generic and \
1587 (arg.type.is_extension_type or arg.type.is_builtin_type):
1588 arg.needs_type_test = 1
1589 any_type_tests_needed = 1
1590 elif arg.type is PyrexTypes.c_py_ssize_t_type:
1591 # Want to use __index__ rather than __int__ method
1592 # that PyArg_ParseTupleAndKeywords calls
1593 arg.needs_conversion = 1
1594 arg.hdr_type = PyrexTypes.py_object_type
1595 arg.hdr_cname = Naming.arg_prefix + arg.name
1596 if any_type_tests_needed:
1597 env.use_utility_code(arg_type_test_utility_code)
1599 def bad_signature(self):
1600 sig = self.entry.signature
1601 expected_str = "%d" % sig.num_fixed_args()
1602 if sig.has_generic_args:
1603 expected_str = expected_str + " or more"
1604 name = self.name
1605 if name.startswith("__") and name.endswith("__"):
1606 desc = "Special method"
1607 else:
1608 desc = "Method"
1609 error(self.pos,
1610 "%s %s has wrong number of arguments "
1611 "(%d declared, %s expected)" % (
1612 desc, self.name, len(self.args), expected_str))
1614 def signature_has_nongeneric_args(self):
1615 argcount = len(self.args)
1616 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1617 return 0
1618 return 1
1620 def signature_has_generic_args(self):
1621 return self.entry.signature.has_generic_args
1623 def declare_pyfunction(self, env):
1624 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1625 name = self.name
1626 entry = env.lookup_here(self.name)
1627 if entry and entry.type.is_cfunction and not self.is_wrapper:
1628 warning(self.pos, "Overriding cdef method with def method.", 5)
1629 entry = env.declare_pyfunction(self.name, self.pos)
1630 self.entry = entry
1631 prefix = env.scope_prefix
1632 entry.func_cname = \
1633 Naming.pyfunc_prefix + prefix + name
1634 entry.pymethdef_cname = \
1635 Naming.pymethdef_prefix + prefix + name
1636 if Options.docstrings:
1637 entry.doc = embed_position(self.pos, self.doc)
1638 entry.doc_cname = \
1639 Naming.funcdoc_prefix + prefix + name
1640 else:
1641 entry.doc = None
1643 def declare_arguments(self, env):
1644 for arg in self.args:
1645 if not arg.name:
1646 error(arg.pos, "Missing argument name")
1647 if arg.needs_conversion:
1648 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1649 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1650 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1651 if arg.type.is_pyobject:
1652 arg.entry.init = "0"
1653 arg.entry.init_to_none = 0
1654 else:
1655 arg.entry = self.declare_argument(env, arg)
1656 arg.entry.used = 1
1657 arg.entry.is_self_arg = arg.is_self_arg
1658 if not arg.is_self_arg:
1659 arg.name_entry = env.get_string_const(
1660 arg.name, identifier = True)
1661 env.add_py_string(arg.name_entry, identifier = True)
1662 if arg.hdr_type:
1663 if arg.is_self_arg or \
1664 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1665 arg.entry.is_declared_generic = 1
1666 self.declare_python_arg(env, self.star_arg)
1667 self.declare_python_arg(env, self.starstar_arg)
1669 def declare_python_arg(self, env, arg):
1670 if arg:
1671 entry = env.declare_var(arg.name,
1672 PyrexTypes.py_object_type, arg.pos)
1673 entry.used = 1
1674 entry.init = "0"
1675 entry.init_to_none = 0
1676 entry.xdecref_cleanup = 1
1677 arg.entry = entry
1678 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1680 def analyse_expressions(self, env):
1681 self.analyse_default_values(env)
1682 if env.is_py_class_scope:
1683 self.synthesize_assignment_node(env)
1685 def synthesize_assignment_node(self, env):
1686 import ExprNodes
1687 self.assmt = SingleAssignmentNode(self.pos,
1688 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1689 rhs = ExprNodes.UnboundMethodNode(self.pos,
1690 class_cname = env.class_obj_cname,
1691 function = ExprNodes.PyCFunctionNode(self.pos,
1692 pymethdef_cname = self.entry.pymethdef_cname)))
1693 self.assmt.analyse_declarations(env)
1694 self.assmt.analyse_expressions(env)
1696 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1697 arg_code_list = []
1698 sig = self.entry.signature
1699 if sig.has_dummy_arg:
1700 arg_code_list.append(
1701 "PyObject *%s" % Naming.self_cname)
1702 for arg in self.args:
1703 if not arg.is_generic:
1704 if arg.is_self_arg:
1705 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1706 else:
1707 arg_code_list.append(
1708 arg.hdr_type.declaration_code(arg.hdr_cname))
1709 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1710 arg_code_list.append("PyObject *unused")
1711 if sig.has_generic_args:
1712 arg_code_list.append(
1713 "PyObject *%s, PyObject *%s"
1714 % (Naming.args_cname, Naming.kwds_cname))
1715 arg_code = ", ".join(arg_code_list)
1716 dc = self.return_type.declaration_code(self.entry.func_cname)
1717 header = "static %s(%s)" % (dc, arg_code)
1718 code.putln("%s; /*proto*/" % header)
1719 if proto_only:
1720 return
1721 if self.entry.doc and Options.docstrings:
1722 docstr = self.entry.doc
1723 if not isinstance(docstr, str):
1724 docstr = docstr.utf8encode()
1725 code.putln(
1726 'static char %s[] = "%s";' % (
1727 self.entry.doc_cname,
1728 split_docstring(escape_byte_string(docstr))))
1729 if with_pymethdef:
1730 code.put(
1731 "static PyMethodDef %s = " %
1732 self.entry.pymethdef_cname)
1733 code.put_pymethoddef(self.entry, ";")
1734 code.putln("%s {" % header)
1736 def generate_argument_declarations(self, env, code):
1737 for arg in self.args:
1738 if arg.is_generic: # or arg.needs_conversion:
1739 if arg.needs_conversion:
1740 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1741 else:
1742 code.put_var_declaration(arg.entry)
1744 def generate_keyword_list(self, code):
1745 if self.signature_has_generic_args() and \
1746 self.signature_has_nongeneric_args():
1747 code.put(
1748 "static PyObject **%s[] = {" %
1749 Naming.pykwdlist_cname)
1750 for arg in self.args:
1751 if arg.is_generic:
1752 code.put('&%s,' % arg.name_entry.pystring_cname)
1753 code.putln("0};")
1755 def generate_argument_parsing_code(self, env, code):
1756 # Generate PyArg_ParseTuple call for generic
1757 # arguments, if any.
1758 if self.entry.signature.has_dummy_arg:
1759 # get rid of unused argument warning
1760 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1762 old_error_label = code.new_error_label()
1763 our_error_label = code.error_label
1764 end_label = code.new_label("argument_unpacking_done")
1766 has_kwonly_args = self.num_kwonly_args > 0
1767 has_star_or_kw_args = self.star_arg is not None \
1768 or self.starstar_arg is not None or has_kwonly_args
1770 if not self.signature_has_generic_args():
1771 if has_star_or_kw_args:
1772 error(self.pos, "This method cannot have * or keyword arguments")
1773 self.generate_argument_conversion_code(code)
1775 elif not self.signature_has_nongeneric_args():
1776 # func(*args) or func(**kw) or func(*args, **kw)
1777 self.generate_stararg_copy_code(code)
1779 else:
1780 positional_args = []
1781 kw_only_args = []
1782 default_seen = 0
1783 for arg in self.args:
1784 arg_entry = arg.entry
1785 if arg.is_generic:
1786 if arg.default:
1787 code.putln(
1788 "%s = %s;" % (
1789 arg_entry.cname,
1790 arg.default_result_code))
1791 default_seen = 1
1792 if not arg.is_self_arg:
1793 if arg.kw_only:
1794 kw_only_args.append(arg)
1795 else:
1796 positional_args.append(arg)
1797 elif arg.kw_only:
1798 kw_only_args.append(arg)
1799 default_seen = 1
1800 elif default_seen:
1801 error(arg.pos, "Non-default argument following default argument")
1802 elif not arg.is_self_arg:
1803 positional_args.append(arg)
1804 if arg.needs_conversion:
1805 format = arg.hdr_type.parsetuple_format
1806 else:
1807 format = arg_entry.type.parsetuple_format
1808 if not format:
1809 error(arg.pos,
1810 "Cannot convert Python object argument to type '%s' (when parsing input arguments)"
1811 % arg.type)
1813 self.generate_tuple_and_keyword_parsing_code(
1814 positional_args, kw_only_args, end_label, code)
1816 code.error_label = old_error_label
1817 if code.label_used(our_error_label):
1818 if not code.label_used(end_label):
1819 code.put_goto(end_label)
1820 code.put_label(our_error_label)
1821 if has_star_or_kw_args:
1822 self.generate_arg_decref(self.star_arg, code)
1823 if self.starstar_arg:
1824 if self.starstar_arg.entry.xdecref_cleanup:
1825 code.put_var_xdecref(self.starstar_arg.entry)
1826 else:
1827 code.put_var_decref(self.starstar_arg.entry)
1828 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1829 code.putln("return %s;" % self.error_value())
1830 if code.label_used(end_label):
1831 code.put_label(end_label)
1833 def generate_arg_assignment(self, arg, item, code):
1834 if arg.type.is_pyobject:
1835 if arg.is_generic:
1836 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1837 code.putln("%s = %s;" % (arg.entry.cname, item))
1838 else:
1839 func = arg.type.from_py_function
1840 if func:
1841 code.putln("%s = %s(%s); %s" % (
1842 arg.entry.cname,
1843 func,
1844 item,
1845 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1846 else:
1847 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1849 def generate_arg_xdecref(self, arg, code):
1850 if arg:
1851 code.put_var_xdecref(arg.entry)
1853 def generate_arg_decref(self, arg, code):
1854 if arg:
1855 code.put_var_decref(arg.entry)
1857 def generate_stararg_copy_code(self, code):
1858 if not self.star_arg:
1859 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1860 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1861 Naming.args_cname)
1862 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
1863 self.name.utf8encode(), Naming.args_cname, self.error_value()))
1864 code.putln("}")
1866 code.globalstate.use_utility_code(keyword_string_check_utility_code)
1868 if self.starstar_arg:
1869 if self.star_arg:
1870 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
1871 else:
1872 kwarg_check = "%s" % Naming.kwds_cname
1873 else:
1874 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
1875 Naming.kwds_cname, Naming.kwds_cname)
1876 code.putln(
1877 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
1878 kwarg_check, Naming.kwds_cname, self.name,
1879 bool(self.starstar_arg), self.error_value()))
1881 if self.starstar_arg:
1882 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
1883 self.starstar_arg.entry.cname,
1884 Naming.kwds_cname,
1885 Naming.kwds_cname))
1886 code.putln("if (unlikely(!%s)) return %s;" % (
1887 self.starstar_arg.entry.cname, self.error_value()))
1888 self.starstar_arg.entry.xdecref_cleanup = 0
1890 if self.star_arg:
1891 code.put_incref(Naming.args_cname, py_object_type)
1892 code.putln("%s = %s;" % (
1893 self.star_arg.entry.cname,
1894 Naming.args_cname))
1895 self.star_arg.entry.xdecref_cleanup = 0
1897 def generate_tuple_and_keyword_parsing_code(self, positional_args,
1898 kw_only_args, success_label, code):
1899 argtuple_error_label = code.new_label("argtuple_error")
1901 min_positional_args = self.num_required_args - self.num_required_kw_args
1902 if len(self.args) > 0 and self.args[0].is_self_arg:
1903 min_positional_args -= 1
1904 max_positional_args = len(positional_args)
1905 has_fixed_positional_count = not self.star_arg and \
1906 min_positional_args == max_positional_args
1908 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
1909 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1910 if self.num_required_kw_args:
1911 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
1913 if self.starstar_arg or self.star_arg:
1914 self.generate_stararg_init_code(max_positional_args, code)
1916 # --- optimised code when we receive keyword arguments
1917 if self.num_required_kw_args:
1918 likely_hint = "likely"
1919 else:
1920 likely_hint = "unlikely"
1921 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
1922 self.generate_keyword_unpacking_code(
1923 min_positional_args, max_positional_args,
1924 has_fixed_positional_count,
1925 positional_args, kw_only_args, argtuple_error_label, code)
1927 # --- optimised code when we do not receive any keyword arguments
1928 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
1929 # Python raises arg tuple related errors first, so we must
1930 # check the length here
1931 if min_positional_args == max_positional_args and not self.star_arg:
1932 compare = '!='
1933 else:
1934 compare = '<'
1935 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
1936 Naming.args_cname, compare, min_positional_args))
1937 code.put_goto(argtuple_error_label)
1939 if self.num_required_kw_args:
1940 # pure error case: keywords required but not passed
1941 if max_positional_args > min_positional_args and not self.star_arg:
1942 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
1943 Naming.args_cname, max_positional_args))
1944 code.put_goto(argtuple_error_label)
1945 code.putln('} else {')
1946 for i, arg in enumerate(kw_only_args):
1947 if not arg.default:
1948 # required keyword-only argument missing
1949 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
1950 self.name.utf8encode(),
1951 arg.name_entry.pystring_cname))
1952 code.putln(code.error_goto(self.pos))
1953 break
1955 elif min_positional_args == max_positional_args:
1956 # parse the exact number of positional arguments from the
1957 # args tuple
1958 code.putln('} else {')
1959 for i, arg in enumerate(positional_args):
1960 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
1961 self.generate_arg_assignment(arg, item, code)
1963 else:
1964 # parse the positional arguments from the variable length
1965 # args tuple
1966 code.putln('} else {')
1967 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
1968 if self.star_arg:
1969 code.putln('default:')
1970 reversed_args = list(enumerate(positional_args))[::-1]
1971 for i, arg in reversed_args:
1972 if i >= min_positional_args-1:
1973 if min_positional_args > 1:
1974 code.putln('case %2d:' % (i+1)) # pure code beautification
1975 else:
1976 code.put('case %2d: ' % (i+1))
1977 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
1978 self.generate_arg_assignment(arg, item, code)
1979 if min_positional_args == 0:
1980 code.put('case 0: ')
1981 code.putln('break;')
1982 if self.star_arg:
1983 if min_positional_args:
1984 for i in range(min_positional_args-1, -1, -1):
1985 code.putln('case %2d:' % i)
1986 code.put_goto(argtuple_error_label)
1987 else:
1988 code.put('default: ')
1989 code.put_goto(argtuple_error_label)
1990 code.putln('}')
1992 code.putln('}')
1994 if code.label_used(argtuple_error_label):
1995 code.put_goto(success_label)
1996 code.put_label(argtuple_error_label)
1997 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
1998 self.name.utf8encode(), has_fixed_positional_count,
1999 min_positional_args, max_positional_args,
2000 Naming.args_cname))
2001 code.putln(code.error_goto(self.pos))
2003 def generate_stararg_init_code(self, max_positional_args, code):
2004 if self.starstar_arg:
2005 self.starstar_arg.entry.xdecref_cleanup = 0
2006 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2007 self.starstar_arg.entry.cname,
2008 self.starstar_arg.entry.cname,
2009 self.error_value()))
2010 if self.star_arg:
2011 self.star_arg.entry.xdecref_cleanup = 0
2012 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2013 Naming.args_cname,
2014 max_positional_args))
2015 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2016 self.star_arg.entry.cname, Naming.args_cname,
2017 max_positional_args, Naming.args_cname))
2018 if self.starstar_arg:
2019 code.putln("")
2020 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2021 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2022 code.putln('return %s;' % self.error_value())
2023 code.putln('}')
2024 else:
2025 code.putln("if (unlikely(!%s)) return %s;" % (
2026 self.star_arg.entry.cname, self.error_value()))
2027 code.putln('} else {')
2028 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2029 code.put_incref(Naming.empty_tuple, py_object_type)
2030 code.putln('}')
2032 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2033 has_fixed_positional_count, positional_args,
2034 kw_only_args, argtuple_error_label, code):
2035 all_args = tuple(positional_args) + tuple(kw_only_args)
2036 max_args = len(all_args)
2038 code.putln("PyObject* values[%d] = {%s};" % (
2039 max_args, ('0,'*max_args)[:-1]))
2040 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2041 Naming.kwds_cname)
2043 # parse the tuple and check that it's not too long
2044 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2045 if self.star_arg:
2046 code.putln('default:')
2047 for i in range(max_positional_args-1, -1, -1):
2048 code.put('case %2d: ' % (i+1))
2049 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2050 i, Naming.args_cname, i))
2051 code.putln('case 0: break;')
2052 if not self.star_arg:
2053 code.put('default: ') # more arguments than allowed
2054 code.put_goto(argtuple_error_label)
2055 code.putln('}')
2057 # now fill up the required arguments with values from the kw dict
2058 last_required_arg = -1
2059 for i, arg in enumerate(all_args):
2060 if not arg.default:
2061 last_required_arg = i
2062 if last_required_arg >= 0:
2063 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2064 for i, arg in enumerate(all_args[:last_required_arg+1]):
2065 if i <= max_positional_args:
2066 if self.star_arg and i == max_positional_args:
2067 code.putln('default:')
2068 else:
2069 code.putln('case %2d:' % i)
2070 if arg.default:
2071 # handled in ParseOptionalKeywords() below
2072 continue
2073 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2074 i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2075 if i < min_positional_args:
2076 code.putln('if (likely(values[%d])) kw_args--;' % i);
2077 if i == 0:
2078 # special case: we know arg 0 is missing
2079 code.put('else ')
2080 code.put_goto(argtuple_error_label)
2081 else:
2082 # print the correct number of values (args or
2083 # kwargs) that were passed into positional
2084 # arguments up to this point
2085 code.putln('else {')
2086 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2087 self.name.utf8encode(), has_fixed_positional_count,
2088 min_positional_args, max_positional_args, i))
2089 code.putln(code.error_goto(self.pos))
2090 code.putln('}')
2091 else:
2092 code.putln('if (values[%d]) kw_args--;' % i);
2093 if arg.kw_only and not arg.default:
2094 code.putln('else {')
2095 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2096 self.name.utf8encode(), arg.name_entry.pystring_cname))
2097 code.putln(code.error_goto(self.pos))
2098 code.putln('}')
2099 code.putln('}')
2101 code.putln('if (unlikely(kw_args > 0)) {')
2102 # non-positional kw args left in dict: default args, **kwargs or error
2103 if self.star_arg:
2104 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2105 Naming.args_cname, max_positional_args,
2106 Naming.args_cname, max_positional_args))
2107 pos_arg_count = "used_pos_args"
2108 else:
2109 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2110 code.globalstate.use_utility_code(parse_keywords_utility_code)
2111 code.put(
2112 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2113 Naming.kwds_cname,
2114 Naming.pykwdlist_cname,
2115 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2116 pos_arg_count,
2117 self.name.utf8encode()))
2118 code.putln(code.error_goto(self.pos))
2119 code.putln('}')
2121 # convert arg values to their final type and assign them
2122 for i, arg in enumerate(all_args):
2123 if arg.default:
2124 code.putln("if (values[%d]) {" % i)
2125 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2126 if arg.default:
2127 code.putln('}')
2129 def generate_argument_conversion_code(self, code):
2130 # Generate code to convert arguments from
2131 # signature type to declared type, if needed.
2132 for arg in self.args:
2133 if arg.needs_conversion:
2134 self.generate_arg_conversion(arg, code)
2136 def generate_arg_conversion(self, arg, code):
2137 # Generate conversion code for one argument.
2138 old_type = arg.hdr_type
2139 new_type = arg.type
2140 if old_type.is_pyobject:
2141 if arg.default:
2142 code.putln("if (%s) {" % arg.hdr_cname)
2143 else:
2144 code.putln("assert(%s); {" % arg.hdr_cname)
2145 self.generate_arg_conversion_from_pyobject(arg, code)
2146 code.putln("}")
2147 elif new_type.is_pyobject:
2148 self.generate_arg_conversion_to_pyobject(arg, code)
2149 else:
2150 if new_type.assignable_from(old_type):
2151 code.putln(
2152 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2153 else:
2154 error(arg.pos,
2155 "Cannot convert 1 argument from '%s' to '%s'" %
2156 (old_type, new_type))
2158 def generate_arg_conversion_from_pyobject(self, arg, code):
2159 new_type = arg.type
2160 func = new_type.from_py_function
2161 # copied from CoerceFromPyTypeNode
2162 if func:
2163 code.putln("%s = %s(%s); %s" % (
2164 arg.entry.cname,
2165 func,
2166 arg.hdr_cname,
2167 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2168 else:
2169 error(arg.pos,
2170 "Cannot convert Python object argument to type '%s'"
2171 % new_type)
2173 def generate_arg_conversion_to_pyobject(self, arg, code):
2174 old_type = arg.hdr_type
2175 func = old_type.to_py_function
2176 if func:
2177 code.putln("%s = %s(%s); %s" % (
2178 arg.entry.cname,
2179 func,
2180 arg.hdr_cname,
2181 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2182 else:
2183 error(arg.pos,
2184 "Cannot convert argument of type '%s' to Python object"
2185 % old_type)
2187 def generate_argument_type_tests(self, code):
2188 # Generate type tests for args whose signature
2189 # type is PyObject * and whose declared type is
2190 # a subtype thereof.
2191 for arg in self.args:
2192 if arg.needs_type_test:
2193 self.generate_arg_type_test(arg, code)
2195 def generate_arg_type_test(self, arg, code):
2196 # Generate type test for one argument.
2197 if arg.type.typeobj_is_available():
2198 typeptr_cname = arg.type.typeptr_cname
2199 arg_code = "((PyObject *)%s)" % arg.entry.cname
2200 code.putln(
2201 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2202 arg_code,
2203 typeptr_cname,
2204 not arg.not_none,
2205 arg.name,
2206 arg.type.is_builtin_type,
2207 code.error_goto(arg.pos)))
2208 else:
2209 error(arg.pos, "Cannot test type of extern C class "
2210 "without type object name specification")
2212 def error_value(self):
2213 return self.entry.signature.error_value
2215 def caller_will_check_exceptions(self):
2216 return 1
2218 class OverrideCheckNode(StatNode):
2219 # A Node for dispatching to the def method if it
2220 # is overriden.
2221 #
2222 # py_func
2223 #
2224 # args
2225 # func_temp
2226 # body
2228 child_attrs = ['body']
2230 body = None
2232 def analyse_expressions(self, env):
2233 self.args = env.arg_entries
2234 if self.py_func.is_module_scope:
2235 first_arg = 0
2236 else:
2237 first_arg = 1
2238 import ExprNodes
2239 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2240 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2241 call_node = ExprNodes.SimpleCallNode(self.pos,
2242 function=self.func_node,
2243 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2244 self.body = ReturnStatNode(self.pos, value=call_node)
2245 self.body.analyse_expressions(env)
2247 def generate_execution_code(self, code):
2248 # Check to see if we are an extension type
2249 if self.py_func.is_module_scope:
2250 self_arg = "((PyObject *)%s)" % Naming.module_cname
2251 else:
2252 self_arg = "((PyObject *)%s)" % self.args[0].cname
2253 code.putln("/* Check if called by wrapper */")
2254 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2255 code.putln("/* Check if overriden in Python */")
2256 if self.py_func.is_module_scope:
2257 code.putln("else {")
2258 else:
2259 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2260 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2261 # need to get attribute manually--scope would return cdef method
2262 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2263 # It appears that this type is not anywhere exposed in the Python/C API
2264 is_builtin_function_or_method = '(strcmp(Py_TYPE(%s)->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result()
2265 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2266 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2267 self.body.generate_execution_code(code)
2268 code.putln('}')
2269 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2270 code.putln("}")
2272 class ClassDefNode(StatNode, BlockNode):
2273 pass
2275 class PyClassDefNode(ClassDefNode):
2276 # A Python class definition.
2277 #
2278 # name EncodedString Name of the class
2279 # doc string or None
2280 # body StatNode Attribute definition code
2281 # entry Symtab.Entry
2282 # scope PyClassScope
2283 #
2284 # The following subnodes are constructed internally:
2285 #
2286 # dict DictNode Class dictionary
2287 # classobj ClassNode Class object
2288 # target NameNode Variable to assign class object to
2290 child_attrs = ["body", "dict", "classobj", "target"]
2292 def __init__(self, pos, name, bases, doc, body):
2293 StatNode.__init__(self, pos)
2294 self.name = name
2295 self.doc = doc
2296 self.body = body
2297 import ExprNodes
2298 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2299 if self.doc and Options.docstrings:
2300 doc = embed_position(self.pos, self.doc)
2301 doc_node = ExprNodes.StringNode(pos, value = doc)
2302 else:
2303 doc_node = None
2304 self.classobj = ExprNodes.ClassNode(pos, name = name,
2305 bases = bases, dict = self.dict, doc = doc_node)
2306 self.target = ExprNodes.NameNode(pos, name = name)
2308 def as_cclass(self):
2309 """
2310 Return this node as if it were declared as an extension class"
2311 """
2312 bases = self.classobj.bases.args
2313 if len(bases) == 0:
2314 base_class_name = None
2315 base_class_module = None
2316 elif len(bases) == 1:
2317 base = bases[0]
2318 path = []
2319 while isinstance(base, ExprNodes.AttributeNode):
2320 path.insert(0, base.attribute)
2321 base = base.obj
2322 if isinstance(base, ExprNodes.NameNode):
2323 path.insert(0, base.name)
2324 base_class_name = path[-1]
2325 if len(path) > 1:
2326 base_class_module = u'.'.join(path[:-1])
2327 else:
2328 base_class_module = None
2329 else:
2330 error(self.classobj.bases.args.pos, "Invalid base class")
2331 else:
2332 error(self.classobj.bases.args.pos, "C class may only have one base class")
2333 return None
2335 return CClassDefNode(self.pos,
2336 visibility = 'private',
2337 module_name = None,
2338 class_name = self.name,
2339 base_class_module = base_class_module,
2340 base_class_name = base_class_name,
2341 body = self.body,
2342 in_pxd = False,
2343 doc = self.doc)
2345 def create_scope(self, env):
2346 genv = env
2347 while env.is_py_class_scope or env.is_c_class_scope:
2348 env = env.outer_scope
2349 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2350 return cenv
2352 def analyse_declarations(self, env):
2353 self.target.analyse_target_declaration(env)
2354 cenv = self.create_scope(env)
2355 cenv.class_obj_cname = self.target.entry.cname
2356 self.body.analyse_declarations(cenv)
2358 def analyse_expressions(self, env):
2359 self.dict.analyse_expressions(env)
2360 self.classobj.analyse_expressions(env)
2361 genv = env.global_scope()
2362 cenv = self.scope
2363 cenv.class_dict_cname = self.dict.result()
2364 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2365 self.body.analyse_expressions(cenv)
2366 self.target.analyse_target_expression(env, self.classobj)
2367 self.dict.release_temp(env)
2368 #self.classobj.release_temp(env)
2369 #self.target.release_target_temp(env)
2371 def generate_function_definitions(self, env, code):
2372 self.generate_py_string_decls(self.scope, code)
2373 self.body.generate_function_definitions(self.scope, code)
2375 def generate_execution_code(self, code):
2376 self.dict.generate_evaluation_code(code)
2377 self.classobj.generate_evaluation_code(code)
2378 self.body.generate_execution_code(code)
2379 self.target.generate_assignment_code(self.classobj, code)
2380 self.dict.generate_disposal_code(code)
2383 class CClassDefNode(ClassDefNode):
2384 # An extension type definition.
2385 #
2386 # visibility 'private' or 'public' or 'extern'
2387 # typedef_flag boolean
2388 # api boolean
2389 # module_name string or None For import of extern type objects
2390 # class_name string Unqualified name of class
2391 # as_name string or None Name to declare as in this scope
2392 # base_class_module string or None Module containing the base class
2393 # base_class_name string or None Name of the base class
2394 # objstruct_name string or None Specified C name of object struct
2395 # typeobj_name string or None Specified C name of type object
2396 # in_pxd boolean Is in a .pxd file
2397 # doc string or None
2398 # body StatNode or None
2399 # entry Symtab.Entry
2400 # base_type PyExtensionType or None
2401 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2402 # buffer_defaults_pos
2404 child_attrs = ["body"]
2405 buffer_defaults_node = None
2406 buffer_defaults_pos = None
2407 typedef_flag = False
2408 api = False
2409 objstruct_name = None
2410 typeobj_name = None
2412 def analyse_declarations(self, env):
2413 #print "CClassDefNode.analyse_declarations:", self.class_name
2414 #print "...visibility =", self.visibility
2415 #print "...module_name =", self.module_name
2417 import Buffer
2418 if self.buffer_defaults_node:
2419 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2420 env, [], self.buffer_defaults_node,
2421 need_complete=False)
2422 else:
2423 buffer_defaults = None
2425 if env.in_cinclude and not self.objstruct_name:
2426 error(self.pos, "Object struct name specification required for "
2427 "C class defined in 'extern from' block")
2428 self.base_type = None
2429 # Now that module imports are cached, we need to
2430 # import the modules for extern classes.
2431 if self.module_name:
2432 self.module = None
2433 for module in env.cimported_modules:
2434 if module.name == self.module_name:
2435 self.module = module
2436 if self.module is None:
2437 self.module = ModuleScope(self.module_name, None, env.context)
2438 self.module.has_extern_class = 1
2439 env.cimported_modules.append(self.module)
2441 if self.base_class_name:
2442 if self.base_class_module:
2443 base_class_scope = env.find_module(self.base_class_module, self.pos)
2444 else:
2445 base_class_scope = env
2446 if base_class_scope:
2447 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2448 if base_class_entry:
2449 if not base_class_entry.is_type:
2450 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2451 elif not base_class_entry.type.is_extension_type:
2452 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2453 elif not base_class_entry.type.is_complete():
2454 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2455 else:
2456 self.base_type = base_class_entry.type
2457 has_body = self.body is not None
2458 if self.module_name and self.visibility != 'extern':
2459 module_path = self.module_name.split(".")
2460 home_scope = env.find_imported_module(module_path, self.pos)
2461 if not home_scope:
2462 return
2463 else:
2464 home_scope = env
2465 self.entry = home_scope.declare_c_class(
2466 name = self.class_name,
2467 pos = self.pos,
2468 defining = has_body and self.in_pxd,
2469 implementing = has_body and not self.in_pxd,
2470 module_name = self.module_name,
2471 base_type = self.base_type,
2472 objstruct_cname = self.objstruct_name,
2473 typeobj_cname = self.typeobj_name,
2474 visibility = self.visibility,
2475 typedef_flag = self.typedef_flag,
2476 api = self.api,
2477 buffer_defaults = buffer_defaults)
2478 if home_scope is not env and self.visibility == 'extern':
2479 env.add_imported_entry(self.class_name, self.entry, pos)
2480 scope = self.entry.type.scope
2482 if self.doc and Options.docstrings:
2483 scope.doc = embed_position(self.pos, self.doc)
2485 if has_body:
2486 self.body.analyse_declarations(scope)
2487 if self.in_pxd:
2488 scope.defined = 1
2489 else:
2490 scope.implemented = 1
2491 env.allocate_vtable_names(self.entry)
2493 def analyse_expressions(self, env):
2494 if self.body:
2495 scope = self.entry.type.scope
2496 self.body.analyse_expressions(scope)
2498 def generate_function_definitions(self, env, code):
2499 self.generate_py_string_decls(self.entry.type.scope, code)
2500 if self.body:
2501 self.body.generate_function_definitions(
2502 self.entry.type.scope, code)
2504 def generate_execution_code(self, code):
2505 # This is needed to generate evaluation code for
2506 # default values of method arguments.
2507 if self.body:
2508 self.body.generate_execution_code(code)
2510 def annotate(self, code):
2511 if self.body:
2512 self.body.annotate(code)
2515 class PropertyNode(StatNode):
2516 # Definition of a property in an extension type.
2517 #
2518 # name string
2519 # doc EncodedString or None Doc string
2520 # body StatListNode
2522 child_attrs = ["body"]
2524 def analyse_declarations(self, env):
2525 entry = env.declare_property(self.name, self.doc, self.pos)
2526 if entry:
2527 if self.doc and Options.docstrings:
2528 doc_entry = env.get_string_const(
2529 self.doc, identifier = False)
2530 entry.doc_cname = doc_entry.cname
2531 self.body.analyse_declarations(entry.scope)
2533 def analyse_expressions(self, env):
2534 self.body.analyse_expressions(env)
2536 def generate_function_definitions(self, env, code):
2537 self.body.generate_function_definitions(env, code)
2539 def generate_execution_code(self, code):
2540 pass
2542 def annotate(self, code):
2543 self.body.annotate(code)
2546 class GlobalNode(StatNode):
2547 # Global variable declaration.
2548 #
2549 # names [string]
2551 child_attrs = []
2553 def analyse_declarations(self, env):
2554 for name in self.names:
2555 env.declare_global(name, self.pos)
2557 def analyse_expressions(self, env):
2558 pass
2560 def generate_execution_code(self, code):
2561 pass
2564 class ExprStatNode(StatNode):
2565 # Expression used as a statement.
2566 #
2567 # expr ExprNode
2569 child_attrs = ["expr"]
2571 def analyse_declarations(self, env):
2572 import ExprNodes
2573 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2574 func = self.expr.function.as_cython_attribute()
2575 if func == u'declare':
2576 args, kwds = self.expr.explicit_args_kwds()
2577 if len(args):
2578 error(self.expr.pos, "Variable names must be specified.")
2579 for var, type_node in kwds.key_value_pairs:
2580 type = type_node.analyse_as_type(env)
2581 if type is None:
2582 error(type_node.pos, "Unknown type")
2583 else:
2584 env.declare_var(var.value, type, var.pos, is_cdef = True)
2585 self.__class__ = PassStatNode
2587 def analyse_expressions(self, env):
2588 self.expr.analyse_expressions(env)
2589 self.expr.release_temp(env)
2591 def generate_execution_code(self, code):
2592 self.expr.generate_evaluation_code(code)
2593 if not self.expr.is_temp and self.expr.result():
2594 code.putln("%s;" % self.expr.result())
2595 self.expr.generate_disposal_code(code)
2597 def annotate(self, code):
2598 self.expr.annotate(code)
2601 class AssignmentNode(StatNode):
2602 # Abstract base class for assignment nodes.
2603 #
2604 # The analyse_expressions and generate_execution_code
2605 # phases of assignments are split into two sub-phases
2606 # each, to enable all the right hand sides of a
2607 # parallel assignment to be evaluated before assigning
2608 # to any of the left hand sides.
2610 def analyse_expressions(self, env):
2611 self.analyse_types(env)
2612 self.allocate_rhs_temps(env)
2613 self.allocate_lhs_temps(env)
2615 # def analyse_expressions(self, env):
2616 # self.analyse_expressions_1(env)
2617 # self.analyse_expressions_2(env)
2619 def generate_execution_code(self, code):
2620 self.generate_rhs_evaluation_code(code)
2621 self.generate_assignment_code(code)
2624 class SingleAssignmentNode(AssignmentNode):
2625 # The simplest case:
2626 #
2627 # a = b
2628 #
2629 # lhs ExprNode Left hand side
2630 # rhs ExprNode Right hand side
2631 # first bool Is this guaranteed the first assignment to lhs?
2633 child_attrs = ["lhs", "rhs"]
2634 first = False
2635 declaration_only = False
2637 def analyse_declarations(self, env):
2638 import ExprNodes
2640 # handle declarations of the form x = cython.foo()
2641 if isinstance(self.rhs, ExprNodes.CallNode):
2642 func_name = self.rhs.function.as_cython_attribute()
2643 if func_name:
2644 args, kwds = self.rhs.explicit_args_kwds()
2646 if func_name in ['declare', 'typedef']:
2647 if len(args) > 2 or kwds is not None:
2648 error(rhs.pos, "Can only declare one type at a time.")
2649 return
2650 type = args[0].analyse_as_type(env)
2651 if type is None:
2652 error(args[0].pos, "Unknown type")
2653 return
2654 lhs = self.lhs
2655 if func_name == 'declare':
2656 if isinstance(lhs, ExprNodes.NameNode):
2657 vars = [(lhs.name, lhs.pos)]
2658 elif isinstance(lhs, ExprNodes.TupleNode):
2659 vars = [(var.name, var.pos) for var in lhs.args]
2660 else:
2661 error(lhs.pos, "Invalid declaration")
2662 return
2663 for var, pos in vars:
2664 env.declare_var(var, type, pos, is_cdef = True)
2665 if len(args) == 2:
2666 # we have a value
2667 self.rhs = args[1]
2668 else:
2669 self.declaration_only = True
2670 else:
2671 self.declaration_only = True
2672 if not isinstance(lhs, ExprNodes.NameNode):
2673 error(lhs.pos, "Invalid declaration.")
2674 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2676 elif func_name in ['struct', 'union']:
2677 self.declaration_only = True
2678 if len(args) > 0 or kwds is None:
2679 error(rhs.pos, "Struct or union members must be given by name.")
2680 return
2681 members = []
2682 for member, type_node in kwds.key_value_pairs:
2683 type = type_node.analyse_as_type(env)
2684 if type is None:
2685 error(type_node.pos, "Unknown type")
2686 else:
2687 members.append((member.value, type, member.pos))
2688 if len(members) < len(kwds.key_value_pairs):
2689 return
2690 if not isinstance(self.lhs, ExprNodes.NameNode):
2691 error(self.lhs.pos, "Invalid declaration.")
2692 name = self.lhs.name
2693 scope = StructOrUnionScope(name)
2694 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2695 for member, type, pos in members:
2696 scope.declare_var(member, type, pos)
2698 if self.declaration_only:
2699 return
2700 else:
2701 self.lhs.analyse_target_declaration(env)
2703 def analyse_types(self, env, use_temp = 0):
2704 self.rhs.analyse_types(env)
2705 self.lhs.analyse_target_types(env)
2706 self.lhs.gil_assignment_check(env)
2707 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2708 if use_temp:
2709 self.rhs = self.rhs.coerce_to_temp(env)
2711 def allocate_rhs_temps(self, env):
2712 self.rhs.allocate_temps(env)
2714 def allocate_lhs_temps(self, env):
2715 self.lhs.allocate_target_temps(env, self.rhs)
2716 #self.lhs.release_target_temp(env)
2717 #self.rhs.release_temp(env)
2719 # def analyse_expressions_1(self, env, use_temp = 0):
2720 # self.rhs.analyse_types(env)
2721 # self.lhs.analyse_target_types(env)
2722 # self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2723 # if use_temp:
2724 # self.rhs = self.rhs.coerce_to_temp(env)
2725 # self.rhs.allocate_temps(env)
2726 #
2727 # def analyse_expressions_2(self, env):
2728 # self.lhs.allocate_target_temps(env)
2729 # self.lhs.release_target_temp(env)
2730 # self.rhs.release_temp(env)
2732 def generate_rhs_evaluation_code(self, code):
2733 self.rhs.generate_evaluation_code(code)
2735 def generate_assignment_code(self, code):
2736 self.lhs.generate_assignment_code(self.rhs, code)
2738 def annotate(self, code):
2739 self.lhs.annotate(code)
2740 self.rhs.annotate(code)
2743 class CascadedAssignmentNode(AssignmentNode):
2744 # An assignment with multiple left hand sides:
2745 #
2746 # a = b = c
2747 #
2748 # lhs_list [ExprNode] Left hand sides
2749 # rhs ExprNode Right hand sides
2750 #
2751 # Used internally:
2752 #
2753 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2755 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2756 coerced_rhs_list = None
2758 def analyse_declarations(self, env):
2759 for lhs in self.lhs_list:
2760 lhs.analyse_target_declaration(env)
2762 def analyse_types(self, env, use_temp = 0):
2763 self.rhs.analyse_types(env)
2764 if use_temp:
2765 self.rhs = self.rhs.coerce_to_temp(env)
2766 else:
2767 self.rhs = self.rhs.coerce_to_simple(env)
2768 from ExprNodes import CloneNode
2769 self.coerced_rhs_list = []
2770 for lhs in self.lhs_list:
2771 lhs.analyse_target_types(env)
2772 lhs.gil_assignment_check(env)
2773 rhs = CloneNode(self.rhs)
2774 rhs = rhs.coerce_to(lhs.type, env)
2775 self.coerced_rhs_list.append(rhs)
2777 def allocate_rhs_temps(self, env):
2778 self.rhs.allocate_temps(env)
2780 def allocate_lhs_temps(self, env):
2781 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2782 rhs.allocate_temps(env)
2783 lhs.allocate_target_temps(env, rhs)
2784 #lhs.release_target_temp(env)
2785 #rhs.release_temp(env)
2786 self.rhs.release_temp(env)
2788 # def analyse_expressions_1(self, env, use_temp = 0):
2789 # self.rhs.analyse_types(env)
2790 # if use_temp:
2791 # self.rhs = self.rhs.coerce_to_temp(env)
2792 # else:
2793 # self.rhs = self.rhs.coerce_to_simple(env)
2794 # self.rhs.allocate_temps(env)
2795 #
2796 # def analyse_expressions_2(self, env):
2797 # from ExprNodes import CloneNode
2798 # self.coerced_rhs_list = []
2799 # for lhs in self.lhs_list:
2800 # lhs.analyse_target_types(env)
2801 # rhs = CloneNode(self.rhs)
2802 # rhs = rhs.coerce_to(lhs.type, env)
2803 # self.coerced_rhs_list.append(rhs)
2804 # rhs.allocate_temps(env)
2805 # lhs.allocate_target_temps(env)
2806 # lhs.release_target_temp(env)
2807 # rhs.release_temp(env)
2808 # self.rhs.release_temp(env)
2810 def generate_rhs_evaluation_code(self, code):
2811 self.rhs.generate_evaluation_code(code)
2813 def generate_assignment_code(self, code):
2814 for i in range(len(self.lhs_list)):
2815 lhs = self.lhs_list[i]
2816 rhs = self.coerced_rhs_list[i]
2817 rhs.generate_evaluation_code(code)
2818 lhs.generate_assignment_code(rhs, code)
2819 # Assignment has disposed of the cloned RHS
2820 self.rhs.generate_disposal_code(code)
2822 def annotate(self, code):
2823 for i in range(len(self.lhs_list)):
2824 lhs = self.lhs_list[i].annotate(code)
2825 rhs = self.coerced_rhs_list[i].annotate(code)
2826 self.rhs.annotate(code)
2829 class ParallelAssignmentNode(AssignmentNode):
2830 # A combined packing/unpacking assignment:
2831 #
2832 # a, b, c = d, e, f
2833 #
2834 # This has been rearranged by the parser into
2835 #
2836 # a = d ; b = e ; c = f
2837 #
2838 # but we must evaluate all the right hand sides
2839 # before assigning to any of the left hand sides.
2840 #
2841 # stats [AssignmentNode] The constituent assignments
2843 child_attrs = ["stats"]
2845 def analyse_declarations(self, env):
2846 for stat in self.stats:
2847 stat.analyse_declarations(env)
2849 def analyse_expressions(self, env):
2850 for stat in self.stats:
2851 stat.analyse_types(env, use_temp = 1)
2852 stat.allocate_rhs_temps(env)
2853 for stat in self.stats:
2854 stat.allocate_lhs_temps(env)
2856 # def analyse_expressions(self, env):
2857 # for stat in self.stats:
2858 # stat.analyse_expressions_1(env, use_temp = 1)
2859 # for stat in self.stats:
2860 # stat.analyse_expressions_2(env)
2862 def generate_execution_code(self, code):
2863 for stat in self.stats:
2864 stat.generate_rhs_evaluation_code(code)
2865 for stat in self.stats:
2866 stat.generate_assignment_code(code)
2868 def annotate(self, code):
2869 for stat in self.stats:
2870 stat.annotate(code)
2873 class InPlaceAssignmentNode(AssignmentNode):
2874 # An in place arithmatic operand:
2875 #
2876 # a += b
2877 # a -= b
2878 # ...
2879 #
2880 # lhs ExprNode Left hand side
2881 # rhs ExprNode Right hand side
2882 # op char one of "+-*/%^&|"
2883 # dup (ExprNode) copy of lhs used for operation (auto-generated)
2884 #
2885 # This code is a bit tricky because in order to obey Python
2886 # semantics the sub-expressions (e.g. indices) of the lhs must
2887 # not be evaluated twice. So we must re-use the values calculated
2888 # in evaluation phase for the assignment phase as well.
2889 # Fortunately, the type of the lhs node is fairly constrained
2890 # (it must be a NameNode, AttributeNode, or IndexNode).
2892 child_attrs = ["lhs", "rhs"]
2893 dup = None
2895 def analyse_declarations(self, env):
2896 self.lhs.analyse_target_declaration(env)
2898 def analyse_types(self, env):
2899 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
2900 self.rhs.analyse_types(env)
2901 self.lhs.analyse_target_types(env)
2902 if Options.incref_local_binop and self.dup.type.is_pyobject:
2903 self.dup = self.dup.coerce_to_temp(env)
2905 def allocate_rhs_temps(self, env):
2906 import ExprNodes
2907 if self.lhs.type.is_pyobject:
2908 self.rhs = self.rhs.coerce_to_pyobject(env)
2909 elif self.rhs.type.is_pyobject:
2910 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2911 if self.lhs.type.is_pyobject:
2912 self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
2913 self.result_value.allocate_temps(env)
2914 # if use_temp:
2915 # self.rhs = self.rhs.coerce_to_temp(env)
2916 self.rhs.allocate_temps(env)
2917 self.dup.allocate_subexpr_temps(env)
2918 self.dup.allocate_temp(env)
2920 def allocate_lhs_temps(self, env):
2921 self.lhs.allocate_target_temps(env, self.rhs)
2922 # self.lhs.release_target_temp(env)
2923 self.dup.release_temp(env)
2924 if self.dup.is_temp:
2925 self.dup.release_subexpr_temps(env)
2926 # self.rhs.release_temp(env)
2927 if self.lhs.type.is_pyobject:
2928 self.result_value.release_temp(env)
2930 def generate_execution_code(self, code):
2931 self.rhs.generate_evaluation_code(code)
2932 self.dup.generate_subexpr_evaluation_code(code)
2933 # self.dup.generate_result_code is run only if it is not buffer access
2934 if self.operator == "**":
2935 extra = ", Py_None"
2936 else:
2937 extra = ""
2938 import ExprNodes
2939 if self.lhs.type.is_pyobject:
2940 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
2941 error(self.pos, "In-place operators not allowed on object buffers in this release.")
2942 self.dup.generate_result_code(code)
2943 code.putln(
2944 "%s = %s(%s, %s%s); %s" % (
2945 self.result_value.result(),
2946 self.py_operation_function(),
2947 self.dup.py_result(),
2948 self.rhs.py_result(),
2949 extra,
2950 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
2951 self.result_value.generate_evaluation_code(code) # May be a type check...
2952 self.rhs.generate_disposal_code(code)
2953 self.dup.generate_disposal_code(code)
2954 self.lhs.generate_assignment_code(self.result_value, code)
2955 else:
2956 c_op = self.operator
2957 if c_op == "//":
2958 c_op = "/"
2959 elif c_op == "**":
2960 if self.lhs.type.is_int and self.rhs.type.is_int:
2961 error(self.pos, "** with two C int types is ambiguous")
2962 else:
2963 error(self.pos, "No C inplace power operator")
2964 # have to do assignment directly to avoid side-effects
2965 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
2966 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
2967 else:
2968 self.dup.generate_result_code(code)
2969 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
2970 self.rhs.generate_disposal_code(code)
2971 if self.dup.is_temp:
2972 self.dup.generate_subexpr_disposal_code(code)
2974 def create_dup_node(self, env):
2975 import ExprNodes
2976 self.dup = self.lhs
2977 self.dup.analyse_types(env)
2978 if isinstance(self.lhs, ExprNodes.NameNode):
2979 target_lhs = ExprNodes.NameNode(self.dup.pos,
2980 name = self.dup.name,
2981 is_temp = self.dup.is_temp,
2982 entry = self.dup.entry)
2983 elif isinstance(self.lhs, ExprNodes.AttributeNode):
2984 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
2985 obj = ExprNodes.CloneNode(self.lhs.obj),
2986 attribute = self.dup.attribute,
2987 is_temp = self.dup.is_temp)
2988 elif isinstance(self.lhs, ExprNodes.IndexNode):
2989 if self.lhs.index:
2990 index = ExprNodes.CloneNode(self.lhs.index)
2991 else:
2992 index = None
2993 if self.lhs.indices:
2994 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
2995 else:
2996 indices = []
2997 target_lhs = ExprNodes.IndexNode(self.dup.pos,
2998 base = ExprNodes.CloneNode(self.dup.base),
2999 index = index,
3000 indices = indices,
3001 is_temp = self.dup.is_temp)
3002 self.lhs = target_lhs
3003 return self.dup
3005 def py_operation_function(self):
3006 return self.py_functions[self.operator]
3008 py_functions = {
3009 "|": "PyNumber_InPlaceOr",
3010 "^": "PyNumber_InPlaceXor",
3011 "&": "PyNumber_InPlaceAnd",
3012 "+": "PyNumber_InPlaceAdd",
3013 "-": "PyNumber_InPlaceSubtract",
3014 "*": "PyNumber_InPlaceMultiply",
3015 "/": "PyNumber_InPlaceDivide",
3016 "%": "PyNumber_InPlaceRemainder",
3017 "<<": "PyNumber_InPlaceLshift",
3018 ">>": "PyNumber_InPlaceRshift",
3019 "**": "PyNumber_InPlacePower",
3020 "//": "PyNumber_InPlaceFloorDivide",
3021 }
3023 def annotate(self, code):
3024 self.lhs.annotate(code)
3025 self.rhs.annotate(code)
3026 self.dup.annotate(code)
3029 class PrintStatNode(StatNode):
3030 # print statement
3031 #
3032 # arg_tuple TupleNode
3033 # append_newline boolean
3035 child_attrs = ["arg_tuple"]
3037 def analyse_expressions(self, env):
3038 self.arg_tuple.analyse_expressions(env)
3039 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3040 self.arg_tuple.release_temp(env)
3041 env.use_utility_code(printing_utility_code)
3042 self.gil_check(env)
3044 gil_message = "Python print statement"
3046 def generate_execution_code(self, code):
3047 self.arg_tuple.generate_evaluation_code(code)
3048 code.putln(
3049 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3050 self.arg_tuple.py_result(),
3051 self.append_newline,
3052 code.error_goto(self.pos)))
3053 self.arg_tuple.generate_disposal_code(code)
3055 def annotate(self, code):
3056 self.arg_tuple.annotate(code)
3059 class DelStatNode(StatNode):
3060 # del statement
3061 #
3062 # args [ExprNode]
3064 child_attrs = ["args"]
3066 def analyse_declarations(self, env):
3067 for arg in self.args:
3068 arg.analyse_target_declaration(env)
3070 def analyse_expressions(self, env):
3071 for arg in self.args:
3072 arg.analyse_target_expression(env, None)
3073 if arg.type.is_pyobject:
3074 self.gil_check(env)
3075 else:
3076 error(arg.pos, "Deletion of non-Python object")
3077 #arg.release_target_temp(env)
3079 gil_message = "Deleting Python object"
3081 def generate_execution_code(self, code):
3082 for arg in self.args:
3083 if arg.type.is_pyobject:
3084 arg.generate_deletion_code(code)
3085 # else error reported earlier
3087 def annotate(self, code):
3088 for arg in self.args:
3089 arg.annotate(code)
3092 class PassStatNode(StatNode):
3093 # pass statement
3095 child_attrs = []
3097 def analyse_expressions(self, env):
3098 pass
3100 def generate_execution_code(self, code):
3101 pass
3104 class BreakStatNode(StatNode):
3106 child_attrs = []
3108 def analyse_expressions(self, env):
3109 pass
3111 def generate_execution_code(self, code):
3112 if not code.break_label:
3113 error(self.pos, "break statement not inside loop")
3114 else:
3115 #code.putln(
3116 # "goto %s;" %
3117 # code.break_label)
3118 code.put_goto(code.break_label)
3121 class ContinueStatNode(StatNode):
3123 child_attrs = []
3125 def analyse_expressions(self, env):
3126 pass
3128 def generate_execution_code(self, code):
3129 if code.funcstate.in_try_finally:
3130 error(self.pos, "continue statement inside try of try...finally")
3131 elif not code.continue_label:
3132 error(self.pos, "continue statement not inside loop")
3133 else:
3134 code.put_goto(code.continue_label)
3137 class ReturnStatNode(StatNode):
3138 # return statement
3139 #
3140 # value ExprNode or None
3141 # return_type PyrexType
3142 # temps_in_use [Entry] Temps in use at time of return
3144 child_attrs = ["value"]
3146 def analyse_expressions(self, env):
3147 return_type = env.return_type
3148 self.return_type = return_type
3149 self.temps_in_use = env.temps_in_use()
3150 if not return_type:
3151 error(self.pos, "Return not inside a function body")
3152 return
3153 if self.value:
3154 self.value.analyse_types(env)
3155 if return_type.is_void or return_type.is_returncode:
3156 error(self.value.pos,
3157 "Return with value in void function")
3158 else:
3159 self.value = self.value.coerce_to(env.return_type, env)
3160 self.value.allocate_temps(env)
3161 self.value.release_temp(env)
3162 else:
3163 if (not return_type.is_void
3164 and not return_type.is_pyobject
3165 and not return_type.is_returncode):
3166 error(self.pos, "Return value required")
3167 if return_type.is_pyobject:
3168 self.gil_check(env)
3170 gil_message = "Returning Python object"
3172 def generate_execution_code(self, code):
3173 code.mark_pos(self.pos)
3174 if not self.return_type:
3175 # error reported earlier
3176 return
3177 if self.value:
3178 self.value.generate_evaluation_code(code)
3179 self.value.make_owned_reference(code)
3180 code.putln(
3181 "%s = %s;" % (
3182 Naming.retval_cname,
3183 self.value.result_as(self.return_type)))
3184 self.value.generate_post_assignment_code(code)
3185 else:
3186 if self.return_type.is_pyobject:
3187 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3188 elif self.return_type.is_returncode:
3189 code.putln(
3190 "%s = %s;" % (
3191 Naming.retval_cname,
3192 self.return_type.default_value))
3193 for entry in self.temps_in_use:
3194 code.put_var_decref_clear(entry)
3195 #code.putln(
3196 # "goto %s;" %
3197 # code.return_label)
3198 code.put_goto(code.return_label)
3200 def annotate(self, code):
3201 if self.value:
3202 self.value.annotate(code)
3205 class RaiseStatNode(StatNode):
3206 # raise statement
3207 #
3208 # exc_type ExprNode or None
3209 # exc_value ExprNode or None
3210 # exc_tb ExprNode or None
3212 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3214 def analyse_expressions(self, env):
3215 if self.exc_type:
3216 self.exc_type.analyse_types(env)
3217 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3218 self.exc_type.allocate_temps(env)
3219 if self.exc_value:
3220 self.exc_value.analyse_types(env)
3221 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3222 self.exc_value.allocate_temps(env)
3223 if self.exc_tb:
3224 self.exc_tb.analyse_types(env)
3225 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3226 self.exc_tb.allocate_temps(env)
3227 if self.exc_type:
3228 self.exc_type.release_temp(env)
3229 if self.exc_value:
3230 self.exc_value.release_temp(env)
3231 if self.exc_tb:
3232 self.exc_tb.release_temp(env)
3233 env.use_utility_code(raise_utility_code)
3234 env.use_utility_code(restore_exception_utility_code)
3235 self.gil_check(env)
3237 gil_message = "Raising exception"
3239 def generate_execution_code(self, code):
3240 if self.exc_type:
3241 self.exc_type.generate_evaluation_code(code)
3242 type_code = self.exc_type.py_result()
3243 else:
3244 type_code = 0
3245 if self.exc_value:
3246 self.exc_value.generate_evaluation_code(code)
3247 value_code = self.exc_value.py_result()
3248 else:
3249 value_code = "0"
3250 if self.exc_tb:
3251 self.exc_tb.generate_evaluation_code(code)
3252 tb_code = self.exc_tb.py_result()
3253 else:
3254 tb_code = "0"
3255 if self.exc_type or self.exc_value or self.exc_tb:
3256 code.putln(
3257 "__Pyx_Raise(%s, %s, %s);" % (
3258 type_code,
3259 value_code,
3260 tb_code))
3261 else:
3262 code.putln(
3263 "__Pyx_ReRaise();")
3264 if self.exc_type:
3265 self.exc_type.generate_disposal_code(code)
3266 if self.exc_value:
3267 self.exc_value.generate_disposal_code(code)
3268 if self.exc_tb:
3269 self.exc_tb.generate_disposal_code(code)
3270 code.putln(
3271 code.error_goto(self.pos))
3273 def annotate(self, code):
3274 if self.exc_type:
3275 self.exc_type.annotate(code)
3276 if self.exc_value:
3277 self.exc_value.annotate(code)
3278 if self.exc_tb:
3279 self.exc_tb.annotate(code)
3282 class ReraiseStatNode(StatNode):
3284 child_attrs = []
3286 def analyse_expressions(self, env):
3287 self.gil_check(env)
3288 env.use_utility_code(raise_utility_code)
3289 env.use_utility_code(restore_exception_utility_code)
3291 gil_message = "Raising exception"
3293 def generate_execution_code(self, code):
3294 vars = code.funcstate.exc_vars
3295 if vars:
3296 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3297 code.putln(code.error_goto(self.pos))
3298 else:
3299 error(self.pos, "Reraise not inside except clause")
3302 class AssertStatNode(StatNode):
3303 # assert statement
3304 #
3305 # cond ExprNode
3306 # value ExprNode or None
3308 child_attrs = ["cond", "value"]
3310 def analyse_expressions(self, env):
3311 self.cond = self.cond.analyse_boolean_expression(env)
3312 if self.value:
3313 self.value.analyse_types(env)
3314 self.value = self.value.coerce_to_pyobject(env)
3315 self.value.allocate_temps(env)
3316 self.cond.release_temp(env)
3317 if self.value:
3318 self.value.release_temp(env)
3319 self.gil_check(env)
3320 #env.recycle_pending_temps() # TEMPORARY
3322 gil_message = "Raising exception"
3324 def generate_execution_code(self, code):
3325 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3326 self.cond.generate_evaluation_code(code)
3327 code.putln(
3328 "if (unlikely(!%s)) {" %
3329 self.cond.result())
3330 if self.value:
3331 self.value.generate_evaluation_code(code)
3332 code.putln(
3333 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3334 self.value.py_result())
3335 self.value.generate_disposal_code(code)
3336 else:
3337 code.putln(
3338 "PyErr_SetNone(PyExc_AssertionError);")
3339 code.putln(
3340 code.error_goto(self.pos))
3341 code.putln(
3342 "}")
3343 self.cond.generate_disposal_code(code)
3344 code.putln("#endif")
3346 def annotate(self, code):
3347 self.cond.annotate(code)
3348 if self.value:
3349 self.value.annotate(code)
3352 class IfStatNode(StatNode):
3353 # if statement
3354 #
3355 # if_clauses [IfClauseNode]
3356 # else_clause StatNode or None
3358 child_attrs = ["if_clauses", "else_clause"]
3360 def analyse_control_flow(self, env):
3361 env.start_branching(self.pos)
3362 for if_clause in self.if_clauses:
3363 if_clause.analyse_control_flow(env)
3364 env.next_branch(if_clause.end_pos())
3365 if self.else_clause:
3366 self.else_clause.analyse_control_flow(env)
3367 env.finish_branching(self.end_pos())
3369 def analyse_declarations(self, env):
3370 for if_clause in self.if_clauses:
3371 if_clause.analyse_declarations(env)
3372 if self.else_clause:
3373 self.else_clause.analyse_declarations(env)
3375 def analyse_expressions(self, env):
3376 for if_clause in self.if_clauses:
3377 if_clause.analyse_expressions(env)
3378 if self.else_clause:
3379 self.else_clause.analyse_expressions(env)
3381 def generate_execution_code(self, code):
3382 code.mark_pos(self.pos)
3383 end_label = code.new_label()
3384 for if_clause in self.if_clauses:
3385 if_clause.generate_execution_code(code, end_label)
3386 if self.else_clause:
3387 code.putln("/*else*/ {")
3388 self.else_clause.generate_execution_code(code)
3389 code.putln("}")
3390 code.put_label(end_label)
3392 def annotate(self, code):
3393 for if_clause in self.if_clauses:
3394 if_clause.annotate(code)
3395 if self.else_clause:
3396 self.else_clause.annotate(code)
3399 class IfClauseNode(Node):
3400 # if or elif clause in an if statement
3401 #
3402 # condition ExprNode
3403 # body StatNode
3405 child_attrs = ["condition", "body"]
3407 def analyse_control_flow(self, env):
3408 self.body.analyse_control_flow(env)
3410 def analyse_declarations(self, env):
3411 self.condition.analyse_declarations(env)
3412 self.body.analyse_declarations(env)
3414 def analyse_expressions(self, env):
3415 self.condition = \
3416 self.condition.analyse_temp_boolean_expression(env)
3417 self.condition.release_temp(env)
3418 self.body.analyse_expressions(env)
3420 def generate_execution_code(self, code, end_label):
3421 self.condition.generate_evaluation_code(code)
3422 code.putln(
3423 "if (%s) {" %
3424 self.condition.result())
3425 self.body.generate_execution_code(code)
3426 #code.putln(
3427 # "goto %s;" %
3428 # end_label)
3429 code.put_goto(end_label)
3430 code.putln("}")
3432 def annotate(self, code):
3433 self.condition.annotate(code)
3434 self.body.annotate(code)
3437 class SwitchCaseNode(StatNode):
3438 # Generated in the optimization of an if-elif-else node
3439 #
3440 # conditions [ExprNode]
3441 # body StatNode
3443 child_attrs = ['conditions', 'body']
3445 def generate_execution_code(self, code):
3446 for cond in self.conditions:
3447 code.putln("case %s:" % cond.calculate_result_code())
3448 self.body.generate_execution_code(code)
3449 code.putln("break;")
3451 def annotate(self, code):
3452 for cond in self.conditions:
3453 cond.annotate(code)
3454 self.body.annotate(code)
3456 class SwitchStatNode(StatNode):
3457 # Generated in the optimization of an if-elif-else node
3458 #
3459 # test ExprNode
3460 # cases [SwitchCaseNode]
3461 # else_clause StatNode or None
3463 child_attrs = ['test', 'cases', 'else_clause']
3465 def generate_execution_code(self, code):
3466 code.putln("switch (%s) {" % self.test.calculate_result_code())
3467 for case in self.cases:
3468 case.generate_execution_code(code)
3469 if self.else_clause is not None:
3470 code.putln("default:")
3471 self.else_clause.generate_execution_code(code)
3472 code.putln("break;")
3473 code.putln("}")
3475 def annotate(self, code):
3476 self.test.annotate(code)
3477 for case in self.cases:
3478 case.annotate(code)
3479 if self.else_clause is not None:
3480 self.else_clause.annotate(code)
3482 class LoopNode:
3484 def analyse_control_flow(self, env):
3485 env.start_branching(self.pos)
3486 self.body.analyse_control_flow(env)
3487 env.next_branch(self.body.end_pos())
3488 if self.else_clause:
3489 self.else_clause.analyse_control_flow(env)
3490 env.finish_branching(self.end_pos())
3493 class WhileStatNode(LoopNode, StatNode):
3494 # while statement
3495 #
3496 # condition ExprNode
3497 # body StatNode
3498 # else_clause StatNode
3500 child_attrs = ["condition", "body", "else_clause"]
3502 def analyse_declarations(self, env):
3503 self.body.analyse_declarations(env)
3504 if self.else_clause:
3505 self.else_clause.analyse_declarations(env)
3507 def analyse_expressions(self, env):
3508 self.condition = \
3509 self.condition.analyse_temp_boolean_expression(env)
3510 self.condition.release_temp(env)
3511 #env.recycle_pending_temps() # TEMPORARY
3512 self.body.analyse_expressions(env)
3513 if self.else_clause:
3514 self.else_clause.analyse_expressions(env)
3516 def generate_execution_code(self, code):
3517 old_loop_labels = code.new_loop_labels()
3518 code.putln(
3519 "while (1) {")
3520 self.condition.generate_evaluation_code(code)
3521 code.putln(
3522 "if (!%s) break;" %
3523 self.condition.result())
3524 self.body.generate_execution_code(code)
3525 code.put_label(code.continue_label)
3526 code.putln("}")
3527 break_label = code.break_label
3528 code.set_loop_labels(old_loop_labels)
3529 if self.else_clause:
3530 code.putln("/*else*/ {")
3531 self.else_clause.generate_execution_code(code)
3532 code.putln("}")
3533 code.put_label(break_label)
3535 def annotate(self, code):
3536 self.condition.annotate(code)
3537 self.body.annotate(code)
3538 if self.else_clause:
3539 self.else_clause.annotate(code)
3542 def ForStatNode(pos, **kw):
3543 if kw.has_key('iterator'):
3544 return ForInStatNode(pos, **kw)
3545 else:
3546 return ForFromStatNode(pos, **kw)
3548 class ForInStatNode(LoopNode, StatNode):
3549 # for statement
3550 #
3551 # target ExprNode
3552 # iterator IteratorNode
3553 # body StatNode
3554 # else_clause StatNode
3555 # item NextNode used internally
3557 child_attrs = ["target", "iterator", "body", "else_clause"]
3558 item = None
3560 def analyse_declarations(self, env):
3561 self.target.analyse_target_declaration(env)
3562 self.body.analyse_declarations(env)
3563 if self.else_clause:
3564 self.else_clause.analyse_declarations(env)
3566 def analyse_range_step(self, args):
3567 import ExprNodes
3568 # The direction must be determined at compile time to set relations.
3569 # Otherwise, return False.
3570 if len(args) < 3:
3571 self.step = ExprNodes.IntNode(pos = args[0].pos, value='1')
3572 self.relation1 = '<='
3573 self.relation2 = '<'
3574 return True
3575 else:
3576 step = args[2]
3577 if isinstance(step, ExprNodes.UnaryMinusNode) and isinstance(step.operand, ExprNodes.IntNode):
3578 step = ExprNodes.IntNode(pos = step.pos, value=str(-int(step.operand.value, 0)))
3579 if isinstance(step, ExprNodes.IntNode):
3580 step_value = int(step.value, 0)
3581 if step_value > 0:
3582 self.step = step
3583 self.relation1 = '<='
3584 self.relation2 = '<'
3585 return True
3586 elif step_value < 0:
3587 self.step = ExprNodes.IntNode(pos = step.pos, value=str(-step_value))
3588 self.relation1 = '>='
3589 self.relation2 = '>'
3590 return True
3591 return False
3594 def analyse_expressions(self, env):
3595 import ExprNodes
3596 self.target.analyse_target_types(env)
3597 if Options.convert_range and self.target.type.is_int:
3598 sequence = self.iterator.sequence
3599 if isinstance(sequence, ExprNodes.SimpleCallNode) \
3600 and sequence.self is None \
3601 and isinstance(sequence.function, ExprNodes.NameNode) \
3602 and (sequence.function.name == 'range' or sequence.function.name == 'xrange'):
3603 args = sequence.args
3604 # Make sure we can determine direction from step
3605 if self.analyse_range_step(args):
3606 # Mutate to ForFrom loop type
3607 self.__class__ = ForFromStatNode
3608 if len(args) == 1:
3609 self.bound1 = ExprNodes.IntNode(pos = sequence.pos, value='0')
3610 self.bound2 = args[0]
3611 else:
3612 self.bound1 = args[0]
3613 self.bound2 = args[1]
3614 ForFromStatNode.analyse_expressions(self, env)
3615 return
3617 self.iterator.analyse_expressions(env)
3618 self.item = ExprNodes.NextNode(self.iterator, env)
3619 self.item = self.item.coerce_to(self.target.type, env)
3620 self.item.allocate_temps(env)
3621 self.target.allocate_target_temps(env, self.item)
3622 #self.item.release_temp(env)
3623 #self.target.release_target_temp(env)
3624 self.body.analyse_expressions(env)
3625 if self.else_clause:
3626 self.else_clause.analyse_expressions(env)
3627 self.iterator.release_temp(env)
3629 def generate_execution_code(self, code):
3630 old_loop_labels = code.new_loop_labels()
3631 self.iterator.generate_evaluation_code(code)
3632 code.putln(
3633 "for (;;) {")
3634 self.item.generate_evaluation_code(code)
3635 self.target.generate_assignment_code(self.item, code)
3636 self.body.generate_execution_code(code)
3637 code.put_label(code.continue_label)
3638 code.putln(
3639 "}")
3640 break_label = code.break_label
3641 code.set_loop_labels(old_loop_labels)
3642 if self.else_clause:
3643 code.putln("/*else*/ {")
3644 self.else_clause.generate_execution_code(code)
3645 code.putln("}")
3646 code.put_label(break_label)
3647 self.iterator.generate_disposal_code(code)
3649 def annotate(self, code):
3650 self.target.annotate(code)
3651 self.iterator.annotate(code)
3652 self.body.annotate(code)
3653 if self.else_clause:
3654 self.else_clause.annotate(code)
3655 self.item.annotate(code)
3658 class ForFromStatNode(LoopNode, StatNode):
3659 # for name from expr rel name rel expr
3660 #
3661 # target NameNode
3662 # bound1 ExprNode
3663 # relation1 string
3664 # relation2 string
3665 # bound2 ExprNode
3666 # step ExprNode or None
3667 # body StatNode
3668 # else_clause StatNode or None
3669 #
3670 # Used internally:
3671 #
3672 # is_py_target bool
3673 # loopvar_name string
3674 # py_loopvar_node PyTempNode or None
3675 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3677 def analyse_declarations(self, env):
3678 self.target.analyse_target_declaration(env)
3679 self.body.analyse_declarations(env)
3680 if self.else_clause:
3681 self.else_clause.analyse_declarations(env)
3683 def analyse_expressions(self, env):
3684 import ExprNodes
3685 self.target.analyse_target_types(env)
3686 self.bound1.analyse_types(env)
3687 self.bound2.analyse_types(env)
3688 if self.target.type.is_numeric:
3689 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3690 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3691 else:
3692 self.bound1 = self.bound1.coerce_to_integer(env)
3693 self.bound2 = self.bound2.coerce_to_integer(env)
3694 if self.step is not None:
3695 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3696 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3697 self.step.analyse_types(env)
3698 self.step = self.step.coerce_to_integer(env)
3699 if not (self.bound2.is_name or self.bound2.is_literal):
3700 self.bound2 = self.bound2.coerce_to_temp(env)
3701 target_type = self.target.type
3702 if not (target_type.is_pyobject or target_type.is_numeric):
3703 error(self.target.pos,
3704 "Integer for-loop variable must be of type int or Python object")
3705 #if not (target_type.is_pyobject
3706 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3707 # error(self.target.pos,
3708 # "Cannot assign integer to variable of type '%s'" % target_type)
3709 if target_type.is_numeric:
3710 self.is_py_target = 0
3711 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3712 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3713 self.loopvar_name = self.target.entry.cname
3714 self.py_loopvar_node = None
3715 else:
3716 self.is_py_target = 1
3717 c_loopvar_node = ExprNodes.TempNode(self.pos,
3718 PyrexTypes.c_long_type, env)
3719 c_loopvar_node.allocate_temps(env)
3720 self.loopvar_name = c_loopvar_node.result()
3721 self.py_loopvar_node = \
3722 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3723 self.bound1.allocate_temps(env)
3724 self.bound2.allocate_temps(env)
3725 if self.step is not None:
3726 self.step.allocate_temps(env)
3727 if self.is_py_target:
3728 self.py_loopvar_node.allocate_temps(env)
3729 self.target.allocate_target_temps(env, self.py_loopvar_node)
3730 #self.target.release_target_temp(env)
3731 #self.py_loopvar_node.release_temp(env)
3732 self.body.analyse_expressions(env)
3733 if self.is_py_target:
3734 c_loopvar_node.release_temp(env)
3735 if self.else_clause:
3736 self.else_clause.analyse_expressions(env)
3737 self.bound1.release_temp(env)
3738 self.bound2.release_temp(env)
3739 if self.step is not None:
3740 self.step.release_temp(env)
3742 def generate_execution_code(self, code):
3743 old_loop_labels = code.new_loop_labels()
3744 self.bound1.generate_evaluation_code(code)
3745 self.bound2.generate_evaluation_code(code)
3746 offset, incop = self.relation_table[self.relation1]
3747 if self.step is not None:
3748 self.step.generate_evaluation_code(code)
3749 incop = "%s=%s" % (incop[0], self.step.result())
3750 code.putln(
3751 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3752 self.loopvar_name,
3753 self.bound1.result(), offset,
3754 self.loopvar_name, self.relation2, self.bound2.result(),
3755 self.loopvar_name, incop))
3756 if self.py_loopvar_node:
3757 self.py_loopvar_node.generate_evaluation_code(code)
3758 self.target.generate_assignment_code(self.py_loopvar_node, code)
3759 self.body.generate_execution_code(code)
3760 code.put_label(code.continue_label)
3761 code.putln("}")
3762 break_label = code.break_label
3763 code.set_loop_labels(old_loop_labels)
3764 if self.else_clause:
3765 code.putln("/*else*/ {")
3766 self.else_clause.generate_execution_code(code)
3767 code.putln("}")
3768 code.put_label(break_label)
3769 self.bound1.generate_disposal_code(code)
3770 self.bound2.generate_disposal_code(code)
3771 if self.step is not None:
3772 self.step.generate_disposal_code(code)
3774 relation_table = {
3775 # {relop : (initial offset, increment op)}
3776 '<=': ("", "++"),
3777 '<' : ("+1", "++"),
3778 '>=': ("", "--"),
3779 '>' : ("-1", "--")
3780 }
3782 def annotate(self, code):
3783 self.target.annotate(code)
3784 self.bound1.annotate(code)
3785 self.bound2.annotate(code)
3786 if self.step:
3787 self.bound2.annotate(code)
3788 self.body.annotate(code)
3789 if self.else_clause:
3790 self.else_clause.annotate(code)
3793 class WithStatNode(StatNode):
3794 """
3795 Represents a Python with statement.
3797 This is only used at parse tree level; and is not present in
3798 analysis or generation phases.
3799 """
3800 # manager The with statement manager object
3801 # target Node (lhs expression)
3802 # body StatNode
3803 child_attrs = ["manager", "target", "body"]
3805 class TryExceptStatNode(StatNode):
3806 # try .. except statement
3807 #
3808 # body StatNode
3809 # except_clauses [ExceptClauseNode]
3810 # else_clause StatNode or None
3811 # cleanup_list [Entry] temps to clean up on error
3813 child_attrs = ["body", "except_clauses", "else_clause"]
3815 def analyse_control_flow(self, env):
3816 env.start_branching(self.pos)
3817 self.body.analyse_control_flow(env)
3818 successful_try = env.control_flow # grab this for later
3819 env.next_branch(self.body.end_pos())
3820 env.finish_branching(self.body.end_pos())
3822 env.start_branching(self.except_clauses[0].pos)
3823 for except_clause in self.except_clauses:
3824 except_clause.analyse_control_flow(env)
3825 env.next_branch(except_clause.end_pos())
3827 # the else cause it executed only when the try clause finishes
3828 env.control_flow.incoming = successful_try
3829 if self.else_clause:
3830 self.else_clause.analyse_control_flow(env)
3831 env.finish_branching(self.end_pos())
3833 def analyse_declarations(self, env):
3834 self.body.analyse_declarations(env)
3835 for except_clause in self.except_clauses:
3836 except_clause.analyse_declarations(env)
3837 if self.else_clause:
3838 self.else_clause.analyse_declarations(env)
3839 self.gil_check(env)
3840 env.use_utility_code(reset_exception_utility_code)
3842 def analyse_expressions(self, env):
3843 self.body.analyse_expressions(env)
3844 self.cleanup_list = env.free_temp_entries[:]
3845 default_clause_seen = 0
3846 for except_clause in self.except_clauses:
3847 except_clause.analyse_expressions(env)
3848 if default_clause_seen:
3849 error(except_clause.pos, "default 'except:' must be last")
3850 if not except_clause.pattern:
3851 default_clause_seen = 1
3852 self.has_default_clause = default_clause_seen
3853 if self.else_clause:
3854 self.else_clause.analyse_expressions(env)
3855 self.gil_check(env)
3857 gil_message = "Try-except statement"
3859 def generate_execution_code(self, code):
3860 old_return_label = code.return_label
3861 old_error_label = code.new_error_label()
3862 our_error_label = code.error_label
3863 except_end_label = code.new_label('exception_handled')
3864 except_error_label = code.new_label('except_error')
3865 except_return_label = code.new_label('except_return')
3866 try_end_label = code.new_label('try')
3868 code.putln("{")
3869 code.putln("PyObject %s;" %
3870 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
3871 code.putln("__Pyx_ExceptionSave(%s);" %
3872 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
3873 code.putln(
3874 "/*try:*/ {")
3875 self.body.generate_execution_code(code)
3876 code.putln(
3877 "}")
3878 code.error_label = except_error_label
3879 code.return_label = except_return_label
3880 if self.else_clause:
3881 code.putln(
3882 "/*else:*/ {")
3883 self.else_clause.generate_execution_code(code)
3884 code.putln(
3885 "}")
3886 code.put_goto(try_end_label)
3887 code.put_label(our_error_label)
3888 code.put_var_xdecrefs_clear(self.cleanup_list)
3889 for except_clause in self.except_clauses:
3890 except_clause.generate_handling_code(code, except_end_label)
3892 error_label_used = code.label_used(except_error_label)
3893 if error_label_used or not self.has_default_clause:
3894 if error_label_used:
3895 code.put_label(except_error_label)
3896 for var in Naming.exc_save_vars:
3897 code.put_xdecref(var, py_object_type)
3898 code.put_goto(old_error_label)
3900 if code.label_used(except_return_label):
3901 code.put_label(except_return_label)
3902 code.putln("__Pyx_ExceptionReset(%s);" %
3903 ', '.join(Naming.exc_save_vars))
3904 code.put_goto(old_return_label)
3906 if code.label_used(except_end_label):
3907 code.put_label(except_end_label)
3908 code.putln("__Pyx_ExceptionReset(%s);" %
3909 ', '.join(Naming.exc_save_vars))
3910 code.put_label(try_end_label)
3911 code.putln("}")
3913 code.return_label = old_return_label
3914 code.error_label = old_error_label
3916 def annotate(self, code):
3917 self.body.annotate(code)
3918 for except_node in self.except_clauses:
3919 except_node.annotate(code)
3920 if self.else_clause:
3921 self.else_clause.annotate(code)
3924 class ExceptClauseNode(Node):
3925 # Part of try ... except statement.
3926 #
3927 # pattern ExprNode
3928 # target ExprNode or None
3929 # body StatNode
3930 # excinfo_target NameNode or None optional target for exception info
3931 # match_flag string result of exception match
3932 # exc_value ExcValueNode used internally
3933 # function_name string qualified name of enclosing function
3934 # exc_vars (string * 3) local exception variables
3936 # excinfo_target is never set by the parser, but can be set by a transform
3937 # in order to extract more extensive information about the exception as a
3938 # sys.exc_info()-style tuple into a target variable
3940 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
3942 exc_value = None
3943 excinfo_target = None
3945 def analyse_declarations(self, env):
3946 if self.target:
3947 self.target.analyse_target_declaration(env)
3948 if self.excinfo_target is not None:
3949 self.excinfo_target.analyse_target_declaration(env)
3950 self.body.analyse_declarations(env)
3952 def analyse_expressions(self, env):
3953 import ExprNodes
3954 genv = env.global_scope()
3955 self.function_name = env.qualified_name
3956 if self.pattern:
3957 self.pattern.analyse_expressions(env)
3958 self.pattern = self.pattern.coerce_to_pyobject(env)
3959 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
3960 self.pattern.release_temp(env)
3961 env.release_temp(self.match_flag)
3962 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
3963 if self.target:
3964 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
3965 self.exc_value.allocate_temps(env)
3966 self.target.analyse_target_expression(env, self.exc_value)
3967 if self.excinfo_target is not None:
3968 import ExprNodes
3969 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
3970 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
3971 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
3972 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
3973 ])
3974 self.excinfo_tuple.analyse_expressions(env)
3975 self.excinfo_tuple.allocate_temps(env)
3976 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
3978 self.body.analyse_expressions(env)
3979 for var in self.exc_vars:
3980 env.release_temp(var)
3981 env.use_utility_code(get_exception_utility_code)
3982 env.use_utility_code(restore_exception_utility_code)
3984 def generate_handling_code(self, code, end_label):
3985 code.mark_pos(self.pos)
3986 if self.pattern:
3987 self.pattern.generate_evaluation_code(code)
3988 code.putln(
3989 "%s = PyErr_ExceptionMatches(%s);" % (
3990 self.match_flag,
3991 self.pattern.py_result()))
3992 self.pattern.generate_disposal_code(code)
3993 code.putln(
3994 "if (%s) {" %
3995 self.match_flag)
3996 else:
3997 code.putln("/*except:*/ {")
3998 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
3999 # We always have to fetch the exception value even if
4000 # there is no target, because this also normalises the
4001 # exception and stores it in the thread state.
4002 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
4003 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4004 code.error_goto(self.pos)))
4005 if self.target:
4006 self.exc_value.generate_evaluation_code(code)
4007 self.target.generate_assignment_code(self.exc_value, code)
4008 if self.excinfo_target is not None:
4009 self.excinfo_tuple.generate_evaluation_code(code)
4010 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4012 old_exc_vars = code.funcstate.exc_vars
4013 code.funcstate.exc_vars = self.exc_vars
4014 self.body.generate_execution_code(code)
4015 code.funcstate.exc_vars = old_exc_vars
4016 for var in self.exc_vars:
4017 code.putln("Py_DECREF(%s); %s = 0;" % (var, var))
4018 code.put_goto(end_label)
4019 code.putln(
4020 "}")
4022 def annotate(self, code):
4023 if self.pattern:
4024 self.pattern.annotate(code)
4025 if self.target:
4026 self.target.annotate(code)
4027 self.body.annotate(code)
4030 class TryFinallyStatNode(StatNode):
4031 # try ... finally statement
4032 #
4033 # body StatNode
4034 # finally_clause StatNode
4035 #
4036 # cleanup_list [Entry] temps to clean up on error
4037 #
4038 # The plan is that we funnel all continue, break
4039 # return and error gotos into the beginning of the
4040 # finally block, setting a variable to remember which
4041 # one we're doing. At the end of the finally block, we
4042 # switch on the variable to figure out where to go.
4043 # In addition, if we're doing an error, we save the
4044 # exception on entry to the finally block and restore
4045 # it on exit.
4047 child_attrs = ["body", "finally_clause"]
4049 preserve_exception = 1
4051 disallow_continue_in_try_finally = 0
4052 # There doesn't seem to be any point in disallowing
4053 # continue in the try block, since we have no problem
4054 # handling it.
4056 def create_analysed(pos, env, body, finally_clause):
4057 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4058 node.cleanup_list = []
4059 return node
4060 create_analysed = staticmethod(create_analysed)
4062 def analyse_control_flow(self, env):
4063 env.start_branching(self.pos)
4064 self.body.analyse_control_flow(env)
4065 env.next_branch(self.body.end_pos())
4066 env.finish_branching(self.body.end_pos())
4067 self.finally_clause.analyse_control_flow(env)
4069 def analyse_declarations(self, env):
4070 self.body.analyse_declarations(env)
4071 self.finally_clause.analyse_declarations(env)
4073 def analyse_expressions(self, env):
4074 self.body.analyse_expressions(env)
4075 self.cleanup_list = env.free_temp_entries[:]
4076 self.finally_clause.analyse_expressions(env)
4077 self.gil_check(env)
4079 gil_message = "Try-finally statement"
4081 def generate_execution_code(self, code):
4082 old_error_label = code.error_label
4083 old_labels = code.all_new_labels()
4084 new_labels = code.get_all_labels()
4085 new_error_label = code.error_label
4086 catch_label = code.new_label()
4087 code.putln(
4088 "/*try:*/ {")
4089 if self.disallow_continue_in_try_finally:
4090 was_in_try_finally = code.funcstate.in_try_finally
4091 code.funcstate.in_try_finally = 1
4092 self.body.generate_execution_code(code)
4093 if self.disallow_continue_in_try_finally:
4094 code.funcstate.in_try_finally = was_in_try_finally
4095 code.putln(
4096 "}")
4097 code.putln(
4098 "/*finally:*/ {")
4099 cases_used = []
4100 error_label_used = 0
4101 for i, new_label in enumerate(new_labels):
4102 if new_label in code.labels_used:
4103 cases_used.append(i)
4104 if new_label == new_error_label:
4105 error_label_used = 1
4106 error_label_case = i
4107 if cases_used:
4108 code.putln(
4109 "int __pyx_why;")
4110 if error_label_used and self.preserve_exception:
4111 code.putln(
4112 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4113 code.putln(
4114 "int %s;" % Naming.exc_lineno_name)
4115 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4116 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4117 code.putln(exc_var_init_zero)
4118 else:
4119 exc_var_init_zero = None
4120 code.use_label(catch_label)
4121 code.putln(
4122 "__pyx_why = 0; goto %s;" % catch_label)
4123 for i in cases_used:
4124 new_label = new_labels[i]
4125 #if new_label and new_label != "<try>":
4126 if new_label == new_error_label and self.preserve_exception:
4127 self.put_error_catcher(code,
4128 new_error_label, i+1, catch_label)
4129 else:
4130 code.put('%s: ' % new_label)
4131 if exc_var_init_zero:
4132 code.putln(exc_var_init_zero)
4133 code.putln("__pyx_why = %s; goto %s;" % (
4134 i+1,
4135 catch_label))
4136 code.put_label(catch_label)
4137 code.set_all_labels(old_labels)
4138 if error_label_used:
4139 code.new_error_label()
4140 finally_error_label = code.error_label
4141 self.finally_clause.generate_execution_code(code)
4142 if error_label_used:
4143 if finally_error_label in code.labels_used and self.preserve_exception:
4144 over_label = code.new_label()
4145 code.put_goto(over_label);
4146 code.put_label(finally_error_label)
4147 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4148 for var in Naming.exc_vars:
4149 code.putln("Py_XDECREF(%s);" % var)
4150 code.putln("}")
4151 code.put_goto(old_error_label)
4152 code.put_label(over_label)
4153 code.error_label = old_error_label
4154 if cases_used:
4155 code.putln(
4156 "switch (__pyx_why) {")
4157 for i in cases_used:
4158 old_label = old_labels[i]
4159 if old_label == old_error_label and self.preserve_exception:
4160 self.put_error_uncatcher(code, i+1, old_error_label)
4161 else:
4162 code.use_label(old_label)
4163 code.putln(
4164 "case %s: goto %s;" % (
4165 i+1,
4166 old_label))
4167 code.putln(
4168 "}")
4169 code.putln(
4170 "}")
4172 def put_error_catcher(self, code, error_label, i, catch_label):
4173 code.globalstate.use_utility_code(restore_exception_utility_code)
4174 code.putln(
4175 "%s: {" %
4176 error_label)
4177 code.putln(
4178 "__pyx_why = %s;" %
4179 i)
4180 code.put_var_xdecrefs_clear(self.cleanup_list)
4181 code.putln(
4182 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4183 Naming.exc_vars)
4184 code.putln(
4185 "%s = %s;" % (
4186 Naming.exc_lineno_name, Naming.lineno_cname))
4187 #code.putln(
4188 # "goto %s;" %
4189 # catch_label)
4190 code.put_goto(catch_label)
4191 code.putln(
4192 "}")
4194 def put_error_uncatcher(self, code, i, error_label):
4195 code.globalstate.use_utility_code(restore_exception_utility_code)
4196 code.putln(
4197 "case %s: {" %
4198 i)
4199 code.putln(
4200 "__Pyx_ErrRestore(%s, %s, %s);" %
4201 Naming.exc_vars)
4202 code.putln(
4203 "%s = %s;" % (
4204 Naming.lineno_cname, Naming.exc_lineno_name))
4205 for var in Naming.exc_vars:
4206 code.putln(
4207 "%s = 0;" %
4208 var)
4209 code.put_goto(error_label)
4210 code.putln(
4211 "}")
4213 def annotate(self, code):
4214 self.body.annotate(code)
4215 self.finally_clause.annotate(code)
4218 class GILStatNode(TryFinallyStatNode):
4219 # 'with gil' or 'with nogil' statement
4220 #
4221 # state string 'gil' or 'nogil'
4223 child_attrs = []
4225 preserve_exception = 0
4227 def __init__(self, pos, state, body):
4228 self.state = state
4229 TryFinallyStatNode.__init__(self, pos,
4230 body = body,
4231 finally_clause = GILExitNode(pos, state = state))
4233 def analyse_expressions(self, env):
4234 was_nogil = env.nogil
4235 env.nogil = 1
4236 TryFinallyStatNode.analyse_expressions(self, env)
4237 env.nogil = was_nogil
4239 def gil_check(self, env):
4240 pass
4242 def generate_execution_code(self, code):
4243 code.putln("/*with %s:*/ {" % self.state)
4244 if self.state == 'gil':
4245 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
4246 else:
4247 code.putln("PyThreadState *_save;")
4248 code.putln("Py_UNBLOCK_THREADS")
4249 TryFinallyStatNode.generate_execution_code(self, code)
4250 code.putln("}")
4253 class GILExitNode(StatNode):
4254 # Used as the 'finally' block in a GILStatNode
4255 #
4256 # state string 'gil' or 'nogil'
4258 child_attrs = []
4260 def analyse_expressions(self, env):
4261 pass
4263 def generate_execution_code(self, code):
4264 if self.state == 'gil':
4265 code.putln("PyGILState_Release();")
4266 else:
4267 code.putln("Py_BLOCK_THREADS")
4270 class CImportStatNode(StatNode):
4271 # cimport statement
4272 #
4273 # module_name string Qualified name of module being imported
4274 # as_name string or None Name specified in "as" clause, if any
4276 child_attrs = []
4278 def analyse_declarations(self, env):
4279 if not env.is_module_scope:
4280 error(self.pos, "cimport only allowed at module level")
4281 return
4282 module_scope = env.find_module(self.module_name, self.pos)
4283 if "." in self.module_name:
4284 names = [EncodedString(name) for name in self.module_name.split(".")]
4285 top_name = names[0]
4286 top_module_scope = env.context.find_submodule(top_name)
4287 module_scope = top_module_scope
4288 for name in names[1:]:
4289 submodule_scope = module_scope.find_submodule(name)
4290 module_scope.declare_module(name, submodule_scope, self.pos)
4291 module_scope = submodule_scope
4292 if self.as_name:
4293 env.declare_module(self.as_name, module_scope, self.pos)
4294 else:
4295 env.declare_module(top_name, top_module_scope, self.pos)
4296 else:
4297 name = self.as_name or self.module_name
4298 env.declare_module(name, module_scope, self.pos)
4300 def analyse_expressions(self, env):
4301 pass
4303 def generate_execution_code(self, code):
4304 pass
4307 class FromCImportStatNode(StatNode):
4308 # from ... cimport statement
4309 #
4310 # module_name string Qualified name of module
4311 # imported_names [(pos, name, as_name, kind)] Names to be imported
4313 child_attrs = []
4315 def analyse_declarations(self, env):
4316 if not env.is_module_scope:
4317 error(self.pos, "cimport only allowed at module level")
4318 return
4319 module_scope = env.find_module(self.module_name, self.pos)
4320 env.add_imported_module(module_scope)
4321 for pos, name, as_name, kind in self.imported_names:
4322 if name == "*":
4323 for local_name, entry in module_scope.entries.items():
4324 env.add_imported_entry(local_name, entry, pos)
4325 else:
4326 entry = module_scope.lookup(name)
4327 if entry:
4328 if kind and not self.declaration_matches(entry, kind):
4329 entry.redeclared(pos)
4330 else:
4331 if kind == 'struct' or kind == 'union':
4332 entry = module_scope.declare_struct_or_union(name,
4333 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4334 elif kind == 'class':
4335 entry = module_scope.declare_c_class(name, pos = pos,
4336 module_name = self.module_name)
4337 else:
4338 error(pos, "Name '%s' not declared in module '%s'"
4339 % (name, self.module_name))
4341 if entry:
4342 local_name = as_name or name
4343 env.add_imported_entry(local_name, entry, pos)
4345 def declaration_matches(self, entry, kind):
4346 if not entry.is_type:
4347 return 0
4348 type = entry.type
4349 if kind == 'class':
4350 if not type.is_extension_type:
4351 return 0
4352 else:
4353 if not type.is_struct_or_union:
4354 return 0
4355 if kind <> type.kind:
4356 return 0
4357 return 1
4359 def analyse_expressions(self, env):
4360 pass
4362 def generate_execution_code(self, code):
4363 pass
4366 class FromImportStatNode(StatNode):
4367 # from ... import statement
4368 #
4369 # module ImportNode
4370 # items [(string, NameNode)]
4371 # interned_items [(string, NameNode)]
4372 # item PyTempNode used internally
4373 # import_star boolean used internally
4375 child_attrs = ["module"]
4376 import_star = 0
4378 def analyse_declarations(self, env):
4379 for name, target in self.items:
4380 if name == "*":
4381 if not env.is_module_scope:
4382 error(self.pos, "import * only allowed at module level")
4383 return
4384 env.has_import_star = 1
4385 self.import_star = 1
4386 else:
4387 target.analyse_target_declaration(env)
4389 def analyse_expressions(self, env):
4390 import ExprNodes
4391 self.module.analyse_expressions(env)
4392 self.item = ExprNodes.PyTempNode(self.pos, env)
4393 self.item.allocate_temp(env)
4394 self.interned_items = []
4395 for name, target in self.items:
4396 if name == '*':
4397 for _, entry in env.entries.items():
4398 if not entry.is_type and entry.type.is_extension_type:
4399 env.use_utility_code(ExprNodes.type_test_utility_code)
4400 break
4401 else:
4402 self.interned_items.append(
4403 (env.intern_identifier(name), target))
4404 target.analyse_target_expression(env, None)
4405 #target.release_target_temp(env) # was release_temp ?!?
4406 self.module.release_temp(env)
4407 self.item.release_temp(env)
4409 def generate_execution_code(self, code):
4410 self.module.generate_evaluation_code(code)
4411 if self.import_star:
4412 code.putln(
4413 'if (%s(%s) < 0) %s;' % (
4414 Naming.import_star,
4415 self.module.py_result(),
4416 code.error_goto(self.pos)))
4417 for cname, target in self.interned_items:
4418 code.putln(
4419 '%s = PyObject_GetAttr(%s, %s); %s' % (
4420 self.item.result(),
4421 self.module.py_result(),
4422 cname,
4423 code.error_goto_if_null(self.item.result(), self.pos)))
4424 target.generate_assignment_code(self.item, code)
4425 self.module.generate_disposal_code(code)
4429 #------------------------------------------------------------------------------------
4430 #
4431 # Runtime support code
4432 #
4433 #------------------------------------------------------------------------------------
4435 utility_function_predeclarations = \
4436 """
4437 #ifdef __GNUC__
4438 #define INLINE __inline__
4439 #elif _WIN32
4440 #define INLINE __inline
4441 #else
4442 #define INLINE
4443 #endif
4445 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4447 """ + """
4449 static int %(skip_dispatch_cname)s = 0;
4451 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4453 if Options.gcc_branch_hints:
4454 branch_prediction_macros = \
4455 """
4456 #ifdef __GNUC__
4457 /* Test for GCC > 2.95 */
4458 #if __GNUC__ > 2 || \
4459 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4460 #define likely(x) __builtin_expect(!!(x), 1)
4461 #define unlikely(x) __builtin_expect(!!(x), 0)
4462 #else /* __GNUC__ > 2 ... */
4463 #define likely(x) (x)
4464 #define unlikely(x) (x)
4465 #endif /* __GNUC__ > 2 ... */
4466 #else /* __GNUC__ */
4467 #define likely(x) (x)
4468 #define unlikely(x) (x)
4469 #endif /* __GNUC__ */
4470 """
4471 else:
4472 branch_prediction_macros = \
4473 """
4474 #define likely(x) (x)
4475 #define unlikely(x) (x)
4476 """
4478 #get_name_predeclaration = \
4479 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4481 #get_name_interned_predeclaration = \
4482 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4484 #------------------------------------------------------------------------------------
4486 printing_utility_code = UtilityCode(
4487 proto = """
4488 static int __Pyx_Print(PyObject *, int); /*proto*/
4489 #if PY_MAJOR_VERSION >= 3
4490 static PyObject* %s = 0;
4491 static PyObject* %s = 0;
4492 #endif
4493 """ % (Naming.print_function, Naming.print_function_kwargs),
4494 impl = r"""
4495 #if PY_MAJOR_VERSION < 3
4496 static PyObject *__Pyx_GetStdout(void) {
4497 PyObject *f = PySys_GetObject((char *)"stdout");
4498 if (!f) {
4499 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4500 }
4501 return f;
4502 }
4504 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4505 PyObject *f;
4506 PyObject* v;
4507 int i;
4509 if (!(f = __Pyx_GetStdout()))
4510 return -1;
4511 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4512 if (PyFile_SoftSpace(f, 1)) {
4513 if (PyFile_WriteString(" ", f) < 0)
4514 return -1;
4515 }
4516 v = PyTuple_GET_ITEM(arg_tuple, i);
4517 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4518 return -1;
4519 if (PyString_Check(v)) {
4520 char *s = PyString_AsString(v);
4521 Py_ssize_t len = PyString_Size(v);
4522 if (len > 0 &&
4523 isspace(Py_CHARMASK(s[len-1])) &&
4524 s[len-1] != ' ')
4525 PyFile_SoftSpace(f, 0);
4526 }
4527 }
4528 if (newline) {
4529 if (PyFile_WriteString("\n", f) < 0)
4530 return -1;
4531 PyFile_SoftSpace(f, 0);
4532 }
4533 return 0;
4534 }
4536 #else /* Python 3 has a print function */
4537 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4538 PyObject* kwargs = 0;
4539 PyObject* result = 0;
4540 PyObject* end_string;
4541 if (!%(PRINT_FUNCTION)s) {
4542 %(PRINT_FUNCTION)s = PyObject_GetAttrString(%(BUILTINS)s, "print");
4543 if (!%(PRINT_FUNCTION)s)
4544 return -1;
4545 }
4546 if (!newline) {
4547 if (!%(PRINT_KWARGS)s) {
4548 %(PRINT_KWARGS)s = PyDict_New();
4549 if (!%(PRINT_KWARGS)s)
4550 return -1;
4551 end_string = PyUnicode_FromStringAndSize(" ", 1);
4552 if (!end_string)
4553 return -1;
4554 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4555 Py_DECREF(end_string);
4556 return -1;
4557 }
4558 Py_DECREF(end_string);
4559 }
4560 kwargs = %(PRINT_KWARGS)s;
4561 }
4562 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4563 if (!result)
4564 return -1;
4565 Py_DECREF(result);
4566 return 0;
4567 }
4568 #endif
4569 """ % {'BUILTINS' : Naming.builtins_cname,
4570 'PRINT_FUNCTION' : Naming.print_function,
4571 'PRINT_KWARGS' : Naming.print_function_kwargs}
4572 )
4574 #------------------------------------------------------------------------------------
4576 # The following function is based on do_raise() from ceval.c.
4578 raise_utility_code = UtilityCode(
4579 proto = """
4580 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4581 """,
4582 impl = """
4583 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4584 Py_XINCREF(type);
4585 Py_XINCREF(value);
4586 Py_XINCREF(tb);
4587 /* First, check the traceback argument, replacing None with NULL. */
4588 if (tb == Py_None) {
4589 Py_DECREF(tb);
4590 tb = 0;
4591 }
4592 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4593 PyErr_SetString(PyExc_TypeError,
4594 "raise: arg 3 must be a traceback or None");
4595 goto raise_error;
4596 }
4597 /* Next, replace a missing value with None */
4598 if (value == NULL) {
4599 value = Py_None;
4600 Py_INCREF(value);
4601 }
4602 #if PY_VERSION_HEX < 0x02050000
4603 if (!PyClass_Check(type))
4604 #else
4605 if (!PyType_Check(type))
4606 #endif
4607 {
4608 /* Raising an instance. The value should be a dummy. */
4609 if (value != Py_None) {
4610 PyErr_SetString(PyExc_TypeError,
4611 "instance exception may not have a separate value");
4612 goto raise_error;
4613 }
4614 /* Normalize to raise <class>, <instance> */
4615 Py_DECREF(value);
4616 value = type;
4617 #if PY_VERSION_HEX < 0x02050000
4618 if (PyInstance_Check(type)) {
4619 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4620 Py_INCREF(type);
4621 }
4622 else {
4623 type = 0;
4624 PyErr_SetString(PyExc_TypeError,
4625 "raise: exception must be an old-style class or instance");
4626 goto raise_error;
4627 }
4628 #else
4629 type = (PyObject*) Py_TYPE(type);
4630 Py_INCREF(type);
4631 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4632 PyErr_SetString(PyExc_TypeError,
4633 "raise: exception class must be a subclass of BaseException");
4634 goto raise_error;
4635 }
4636 #endif
4637 }
4638 __Pyx_ErrRestore(type, value, tb);
4639 return;
4640 raise_error:
4641 Py_XDECREF(value);
4642 Py_XDECREF(type);
4643 Py_XDECREF(tb);
4644 return;
4645 }
4646 """)
4648 #------------------------------------------------------------------------------------
4650 reraise_utility_code = UtilityCode(
4651 proto = """
4652 static void __Pyx_ReRaise(void); /*proto*/
4653 """,
4654 impl = """
4655 static void __Pyx_ReRaise(void) {
4656 PyThreadState *tstate = PyThreadState_Get();
4657 PyObject *type = tstate->exc_type;
4658 PyObject *value = tstate->exc_value;
4659 PyObject *tb = tstate->exc_traceback;
4660 Py_XINCREF(type);
4661 Py_XINCREF(value);
4662 Py_XINCREF(tb);
4663 __Pyx_ErrRestore(type, value, tb);
4664 }
4665 """)
4667 #------------------------------------------------------------------------------------
4669 arg_type_test_utility_code = UtilityCode(
4670 proto = """
4671 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4672 const char *name, int exact); /*proto*/
4673 """,
4674 impl = """
4675 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4676 const char *name, int exact)
4677 {
4678 if (!type) {
4679 PyErr_Format(PyExc_SystemError, "Missing type object");
4680 return 0;
4681 }
4682 if (none_allowed && obj == Py_None) return 1;
4683 else if (exact) {
4684 if (Py_TYPE(obj) == type) return 1;
4685 }
4686 else {
4687 if (PyObject_TypeCheck(obj, type)) return 1;
4688 }
4689 PyErr_Format(PyExc_TypeError,
4690 "Argument '%s' has incorrect type (expected %s, got %s)",
4691 name, type->tp_name, Py_TYPE(obj)->tp_name);
4692 return 0;
4693 }
4694 """)
4696 #------------------------------------------------------------------------------------
4697 #
4698 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
4699 # many or too few positional arguments were found. This handles
4700 # Py_ssize_t formatting correctly.
4702 raise_argtuple_invalid_utility_code = UtilityCode(
4703 proto = """
4704 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
4705 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
4706 """,
4707 impl = """
4708 static void __Pyx_RaiseArgtupleInvalid(
4709 const char* func_name,
4710 int exact,
4711 Py_ssize_t num_min,
4712 Py_ssize_t num_max,
4713 Py_ssize_t num_found)
4714 {
4715 Py_ssize_t num_expected;
4716 const char *number, *more_or_less;
4718 if (num_found < num_min) {
4719 num_expected = num_min;
4720 more_or_less = "at least";
4721 } else {
4722 num_expected = num_max;
4723 more_or_less = "at most";
4724 }
4725 if (exact) {
4726 more_or_less = "exactly";
4727 }
4728 number = (num_expected == 1) ? "" : "s";
4729 PyErr_Format(PyExc_TypeError,
4730 #if PY_VERSION_HEX < 0x02050000
4731 "%s() takes %s %d positional argument%s (%d given)",
4732 #else
4733 "%s() takes %s %zd positional argument%s (%zd given)",
4734 #endif
4735 func_name, more_or_less, num_expected, number, num_found);
4736 }
4737 """)
4739 raise_keyword_required_utility_code = UtilityCode(
4740 proto = """
4741 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
4742 """,
4743 impl = """
4744 static INLINE void __Pyx_RaiseKeywordRequired(
4745 const char* func_name,
4746 PyObject* kw_name)
4747 {
4748 PyErr_Format(PyExc_TypeError,
4749 #if PY_MAJOR_VERSION >= 3
4750 "%s() needs keyword-only argument %U", func_name, kw_name);
4751 #else
4752 "%s() needs keyword-only argument %s", func_name,
4753 PyString_AS_STRING(kw_name));
4754 #endif
4755 }
4756 """)
4758 raise_double_keywords_utility_code = UtilityCode(
4759 proto = """
4760 static void __Pyx_RaiseDoubleKeywordsError(
4761 const char* func_name, PyObject* kw_name); /*proto*/
4762 """,
4763 impl = """
4764 static void __Pyx_RaiseDoubleKeywordsError(
4765 const char* func_name,
4766 PyObject* kw_name)
4767 {
4768 PyErr_Format(PyExc_TypeError,
4769 #if PY_MAJOR_VERSION >= 3
4770 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
4771 #else
4772 "%s() got multiple values for keyword argument '%s'", func_name,
4773 PyString_AS_STRING(kw_name));
4774 #endif
4775 }
4776 """)
4778 #------------------------------------------------------------------------------------
4779 #
4780 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
4781 # were passed to a function, or if any keywords were passed to a
4782 # function that does not accept them.
4784 keyword_string_check_utility_code = UtilityCode(
4785 proto = """
4786 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
4787 const char* function_name, int kw_allowed); /*proto*/
4788 """,
4789 impl = """
4790 static INLINE int __Pyx_CheckKeywordStrings(
4791 PyObject *kwdict,
4792 const char* function_name,
4793 int kw_allowed)
4794 {
4795 PyObject* key = 0;
4796 Py_ssize_t pos = 0;
4797 while (PyDict_Next(kwdict, &pos, &key, 0)) {
4798 #if PY_MAJOR_VERSION < 3
4799 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
4800 #else
4801 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
4802 #endif
4803 goto invalid_keyword_type;
4804 }
4805 if ((!kw_allowed) && unlikely(key))
4806 goto invalid_keyword;
4807 return 1;
4808 invalid_keyword_type:
4809 PyErr_Format(PyExc_TypeError,
4810 "%s() keywords must be strings", function_name);
4811 return 0;
4812 invalid_keyword:
4813 PyErr_Format(PyExc_TypeError,
4814 #if PY_MAJOR_VERSION < 3
4815 "%s() got an unexpected keyword argument '%s'",
4816 function_name, PyString_AsString(key));
4817 #else
4818 "%s() got an unexpected keyword argument '%U'",
4819 function_name, key);
4820 #endif
4821 return 0;
4822 }
4823 """)
4825 #------------------------------------------------------------------------------------
4826 #
4827 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
4828 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
4829 # keywords will raise an invalid keyword error.
4830 #
4831 # Three kinds of errors are checked: 1) non-string keywords, 2)
4832 # unexpected keywords and 3) overlap with positional arguments.
4833 #
4834 # If num_posargs is greater 0, it denotes the number of positional
4835 # arguments that were passed and that must therefore not appear
4836 # amongst the keywords as well.
4837 #
4838 # This method does not check for required keyword arguments.
4839 #
4841 parse_keywords_utility_code = UtilityCode(
4842 proto = """
4843 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
4844 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
4845 const char* function_name); /*proto*/
4846 """,
4847 impl = """
4848 static int __Pyx_ParseOptionalKeywords(
4849 PyObject *kwds,
4850 PyObject **argnames[],
4851 PyObject *kwds2,
4852 PyObject *values[],
4853 Py_ssize_t num_pos_args,
4854 const char* function_name)
4855 {
4856 PyObject *key = 0, *value = 0;
4857 Py_ssize_t pos = 0;
4858 PyObject*** name;
4859 PyObject*** first_kw_arg = argnames + num_pos_args;
4861 while (PyDict_Next(kwds, &pos, &key, &value)) {
4862 #if PY_MAJOR_VERSION < 3
4863 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
4864 #else
4865 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
4866 #endif
4867 goto invalid_keyword_type;
4868 } else {
4869 name = argnames;
4870 while (*name && (**name != key)) name++;
4871 if (*name) {
4872 if (name < first_kw_arg) goto arg_passed_twice;
4873 values[name-argnames] = value;
4874 } else {
4875 for (name = first_kw_arg; *name; name++) {
4876 #if PY_MAJOR_VERSION >= 3
4877 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
4878 PyUnicode_Compare(**name, key) == 0) break;
4879 #else
4880 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
4881 strcmp(PyString_AS_STRING(**name),
4882 PyString_AS_STRING(key)) == 0) break;
4883 #endif
4884 }
4885 if (*name) {
4886 values[name-argnames] = value;
4887 } else {
4888 /* unexpected keyword found */
4889 for (name=argnames; name != first_kw_arg; name++) {
4890 if (**name == key) goto arg_passed_twice;
4891 #if PY_MAJOR_VERSION >= 3
4892 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
4893 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
4894 #else
4895 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
4896 strcmp(PyString_AS_STRING(**name),
4897 PyString_AS_STRING(key)) == 0) goto arg_passed_twice;
4898 #endif
4899 }
4900 if (kwds2) {
4901 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
4902 } else {
4903 goto invalid_keyword;
4904 }
4905 }
4906 }
4907 }
4908 }
4909 return 0;
4910 arg_passed_twice:
4911 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
4912 goto bad;
4913 invalid_keyword_type:
4914 PyErr_Format(PyExc_TypeError,
4915 "%s() keywords must be strings", function_name);
4916 goto bad;
4917 invalid_keyword:
4918 PyErr_Format(PyExc_TypeError,
4919 #if PY_MAJOR_VERSION < 3
4920 "%s() got an unexpected keyword argument '%s'",
4921 function_name, PyString_AsString(key));
4922 #else
4923 "%s() got an unexpected keyword argument '%U'",
4924 function_name, key);
4925 #endif
4926 bad:
4927 return -1;
4928 }
4929 """)
4931 #------------------------------------------------------------------------------------
4933 unraisable_exception_utility_code = UtilityCode(
4934 proto = """
4935 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
4936 """,
4937 impl = """
4938 static void __Pyx_WriteUnraisable(const char *name) {
4939 PyObject *old_exc, *old_val, *old_tb;
4940 PyObject *ctx;
4941 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
4942 #if PY_MAJOR_VERSION < 3
4943 ctx = PyString_FromString(name);
4944 #else
4945 ctx = PyUnicode_FromString(name);
4946 #endif
4947 __Pyx_ErrRestore(old_exc, old_val, old_tb);
4948 if (!ctx) {
4949 PyErr_WriteUnraisable(Py_None);
4950 } else {
4951 PyErr_WriteUnraisable(ctx);
4952 Py_DECREF(ctx);
4953 }
4954 }
4955 """)
4957 #------------------------------------------------------------------------------------
4959 traceback_utility_code = UtilityCode(
4960 proto = """
4961 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
4962 """,
4963 impl = """
4964 #include "compile.h"
4965 #include "frameobject.h"
4966 #include "traceback.h"
4968 static void __Pyx_AddTraceback(const char *funcname) {
4969 PyObject *py_srcfile = 0;
4970 PyObject *py_funcname = 0;
4971 PyObject *py_globals = 0;
4972 PyObject *empty_string = 0;
4973 PyCodeObject *py_code = 0;
4974 PyFrameObject *py_frame = 0;
4976 #if PY_MAJOR_VERSION < 3
4977 py_srcfile = PyString_FromString(%(FILENAME)s);
4978 #else
4979 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
4980 #endif
4981 if (!py_srcfile) goto bad;
4982 if (%(CLINENO)s) {
4983 #if PY_MAJOR_VERSION < 3
4984 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
4985 #else
4986 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
4987 #endif
4988 }
4989 else {
4990 #if PY_MAJOR_VERSION < 3
4991 py_funcname = PyString_FromString(funcname);
4992 #else
4993 py_funcname = PyUnicode_FromString(funcname);
4994 #endif
4995 }
4996 if (!py_funcname) goto bad;
4997 py_globals = PyModule_GetDict(%(GLOBALS)s);
4998 if (!py_globals) goto bad;
4999 #if PY_MAJOR_VERSION < 3
5000 empty_string = PyString_FromStringAndSize("", 0);
5001 #else
5002 empty_string = PyBytes_FromStringAndSize("", 0);
5003 #endif
5004 if (!empty_string) goto bad;
5005 py_code = PyCode_New(
5006 0, /*int argcount,*/
5007 #if PY_MAJOR_VERSION >= 3
5008 0, /*int kwonlyargcount,*/
5009 #endif
5010 0, /*int nlocals,*/
5011 0, /*int stacksize,*/
5012 0, /*int flags,*/
5013 empty_string, /*PyObject *code,*/
5014 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5015 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5016 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5017 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5018 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5019 py_srcfile, /*PyObject *filename,*/
5020 py_funcname, /*PyObject *name,*/
5021 %(LINENO)s, /*int firstlineno,*/
5022 empty_string /*PyObject *lnotab*/
5023 );
5024 if (!py_code) goto bad;
5025 py_frame = PyFrame_New(
5026 PyThreadState_GET(), /*PyThreadState *tstate,*/
5027 py_code, /*PyCodeObject *code,*/
5028 py_globals, /*PyObject *globals,*/
5029 0 /*PyObject *locals*/
5030 );
5031 if (!py_frame) goto bad;
5032 py_frame->f_lineno = %(LINENO)s;
5033 PyTraceBack_Here(py_frame);
5034 bad:
5035 Py_XDECREF(py_srcfile);
5036 Py_XDECREF(py_funcname);
5037 Py_XDECREF(empty_string);
5038 Py_XDECREF(py_code);
5039 Py_XDECREF(py_frame);
5040 }
5041 """ % {
5042 'FILENAME': Naming.filename_cname,
5043 'LINENO': Naming.lineno_cname,
5044 'CFILENAME': Naming.cfilenm_cname,
5045 'CLINENO': Naming.clineno_cname,
5046 'GLOBALS': Naming.module_cname,
5047 'EMPTY_TUPLE' : Naming.empty_tuple,
5048 })
5050 restore_exception_utility_code = UtilityCode(
5051 proto = """
5052 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5053 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5054 """,
5055 impl = """
5056 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5057 PyObject *tmp_type, *tmp_value, *tmp_tb;
5058 PyThreadState *tstate = PyThreadState_GET();
5060 tmp_type = tstate->curexc_type;
5061 tmp_value = tstate->curexc_value;
5062 tmp_tb = tstate->curexc_traceback;
5063 tstate->curexc_type = type;
5064 tstate->curexc_value = value;
5065 tstate->curexc_traceback = tb;
5066 Py_XDECREF(tmp_type);
5067 Py_XDECREF(tmp_value);
5068 Py_XDECREF(tmp_tb);
5069 }
5071 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5072 PyThreadState *tstate = PyThreadState_GET();
5073 *type = tstate->curexc_type;
5074 *value = tstate->curexc_value;
5075 *tb = tstate->curexc_traceback;
5077 tstate->curexc_type = 0;
5078 tstate->curexc_value = 0;
5079 tstate->curexc_traceback = 0;
5080 }
5082 """)
5084 #------------------------------------------------------------------------------------
5086 set_vtable_utility_code = UtilityCode(
5087 proto = """
5088 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5089 """,
5090 impl = """
5091 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5092 PyObject *pycobj = 0;
5093 int result;
5095 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5096 if (!pycobj)
5097 goto bad;
5098 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5099 goto bad;
5100 result = 0;
5101 goto done;
5103 bad:
5104 result = -1;
5105 done:
5106 Py_XDECREF(pycobj);
5107 return result;
5108 }
5109 """)
5111 #------------------------------------------------------------------------------------
5113 get_vtable_utility_code = UtilityCode(
5114 proto = """
5115 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5116 """,
5117 impl = r"""
5118 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5119 int result;
5120 PyObject *pycobj;
5122 pycobj = PyMapping_GetItemString(dict, "__pyx_vtable__");
5123 if (!pycobj)
5124 goto bad;
5125 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5126 if (!*(void **)vtabptr)
5127 goto bad;
5128 result = 0;
5129 goto done;
5131 bad:
5132 result = -1;
5133 done:
5134 Py_XDECREF(pycobj);
5135 return result;
5136 }
5137 """)
5139 #------------------------------------------------------------------------------------
5141 init_string_tab_utility_code = UtilityCode(
5142 proto = """
5143 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5144 """,
5145 impl = """
5146 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5147 while (t->p) {
5148 #if PY_MAJOR_VERSION < 3
5149 if (t->is_unicode && (!t->is_identifier)) {
5150 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5151 } else if (t->intern) {
5152 *t->p = PyString_InternFromString(t->s);
5153 } else {
5154 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5155 }
5156 #else /* Python 3+ has unicode identifiers */
5157 if (t->is_identifier || (t->is_unicode && t->intern)) {
5158 *t->p = PyUnicode_InternFromString(t->s);
5159 } else if (t->is_unicode) {
5160 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5161 } else {
5162 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5163 }
5164 #endif
5165 if (!*t->p)
5166 return -1;
5167 ++t;
5168 }
5169 return 0;
5170 }
5171 """)
5173 #------------------------------------------------------------------------------------
5175 get_exception_utility_code = UtilityCode(
5176 proto = """
5177 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5178 """,
5179 impl = """
5180 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5181 PyObject *tmp_type, *tmp_value, *tmp_tb;
5182 PyThreadState *tstate = PyThreadState_GET();
5183 __Pyx_ErrFetch(type, value, tb);
5184 PyErr_NormalizeException(type, value, tb);
5185 if (PyErr_Occurred())
5186 goto bad;
5187 Py_INCREF(*type);
5188 Py_INCREF(*value);
5189 Py_INCREF(*tb);
5190 tmp_type = tstate->exc_type;
5191 tmp_value = tstate->exc_value;
5192 tmp_tb = tstate->exc_traceback;
5193 tstate->exc_type = *type;
5194 tstate->exc_value = *value;
5195 tstate->exc_traceback = *tb;
5196 /* Make sure tstate is in a consistent state when we XDECREF
5197 these objects (XDECREF may run arbitrary code). */
5198 Py_XDECREF(tmp_type);
5199 Py_XDECREF(tmp_value);
5200 Py_XDECREF(tmp_tb);
5201 return 0;
5202 bad:
5203 Py_XDECREF(*type);
5204 Py_XDECREF(*value);
5205 Py_XDECREF(*tb);
5206 return -1;
5207 }
5209 """)
5211 #------------------------------------------------------------------------------------
5213 reset_exception_utility_code = UtilityCode(
5214 proto = """
5215 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5216 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5217 """,
5218 impl = """
5219 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5220 PyThreadState *tstate = PyThreadState_GET();
5221 *type = tstate->exc_type;
5222 *value = tstate->exc_value;
5223 *tb = tstate->exc_traceback;
5224 Py_XINCREF(*type);
5225 Py_XINCREF(*value);
5226 Py_XINCREF(*tb);
5227 }
5229 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5230 PyObject *tmp_type, *tmp_value, *tmp_tb;
5231 PyThreadState *tstate = PyThreadState_GET();
5232 tmp_type = tstate->exc_type;
5233 tmp_value = tstate->exc_value;
5234 tmp_tb = tstate->exc_traceback;
5235 tstate->exc_type = type;
5236 tstate->exc_value = value;
5237 tstate->exc_traceback = tb;
5238 Py_XDECREF(tmp_type);
5239 Py_XDECREF(tmp_value);
5240 Py_XDECREF(tmp_tb);
5241 }
5242 """)
5244 #------------------------------------------------------------------------------------
