Nodes.py 215 KB
Newer Older
William Stein's avatar
William Stein committed
1 2 3 4
#
#   Pyrex - Parse tree nodes
#

5
import sys, os, time, copy
William Stein's avatar
William Stein committed
6 7

import Code
8
import Builtin
9
from Errors import error, warning, InternalError
William Stein's avatar
William Stein committed
10 11
import Naming
import PyrexTypes
12
import TypeSlots
13
from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType
14
from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
William Stein's avatar
William Stein committed
15
    StructOrUnionScope, PyClassScope, CClassScope
16
from Cython.Utils import open_new_file, replace_suffix, UtilityCode
17
from StringEncoding import EncodedString, escape_byte_string, split_docstring
William Stein's avatar
William Stein committed
18
import Options
19
import ControlFlow
20
import DebugFlags
William Stein's avatar
William Stein committed
21

Gary Furnish's avatar
Gary Furnish committed
22
absolute_path_length = 0
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

def relative_position(pos):
    """
    We embed the relative filename in the generated C file, since we
    don't want to have to regnerate and compile all the source code
    whenever the Python install directory moves (which could happen,
    e.g,. when distributing binaries.)
    
    INPUT:
        a position tuple -- (absolute filename, line number column position)

    OUTPUT:
        relative filename
        line number

    AUTHOR: William Stein
    """
Gary Furnish's avatar
Gary Furnish committed
40 41 42
    global absolute_path_length
    if absolute_path_length==0:
        absolute_path_length = len(os.path.abspath(os.getcwd())) 
43
    return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
44 45 46 47

def embed_position(pos, docstring):
    if not Options.embed_pos_in_docstring:
        return docstring
48
    pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
49 50
    if docstring is None:
        # unicode string
51
        return EncodedString(pos_line)
52 53 54 55 56 57 58 59 60 61 62 63

    # make sure we can encode the filename in the docstring encoding
    # otherwise make the docstring a unicode string
    encoding = docstring.encoding
    if encoding is not None:
        try:
            encoded_bytes = pos_line.encode(encoding)
        except UnicodeEncodeError:
            encoding = None

    if not docstring:
        # reuse the string encoding of the original docstring
64
        doc = EncodedString(pos_line)
65
    else:
66
        doc = EncodedString(pos_line + u'\n' + docstring)
67 68
    doc.encoding = encoding
    return doc
69

70 71 72 73 74 75 76

from Code import CCodeWriter
from types import FunctionType

def write_func_call(func):
    def f(*args, **kwds):
        if len(args) > 1 and isinstance(args[1], CCodeWriter):
Robert Bradshaw's avatar
Robert Bradshaw committed
77 78
            # here we annotate the code with this function call
            # but only if new code is generated
79
            node, code = args[:2]
Robert Bradshaw's avatar
Robert Bradshaw committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
            marker = '                    /* %s -> %s.%s %s */' % (
                    ' ' * code.call_level,
                    node.__class__.__name__, 
                    func.__name__, 
                    node.pos[1:])
            pristine = code.buffer.stream.tell()
            code.putln(marker)
            start = code.buffer.stream.tell()
            code.call_level += 4
            res = func(*args, **kwds)
            code.call_level -= 4
            if start == code.buffer.stream.tell():
                code.buffer.stream.seek(pristine)
            else:
                marker = marker.replace('->', '<-')
                code.putln(marker)
            return res
        else:
            return func(*args, **kwds)
99 100 101 102
    return f

class VerboseCodeWriter(type):
    # Set this as a metaclass to trace function calls in code.
Robert Bradshaw's avatar
Robert Bradshaw committed
103
    # This slows down code generation and makes much larger files. 
104 105 106 107 108 109 110 111
    def __new__(cls, name, bases, attrs):
        attrs = dict(attrs)
        for mname, m in attrs.items():
            if isinstance(m, FunctionType):
                attrs[mname] = write_func_call(m)
        return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)


Stefan Behnel's avatar
Stefan Behnel committed
112
class Node(object):
William Stein's avatar
William Stein committed
113 114 115
    #  pos         (string, int, int)   Source file position
    #  is_name     boolean              Is a NameNode
    #  is_literal  boolean              Is a ConstNode
116

117 118
    if DebugFlags.debug_trace_code_generation:
        __metaclass__ = VerboseCodeWriter
119
    
William Stein's avatar
William Stein committed
120 121
    is_name = 0
    is_literal = 0
122
    temps = None
123

124 125 126
    # All descandants should set child_attrs to a list of the attributes
    # containing nodes considered "children" in the tree. Each such attribute
    # can either contain a single node or a list of nodes. See Visitor.py.
127
    child_attrs = None
William Stein's avatar
William Stein committed
128 129 130 131 132
    
    def __init__(self, pos, **kw):
        self.pos = pos
        self.__dict__.update(kw)
    
133 134 135 136 137 138 139 140 141
    gil_message = "Operation"

    def gil_check(self, env):
        if env.nogil:
            self.gil_error()

    def gil_error(self):
        error(self.pos, "%s not allowed without gil" % self.gil_message)

142 143 144 145 146 147
    def clone_node(self):
        """Clone the node. This is defined as a shallow copy, except for member lists
           amongst the child attributes (from get_child_accessors) which are also
           copied. Lists containing child nodes are thus seen as a way for the node
           to hold multiple children directly; the list is not treated as a seperate
           level in the tree."""
148 149 150
        result = copy.copy(self)
        for attrname in result.child_attrs:
            value = getattr(result, attrname)
151
            if isinstance(value, list):
152
                setattr(result, attrname, [x for x in value])
153
        return result
154
    
155
    
William Stein's avatar
William Stein committed
156
    #
157
    #  There are 4 phases of parse tree processing, applied in order to
William Stein's avatar
William Stein committed
158 159
    #  all the statements in a given scope-block:
    #
160 161 162 163
    #  (0) analyse_control_flow
    #        Create the control flow tree into which state can be asserted and
    #        queried.
    #
William Stein's avatar
William Stein committed
164 165 166 167 168
    #  (1) analyse_declarations
    #        Make symbol table entries for all declarations at the current
    #        level, both explicit (def, cdef, etc.) and implicit (assignment
    #        to an otherwise undeclared name).
    #
169
    #  (2) analyse_expressions
William Stein's avatar
William Stein committed
170 171 172 173 174 175 176
    #         Determine the result types of expressions and fill in the
    #         'type' attribute of each ExprNode. Insert coercion nodes into the
    #         tree where needed to convert to and from Python objects. 
    #         Allocate temporary locals for intermediate results. Fill
    #         in the 'result_code' attribute of each ExprNode with a C code
    #         fragment.
    #
177
    #  (3) generate_code
William Stein's avatar
William Stein committed
178 179 180 181 182
    #         Emit C code for all declarations, statements and expressions.
    #         Recursively applies the 3 processing phases to the bodies of
    #         functions.
    #
    
183 184 185
    def analyse_control_flow(self, env):
        pass
    
William Stein's avatar
William Stein committed
186 187 188 189 190 191 192 193 194 195
    def analyse_declarations(self, env):
        pass
    
    def analyse_expressions(self, env):
        raise InternalError("analyse_expressions not implemented for %s" % \
            self.__class__.__name__)
    
    def generate_code(self, code):
        raise InternalError("generate_code not implemented for %s" % \
            self.__class__.__name__)
196 197 198 199 200
            
    def annotate(self, code):
        # mro does the wrong thing
        if isinstance(self, BlockNode):
            self.body.annotate(code)
201 202 203 204 205
            
    def end_pos(self):
        try:
            return self._end_pos
        except AttributeError:
Stefan Behnel's avatar
Stefan Behnel committed
206
            pos = self.pos
207 208 209
            if not self.child_attrs:
                self._end_pos = pos
                return pos
210
            for attr in self.child_attrs:
211
                child = getattr(self, attr)
212
                # Sometimes lists, sometimes nodes
213 214 215
                if child is None:
                    pass
                elif isinstance(child, list):
Stefan Behnel's avatar
Stefan Behnel committed
216 217
                    for c in child:
                        pos = max(pos, c.end_pos())
218
                else:
Stefan Behnel's avatar
Stefan Behnel committed
219 220 221
                    pos = max(pos, child.end_pos())
            self._end_pos = pos
            return pos
William Stein's avatar
William Stein committed
222

223
    def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
224 225
        if cutoff == 0:
            return "<...nesting level cutoff...>"
226 227 228 229 230
        if encountered is None:
            encountered = set()
        if id(self) in encountered:
            return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
        encountered.add(id(self))
231
        
232 233
        def dump_child(x, level):
            if isinstance(x, Node):
234
                return x.dump(level, filter_out, cutoff-1, encountered)
235
            elif isinstance(x, list):
Robert Bradshaw's avatar
Robert Bradshaw committed
236
                return "[%s]" % ", ".join([dump_child(item, level) for item in x])
237 238 239 240 241 242
            else:
                return repr(x)
            
        
        attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
        if len(attrs) == 0:
243
            return "<%s (%d)>" % (self.__class__.__name__, id(self))
244 245
        else:
            indent = "  " * level
246
            res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
247 248 249 250
            for key, value in attrs:
                res += "%s  %s: %s\n" % (indent, key, dump_child(value, level + 1))
            res += "%s>" % indent
            return res
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297

class CompilerDirectivesNode(Node):
    """
    Sets compiler directives for the children nodes
    """
    #  directives     {string:value}  A dictionary holding the right value for
    #                                 *all* possible directives.
    #  body           Node
    child_attrs = ["body"]

    def analyse_control_flow(self, env):
        old = env.directives
        env.directives = self.directives
        self.body.analyse_control_flow(env)
        env.directives = old

    def analyse_declarations(self, env):
        old = env.directives
        env.directives = self.directives
        self.body.analyse_declarations(env)
        env.directives = old
    
    def analyse_expressions(self, env):
        old = env.directives
        env.directives = self.directives
        self.body.analyse_expressions(env)
        env.directives = old

    def generate_function_definitions(self, env, code):
        env_old = env.directives
        code_old = code.globalstate.directives
        code.globalstate.directives = self.directives
        self.body.generate_function_definitions(env, code)
        env.directives = env_old
        code.globalstate.directives = code_old
            
    def generate_execution_code(self, code):
        old = code.globalstate.directives
        code.globalstate.directives = self.directives
        self.body.generate_execution_code(code)
        code.globalstate.directives = old
            
    def annotate(self, code):
        old = code.globalstate.directives
        code.globalstate.directives = self.directives
        self.body.annotate(code)
        code.globalstate.directives = old
298
        
Stefan Behnel's avatar
Stefan Behnel committed
299
class BlockNode(object):
William Stein's avatar
William Stein committed
300 301 302 303 304 305
    #  Mixin class for nodes representing a declaration block.

    def generate_const_definitions(self, env, code):
        if env.const_entries:
            for entry in env.const_entries:
                if not entry.is_interned:
306
                    code.globalstate.add_const_definition(entry)
307 308 309 310 311

    def generate_interned_string_decls(self, env, code):
        entries = env.global_scope().new_interned_string_entries
        if entries:
            for entry in entries:
312
                code.globalstate.add_interned_string_decl(entry)
313 314
            del entries[:]

William Stein's avatar
William Stein committed
315
    def generate_py_string_decls(self, env, code):
316 317
        if env is None:
            return # earlier error
William Stein's avatar
William Stein committed
318 319 320
        entries = env.pystring_entries
        if entries:
            for entry in entries:
321
                if not entry.is_interned:
322
                    code.globalstate.add_py_string_decl(entry)
323

324 325 326 327 328 329 330
    def generate_interned_num_decls(self, env, code):
        #  Flush accumulated interned nums from the global scope
        #  and generate declarations for them.
        genv = env.global_scope()
        entries = genv.interned_nums
        if entries:
            for entry in entries:
331
                code.globalstate.add_interned_num_decl(entry)
332
            del entries[:]
William Stein's avatar
William Stein committed
333

334
    def generate_cached_builtins_decls(self, env, code):
335
        entries = env.global_scope().undeclared_cached_builtins
336
        for entry in entries:
337
            code.globalstate.add_cached_builtin_decl(entry)
338
        del entries[:]
339
        
William Stein's avatar
William Stein committed
340 341 342 343

class StatListNode(Node):
    # stats     a list of StatNode
    
344
    child_attrs = ["stats"]
345 346 347 348 349

    def create_analysed(pos, env, *args, **kw):
        node = StatListNode(pos, *args, **kw)
        return node # No node-specific analysis necesarry
    create_analysed = staticmethod(create_analysed)
350
    
351 352 353 354
    def analyse_control_flow(self, env):
        for stat in self.stats:
            stat.analyse_control_flow(env)

William Stein's avatar
William Stein committed
355 356 357 358 359 360 361 362 363 364
    def analyse_declarations(self, env):
        #print "StatListNode.analyse_declarations" ###
        for stat in self.stats:
            stat.analyse_declarations(env)
    
    def analyse_expressions(self, env):
        #print "StatListNode.analyse_expressions" ###
        for stat in self.stats:
            stat.analyse_expressions(env)
    
365
    def generate_function_definitions(self, env, code):
William Stein's avatar
William Stein committed
366 367
        #print "StatListNode.generate_function_definitions" ###
        for stat in self.stats:
368
            stat.generate_function_definitions(env, code)
William Stein's avatar
William Stein committed
369 370 371 372 373 374
            
    def generate_execution_code(self, code):
        #print "StatListNode.generate_execution_code" ###
        for stat in self.stats:
            code.mark_pos(stat.pos)
            stat.generate_execution_code(code)
375 376 377 378
            
    def annotate(self, code):
        for stat in self.stats:
            stat.annotate(code)
William Stein's avatar
William Stein committed
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
    

class StatNode(Node):
    #
    #  Code generation for statements is split into the following subphases:
    #
    #  (1) generate_function_definitions
    #        Emit C code for the definitions of any structs,
    #        unions, enums and functions defined in the current
    #        scope-block.
    #
    #  (2) generate_execution_code
    #        Emit C code for executable statements.
    #
    
394
    def generate_function_definitions(self, env, code):
William Stein's avatar
William Stein committed
395 396 397 398 399 400 401 402 403 404 405
        pass
    
    def generate_execution_code(self, code):
        raise InternalError("generate_execution_code not implemented for %s" % \
            self.__class__.__name__)


class CDefExternNode(StatNode):
    #  include_file   string or None
    #  body           StatNode
    
406 407
    child_attrs = ["body"]
    
William Stein's avatar
William Stein committed
408 409 410 411 412 413 414 415 416 417 418 419 420
    def analyse_declarations(self, env):
        if self.include_file:
            env.add_include_file(self.include_file)
        old_cinclude_flag = env.in_cinclude
        env.in_cinclude = 1
        self.body.analyse_declarations(env)
        env.in_cinclude = old_cinclude_flag
    
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        pass
421 422 423

    def annotate(self, code):
        self.body.annotate(code)
William Stein's avatar
William Stein committed
424 425 426 427 428 429 430 431 432 433 434 435
        

class CDeclaratorNode(Node):
    # Part of a C declaration.
    #
    # Processing during analyse_declarations phase:
    #
    #   analyse
    #      Returns (name, type) pair where name is the
    #      CNameDeclaratorNode of the name being declared 
    #      and type is the type it is being declared as.
    #
436 437 438
    #  calling_convention  string   Calling convention of CFuncDeclaratorNode
    #                               for which this is a base 

439 440
    child_attrs = []

441 442
    calling_convention = ""

William Stein's avatar
William Stein committed
443 444

class CNameDeclaratorNode(CDeclaratorNode):
Robert Bradshaw's avatar
Robert Bradshaw committed
445 446 447
    #  name    string             The Pyrex name being declared
    #  cname   string or None     C name, if specified
    #  default ExprNode or None   the value assigned on declaration
William Stein's avatar
William Stein committed
448
    
Robert Bradshaw's avatar
Robert Bradshaw committed
449
    child_attrs = ['default']
450
    
451
    default = None
452
    
453 454
    def analyse(self, base_type, env, nonempty = 0):
        if nonempty and self.name == '':
455 456
            # May have mistaken the name for the type. 
            if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
457
                error(self.pos, "Missing argument name")
458 459
            elif base_type.is_void:
                error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
460 461 462
            else:
                self.name = base_type.declaration_code("", for_display=1, pyrex=1)
                base_type = py_object_type
463
        self.type = base_type
William Stein's avatar
William Stein committed
464
        return self, base_type
465
        
William Stein's avatar
William Stein committed
466 467 468
class CPtrDeclaratorNode(CDeclaratorNode):
    # base     CDeclaratorNode
    
469 470
    child_attrs = ["base"]

471
    def analyse(self, base_type, env, nonempty = 0):
William Stein's avatar
William Stein committed
472 473 474 475
        if base_type.is_pyobject:
            error(self.pos,
                "Pointer base type cannot be a Python object")
        ptr_type = PyrexTypes.c_ptr_type(base_type)
476
        return self.base.analyse(ptr_type, env, nonempty = nonempty)
William Stein's avatar
William Stein committed
477 478 479 480
        
class CArrayDeclaratorNode(CDeclaratorNode):
    # base        CDeclaratorNode
    # dimension   ExprNode
481 482

    child_attrs = ["base", "dimension"]
William Stein's avatar
William Stein committed
483
    
484
    def analyse(self, base_type, env, nonempty = 0):
William Stein's avatar
William Stein committed
485 486 487 488
        if self.dimension:
            self.dimension.analyse_const_expression(env)
            if not self.dimension.type.is_int:
                error(self.dimension.pos, "Array dimension not integer")
489
            size = self.dimension.result()
490 491 492 493 494
            try:
                size = int(size)
            except ValueError:
                # runtime constant?
                pass
William Stein's avatar
William Stein committed
495 496 497 498 499 500 501 502
        else:
            size = None
        if not base_type.is_complete():
            error(self.pos,
                "Array element type '%s' is incomplete" % base_type)
        if base_type.is_pyobject:
            error(self.pos,
                "Array element cannot be a Python object")
503 504 505
        if base_type.is_cfunction:
            error(self.pos,
                "Array element cannot be a function")
William Stein's avatar
William Stein committed
506
        array_type = PyrexTypes.c_array_type(base_type, size)
507
        return self.base.analyse(array_type, env, nonempty = nonempty)
William Stein's avatar
William Stein committed
508 509 510 511 512 513 514 515


class CFuncDeclaratorNode(CDeclaratorNode):
    # base             CDeclaratorNode
    # args             [CArgDeclNode]
    # has_varargs      boolean
    # exception_value  ConstNode
    # exception_check  boolean    True if PyErr_Occurred check needed
516 517
    # nogil            boolean    Can be called without gil
    # with_gil         boolean    Acquire gil around function body
518
    
519 520
    child_attrs = ["base", "args", "exception_value"]

521
    overridable = 0
522
    optional_arg_count = 0
William Stein's avatar
William Stein committed
523

524
    def analyse(self, return_type, env, nonempty = 0):
525 526
        if nonempty:
            nonempty -= 1
William Stein's avatar
William Stein committed
527 528
        func_type_args = []
        for arg_node in self.args:
529
            name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
William Stein's avatar
William Stein committed
530 531 532 533 534 535 536 537 538
            name = name_declarator.name
            if name_declarator.cname:
                error(self.pos, 
                    "Function argument cannot have C name specification")
            # Turn *[] argument into **
            if type.is_array:
                type = PyrexTypes.c_ptr_type(type.base_type)
            # Catch attempted C-style func(void) decl
            if type.is_void:
Robert Bradshaw's avatar
Robert Bradshaw committed
539
                error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
540 541 542
#            if type.is_pyobject and self.nogil:
#                error(self.pos,
#                    "Function with Python argument cannot be declared nogil")
William Stein's avatar
William Stein committed
543 544 545
            func_type_args.append(
                PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
            if arg_node.default:
546
                self.optional_arg_count += 1
547 548
            elif self.optional_arg_count:
                error(self.pos, "Non-default argument follows default argument")
549 550 551
        
        if self.optional_arg_count:
            scope = StructOrUnionScope()
552
            arg_count_member = '%sn' % Naming.pyrex_prefix
Robert Bradshaw's avatar
Robert Bradshaw committed
553
            scope.declare_var(arg_count_member, PyrexTypes.c_int_type, self.pos)
554 555
            for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
                scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
556
            struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
557 558 559 560 561 562
            self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
                                        kind = 'struct',
                                        scope = scope,
                                        typedef_flag = 0,
                                        pos = self.pos,
                                        cname = struct_cname)
563
            self.op_args_struct.defined_in_pxd = 1
564 565
            self.op_args_struct.used = 1
        
William Stein's avatar
William Stein committed
566 567
        exc_val = None
        exc_check = 0
568 569
        if self.exception_check == '+':
            env.add_include_file('stdexcept')
William Stein's avatar
William Stein committed
570
        if return_type.is_pyobject \
Robert Bradshaw's avatar
Robert Bradshaw committed
571 572
            and (self.exception_value or self.exception_check) \
            and self.exception_check != '+':
William Stein's avatar
William Stein committed
573 574 575 576 577
                error(self.pos,
                    "Exception clause not allowed for function returning Python object")
        else:
            if self.exception_value:
                self.exception_value.analyse_const_expression(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
578 579 580 581 582 583 584 585 586
                if self.exception_check == '+':
                    exc_val_type = self.exception_value.type
                    if not exc_val_type.is_error and \
                          not exc_val_type.is_pyobject and \
                          not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
                        error(self.exception_value.pos,
                            "Exception value must be a Python exception or cdef function with no arguments.")
                    exc_val = self.exception_value
                else:
587
                    exc_val = self.exception_value.result()
Robert Bradshaw's avatar
Robert Bradshaw committed
588 589 590
                    if not return_type.assignable_from(self.exception_value.type):
                        error(self.exception_value.pos,
                            "Exception value incompatible with function return type")
William Stein's avatar
William Stein committed
591
            exc_check = self.exception_check
592 593 594 595 596 597
        if return_type.is_array:
            error(self.pos,
                "Function cannot return an array")
        if return_type.is_cfunction:
            error(self.pos,
                "Function cannot return a function")
William Stein's avatar
William Stein committed
598 599
        func_type = PyrexTypes.CFuncType(
            return_type, func_type_args, self.has_varargs, 
600
            optional_arg_count = self.optional_arg_count,
601
            exception_value = exc_val, exception_check = exc_check,
602
            calling_convention = self.base.calling_convention,
603
            nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
604
        if self.optional_arg_count:
605
            func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
William Stein's avatar
William Stein committed
606 607 608 609 610 611 612 613 614 615 616
        return self.base.analyse(func_type, env)


class CArgDeclNode(Node):
    # Item in a function declaration argument list.
    #
    # base_type      CBaseTypeNode
    # declarator     CDeclaratorNode
    # not_none       boolean            Tagged with 'not None'
    # default        ExprNode or None
    # default_entry  Symtab.Entry       Entry for the variable holding the default value
617
    # default_result_code string        cname or code fragment for default value
William Stein's avatar
William Stein committed
618
    # is_self_arg    boolean            Is the "self" arg of an extension type method
619 620
    # is_kw_only     boolean            Is a keyword-only argument

621 622
    child_attrs = ["base_type", "declarator", "default"]

William Stein's avatar
William Stein committed
623
    is_self_arg = 0
624
    is_generic = 1
625 626
    type = None
    name_declarator = None
627

628
    def analyse(self, env, nonempty = 0):
629
        #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
630 631 632 633 634 635 636 637 638 639 640 641
        if self.type is None:
            # The parser may missinterpret names as types...
            # We fix that here.
            if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
                if nonempty:
                    self.declarator.name = self.base_type.name
                    self.base_type.name = None
                    self.base_type.is_basic_c_type = False
                could_be_name = True
            else:
                could_be_name = False
            base_type = self.base_type.analyse(env, could_be_name = could_be_name)
Robert Bradshaw's avatar
Robert Bradshaw committed
642
            if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
643 644
                self.declarator.name = self.base_type.arg_name
            return self.declarator.analyse(base_type, env, nonempty = nonempty)
645
        else:
646
            return self.name_declarator, self.type
William Stein's avatar
William Stein committed
647

648 649 650 651
    def annotate(self, code):
        if self.default:
            self.default.annotate(code)

William Stein's avatar
William Stein committed
652 653 654 655 656 657 658 659 660 661

class CBaseTypeNode(Node):
    # Abstract base class for C base type nodes.
    #
    # Processing during analyse_declarations phase:
    #
    #   analyse
    #     Returns the type.
    
    pass
662 663 664 665 666 667 668 669
    
class CAnalysedBaseTypeNode(Node):
    # type            type
    
    child_attrs = []
    
    def analyse(self, env, could_be_name = False):
        return self.type
William Stein's avatar
William Stein committed
670 671 672 673 674 675 676

class CSimpleBaseTypeNode(CBaseTypeNode):
    # name             string
    # module_path      [string]     Qualifying name components
    # is_basic_c_type  boolean
    # signed           boolean
    # longness         integer
677
    # complex          boolean
William Stein's avatar
William Stein committed
678 679
    # is_self_arg      boolean      Is self argument of C method

680
    child_attrs = []
681
    arg_name = None   # in case the argument name was interpreted as a type
682
    
683
    def analyse(self, env, could_be_name = False):
William Stein's avatar
William Stein committed
684
        # Return type descriptor.
685
        #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
William Stein's avatar
William Stein committed
686 687 688 689 690 691 692 693 694
        type = None
        if self.is_basic_c_type:
            type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
            if not type:
                error(self.pos, "Unrecognised type modifier combination")
        elif self.name == "object" and not self.module_path:
            type = py_object_type
        elif self.name is None:
            if self.is_self_arg and env.is_c_class_scope:
695
                #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
William Stein's avatar
William Stein committed
696 697 698 699
                type = env.parent_type
            else:
                type = py_object_type
        else:
700 701 702 703
            if self.module_path:
                scope = env.find_imported_module(self.module_path, self.pos)
            else:
                scope = env
William Stein's avatar
William Stein committed
704
            if scope:
705 706
                if scope.is_c_class_scope:
                    scope = scope.global_scope()
707
                entry = scope.lookup(self.name)
William Stein's avatar
William Stein committed
708 709
                if entry and entry.is_type:
                    type = entry.type
710 711 712 713 714 715
                elif could_be_name:
                    if self.is_self_arg and env.is_c_class_scope:
                        type = env.parent_type
                    else:
                        type = py_object_type
                    self.arg_name = self.name
William Stein's avatar
William Stein committed
716 717
                else:
                    error(self.pos, "'%s' is not a type identifier" % self.name)
718
        if self.complex:
719 720 721
            if not type.is_numeric or type.is_complex:
                error(self.pos, "can only complexify c numeric types")
            type = PyrexTypes.CComplexType(type)
722
            type.create_declaration_utility_code(env)
William Stein's avatar
William Stein committed
723 724 725 726 727
        if type:
            return type
        else:
            return PyrexTypes.error_type

728
class CBufferAccessTypeNode(CBaseTypeNode):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
729
    #  After parsing:
730 731
    #  positional_args  [ExprNode]        List of positional arguments
    #  keyword_args     DictNode          Keyword arguments
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
732 733 734
    #  base_type_node   CBaseTypeNode

    #  After analysis:
735 736
    #  type             PyrexType.BufferType   ...containing the right options

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
737

738 739
    child_attrs = ["base_type_node", "positional_args",
                   "keyword_args", "dtype_node"]
740

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
741
    dtype_node = None
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
742 743

    name = None
744
    
745
    def analyse(self, env, could_be_name = False):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
746
        base_type = self.base_type_node.analyse(env)
747
        if base_type.is_error: return base_type
748 749 750 751 752 753 754 755 756 757
        import Buffer

        options = Buffer.analyse_buffer_options(
            self.pos,
            env,
            self.positional_args,
            self.keyword_args,
            base_type.buffer_defaults)
        
        self.type = PyrexTypes.BufferType(base_type, **options)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
758
        return self.type
William Stein's avatar
William Stein committed
759 760 761 762 763

class CComplexBaseTypeNode(CBaseTypeNode):
    # base_type   CBaseTypeNode
    # declarator  CDeclaratorNode
    
764 765
    child_attrs = ["base_type", "declarator"]

766 767
    def analyse(self, env, could_be_name = False):
        base = self.base_type.analyse(env, could_be_name)
William Stein's avatar
William Stein committed
768 769 770 771 772 773 774 775 776 777
        _, type = self.declarator.analyse(base, env)
        return type


class CVarDefNode(StatNode):
    #  C variable definition or forward/extern function declaration.
    #
    #  visibility    'private' or 'public' or 'extern'
    #  base_type     CBaseTypeNode
    #  declarators   [CDeclaratorNode]
778
    #  in_pxd        boolean
Stefan Behnel's avatar
Stefan Behnel committed
779
    #  api           boolean
780
    #  need_properties [entry]
781

Robert Bradshaw's avatar
Robert Bradshaw committed
782
    #  decorators    [cython.locals(...)] or None 
783
    #  directive_locals { string : NameNode } locals defined by cython.locals(...)
784 785

    child_attrs = ["base_type", "declarators"]
Robert Bradshaw's avatar
Robert Bradshaw committed
786
    need_properties = ()
Robert Bradshaw's avatar
Robert Bradshaw committed
787 788
    
    decorators = None
789
    directive_locals = {}
William Stein's avatar
William Stein committed
790 791 792 793
    
    def analyse_declarations(self, env, dest_scope = None):
        if not dest_scope:
            dest_scope = env
794
        self.dest_scope = dest_scope
William Stein's avatar
William Stein committed
795
        base_type = self.base_type.analyse(env)
796 797 798 799
        if (dest_scope.is_c_class_scope
                and self.visibility == 'public' 
                and base_type.is_pyobject 
                and (base_type.is_builtin_type or base_type.is_extension_type)):
Robert Bradshaw's avatar
Robert Bradshaw committed
800
            self.need_properties = []
801 802 803 804 805 806
            need_property = True
            visibility = 'private'
        else:
            need_property = False
            visibility = self.visibility
            
William Stein's avatar
William Stein committed
807 808 809 810 811 812 813 814 815 816 817
        for declarator in self.declarators:
            name_declarator, type = declarator.analyse(base_type, env)
            if not type.is_complete():
                if not (self.visibility == 'extern' and type.is_array):
                    error(declarator.pos,
                        "Variable type '%s' is incomplete" % type)
            if self.visibility == 'extern' and type.is_pyobject:
                error(declarator.pos,
                    "Python object cannot be declared extern")
            name = name_declarator.name
            cname = name_declarator.cname
818 819 820
            if name == '':
                error(declarator.pos, "Missing name in declaration.")
                return
William Stein's avatar
William Stein committed
821
            if type.is_cfunction:
822
                entry = dest_scope.declare_cfunction(name, type, declarator.pos,
Stefan Behnel's avatar
Stefan Behnel committed
823 824
                    cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
                    api = self.api)
Robert Bradshaw's avatar
Robert Bradshaw committed
825
                if entry is not None:
826
                    entry.directive_locals = self.directive_locals
William Stein's avatar
William Stein committed
827
            else:
828 829
                if self.directive_locals:
                    s.error("Decorators can only be followed by functions")
830 831 832
                if self.in_pxd and self.visibility != 'extern':
                    error(self.pos, 
                        "Only 'extern' C variable declaration allowed in .pxd file")
833 834 835 836
                entry = dest_scope.declare_var(name, type, declarator.pos,
                            cname = cname, visibility = visibility, is_cdef = 1)
                if need_property:
                    self.need_properties.append(entry)
837
                    entry.needs_property = 1
William Stein's avatar
William Stein committed
838 839 840 841 842 843 844
    

class CStructOrUnionDefNode(StatNode):
    #  name          string
    #  cname         string or None
    #  kind          "struct" or "union"
    #  typedef_flag  boolean
845
    #  visibility    "public" or "private"
Stefan Behnel's avatar
Stefan Behnel committed
846
    #  in_pxd        boolean
William Stein's avatar
William Stein committed
847 848
    #  attributes    [CVarDefNode] or None
    #  entry         Entry
849
    #  packed        boolean
William Stein's avatar
William Stein committed
850
    
851 852
    child_attrs = ["attributes"]

William Stein's avatar
William Stein committed
853 854
    def analyse_declarations(self, env):
        scope = None
855 856
        if self.visibility == 'extern' and self.packed:
            error(self.pos, "Cannot declare extern struct as 'packed'")
William Stein's avatar
William Stein committed
857
        if self.attributes is not None:
858
            scope = StructOrUnionScope(self.name)
William Stein's avatar
William Stein committed
859 860
        self.entry = env.declare_struct_or_union(
            self.name, self.kind, scope, self.typedef_flag, self.pos,
861
            self.cname, visibility = self.visibility, packed = self.packed)
William Stein's avatar
William Stein committed
862
        if self.attributes is not None:
Stefan Behnel's avatar
Stefan Behnel committed
863 864
            if self.in_pxd and not env.in_cinclude:
                self.entry.defined_in_pxd = 1
William Stein's avatar
William Stein committed
865 866
            for attr in self.attributes:
                attr.analyse_declarations(env, scope)
867
            if self.visibility != 'extern':
Stefan Behnel's avatar
Stefan Behnel committed
868
                need_typedef_indirection = False
869 870 871
                for attr in scope.var_entries:
                    type = attr.type
                    while type.is_array:
872 873
                        type = type.base_type
                    if type == self.entry.type:
874 875 876 877 878 879
                        error(attr.pos, "Struct cannot contain itself as a member.")
                    if self.typedef_flag:
                        while type.is_ptr:
                            type = type.base_type
                        if type == self.entry.type:
                            need_typedef_indirection = True
Robert Bradshaw's avatar
Robert Bradshaw committed
880 881 882 883 884 885 886
                if need_typedef_indirection:
                    # C can't handle typedef structs that refer to themselves. 
                    struct_entry = self.entry
                    cname = env.new_const_cname()
                    self.entry = env.declare_typedef(self.name, struct_entry.type, self.pos, cname = self.cname, visibility='ignore')
                    struct_entry.type.typedef_flag = False
                    struct_entry.cname = struct_entry.type.cname = env.new_const_cname()
William Stein's avatar
William Stein committed
887 888 889 890 891 892 893 894 895 896 897 898 899
    
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        pass


class CEnumDefNode(StatNode):
    #  name           string or None
    #  cname          string or None
    #  items          [CEnumDefItemNode]
    #  typedef_flag   boolean
Stefan Behnel's avatar
Stefan Behnel committed
900 901
    #  visibility     "public" or "private"
    #  in_pxd         boolean
William Stein's avatar
William Stein committed
902 903
    #  entry          Entry
    
904 905
    child_attrs = ["items"]
    
William Stein's avatar
William Stein committed
906 907
    def analyse_declarations(self, env):
        self.entry = env.declare_enum(self.name, self.pos,
908 909
            cname = self.cname, typedef_flag = self.typedef_flag,
            visibility = self.visibility)
Stefan Behnel's avatar
Stefan Behnel committed
910 911 912 913 914
        if self.items is not None:
            if self.in_pxd and not env.in_cinclude:
                self.entry.defined_in_pxd = 1
            for item in self.items:
                item.analyse_declarations(env, self.entry)
William Stein's avatar
William Stein committed
915 916

    def analyse_expressions(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
917 918 919
        if self.visibility == 'public':
            self.temp = env.allocate_temp_pyobject()
            env.release_temp(self.temp)
William Stein's avatar
William Stein committed
920 921
    
    def generate_execution_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
922 923 924 925 926 927
        if self.visibility == 'public':
            for item in self.entry.enum_values:
                code.putln("%s = PyInt_FromLong(%s); %s" % (
                        self.temp,
                        item.cname,
                        code.error_goto_if_null(self.temp, item.pos)))
928
                code.put_gotref(self.temp)
929
                code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
Robert Bradshaw's avatar
Robert Bradshaw committed
930 931 932 933
                        Naming.module_cname, 
                        item.name, 
                        self.temp,
                        code.error_goto(item.pos)))
934
                code.put_decref_clear(self.temp, PyrexTypes.py_object_type)
William Stein's avatar
William Stein committed
935 936 937 938 939 940 941


class CEnumDefItemNode(StatNode):
    #  name     string
    #  cname    string or None
    #  value    ExprNode or None
    
942 943
    child_attrs = ["value"]

William Stein's avatar
William Stein committed
944 945 946
    def analyse_declarations(self, env, enum_entry):
        if self.value:
            self.value.analyse_const_expression(env)
947 948 949
            if not self.value.type.is_int:
                self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
                self.value.analyse_const_expression(env)
950
            value = self.value.result()
William Stein's avatar
William Stein committed
951 952 953
        else:
            value = self.name
        entry = env.declare_const(self.name, enum_entry.type, 
Robert Bradshaw's avatar
Robert Bradshaw committed
954
            value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
William Stein's avatar
William Stein committed
955 956 957 958
        enum_entry.enum_values.append(entry)


class CTypeDefNode(StatNode):
Stefan Behnel's avatar
Stefan Behnel committed
959 960 961 962
    #  base_type    CBaseTypeNode
    #  declarator   CDeclaratorNode
    #  visibility   "public" or "private"
    #  in_pxd       boolean
963 964

    child_attrs = ["base_type", "declarator"]
William Stein's avatar
William Stein committed
965 966 967 968 969 970
    
    def analyse_declarations(self, env):
        base = self.base_type.analyse(env)
        name_declarator, type = self.declarator.analyse(base, env)
        name = name_declarator.name
        cname = name_declarator.cname
Stefan Behnel's avatar
Stefan Behnel committed
971
        entry = env.declare_typedef(name, type, self.pos,
972
            cname = cname, visibility = self.visibility)
Stefan Behnel's avatar
Stefan Behnel committed
973 974
        if self.in_pxd and not env.in_cinclude:
            entry.defined_in_pxd = 1
William Stein's avatar
William Stein committed
975 976 977 978 979 980 981 982 983 984 985 986 987
    
    def analyse_expressions(self, env):
        pass
    def generate_execution_code(self, code):
        pass


class FuncDefNode(StatNode, BlockNode):
    #  Base class for function definition nodes.
    #
    #  return_type     PyrexType
    #  #filename        string        C name of filename string const
    #  entry           Symtab.Entry
988
    #  needs_closure   boolean        Whether or not this function has inner functions/classes/yield
989
    #  directive_locals { string : NameNode } locals defined by cython.locals(...)
William Stein's avatar
William Stein committed
990
    
991
    py_func = None
992
    assmt = None
993
    needs_closure = False
994 995 996 997 998 999 1000
    
    def analyse_default_values(self, env):
        genv = env.global_scope()
        for arg in self.args:
            if arg.default:
                if arg.is_generic:
                    if not hasattr(arg, 'default_entry'):
1001
                        arg.default.analyse_types(env)
1002
                        arg.default = arg.default.coerce_to(arg.type, genv)
1003 1004 1005
                        if arg.default.is_literal:
                            arg.default_entry = arg.default
                            arg.default_result_code = arg.default.calculate_result_code()
1006 1007
                            if arg.default.type != arg.type and not arg.type.is_int:
                                arg.default_result_code = arg.type.cast_code(arg.default_result_code)
1008 1009 1010
                        else:
                            arg.default.allocate_temps(genv)
                            arg.default_entry = genv.add_default_value(arg.type)
1011 1012
                            if arg.type.is_pyobject:
                                arg.default_entry.init = 0
1013 1014
                            arg.default_entry.used = 1
                            arg.default_result_code = arg.default_entry.cname
1015 1016 1017 1018
                else:
                    error(arg.pos,
                        "This argument cannot have a default value")
                    arg.default = None
1019
    
1020 1021
    def need_gil_acquisition(self, lenv):
        return 0
1022 1023 1024 1025 1026
        
    def create_local_scope(self, env):
        genv = env
        while env.is_py_class_scope or env.is_c_class_scope:
            env = env.outer_scope
1027
        if self.needs_closure:
1028
            lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
1029 1030
        else:
            lenv = LocalScope(name = self.entry.name, outer_scope = genv)
William Stein's avatar
William Stein committed
1031
        lenv.return_type = self.return_type
1032 1033 1034
        type = self.entry.type
        if type.is_cfunction:
            lenv.nogil = type.nogil and not type.with_gil
1035
        self.local_scope = lenv
1036
        lenv.directives = env.directives
1037 1038
        return lenv
                
1039
    def generate_function_definitions(self, env, code):
1040
        import Buffer
1041 1042 1043

        lenv = self.local_scope

1044 1045 1046
        is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
                             self.entry.scope.is_c_class_scope)

1047
        # Generate C code for header and body of function
1048
        code.enter_cfunc_scope()
1049 1050
        code.return_from_error_cleanup_label = code.new_label()
            
William Stein's avatar
William Stein committed
1051
        # ----- Top-level constants used by this function
1052
        code.mark_pos(self.pos)
1053
        self.generate_interned_num_decls(lenv, code)
1054
        self.generate_interned_string_decls(lenv, code)
William Stein's avatar
William Stein committed
1055
        self.generate_py_string_decls(lenv, code)
1056
        self.generate_cached_builtins_decls(lenv, code)
William Stein's avatar
William Stein committed
1057 1058 1059 1060 1061
        #code.putln("")
        #code.put_var_declarations(lenv.const_entries, static = 1)
        self.generate_const_definitions(lenv, code)
        # ----- Function header
        code.putln("")
1062 1063 1064 1065
        if self.py_func:
            self.py_func.generate_function_header(code, 
                with_pymethdef = env.is_py_class_scope,
                proto_only=True)
William Stein's avatar
William Stein committed
1066 1067 1068
        self.generate_function_header(code,
            with_pymethdef = env.is_py_class_scope)
        # ----- Local variable declarations
1069
        lenv.mangle_closure_cnames(Naming.cur_scope_cname)
William Stein's avatar
William Stein committed
1070
        self.generate_argument_declarations(lenv, code)
1071 1072
        if self.needs_closure:
            code.putln("/* TODO: declare and create scope object */")
William Stein's avatar
William Stein committed
1073 1074 1075
        code.put_var_declarations(lenv.var_entries)
        init = ""
        if not self.return_type.is_void:
1076 1077
            if self.return_type.is_pyobject:
                init = " = NULL"
William Stein's avatar
William Stein committed
1078 1079 1080 1081 1082
            code.putln(
                "%s%s;" % 
                    (self.return_type.declaration_code(
                        Naming.retval_cname),
                    init))
1083
        tempvardecl_code = code.insertion_point()
William Stein's avatar
William Stein committed
1084 1085 1086
        self.generate_keyword_list(code)
        # ----- Extern library function declarations
        lenv.generate_library_function_declarations(code)
1087 1088 1089
        # ----- GIL acquisition
        acquire_gil = self.need_gil_acquisition(lenv)
        if acquire_gil:
Stefan Behnel's avatar
Stefan Behnel committed
1090
            env.use_utility_code(force_init_threads_utility_code)
1091
            code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1092
        # ----- Automatic lead-ins for certain special functions
1093 1094
        if not lenv.nogil:
            code.put_setup_refcount_context(self.entry.name)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1095 1096
        if is_getbuffer_slot:
            self.getbuffer_init(code)
William Stein's avatar
William Stein committed
1097
        # ----- Fetch arguments
1098
        self.generate_argument_parsing_code(env, code)
Robert Bradshaw's avatar
Robert Bradshaw committed
1099 1100 1101 1102 1103
        # If an argument is assigned to in the body, we must 
        # incref it to properly keep track of refcounts.
        for entry in lenv.arg_entries:
            if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
                code.put_var_incref(entry)
1104
        # ----- Initialise local variables 
William Stein's avatar
William Stein committed
1105
        for entry in lenv.var_entries:
1106
            if entry.type.is_pyobject and entry.init_to_none and entry.used:
William Stein's avatar
William Stein committed
1107
                code.put_init_var_to_py_none(entry)
1108 1109
        # ----- Initialise local buffer auxiliary variables
        for entry in lenv.var_entries + lenv.arg_entries:
1110 1111
            if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
                code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1112
        # ----- Check and convert arguments
William Stein's avatar
William Stein committed
1113
        self.generate_argument_type_tests(code)
1114 1115 1116 1117
        # ----- Acquire buffer arguments
        for entry in lenv.arg_entries:
            if entry.type.is_buffer:
                Buffer.put_acquire_arg_buffer(entry, code, self.pos)        
William Stein's avatar
William Stein committed
1118 1119 1120 1121 1122 1123
        # ----- Function body
        self.body.generate_execution_code(code)
        # ----- Default return value
        code.putln("")
        if self.return_type.is_pyobject:
            #if self.return_type.is_extension_type:
1124
            #    lhs = "(PyObject *)%s" % Naming.retval_cname
William Stein's avatar
William Stein committed
1125 1126 1127 1128 1129 1130 1131 1132
            #else:
            lhs = Naming.retval_cname
            code.put_init_to_py_none(lhs, self.return_type)
        else:
            val = self.return_type.default_value
            if val:
                code.putln("%s = %s;" % (Naming.retval_cname, val))
        # ----- Error cleanup
1133 1134 1135
        if code.error_label in code.labels_used:
            code.put_goto(code.return_label)
            code.put_label(code.error_label)
1136
            # cleanup temps the old way
1137
            code.put_var_xdecrefs(lenv.temp_entries)
1138
            # cleanup temps the new way
1139 1140
            for cname, type in code.funcstate.all_managed_temps():
                code.put_xdecref(cname, type)
1141 1142 1143 1144 1145

            # Clean up buffers -- this calls a Python function
            # so need to save and restore error state
            buffers_present = len(lenv.buffer_entries) > 0
            if buffers_present:
1146
                code.globalstate.use_utility_code(restore_exception_utility_code)
1147
                code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1148
                code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1149 1150 1151
                for entry in lenv.buffer_entries:
                    code.putln("%s;" % Buffer.get_release_buffer_code(entry))
                    #code.putln("%s = 0;" % entry.cname)
1152
                code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1153

1154 1155 1156
            err_val = self.error_value()
            exc_check = self.caller_will_check_exceptions()
            if err_val is not None or exc_check:
Robert Bradshaw's avatar
Robert Bradshaw committed
1157
                code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1158
            else:
1159 1160
                warning(self.entry.pos, "Unraisable exception in function '%s'." \
                            % self.entry.qualified_name, 0)
1161 1162 1163 1164
                code.putln(
                    '__Pyx_WriteUnraisable("%s");' % 
                        self.entry.qualified_name)
                env.use_utility_code(unraisable_exception_utility_code)
1165
                env.use_utility_code(restore_exception_utility_code)
1166 1167 1168 1169 1170 1171 1172 1173
            default_retval = self.return_type.default_value
            if err_val is None and default_retval:
                err_val = default_retval
            if err_val is not None:
                code.putln(
                    "%s = %s;" % (
                        Naming.retval_cname, 
                        err_val))
1174 1175 1176 1177 1178 1179 1180 1181

            if is_getbuffer_slot:
                self.getbuffer_error_cleanup(code)

            # If we are using the non-error cleanup section we should
            # jump past it if we have an error. The if-test below determine
            # whether this section is used.
            if buffers_present or is_getbuffer_slot:
1182 1183
                code.put_goto(code.return_from_error_cleanup_label)

1184

1185
        # ----- Non-error return cleanup
1186 1187 1188
        # If you add anything here, remember to add a condition to the
        # if-test above in the error block (so that it can jump past this
        # block).
William Stein's avatar
William Stein committed
1189
        code.put_label(code.return_label)
1190
        for entry in lenv.buffer_entries:
1191 1192
            if entry.used:
                code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1193 1194
        if is_getbuffer_slot:
            self.getbuffer_normal_cleanup(code)
1195 1196
        # ----- Return cleanup for both error and no-error return
        code.put_label(code.return_from_error_cleanup_label)
Robert Bradshaw's avatar
Robert Bradshaw committed
1197 1198 1199 1200
        if not Options.init_local_none:
            for entry in lenv.var_entries:
                if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
                    entry.xdecref_cleanup = 1
1201
        code.put_var_decrefs(lenv.var_entries, used_only = 1)
Robert Bradshaw's avatar
Robert Bradshaw committed
1202
        # Decref any increfed args
1203
        for entry in lenv.arg_entries:
Robert Bradshaw's avatar
Robert Bradshaw committed
1204
            if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1205
                code.put_var_decref(entry)
1206

1207
        # code.putln("/* TODO: decref scope object */")
1208
        # ----- Return
1209
        # This code is duplicated in ModuleNode.generate_module_init_func
1210 1211 1212 1213 1214 1215 1216
        if not lenv.nogil:
            default_retval = self.return_type.default_value
            err_val = self.error_value()
            if err_val is None and default_retval:
                err_val = default_retval
            if self.return_type.is_pyobject:
                code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1217

1218
            code.put_finish_refcount_context()
1219

1220 1221 1222
        if acquire_gil:
            code.putln("PyGILState_Release(_save);")

William Stein's avatar
William Stein committed
1223
        if not self.return_type.is_void:
1224
            code.putln("return %s;" % Naming.retval_cname)
1225
            
William Stein's avatar
William Stein committed
1226
        code.putln("}")
1227 1228
        # ----- Go back and insert temp variable declarations
        tempvardecl_code.put_var_declarations(lenv.temp_entries)
1229
        tempvardecl_code.put_temp_declarations(code.funcstate)
1230
        # ----- Python version
1231
        code.exit_cfunc_scope()
1232
        if self.py_func:
1233
            self.py_func.generate_function_definitions(env, code)
1234
        self.generate_wrapper_functions(code)
William Stein's avatar
William Stein committed
1235 1236 1237 1238 1239 1240 1241 1242

    def declare_argument(self, env, arg):
        if arg.type.is_void:
            error(arg.pos, "Invalid use of 'void'")
        elif not arg.type.is_complete() and not arg.type.is_array:
            error(arg.pos,
                "Argument type '%s' is incomplete" % arg.type)
        return env.declare_arg(arg.name, arg.type, arg.pos)
1243 1244
        
    def generate_wrapper_functions(self, code):
William Stein's avatar
William Stein committed
1245 1246 1247
        pass

    def generate_execution_code(self, code):
1248 1249 1250 1251
        # Evaluate and store argument default values
        for arg in self.args:
            default = arg.default
            if default:
1252 1253 1254
                if not default.is_literal:
                    default.generate_evaluation_code(code)
                    default.make_owned_reference(code)
1255
                    code.putln(
1256
                        "%s = %s;" % (
1257
                            arg.default_entry.cname,
1258
                            default.result_as(arg.default_entry.type)))
1259 1260
                    if default.is_temp and default.type.is_pyobject:
                        code.putln("%s = 0;" % default.result())
1261
                    default.free_temps(code)
1262
                    code.put_var_giveref(arg.default_entry)
1263 1264 1265
        # For Python class methods, create and store function object
        if self.assmt:
            self.assmt.generate_execution_code(code)
William Stein's avatar
William Stein committed
1266

1267
    #
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1268
    # Special code for the __getbuffer__ function
1269 1270 1271 1272 1273 1274 1275
    #
    def getbuffer_init(self, code):
        info = self.local_scope.arg_entries[1].cname
        # Python 3.0 betas have a bug in memoryview which makes it call
        # getbuffer with a NULL parameter. For now we work around this;
        # the following line should be removed when this bug is fixed.
        code.putln("if (%s == NULL) return 0;" % info) 
1276
        code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1277
        code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1278 1279 1280

    def getbuffer_error_cleanup(self, code):
        info = self.local_scope.arg_entries[1].cname
1281
        code.put_gotref("%s->obj" % info)
1282
        code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1283 1284 1285 1286
                   (info, info))

    def getbuffer_normal_cleanup(self, code):
        info = self.local_scope.arg_entries[1].cname
1287 1288 1289 1290
        code.putln("if (%s->obj == Py_None) {" % info)
        code.put_gotref("Py_None")
        code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
        code.putln("}")
William Stein's avatar
William Stein committed
1291 1292 1293 1294

class CFuncDefNode(FuncDefNode):
    #  C function definition.
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
1295
    #  modifiers     ['inline']
William Stein's avatar
William Stein committed
1296 1297 1298 1299
    #  visibility    'private' or 'public' or 'extern'
    #  base_type     CBaseTypeNode
    #  declarator    CDeclaratorNode
    #  body          StatListNode
1300
    #  api           boolean
1301
    #  decorators    [DecoratorNode]        list of decorators
William Stein's avatar
William Stein committed
1302
    #
1303
    #  with_gil      boolean    Acquire GIL around body
William Stein's avatar
William Stein committed
1304
    #  type          CFuncType
1305
    #  py_func       wrapper for calling from Python
1306
    #  overridable   whether or not this is a cpdef function
1307
    #  inline_in_pxd whether this is an inline function in a pxd file
William Stein's avatar
William Stein committed
1308
    
1309
    child_attrs = ["base_type", "declarator", "body", "py_func"]
1310 1311

    inline_in_pxd = False
1312 1313
    decorators = None
    directive_locals = {}
1314

William Stein's avatar
William Stein committed
1315 1316 1317 1318
    def unqualified_name(self):
        return self.entry.name
        
    def analyse_declarations(self, env):
1319
        directive_locals = self.directive_locals = env.directives['locals']
William Stein's avatar
William Stein committed
1320
        base_type = self.base_type.analyse(env)
1321 1322
        # The 2 here is because we need both function and argument names. 
        name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1323 1324 1325
        if not type.is_cfunction:
            error(self.pos, 
                "Suite attached to non-function declaration")
William Stein's avatar
William Stein committed
1326 1327 1328 1329 1330
        # Remember the actual type according to the function header
        # written here, because the type in the symbol table entry
        # may be different if we're overriding a C method inherited
        # from the base type of an extension type.
        self.type = type
1331
        type.is_overridable = self.overridable
1332 1333 1334 1335 1336
        declarator = self.declarator
        while not hasattr(declarator, 'args'):
            declarator = declarator.base
        self.args = declarator.args
        for formal_arg, type_arg in zip(self.args, type.args):
1337
            formal_arg.type = type_arg.type
1338
            formal_arg.name = type_arg.name
1339
            formal_arg.cname = type_arg.cname
William Stein's avatar
William Stein committed
1340 1341 1342 1343 1344
        name = name_declarator.name
        cname = name_declarator.cname
        self.entry = env.declare_cfunction(
            name, type, self.pos, 
            cname = cname, visibility = self.visibility,
1345
            defining = self.body is not None,
1346
            api = self.api, modifiers = self.modifiers)
1347
        self.entry.inline_func_in_pxd = self.inline_in_pxd
William Stein's avatar
William Stein committed
1348
        self.return_type = type.return_type
1349
        
1350 1351 1352 1353 1354 1355
        if self.overridable and not env.is_module_scope:
            if len(self.args) < 1 or not self.args[0].type.is_pyobject:
                # An error will be produced in the cdef function
                self.overridable = False
            
        if self.overridable:
1356
            import ExprNodes
1357
            py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1358
            self.py_func = DefNode(pos = self.pos, 
1359 1360
                                   name = self.entry.name,
                                   args = self.args,
1361 1362
                                   star_arg = None,
                                   starstar_arg = None,
1363
                                   doc = self.doc,
1364 1365
                                   body = py_func_body,
                                   is_wrapper = 1)
1366
            self.py_func.is_module_scope = env.is_module_scope
1367
            self.py_func.analyse_declarations(env)
1368
            self.entry.as_variable = self.py_func.entry
1369 1370
            # Reset scope entry the above cfunction
            env.entries[name] = self.entry
1371 1372
            self.py_func.interned_attr_cname = env.intern_identifier(
                self.py_func.entry.name)
1373 1374 1375
            if not env.is_module_scope or Options.lookup_module_cpdef:
                self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
                self.body = StatListNode(self.pos, stats=[self.override, self.body])
1376
    
1377
    def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1378 1379 1380 1381 1382
        import ExprNodes
        args = self.type.args
        if omit_optional_args:
            args = args[:len(args) - self.type.optional_arg_count]
        arg_names = [arg.name for arg in args]
1383
        if is_module_scope:
1384
            cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1385 1386
        else:
            self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1387
            cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1388 1389
        skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
        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)
1390
        return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1391
    
William Stein's avatar
William Stein committed
1392 1393 1394 1395 1396 1397
    def declare_arguments(self, env):
        for arg in self.type.args:
            if not arg.name:
                error(arg.pos, "Missing argument name")
            self.declare_argument(env, arg)
            
1398
    def need_gil_acquisition(self, lenv):
1399
        type = self.type
1400
        with_gil = self.type.with_gil
1401 1402 1403 1404
        if type.nogil and not with_gil:
            if type.return_type.is_pyobject:
                error(self.pos,
                      "Function with Python return type cannot be declared nogil")
1405 1406 1407 1408 1409
            for entry in lenv.var_entries + lenv.temp_entries:
                if entry.type.is_pyobject:
                    error(self.pos, "Function declared nogil has Python locals or temporaries")
        return with_gil

1410
    def analyse_expressions(self, env):
1411
        self.local_scope.directives = env.directives
1412
        self.analyse_default_values(env)
1413
        if self.py_func is not None:
1414 1415
            self.py_func.analyse_expressions(env)

1416
    def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
William Stein's avatar
William Stein committed
1417 1418
        arg_decls = []
        type = self.type
Stefan Behnel's avatar
Stefan Behnel committed
1419
        visibility = self.entry.visibility
1420
        for arg in type.args[:len(type.args)-type.optional_arg_count]:
William Stein's avatar
William Stein committed
1421
            arg_decls.append(arg.declaration_code())
1422 1423
        if with_dispatch and self.overridable:
            arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1424 1425
        if type.optional_arg_count and with_opt_args:
            arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
William Stein's avatar
William Stein committed
1426 1427 1428 1429
        if type.has_varargs:
            arg_decls.append("...")
        if not arg_decls:
            arg_decls = ["void"]
1430 1431
        if cname is None:
            cname = self.entry.func_cname
1432
        entity = type.function_header_code(cname, ', '.join(arg_decls))
Stefan Behnel's avatar
Stefan Behnel committed
1433
        if visibility == 'public':
William Stein's avatar
William Stein committed
1434 1435 1436 1437 1438
            dll_linkage = "DL_EXPORT"
        else:
            dll_linkage = None
        header = self.return_type.declaration_code(entity,
            dll_linkage = dll_linkage)
1439
        if visibility == 'extern':
William Stein's avatar
William Stein committed
1440
            storage_class = "%s " % Naming.extern_c_macro
1441 1442
        elif visibility == 'public':
            storage_class = ""
William Stein's avatar
William Stein committed
1443
        else:
Stefan Behnel's avatar
Stefan Behnel committed
1444
            storage_class = "static "
Robert Bradshaw's avatar
Robert Bradshaw committed
1445
        code.putln("%s%s %s {" % (
William Stein's avatar
William Stein committed
1446
            storage_class,
1447
            ' '.join(self.modifiers).upper(), # macro forms 
William Stein's avatar
William Stein committed
1448 1449 1450
            header))

    def generate_argument_declarations(self, env, code):
1451
        for arg in self.args:
1452
            if arg.default:
1453
                    code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1454

William Stein's avatar
William Stein committed
1455 1456 1457
    def generate_keyword_list(self, code):
        pass
        
1458
    def generate_argument_parsing_code(self, env, code):
1459
        i = 0
1460 1461
        if self.type.optional_arg_count:
            code.putln('if (%s) {' % Naming.optional_args_cname)
1462
            for arg in self.args:
1463
                if arg.default:
1464 1465
                    # FIXME: simple name prefixing doesn't work when
                    # argument name mangling is in place
1466
                    code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1467 1468 1469 1470
                    declarator = arg.declarator
                    while not hasattr(declarator, 'name'):
                        declarator = declarator.base
                    code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1471 1472 1473
                    i += 1
            for _ in range(self.type.optional_arg_count):
                code.putln('}')
1474
            code.putln('}')
William Stein's avatar
William Stein committed
1475 1476 1477 1478 1479
    
    def generate_argument_conversion_code(self, code):
        pass
    
    def generate_argument_type_tests(self, code):
1480 1481 1482 1483 1484 1485 1486 1487 1488 1489
        # Generate type tests for args whose type in a parent
        # class is a supertype of the declared type.
        for arg in self.type.args:
            if arg.needs_type_test:
                self.generate_arg_type_test(arg, code)
    
    def generate_arg_type_test(self, arg, code):
        # Generate type test for one argument.
        if arg.type.typeobj_is_available():
            typeptr_cname = arg.type.typeptr_cname
1490
            arg_code = "((PyObject *)%s)" % arg.cname
1491
            code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
1492
                'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1493 1494 1495 1496
                    arg_code, 
                    typeptr_cname,
                    not arg.not_none,
                    arg.name,
Robert Bradshaw's avatar
Robert Bradshaw committed
1497
                    type.is_builtin_type,
1498 1499 1500 1501
                    code.error_goto(arg.pos)))
        else:
            error(arg.pos, "Cannot test type of extern C class "
                "without type object name specification")
1502

William Stein's avatar
William Stein committed
1503 1504 1505 1506
    def error_value(self):
        if self.return_type.is_pyobject:
            return "0"
        else:
1507 1508
            #return None
            return self.entry.type.exception_value
William Stein's avatar
William Stein committed
1509 1510
            
    def caller_will_check_exceptions(self):
1511
        return self.entry.type.exception_check
1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522
        
    def generate_wrapper_functions(self, code):
        # If the C signature of a function has changed, we need to generate
        # wrappers to put in the slots here. 
        k = 0
        entry = self.entry
        func_type = entry.type
        while entry.prev_entry is not None:
            k += 1
            entry = entry.prev_entry
            entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1523
            code.putln()
1524 1525 1526 1527 1528
            self.generate_function_header(code, 
                                          0,
                                          with_dispatch = entry.type.is_overridable, 
                                          with_opt_args = entry.type.optional_arg_count, 
                                          cname = entry.func_cname)
1529 1530 1531 1532
            if not self.return_type.is_void:
                code.put('return ')
            args = self.type.args
            arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1533 1534 1535 1536 1537 1538 1539 1540
            if entry.type.is_overridable:
                arglist.append(Naming.skip_dispatch_cname)
            elif func_type.is_overridable:
                arglist.append('0')
            if entry.type.optional_arg_count:
                arglist.append(Naming.optional_args_cname)
            elif func_type.optional_arg_count:
                arglist.append('NULL')
1541 1542
            code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
            code.putln('}')
1543
        
William Stein's avatar
William Stein committed
1544 1545 1546 1547 1548 1549 1550

class PyArgDeclNode(Node):
    # Argument which must be a Python object (used
    # for * and ** arguments).
    #
    # name   string
    # entry  Symtab.Entry
1551
    child_attrs = []
William Stein's avatar
William Stein committed
1552
    
1553 1554 1555 1556 1557 1558 1559

class DecoratorNode(Node):
    # A decorator
    #
    # decorator    NameNode or CallNode
    child_attrs = ['decorator']

William Stein's avatar
William Stein committed
1560 1561 1562 1563 1564

class DefNode(FuncDefNode):
    # A Python function definition.
    #
    # name          string                 the Python name of the function
1565
    # decorators    [DecoratorNode]        list of decorators
William Stein's avatar
William Stein committed
1566 1567 1568
    # args          [CArgDeclNode]         formal arguments
    # star_arg      PyArgDeclNode or None  * argument
    # starstar_arg  PyArgDeclNode or None  ** argument
1569
    # doc           EncodedString or None
William Stein's avatar
William Stein committed
1570 1571 1572 1573 1574 1575 1576
    # body          StatListNode
    #
    #  The following subnode is constructed internally
    #  when the def statement is inside a Python class definition.
    #
    #  assmt   AssignmentNode   Function construction/assignment
    
1577
    child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1578

William Stein's avatar
William Stein committed
1579
    assmt = None
1580
    num_kwonly_args = 0
1581
    num_required_kw_args = 0
1582
    reqd_kw_flags_cname = "0"
1583
    is_wrapper = 0
1584
    decorators = None
1585 1586
    entry = None
    
1587

1588 1589
    def __init__(self, pos, **kwds):
        FuncDefNode.__init__(self, pos, **kwds)
1590
        k = rk = r = 0
1591 1592
        for arg in self.args:
            if arg.kw_only:
1593
                k += 1
1594
                if not arg.default:
1595 1596 1597 1598 1599 1600
                    rk += 1
            if not arg.default:
                r += 1
        self.num_kwonly_args = k
        self.num_required_kw_args = rk
        self.num_required_args = r
1601
        
1602
    def as_cfunction(self, cfunc=None, scope=None):
1603 1604 1605 1606
        if self.star_arg:
            error(self.star_arg.pos, "cdef function cannot have star argument")
        if self.starstar_arg:
            error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622
        if cfunc is None:
            cfunc_args = []
            for formal_arg in self.args:
                name_declarator, type = formal_arg.analyse(scope, nonempty=1)
                cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
                                                          cname = None,
                                                          type = py_object_type,
                                                          pos = formal_arg.pos))
            cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
                                              args = cfunc_args,
                                              has_varargs = False,
                                              exception_value = None,
                                              exception_check = False,
                                              nogil = False,
                                              with_gil = False,
                                              is_overridable = True)
1623
            cfunc = CVarDefNode(self.pos, type=cfunc_type)
1624 1625 1626 1627 1628 1629 1630 1631 1632 1633
        else:
            cfunc_type = cfunc.type
            if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
                error(self.pos, "wrong number of arguments")
                error(declarator.pos, "previous declaration here")
            for formal_arg, type_arg in zip(self.args, cfunc_type.args):
                name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
                if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
                    formal_arg.type = type_arg.type
                    formal_arg.name_declarator = name_declarator
1634
        import ExprNodes
1635
        if cfunc_type.exception_value is None:
1636 1637
            exception_value = None
        else:
1638
            exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1639 1640 1641 1642
        declarator = CFuncDeclaratorNode(self.pos, 
                                         base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
                                         args = self.args,
                                         has_varargs = False,
1643
                                         exception_check = cfunc_type.exception_check,
1644
                                         exception_value = exception_value,
1645 1646
                                         with_gil = cfunc_type.with_gil,
                                         nogil = cfunc_type.nogil)
1647 1648
        return CFuncDefNode(self.pos, 
                            modifiers = [],
1649
                            base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1650 1651 1652
                            declarator = declarator,
                            body = self.body,
                            doc = self.doc,
1653 1654 1655 1656
                            overridable = cfunc_type.is_overridable,
                            type = cfunc_type,
                            with_gil = cfunc_type.with_gil,
                            nogil = cfunc_type.nogil,
1657
                            visibility = 'private',
1658
                            api = False,
1659
                            directive_locals = getattr(cfunc, 'directive_locals', {}))
1660
    
William Stein's avatar
William Stein committed
1661
    def analyse_declarations(self, env):
1662
        directive_locals = self.directive_locals = env.directives['locals']
William Stein's avatar
William Stein committed
1663
        for arg in self.args:
1664 1665 1666 1667 1668 1669 1670 1671
            if hasattr(arg, 'name'):
                type = arg.type
                name_declarator = None
            else:
                base_type = arg.base_type.analyse(env)
                name_declarator, type = \
                    arg.declarator.analyse(base_type, env)
                arg.name = name_declarator.name
1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682
            if arg.name in directive_locals:
                type_node = directive_locals[arg.name]
                other_type = type_node.analyse_as_type(env)
                if other_type is None:
                    error(type_node.pos, "Not a type")
                elif (type is not PyrexTypes.py_object_type 
                        and not type.same_as(other_type)):
                    error(arg.base_type.pos, "Signature does not agree with previous declaration")
                    error(type_node.pos, "Previous declaration here")
                else:
                    type = other_type
1683
            if name_declarator and name_declarator.cname:
William Stein's avatar
William Stein committed
1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696
                error(self.pos,
                    "Python function argument cannot have C name specification")
            arg.type = type.as_argument_type()
            arg.hdr_type = None
            arg.needs_conversion = 0
            arg.needs_type_test = 0
            arg.is_generic = 1
            if arg.not_none and not arg.type.is_extension_type:
                error(self.pos,
                    "Only extension type arguments can have 'not None'")
        self.declare_pyfunction(env)
        self.analyse_signature(env)
        self.return_type = self.entry.signature.return_type()
1697

William Stein's avatar
William Stein committed
1698 1699
    def analyse_signature(self, env):
        any_type_tests_needed = 0
1700 1701 1702 1703 1704
        if self.entry.is_special:
            self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
        elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
            # Use the simpler calling signature for zero- and one-argument functions.
            if self.entry.signature is TypeSlots.pyfunction_signature:
1705 1706
                if len(self.args) == 0:
                    self.entry.signature = TypeSlots.pyfunction_noargs
1707 1708 1709
                elif len(self.args) == 1:
                    if self.args[0].default is None and not self.args[0].kw_only:
                        self.entry.signature = TypeSlots.pyfunction_onearg
1710 1711 1712
            elif self.entry.signature is TypeSlots.pymethod_signature:
                if len(self.args) == 1:
                    self.entry.signature = TypeSlots.unaryfunc
1713 1714 1715
                elif len(self.args) == 2:
                    if self.args[1].default is None and not self.args[1].kw_only:
                        self.entry.signature = TypeSlots.ibinaryfunc
William Stein's avatar
William Stein committed
1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
        sig = self.entry.signature
        nfixed = sig.num_fixed_args()
        for i in range(nfixed):
            if i < len(self.args):
                arg = self.args[i]
                arg.is_generic = 0
                if sig.is_self_arg(i):
                    arg.is_self_arg = 1
                    arg.hdr_type = arg.type = env.parent_type
                    arg.needs_conversion = 0
                else:
                    arg.hdr_type = sig.fixed_arg_type(i)
                    if not arg.type.same_as(arg.hdr_type):
                        if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
                            arg.needs_type_test = 1
                            any_type_tests_needed = 1
                        else:
                            arg.needs_conversion = 1
                if arg.needs_conversion:
                    arg.hdr_cname = Naming.arg_prefix + arg.name
                else:
                    arg.hdr_cname = Naming.var_prefix + arg.name
            else:
                self.bad_signature()
                return
        if nfixed < len(self.args):
            if not sig.has_generic_args:
                self.bad_signature()
            for arg in self.args:
Robert Bradshaw's avatar
Robert Bradshaw committed
1745 1746
                if arg.is_generic and \
                        (arg.type.is_extension_type or arg.type.is_builtin_type):
William Stein's avatar
William Stein committed
1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765
                    arg.needs_type_test = 1
                    any_type_tests_needed = 1
        if any_type_tests_needed:
            env.use_utility_code(arg_type_test_utility_code)
    
    def bad_signature(self):
        sig = self.entry.signature
        expected_str = "%d" % sig.num_fixed_args()
        if sig.has_generic_args:
            expected_str = expected_str + " or more"
        name = self.name
        if name.startswith("__") and name.endswith("__"):
            desc = "Special method"
        else:
            desc = "Method"
        error(self.pos,
            "%s %s has wrong number of arguments "
            "(%d declared, %s expected)" % (
                desc, self.name, len(self.args), expected_str))
1766 1767 1768

    def signature_has_nongeneric_args(self):
        argcount = len(self.args)
Stefan Behnel's avatar
Stefan Behnel committed
1769
        if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1770 1771 1772 1773 1774
            return 0
        return 1

    def signature_has_generic_args(self):
        return self.entry.signature.has_generic_args
William Stein's avatar
William Stein committed
1775 1776
    
    def declare_pyfunction(self, env):
1777 1778
        #print "DefNode.declare_pyfunction:", self.name, "in", env ###
        name = self.name
1779 1780 1781
        entry = env.lookup_here(self.name)
        if entry and entry.type.is_cfunction and not self.is_wrapper:
            warning(self.pos, "Overriding cdef method with def method.", 5)
1782 1783 1784 1785
        entry = env.declare_pyfunction(self.name, self.pos)
        self.entry = entry
        prefix = env.scope_prefix
        entry.func_cname = \
1786
            Naming.pyfunc_prefix + prefix + name
1787 1788
        entry.pymethdef_cname = \
            Naming.pymethdef_prefix + prefix + name
1789 1790
        if Options.docstrings:
            entry.doc = embed_position(self.pos, self.doc)
1791 1792
            entry.doc_cname = \
                Naming.funcdoc_prefix + prefix + name
1793 1794
        else:
            entry.doc = None
1795

William Stein's avatar
William Stein committed
1796 1797 1798 1799 1800 1801
    def declare_arguments(self, env):
        for arg in self.args:
            if not arg.name:
                error(arg.pos, "Missing argument name")
            if arg.needs_conversion:
                arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1802 1803
                env.control_flow.set_state((), (arg.name, 'source'), 'arg')
                env.control_flow.set_state((), (arg.name, 'initalized'), True)
William Stein's avatar
William Stein committed
1804 1805 1806 1807 1808
                if arg.type.is_pyobject:
                    arg.entry.init = "0"
                arg.entry.init_to_none = 0
            else:
                arg.entry = self.declare_argument(env, arg)
1809
            arg.entry.used = 1
William Stein's avatar
William Stein committed
1810
            arg.entry.is_self_arg = arg.is_self_arg
1811 1812 1813 1814
            if not arg.is_self_arg:
                arg.name_entry = env.get_string_const(
                    arg.name, identifier = True)
                env.add_py_string(arg.name_entry, identifier = True)
William Stein's avatar
William Stein committed
1815 1816 1817 1818 1819 1820 1821 1822 1823
            if arg.hdr_type:
                if arg.is_self_arg or \
                    (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
                        arg.entry.is_declared_generic = 1
        self.declare_python_arg(env, self.star_arg)
        self.declare_python_arg(env, self.starstar_arg)

    def declare_python_arg(self, env, arg):
        if arg:
1824
            entry = env.declare_var(arg.name, 
William Stein's avatar
William Stein committed
1825
                PyrexTypes.py_object_type, arg.pos)
1826 1827 1828 1829 1830
            entry.used = 1
            entry.init = "0"
            entry.init_to_none = 0
            entry.xdecref_cleanup = 1
            arg.entry = entry
1831
            env.control_flow.set_state((), (arg.name, 'initalized'), True)
William Stein's avatar
William Stein committed
1832 1833
            
    def analyse_expressions(self, env):
1834
        self.local_scope.directives = env.directives
William Stein's avatar
William Stein committed
1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849
        self.analyse_default_values(env)
        if env.is_py_class_scope:
            self.synthesize_assignment_node(env)
    
    def synthesize_assignment_node(self, env):
        import ExprNodes
        self.assmt = SingleAssignmentNode(self.pos,
            lhs = ExprNodes.NameNode(self.pos, name = self.name),
            rhs = ExprNodes.UnboundMethodNode(self.pos, 
                class_cname = env.class_obj_cname,
                function = ExprNodes.PyCFunctionNode(self.pos,
                    pymethdef_cname = self.entry.pymethdef_cname)))
        self.assmt.analyse_declarations(env)
        self.assmt.analyse_expressions(env)
            
1850
    def generate_function_header(self, code, with_pymethdef, proto_only=0):
William Stein's avatar
William Stein committed
1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862
        arg_code_list = []
        sig = self.entry.signature
        if sig.has_dummy_arg:
            arg_code_list.append(
                "PyObject *%s" % Naming.self_cname)
        for arg in self.args:
            if not arg.is_generic:
                if arg.is_self_arg:
                    arg_code_list.append("PyObject *%s" % arg.hdr_cname)
                else:
                    arg_code_list.append(
                        arg.hdr_type.declaration_code(arg.hdr_cname))
1863
        if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1864
            arg_code_list.append("PyObject *unused")
William Stein's avatar
William Stein committed
1865 1866 1867 1868 1869 1870 1871 1872
        if sig.has_generic_args:
            arg_code_list.append(
                "PyObject *%s, PyObject *%s"
                    % (Naming.args_cname, Naming.kwds_cname))
        arg_code = ", ".join(arg_code_list)
        dc = self.return_type.declaration_code(self.entry.func_cname)
        header = "static %s(%s)" % (dc, arg_code)
        code.putln("%s; /*proto*/" % header)
1873 1874
        if proto_only:
            return
1875
        if self.entry.doc and Options.docstrings:
1876 1877 1878
            docstr = self.entry.doc
            if not isinstance(docstr, str):
                docstr = docstr.utf8encode()
William Stein's avatar
William Stein committed
1879 1880 1881
            code.putln(
                'static char %s[] = "%s";' % (
                    self.entry.doc_cname,
1882
                    split_docstring(escape_byte_string(docstr))))
William Stein's avatar
William Stein committed
1883 1884 1885 1886 1887 1888 1889 1890 1891 1892
        if with_pymethdef:
            code.put(
                "static PyMethodDef %s = " % 
                    self.entry.pymethdef_cname)
            code.put_pymethoddef(self.entry, ";")
        code.putln("%s {" % header)

    def generate_argument_declarations(self, env, code):
        for arg in self.args:
            if arg.is_generic: # or arg.needs_conversion:
1893 1894 1895 1896
                if arg.needs_conversion:
                    code.putln("PyObject *%s = 0;" % arg.hdr_cname)
                else:
                    code.put_var_declaration(arg.entry)
William Stein's avatar
William Stein committed
1897 1898
    
    def generate_keyword_list(self, code):
1899 1900
        if self.signature_has_generic_args() and \
                self.signature_has_nongeneric_args():
William Stein's avatar
William Stein committed
1901
            code.put(
1902 1903
                "static PyObject **%s[] = {" %
                    Naming.pykwdlist_cname)
William Stein's avatar
William Stein committed
1904 1905
            for arg in self.args:
                if arg.is_generic:
1906
                    code.put('&%s,' % arg.name_entry.pystring_cname)
1907
            code.putln("0};")
1908

1909
    def generate_argument_parsing_code(self, env, code):
William Stein's avatar
William Stein committed
1910 1911
        # Generate PyArg_ParseTuple call for generic
        # arguments, if any.
1912 1913 1914 1915
        if self.entry.signature.has_dummy_arg:
            # get rid of unused argument warning
            code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))

1916 1917
        old_error_label = code.new_error_label()
        our_error_label = code.error_label
Stefan Behnel's avatar
Stefan Behnel committed
1918
        end_label = code.new_label("argument_unpacking_done")
1919

1920 1921 1922
        has_kwonly_args = self.num_kwonly_args > 0
        has_star_or_kw_args = self.star_arg is not None \
            or self.starstar_arg is not None or has_kwonly_args
1923

1924
        if not self.signature_has_generic_args():
1925 1926
            if has_star_or_kw_args:
                error(self.pos, "This method cannot have * or keyword arguments")
1927
            self.generate_argument_conversion_code(code)
1928

1929 1930
        elif not self.signature_has_nongeneric_args():
            # func(*args) or func(**kw) or func(*args, **kw)
1931
            self.generate_stararg_copy_code(code)
1932

1933
        else:
1934
            positional_args = []
1935
            kw_only_args = []
William Stein's avatar
William Stein committed
1936 1937 1938 1939 1940 1941
            default_seen = 0
            for arg in self.args:
                arg_entry = arg.entry
                if arg.is_generic:
                    if arg.default:
                        default_seen = 1
1942 1943 1944 1945 1946
                        if not arg.is_self_arg:
                            if arg.kw_only:
                                kw_only_args.append(arg)
                            else:
                                positional_args.append(arg)
1947
                    elif arg.kw_only:
1948
                        kw_only_args.append(arg)
1949
                        default_seen = 1
1950
                    elif default_seen:
William Stein's avatar
William Stein committed
1951
                        error(arg.pos, "Non-default argument following default argument")
1952 1953
                    elif not arg.is_self_arg:
                        positional_args.append(arg)
1954 1955
                if arg.type.from_py_function is None:
                    arg.type.create_from_py_utility_code(env)
1956

1957
            self.generate_tuple_and_keyword_parsing_code(
1958
                positional_args, kw_only_args, end_label, code)
1959

1960 1961
        code.error_label = old_error_label
        if code.label_used(our_error_label):
1962 1963
            if not code.label_used(end_label):
                code.put_goto(end_label)
1964 1965 1966 1967 1968 1969 1970 1971
            code.put_label(our_error_label)
            if has_star_or_kw_args:
                self.generate_arg_decref(self.star_arg, code)
                if self.starstar_arg:
                    if self.starstar_arg.entry.xdecref_cleanup:
                        code.put_var_xdecref(self.starstar_arg.entry)
                    else:
                        code.put_var_decref(self.starstar_arg.entry)
1972
            code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1973
            code.putln("return %s;" % self.error_value())
1974
        if code.label_used(end_label):
1975 1976
            code.put_label(end_label)

1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989
    def generate_arg_assignment(self, arg, item, code):
        if arg.type.is_pyobject:
            if arg.is_generic:
                item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
            code.putln("%s = %s;" % (arg.entry.cname, item))
        else:
            func = arg.type.from_py_function
            if func:
                code.putln("%s = %s(%s); %s" % (
                    arg.entry.cname,
                    func,
                    item,
                    code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1990
            else:
1991
                error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
William Stein's avatar
William Stein committed
1992 1993 1994 1995 1996
    
    def generate_arg_xdecref(self, arg, code):
        if arg:
            code.put_var_xdecref(arg.entry)
    
1997 1998 1999
    def generate_arg_decref(self, arg, code):
        if arg:
            code.put_var_decref(arg.entry)
William Stein's avatar
William Stein committed
2000

2001 2002
    def generate_stararg_copy_code(self, code):
        if not self.star_arg:
2003 2004 2005 2006 2007 2008
            code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
            code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
                       Naming.args_cname)
            code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
                    self.name.utf8encode(), Naming.args_cname, self.error_value()))
            code.putln("}")
2009

2010 2011
        code.globalstate.use_utility_code(keyword_string_check_utility_code)

2012 2013 2014 2015 2016 2017 2018 2019
        if self.starstar_arg:
            if self.star_arg:
                kwarg_check = "unlikely(%s)" % Naming.kwds_cname
            else:
                kwarg_check = "%s" % Naming.kwds_cname
        else:
            kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
                Naming.kwds_cname, Naming.kwds_cname)
2020
        code.putln(
2021 2022
            "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
                kwarg_check, Naming.kwds_cname, self.name,
2023
                bool(self.starstar_arg), self.error_value()))
2024

2025
        if self.starstar_arg:
2026
            code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2027 2028 2029
                    self.starstar_arg.entry.cname,
                    Naming.kwds_cname,
                    Naming.kwds_cname))
2030 2031
            code.putln("if (unlikely(!%s)) return %s;" % (
                    self.starstar_arg.entry.cname, self.error_value()))
2032
            self.starstar_arg.entry.xdecref_cleanup = 0
2033 2034
            code.put_gotref(self.starstar_arg.entry.cname)
            
2035

2036 2037 2038 2039 2040 2041 2042
        if self.star_arg:
            code.put_incref(Naming.args_cname, py_object_type)
            code.putln("%s = %s;" % (
                    self.star_arg.entry.cname,
                    Naming.args_cname))
            self.star_arg.entry.xdecref_cleanup = 0

2043
    def generate_tuple_and_keyword_parsing_code(self, positional_args,
2044 2045
                                                kw_only_args, success_label, code):
        argtuple_error_label = code.new_label("argtuple_error")
2046

2047 2048 2049 2050
        min_positional_args = self.num_required_args - self.num_required_kw_args
        if len(self.args) > 0 and self.args[0].is_self_arg:
            min_positional_args -= 1
        max_positional_args = len(positional_args)
2051 2052
        has_fixed_positional_count = not self.star_arg and \
            min_positional_args == max_positional_args
2053

2054
        code.globalstate.use_utility_code(raise_double_keywords_utility_code)
Stefan Behnel's avatar
Stefan Behnel committed
2055 2056 2057 2058
        code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
        if self.num_required_kw_args:
            code.globalstate.use_utility_code(raise_keyword_required_utility_code)

2059 2060 2061 2062 2063
        if self.starstar_arg or self.star_arg:
            self.generate_stararg_init_code(max_positional_args, code)

        # --- optimised code when we receive keyword arguments
        if self.num_required_kw_args:
2064
            likely_hint = "likely"
2065
        else:
2066 2067
            likely_hint = "unlikely"
        code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2068 2069
        self.generate_keyword_unpacking_code(
            min_positional_args, max_positional_args,
2070
            has_fixed_positional_count,
2071 2072 2073
            positional_args, kw_only_args, argtuple_error_label, code)

        # --- optimised code when we do not receive any keyword arguments
2074
        if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2075 2076 2077 2078 2079 2080 2081 2082 2083
            # Python raises arg tuple related errors first, so we must
            # check the length here
            if min_positional_args == max_positional_args and not self.star_arg:
                compare = '!='
            else:
                compare = '<'
            code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
                    Naming.args_cname, compare, min_positional_args))
            code.put_goto(argtuple_error_label)
2084

2085 2086 2087 2088 2089 2090 2091 2092 2093 2094
        if self.num_required_kw_args:
            # pure error case: keywords required but not passed
            if max_positional_args > min_positional_args and not self.star_arg:
                code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
                        Naming.args_cname, max_positional_args))
                code.put_goto(argtuple_error_label)
            code.putln('} else {')
            for i, arg in enumerate(kw_only_args):
                if not arg.default:
                    # required keyword-only argument missing
2095 2096 2097
                    code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
                            self.name.utf8encode(),
                            arg.name_entry.pystring_cname))
2098 2099
                    code.putln(code.error_goto(self.pos))
                    break
2100

2101 2102 2103
        elif min_positional_args == max_positional_args:
            # parse the exact number of positional arguments from the
            # args tuple
2104 2105 2106 2107 2108
            code.putln('} else {')
            for i, arg in enumerate(positional_args):
                item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
                self.generate_arg_assignment(arg, item, code)
            self.generate_arg_default_assignments(code)
2109

2110 2111 2112 2113
        else:
            # parse the positional arguments from the variable length
            # args tuple
            code.putln('} else {')
2114
            self.generate_arg_default_assignments(code)
2115
            code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2116 2117
            if self.star_arg:
                code.putln('default:')
2118 2119 2120 2121 2122 2123 2124 2125 2126
            reversed_args = list(enumerate(positional_args))[::-1]
            for i, arg in reversed_args:
                if i >= min_positional_args-1:
                    if min_positional_args > 1:
                        code.putln('case %2d:' % (i+1)) # pure code beautification
                    else:
                        code.put('case %2d: ' % (i+1))
                item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
                self.generate_arg_assignment(arg, item, code)
Robert Bradshaw's avatar
Robert Bradshaw committed
2127 2128 2129
            if min_positional_args == 0:
                code.put('case  0: ')
            code.putln('break;')
2130 2131 2132 2133 2134 2135
            if self.star_arg:
                if min_positional_args:
                    for i in range(min_positional_args-1, -1, -1):
                        code.putln('case %2d:' % i)
                    code.put_goto(argtuple_error_label)
            else:
2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150
                code.put('default: ')
                code.put_goto(argtuple_error_label)
            code.putln('}')

        code.putln('}')

        if code.label_used(argtuple_error_label):
            code.put_goto(success_label)
            code.put_label(argtuple_error_label)
            code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
                    self.name.utf8encode(), has_fixed_positional_count,
                    min_positional_args, max_positional_args,
                    Naming.args_cname))
            code.putln(code.error_goto(self.pos))

2151 2152 2153 2154 2155 2156 2157 2158
    def generate_arg_default_assignments(self, code):
        for arg in self.args:
            if arg.is_generic and arg.default:
                code.putln(
                    "%s = %s;" % (
                        arg.entry.cname,
                        arg.default_result_code))

2159
    def generate_stararg_init_code(self, max_positional_args, code):
2160
        if self.starstar_arg:
2161
            self.starstar_arg.entry.xdecref_cleanup = 0
Stefan Behnel's avatar
Stefan Behnel committed
2162 2163 2164 2165
            code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
                    self.starstar_arg.entry.cname,
                    self.starstar_arg.entry.cname,
                    self.error_value()))
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2166
            code.put_gotref(self.starstar_arg.entry.cname)
Stefan Behnel's avatar
Stefan Behnel committed
2167 2168 2169 2170 2171 2172 2173 2174
        if self.star_arg:
            self.star_arg.entry.xdecref_cleanup = 0
            code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
                    Naming.args_cname,
                    max_positional_args))
            code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
                    self.star_arg.entry.cname, Naming.args_cname,
                    max_positional_args, Naming.args_cname))
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2175
            code.put_gotref(self.star_arg.entry.cname)
Stefan Behnel's avatar
Stefan Behnel committed
2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188
            if self.starstar_arg:
                code.putln("")
                code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
                code.put_decref(self.starstar_arg.entry.cname, py_object_type)
                code.putln('return %s;' % self.error_value())
                code.putln('}')
            else:
                code.putln("if (unlikely(!%s)) return %s;" % (
                        self.star_arg.entry.cname, self.error_value()))
            code.putln('} else {')
            code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
            code.put_incref(Naming.empty_tuple, py_object_type)
            code.putln('}')
2189

2190
    def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2191 2192
                                        has_fixed_positional_count, positional_args,
                                        kw_only_args, argtuple_error_label, code):
2193 2194 2195
        all_args = tuple(positional_args) + tuple(kw_only_args)
        max_args = len(all_args)

2196
        default_args = []
2197
        for i, arg in enumerate(all_args):
2198 2199 2200 2201
            if arg.default and arg.type.is_pyobject:
                default_value = arg.default_result_code
                if arg.type is not PyrexTypes.py_object_type:
                    default_value = "(PyObject*)"+default_value
2202
                default_args.append((i, default_value))
2203

2204 2205
        code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
                   Naming.kwds_cname)
2206 2207 2208 2209 2210 2211
        # it looks funny to separate the init-to-0 from setting the
        # default value, but C89 needs this
        code.putln("PyObject* values[%d] = {%s};" % (
            max_args, ','.join(['0']*max_args)))
        for i, default_value in default_args:
            code.putln('values[%d] = %s;' % (i, default_value))
2212

Stefan Behnel's avatar
Stefan Behnel committed
2213
        # parse the tuple and check that it's not too long
2214
        code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
Stefan Behnel's avatar
Stefan Behnel committed
2215 2216
        if self.star_arg:
            code.putln('default:')
2217
        for i in range(max_positional_args-1, -1, -1):
2218
            code.put('case %2d: ' % (i+1))
2219 2220
            code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
                    i, Naming.args_cname, i))
2221
        code.putln('case  0: break;')
2222
        if not self.star_arg:
Stefan Behnel's avatar
Stefan Behnel committed
2223
            code.put('default: ') # more arguments than allowed
2224
            code.put_goto(argtuple_error_label)
2225 2226
        code.putln('}')

Stefan Behnel's avatar
Stefan Behnel committed
2227 2228
        # now fill up the positional/required arguments with values
        # from the kw dict
2229
        if self.num_required_args or max_positional_args > 0:
Stefan Behnel's avatar
Stefan Behnel committed
2230 2231 2232 2233
            last_required_arg = -1
            for i, arg in enumerate(all_args):
                if not arg.default:
                    last_required_arg = i
2234 2235 2236
            if last_required_arg < max_positional_args:
                last_required_arg = max_positional_args-1
            num_required_args = self.num_required_args
Stefan Behnel's avatar
Stefan Behnel committed
2237 2238
            if max_positional_args > 0:
                code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2239
            for i, arg in enumerate(all_args[:last_required_arg+1]):
Stefan Behnel's avatar
Stefan Behnel committed
2240
                if max_positional_args > 0 and i <= max_positional_args:
2241 2242 2243 2244 2245
                    if self.star_arg and i == max_positional_args:
                        code.putln('default:')
                    else:
                        code.putln('case %2d:' % i)
                if arg.default:
2246 2247 2248 2249 2250 2251
                    if arg.kw_only:
                        # handled separately below
                        continue
                    code.putln('if (kw_args > %d) {' % num_required_args)
                    code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
                        Naming.kwds_cname, arg.name_entry.pystring_cname))
Stefan Behnel's avatar
Stefan Behnel committed
2252
                    code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2253 2254 2255 2256
                    code.putln('}')
                else:
                    num_required_args -= 1
                    code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2257
                        i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274
                    code.putln('if (likely(values[%d])) kw_args--;' % i);
                    if i < min_positional_args:
                        if i == 0:
                            # special case: we know arg 0 is missing
                            code.put('else ')
                            code.put_goto(argtuple_error_label)
                        else:
                            # print the correct number of values (args or
                            # kwargs) that were passed into positional
                            # arguments up to this point
                            code.putln('else {')
                            code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
                                    self.name.utf8encode(), has_fixed_positional_count,
                                    min_positional_args, max_positional_args, i))
                            code.putln(code.error_goto(self.pos))
                            code.putln('}')
                    elif arg.kw_only:
2275
                        code.putln('else {')
2276 2277
                        code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
                                self.name.utf8encode(), arg.name_entry.pystring_cname))
2278 2279
                        code.putln(code.error_goto(self.pos))
                        code.putln('}')
Stefan Behnel's avatar
Stefan Behnel committed
2280 2281
            if max_positional_args > 0:
                code.putln('}')
2282

2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304
        if kw_only_args and not self.starstar_arg:
            # unpack optional keyword-only arguments
            # checking for interned strings in a dict is faster than iterating
            # but it's too likely that we must iterate if we expect **kwargs
            optional_args = []
            for i, arg in enumerate(all_args[max_positional_args:]):
                if not arg.kw_only or not arg.default:
                    continue
                optional_args.append((i+max_positional_args, arg))
            if optional_args:
                # this mimics an unrolled loop so that we can "break" out of it
                code.putln('while (kw_args > 0) {')
                code.putln('PyObject* value;')
                for i, arg in optional_args:
                    code.putln(
                        'value = PyDict_GetItem(%s, %s);' % (
                        Naming.kwds_cname, arg.name_entry.pystring_cname))
                    code.putln(
                        'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
                code.putln('break;')
                code.putln('}')

2305
        code.putln('if (unlikely(kw_args > 0)) {')
2306 2307
        # non-positional/-required kw args left in dict: default args,
        # kw-only args, **kwargs or error
Stefan Behnel's avatar
Stefan Behnel committed
2308 2309 2310 2311 2312
        #
        # This is sort of a catch-all: except for checking required
        # arguments, this will always do the right thing for unpacking
        # keyword arguments, so that we can concentrate on optimising
        # common cases above.
2313 2314 2315
        if max_positional_args == 0:
            pos_arg_count = "0"
        elif self.star_arg:
Stefan Behnel's avatar
Stefan Behnel committed
2316 2317 2318 2319 2320 2321
            code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
                    Naming.args_cname, max_positional_args,
                    Naming.args_cname, max_positional_args))
            pos_arg_count = "used_pos_args"
        else:
            pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2322
        code.globalstate.use_utility_code(parse_keywords_utility_code)
Stefan Behnel's avatar
Stefan Behnel committed
2323
        code.put(
2324
            'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
Stefan Behnel's avatar
Stefan Behnel committed
2325 2326 2327 2328 2329
                Naming.kwds_cname,
                Naming.pykwdlist_cname,
                self.starstar_arg and self.starstar_arg.entry.cname or '0',
                pos_arg_count,
                self.name.utf8encode()))
2330
        code.putln(code.error_goto(self.pos))
2331
        code.putln('}')
2332

2333
        # convert arg values to their final type and assign them
2334
        for i, arg in enumerate(all_args):
2335
            if arg.default and not arg.type.is_pyobject:
2336 2337
                code.putln("if (values[%d]) {" % i)
            self.generate_arg_assignment(arg, "values[%d]" % i, code)
2338
            if arg.default and not arg.type.is_pyobject:
2339 2340 2341 2342 2343
                code.putln('} else {')
                code.putln(
                    "%s = %s;" % (
                        arg.entry.cname,
                        arg.default_result_code))
2344
                code.putln('}')
2345

William Stein's avatar
William Stein committed
2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357
    def generate_argument_conversion_code(self, code):
        # Generate code to convert arguments from
        # signature type to declared type, if needed.
        for arg in self.args:
            if arg.needs_conversion:
                self.generate_arg_conversion(arg, code)

    def generate_arg_conversion(self, arg, code):
        # Generate conversion code for one argument.
        old_type = arg.hdr_type
        new_type = arg.type
        if old_type.is_pyobject:
Robert Bradshaw's avatar
Robert Bradshaw committed
2358 2359 2360 2361
            if arg.default:
                code.putln("if (%s) {" % arg.hdr_cname)
            else:
                code.putln("assert(%s); {" % arg.hdr_cname)
William Stein's avatar
William Stein committed
2362
            self.generate_arg_conversion_from_pyobject(arg, code)
Robert Bradshaw's avatar
Robert Bradshaw committed
2363
            code.putln("}")
William Stein's avatar
William Stein committed
2364 2365 2366 2367 2368 2369 2370 2371
        elif new_type.is_pyobject:
            self.generate_arg_conversion_to_pyobject(arg, code)
        else:
            if new_type.assignable_from(old_type):
                code.putln(
                    "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
            else:
                error(arg.pos,
2372
                    "Cannot convert 1 argument from '%s' to '%s'" %
William Stein's avatar
William Stein committed
2373 2374 2375 2376 2377
                        (old_type, new_type))
    
    def generate_arg_conversion_from_pyobject(self, arg, code):
        new_type = arg.type
        func = new_type.from_py_function
2378
        # copied from CoerceFromPyTypeNode
William Stein's avatar
William Stein committed
2379
        if func:
Robert Bradshaw's avatar
Robert Bradshaw committed
2380
            code.putln("%s = %s(%s); %s" % (
William Stein's avatar
William Stein committed
2381 2382 2383
                arg.entry.cname,
                func,
                arg.hdr_cname,
2384
                code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
William Stein's avatar
William Stein committed
2385 2386 2387 2388 2389 2390 2391 2392 2393
        else:
            error(arg.pos, 
                "Cannot convert Python object argument to type '%s'" 
                    % new_type)
    
    def generate_arg_conversion_to_pyobject(self, arg, code):
        old_type = arg.hdr_type
        func = old_type.to_py_function
        if func:
Robert Bradshaw's avatar
Robert Bradshaw committed
2394
            code.putln("%s = %s(%s); %s" % (
William Stein's avatar
William Stein committed
2395 2396 2397
                arg.entry.cname,
                func,
                arg.hdr_cname,
Robert Bradshaw's avatar
Robert Bradshaw committed
2398
                code.error_goto_if_null(arg.entry.cname, arg.pos)))
2399
            code.put_var_gotref(arg.entry)
William Stein's avatar
William Stein committed
2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418
        else:
            error(arg.pos,
                "Cannot convert argument of type '%s' to Python object"
                    % old_type)

    def generate_argument_type_tests(self, code):
        # Generate type tests for args whose signature
        # type is PyObject * and whose declared type is
        # a subtype thereof.
        for arg in self.args:
            if arg.needs_type_test:
                self.generate_arg_type_test(arg, code)
    
    def generate_arg_type_test(self, arg, code):
        # Generate type test for one argument.
        if arg.type.typeobj_is_available():
            typeptr_cname = arg.type.typeptr_cname
            arg_code = "((PyObject *)%s)" % arg.entry.cname
            code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
2419
                'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
William Stein's avatar
William Stein committed
2420 2421 2422 2423
                    arg_code, 
                    typeptr_cname,
                    not arg.not_none,
                    arg.name,
Robert Bradshaw's avatar
Robert Bradshaw committed
2424
                    arg.type.is_builtin_type,
William Stein's avatar
William Stein committed
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435
                    code.error_goto(arg.pos)))
        else:
            error(arg.pos, "Cannot test type of extern C class "
                "without type object name specification")
    
    def error_value(self):
        return self.entry.signature.error_value
    
    def caller_will_check_exceptions(self):
        return 1
            
2436 2437 2438 2439 2440 2441 2442 2443 2444 2445
class OverrideCheckNode(StatNode):
    # A Node for dispatching to the def method if it
    # is overriden. 
    #
    #  py_func
    #
    #  args
    #  func_temp
    #  body
    
Robert Bradshaw's avatar
Robert Bradshaw committed
2446
    child_attrs = ['body']
2447 2448
    
    body = None
Robert Bradshaw's avatar
Robert Bradshaw committed
2449

2450 2451
    def analyse_expressions(self, env):
        self.args = env.arg_entries
2452 2453 2454 2455
        if self.py_func.is_module_scope:
            first_arg = 0
        else:
            first_arg = 1
2456 2457
        import ExprNodes
        self.func_node = ExprNodes.PyTempNode(self.pos, env)
2458
        call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2459 2460
        call_node = ExprNodes.SimpleCallNode(self.pos,
                                             function=self.func_node, 
2461
                                             args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2462 2463 2464 2465 2466
        self.body = ReturnStatNode(self.pos, value=call_node)
        self.body.analyse_expressions(env)
        
    def generate_execution_code(self, code):
        # Check to see if we are an extension type
2467 2468 2469 2470
        if self.py_func.is_module_scope:
            self_arg = "((PyObject *)%s)" % Naming.module_cname
        else:
            self_arg = "((PyObject *)%s)" % self.args[0].cname
2471
        code.putln("/* Check if called by wrapper */")
2472
        code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2473
        code.putln("/* Check if overriden in Python */")
2474 2475 2476
        if self.py_func.is_module_scope:
            code.putln("else {")
        else:
2477
            code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2478
        err = code.error_goto_if_null(self.func_node.result(), self.pos)
2479
        # need to get attribute manually--scope would return cdef method
2480
        code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2481
        code.put_gotref(self.func_node.py_result())
2482
        is_builtin_function_or_method = 'PyCFunction_Check(%s)' % self.func_node.result()
2483
        is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2484 2485 2486
        code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
        self.body.generate_execution_code(code)
        code.putln('}')
2487
        code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2488 2489
        code.putln("}")

Robert Bradshaw's avatar
Robert Bradshaw committed
2490 2491
class ClassDefNode(StatNode, BlockNode):
    pass
2492

Robert Bradshaw's avatar
Robert Bradshaw committed
2493
class PyClassDefNode(ClassDefNode):
William Stein's avatar
William Stein committed
2494 2495
    #  A Python class definition.
    #
Stefan Behnel's avatar
Stefan Behnel committed
2496
    #  name     EncodedString   Name of the class
William Stein's avatar
William Stein committed
2497 2498 2499 2500 2501 2502 2503 2504 2505 2506
    #  doc      string or None
    #  body     StatNode        Attribute definition code
    #  entry    Symtab.Entry
    #  scope    PyClassScope
    #
    #  The following subnodes are constructed internally:
    #
    #  dict     DictNode   Class dictionary
    #  classobj ClassNode  Class object
    #  target   NameNode   Variable to assign class object to
2507 2508

    child_attrs = ["body", "dict", "classobj", "target"]
William Stein's avatar
William Stein committed
2509 2510 2511 2512 2513 2514 2515 2516
    
    def __init__(self, pos, name, bases, doc, body):
        StatNode.__init__(self, pos)
        self.name = name
        self.doc = doc
        self.body = body
        import ExprNodes
        self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2517
        if self.doc and Options.docstrings:
2518
            doc = embed_position(self.pos, self.doc)
2519
            doc_node = ExprNodes.StringNode(pos, value = doc)
William Stein's avatar
William Stein committed
2520 2521
        else:
            doc_node = None
2522
        self.classobj = ExprNodes.ClassNode(pos, name = name,
William Stein's avatar
William Stein committed
2523 2524
            bases = bases, dict = self.dict, doc = doc_node)
        self.target = ExprNodes.NameNode(pos, name = name)
2525
        
2526 2527
    def as_cclass(self):
        """
2528
        Return this node as if it were declared as an extension class
2529 2530 2531 2532 2533 2534 2535 2536
        """
        bases = self.classobj.bases.args
        if len(bases) == 0:
            base_class_name = None
            base_class_module = None
        elif len(bases) == 1:
            base = bases[0]
            path = []
2537 2538
            from ExprNodes import AttributeNode, NameNode
            while isinstance(base, AttributeNode):
2539 2540
                path.insert(0, base.attribute)
                base = base.obj
2541
            if isinstance(base, NameNode):
2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563
                path.insert(0, base.name)
                base_class_name = path[-1]
                if len(path) > 1:
                    base_class_module = u'.'.join(path[:-1])
                else:
                    base_class_module = None
            else:
                error(self.classobj.bases.args.pos, "Invalid base class")
        else:
            error(self.classobj.bases.args.pos, "C class may only have one base class")
            return None
        
        return CClassDefNode(self.pos, 
                             visibility = 'private',
                             module_name = None,
                             class_name = self.name,
                             base_class_module = base_class_module,
                             base_class_name = base_class_name,
                             body = self.body,
                             in_pxd = False,
                             doc = self.doc)
        
2564 2565 2566 2567 2568 2569
    def create_scope(self, env):
        genv = env
        while env.is_py_class_scope or env.is_c_class_scope:
            env = env.outer_scope
        cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
        return cenv
William Stein's avatar
William Stein committed
2570 2571 2572
    
    def analyse_declarations(self, env):
        self.target.analyse_target_declaration(env)
2573
        cenv = self.create_scope(env)
2574
        cenv.directives = env.directives
2575 2576
        cenv.class_obj_cname = self.target.entry.cname
        self.body.analyse_declarations(cenv)
William Stein's avatar
William Stein committed
2577 2578 2579 2580 2581
    
    def analyse_expressions(self, env):
        self.dict.analyse_expressions(env)
        self.classobj.analyse_expressions(env)
        genv = env.global_scope()
2582
        cenv = self.scope
2583 2584
        cenv.class_dict_cname = self.dict.result()
        cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
William Stein's avatar
William Stein committed
2585
        self.body.analyse_expressions(cenv)
2586
        self.target.analyse_target_expression(env, self.classobj)
William Stein's avatar
William Stein committed
2587
        self.dict.release_temp(env)
2588 2589
        #self.classobj.release_temp(env)
        #self.target.release_target_temp(env)
William Stein's avatar
William Stein committed
2590
    
2591
    def generate_function_definitions(self, env, code):
William Stein's avatar
William Stein committed
2592
        self.generate_py_string_decls(self.scope, code)
2593
        self.body.generate_function_definitions(self.scope, code)
William Stein's avatar
William Stein committed
2594 2595 2596 2597 2598 2599 2600
    
    def generate_execution_code(self, code):
        self.dict.generate_evaluation_code(code)
        self.classobj.generate_evaluation_code(code)
        self.body.generate_execution_code(code)
        self.target.generate_assignment_code(self.classobj, code)
        self.dict.generate_disposal_code(code)
2601
        self.dict.free_temps(code)
William Stein's avatar
William Stein committed
2602 2603


Robert Bradshaw's avatar
Robert Bradshaw committed
2604
class CClassDefNode(ClassDefNode):
William Stein's avatar
William Stein committed
2605 2606 2607 2608
    #  An extension type definition.
    #
    #  visibility         'private' or 'public' or 'extern'
    #  typedef_flag       boolean
Stefan Behnel's avatar
Stefan Behnel committed
2609
    #  api                boolean
William Stein's avatar
William Stein committed
2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621
    #  module_name        string or None    For import of extern type objects
    #  class_name         string            Unqualified name of class
    #  as_name            string or None    Name to declare as in this scope
    #  base_class_module  string or None    Module containing the base class
    #  base_class_name    string or None    Name of the base class
    #  objstruct_name     string or None    Specified C name of object struct
    #  typeobj_name       string or None    Specified C name of type object
    #  in_pxd             boolean           Is in a .pxd file
    #  doc                string or None
    #  body               StatNode or None
    #  entry              Symtab.Entry
    #  base_type          PyExtensionType or None
2622 2623
    #  buffer_defaults_node DictNode or None Declares defaults for a buffer
    #  buffer_defaults_pos
2624

2625
    child_attrs = ["body"]
2626 2627
    buffer_defaults_node = None
    buffer_defaults_pos = None
2628 2629 2630 2631
    typedef_flag = False
    api = False
    objstruct_name = None
    typeobj_name = None
2632

William Stein's avatar
William Stein committed
2633 2634 2635 2636
    def analyse_declarations(self, env):
        #print "CClassDefNode.analyse_declarations:", self.class_name
        #print "...visibility =", self.visibility
        #print "...module_name =", self.module_name
2637 2638 2639 2640 2641 2642 2643 2644 2645

        import Buffer
        if self.buffer_defaults_node:
            buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
                                                            env, [], self.buffer_defaults_node,
                                                            need_complete=False)
        else:
            buffer_defaults = None

William Stein's avatar
William Stein committed
2646 2647 2648 2649
        if env.in_cinclude and not self.objstruct_name:
            error(self.pos, "Object struct name specification required for "
                "C class defined in 'extern from' block")
        self.base_type = None
2650 2651 2652 2653 2654 2655 2656 2657 2658
        # Now that module imports are cached, we need to 
        # import the modules for extern classes. 
        if self.module_name:
            self.module = None
            for module in env.cimported_modules:
                if module.name == self.module_name:
                    self.module = module
            if self.module is None:
                self.module = ModuleScope(self.module_name, None, env.context)
2659
                self.module.has_extern_class = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2660
                env.add_imported_module(self.module)
2661

William Stein's avatar
William Stein committed
2662 2663 2664 2665 2666
        if self.base_class_name:
            if self.base_class_module:
                base_class_scope = env.find_module(self.base_class_module, self.pos)
            else:
                base_class_scope = env
2667 2668 2669 2670 2671 2672
            if self.base_class_name == 'object':
                # extension classes are special and don't need to inherit from object
                if base_class_scope is None or base_class_scope.lookup('object') is None:
                    self.base_class_name = None
                    self.base_class_module = None
                    base_class_scope = None
William Stein's avatar
William Stein committed
2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684
            if base_class_scope:
                base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
                if base_class_entry:
                    if not base_class_entry.is_type:
                        error(self.pos, "'%s' is not a type name" % self.base_class_name)
                    elif not base_class_entry.type.is_extension_type:
                        error(self.pos, "'%s' is not an extension type" % self.base_class_name)
                    elif not base_class_entry.type.is_complete():
                        error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
                    else:
                        self.base_type = base_class_entry.type
        has_body = self.body is not None
2685
        if self.module_name and self.visibility != 'extern':
2686 2687 2688 2689 2690 2691
            module_path = self.module_name.split(".")
            home_scope = env.find_imported_module(module_path, self.pos)
            if not home_scope:
                return
        else:
            home_scope = env
2692 2693 2694

        if self.visibility == 'extern':
            if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
2695
                warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
2696

2697
        self.entry = home_scope.declare_c_class(
William Stein's avatar
William Stein committed
2698 2699 2700 2701 2702 2703 2704 2705 2706
            name = self.class_name, 
            pos = self.pos,
            defining = has_body and self.in_pxd,
            implementing = has_body and not self.in_pxd,
            module_name = self.module_name,
            base_type = self.base_type,
            objstruct_cname = self.objstruct_name,
            typeobj_cname = self.typeobj_name,
            visibility = self.visibility,
Stefan Behnel's avatar
Stefan Behnel committed
2707
            typedef_flag = self.typedef_flag,
2708 2709
            api = self.api,
            buffer_defaults = buffer_defaults)
2710 2711
        if home_scope is not env and self.visibility == 'extern':
            env.add_imported_entry(self.class_name, self.entry, pos)
William Stein's avatar
William Stein committed
2712
        scope = self.entry.type.scope
2713 2714
        if scope is not None:
            scope.directives = env.directives
2715

2716
        if self.doc and Options.docstrings:
2717
            scope.doc = embed_position(self.pos, self.doc)
2718
            
William Stein's avatar
William Stein committed
2719 2720 2721 2722 2723 2724 2725 2726 2727 2728
        if has_body:
            self.body.analyse_declarations(scope)
            if self.in_pxd:
                scope.defined = 1
            else:
                scope.implemented = 1
        env.allocate_vtable_names(self.entry)
        
    def analyse_expressions(self, env):
        if self.body:
Robert Bradshaw's avatar
Robert Bradshaw committed
2729 2730
            scope = self.entry.type.scope
            self.body.analyse_expressions(scope)
William Stein's avatar
William Stein committed
2731
    
2732
    def generate_function_definitions(self, env, code):
2733
        self.generate_py_string_decls(self.entry.type.scope, code)
William Stein's avatar
William Stein committed
2734 2735
        if self.body:
            self.body.generate_function_definitions(
2736
                self.entry.type.scope, code)
William Stein's avatar
William Stein committed
2737 2738 2739 2740 2741 2742
    
    def generate_execution_code(self, code):
        # This is needed to generate evaluation code for
        # default values of method arguments.
        if self.body:
            self.body.generate_execution_code(code)
2743 2744 2745 2746
            
    def annotate(self, code):
        if self.body:
            self.body.annotate(code)
William Stein's avatar
William Stein committed
2747 2748 2749 2750 2751 2752


class PropertyNode(StatNode):
    #  Definition of a property in an extension type.
    #
    #  name   string
2753
    #  doc    EncodedString or None    Doc string
William Stein's avatar
William Stein committed
2754 2755
    #  body   StatListNode
    
2756 2757
    child_attrs = ["body"]

William Stein's avatar
William Stein committed
2758 2759 2760
    def analyse_declarations(self, env):
        entry = env.declare_property(self.name, self.doc, self.pos)
        if entry:
2761
            if self.doc and Options.docstrings:
2762 2763
                doc_entry = env.get_string_const(
                    self.doc, identifier = False)
William Stein's avatar
William Stein committed
2764
                entry.doc_cname = doc_entry.cname
2765
            entry.scope.directives = env.directives
William Stein's avatar
William Stein committed
2766
            self.body.analyse_declarations(entry.scope)
2767

William Stein's avatar
William Stein committed
2768 2769 2770
    def analyse_expressions(self, env):
        self.body.analyse_expressions(env)
    
2771 2772
    def generate_function_definitions(self, env, code):
        self.body.generate_function_definitions(env, code)
William Stein's avatar
William Stein committed
2773 2774 2775 2776

    def generate_execution_code(self, code):
        pass

2777 2778 2779
    def annotate(self, code):
        self.body.annotate(code)

William Stein's avatar
William Stein committed
2780 2781 2782 2783 2784 2785

class GlobalNode(StatNode):
    # Global variable declaration.
    #
    # names    [string]
    
2786 2787
    child_attrs = []

William Stein's avatar
William Stein committed
2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802
    def analyse_declarations(self, env):
        for name in self.names:
            env.declare_global(name, self.pos)

    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        pass


class ExprStatNode(StatNode):
    #  Expression used as a statement.
    #
    #  expr   ExprNode
2803 2804

    child_attrs = ["expr"]
William Stein's avatar
William Stein committed
2805
    
Robert Bradshaw's avatar
Robert Bradshaw committed
2806 2807 2808
    def analyse_declarations(self, env):
        import ExprNodes
        if isinstance(self.expr, ExprNodes.GeneralCallNode):
2809
            func = self.expr.function.as_cython_attribute()
Robert Bradshaw's avatar
Robert Bradshaw committed
2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821
            if func == u'declare':
                args, kwds = self.expr.explicit_args_kwds()
                if len(args):
                    error(self.expr.pos, "Variable names must be specified.")
                for var, type_node in kwds.key_value_pairs:
                    type = type_node.analyse_as_type(env)
                    if type is None:
                        error(type_node.pos, "Unknown type")
                    else:
                        env.declare_var(var.value, type, var.pos, is_cdef = True)
                self.__class__ = PassStatNode
    
William Stein's avatar
William Stein committed
2822 2823 2824 2825 2826 2827
    def analyse_expressions(self, env):
        self.expr.analyse_expressions(env)
        self.expr.release_temp(env)
    
    def generate_execution_code(self, code):
        self.expr.generate_evaluation_code(code)
2828 2829
        if not self.expr.is_temp and self.expr.result():
            code.putln("%s;" % self.expr.result())
William Stein's avatar
William Stein committed
2830
        self.expr.generate_disposal_code(code)
2831
        self.expr.free_temps(code)
William Stein's avatar
William Stein committed
2832

2833 2834 2835
    def annotate(self, code):
        self.expr.annotate(code)

William Stein's avatar
William Stein committed
2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846

class AssignmentNode(StatNode):
    #  Abstract base class for assignment nodes.
    #
    #  The analyse_expressions and generate_execution_code
    #  phases of assignments are split into two sub-phases
    #  each, to enable all the right hand sides of a
    #  parallel assignment to be evaluated before assigning
    #  to any of the left hand sides.

    def analyse_expressions(self, env):
2847 2848 2849 2850
        self.analyse_types(env)
        self.allocate_rhs_temps(env)
        self.allocate_lhs_temps(env)

2851 2852 2853
#       def analyse_expressions(self, env):
#           self.analyse_expressions_1(env)
#           self.analyse_expressions_2(env)
William Stein's avatar
William Stein committed
2854 2855 2856 2857

    def generate_execution_code(self, code):
        self.generate_rhs_evaluation_code(code)
        self.generate_assignment_code(code)
2858
        
William Stein's avatar
William Stein committed
2859 2860 2861 2862 2863 2864 2865 2866

class SingleAssignmentNode(AssignmentNode):
    #  The simplest case:
    #
    #    a = b
    #
    #  lhs      ExprNode      Left hand side
    #  rhs      ExprNode      Right hand side
2867
    #  first    bool          Is this guaranteed the first assignment to lhs?
2868 2869
    
    child_attrs = ["lhs", "rhs"]
2870
    first = False
2871
    declaration_only = False
William Stein's avatar
William Stein committed
2872 2873

    def analyse_declarations(self, env):
2874 2875 2876 2877
        import ExprNodes
        
        # handle declarations of the form x = cython.foo()
        if isinstance(self.rhs, ExprNodes.CallNode):
2878
            func_name = self.rhs.function.as_cython_attribute()
2879 2880 2881 2882
            if func_name:
                args, kwds = self.rhs.explicit_args_kwds()
                
                if func_name in ['declare', 'typedef']:
Robert Bradshaw's avatar
Robert Bradshaw committed
2883
                    if len(args) > 2 or kwds is not None:
2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900
                        error(rhs.pos, "Can only declare one type at a time.")
                        return
                    type = args[0].analyse_as_type(env)
                    if type is None:
                        error(args[0].pos, "Unknown type")
                        return
                    lhs = self.lhs
                    if func_name == 'declare':
                        if isinstance(lhs, ExprNodes.NameNode):
                            vars = [(lhs.name, lhs.pos)]
                        elif isinstance(lhs, ExprNodes.TupleNode):
                            vars = [(var.name, var.pos) for var in lhs.args]
                        else:
                            error(lhs.pos, "Invalid declaration")
                            return
                        for var, pos in vars:
                            env.declare_var(var, type, pos, is_cdef = True)
Robert Bradshaw's avatar
Robert Bradshaw committed
2901 2902 2903 2904 2905
                        if len(args) == 2:
                            # we have a value
                            self.rhs = args[1]
                        else:
                            self.declaration_only = True
2906
                    else:
Robert Bradshaw's avatar
Robert Bradshaw committed
2907
                        self.declaration_only = True
2908 2909
                        if not isinstance(lhs, ExprNodes.NameNode):
                            error(lhs.pos, "Invalid declaration.")
2910
                        env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937
                    
                elif func_name in ['struct', 'union']:
                    self.declaration_only = True
                    if len(args) > 0 or kwds is None:
                        error(rhs.pos, "Struct or union members must be given by name.")
                        return
                    members = []
                    for member, type_node in kwds.key_value_pairs:
                        type = type_node.analyse_as_type(env)
                        if type is None:
                            error(type_node.pos, "Unknown type")
                        else:
                            members.append((member.value, type, member.pos))
                    if len(members) < len(kwds.key_value_pairs):
                        return
                    if not isinstance(self.lhs, ExprNodes.NameNode):
                        error(self.lhs.pos, "Invalid declaration.")
                    name = self.lhs.name
                    scope = StructOrUnionScope(name)
                    env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
                    for member, type, pos in members:
                        scope.declare_var(member, type, pos)
                    
        if self.declaration_only:
            return
        else:
            self.lhs.analyse_target_declaration(env)
William Stein's avatar
William Stein committed
2938
    
2939
    def analyse_types(self, env, use_temp = 0):
William Stein's avatar
William Stein committed
2940 2941
        self.rhs.analyse_types(env)
        self.lhs.analyse_target_types(env)
2942
        self.lhs.gil_assignment_check(env)
William Stein's avatar
William Stein committed
2943 2944 2945
        self.rhs = self.rhs.coerce_to(self.lhs.type, env)
        if use_temp:
            self.rhs = self.rhs.coerce_to_temp(env)
2946 2947
    
    def allocate_rhs_temps(self, env):
William Stein's avatar
William Stein committed
2948
        self.rhs.allocate_temps(env)
2949 2950 2951 2952

    def allocate_lhs_temps(self, env):
        self.lhs.allocate_target_temps(env, self.rhs)
        #self.lhs.release_target_temp(env)
2953 2954
        #self.rhs.release_temp(env)

William Stein's avatar
William Stein committed
2955 2956 2957 2958 2959 2960
    def generate_rhs_evaluation_code(self, code):
        self.rhs.generate_evaluation_code(code)
    
    def generate_assignment_code(self, code):
        self.lhs.generate_assignment_code(self.rhs, code)

2961 2962 2963 2964
    def annotate(self, code):
        self.lhs.annotate(code)
        self.rhs.annotate(code)

William Stein's avatar
William Stein committed
2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977

class CascadedAssignmentNode(AssignmentNode):
    #  An assignment with multiple left hand sides:
    #
    #    a = b = c
    #
    #  lhs_list   [ExprNode]   Left hand sides
    #  rhs        ExprNode     Right hand sides
    #
    #  Used internally:
    #
    #  coerced_rhs_list   [ExprNode]   RHS coerced to type of each LHS
    
2978
    child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2979
    coerced_rhs_list = None
2980

William Stein's avatar
William Stein committed
2981 2982 2983 2984
    def analyse_declarations(self, env):
        for lhs in self.lhs_list:
            lhs.analyse_target_declaration(env)
    
2985
    def analyse_types(self, env, use_temp = 0):
William Stein's avatar
William Stein committed
2986 2987 2988 2989 2990 2991 2992 2993 2994
        self.rhs.analyse_types(env)
        if use_temp:
            self.rhs = self.rhs.coerce_to_temp(env)
        else:
            self.rhs = self.rhs.coerce_to_simple(env)
        from ExprNodes import CloneNode
        self.coerced_rhs_list = []
        for lhs in self.lhs_list:
            lhs.analyse_target_types(env)
2995
            lhs.gil_assignment_check(env)
William Stein's avatar
William Stein committed
2996 2997 2998
            rhs = CloneNode(self.rhs)
            rhs = rhs.coerce_to(lhs.type, env)
            self.coerced_rhs_list.append(rhs)
2999 3000 3001 3002 3003 3004

    def allocate_rhs_temps(self, env):
        self.rhs.allocate_temps(env)
    
    def allocate_lhs_temps(self, env):
        for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
William Stein's avatar
William Stein committed
3005
            rhs.allocate_temps(env)
3006 3007 3008
            lhs.allocate_target_temps(env, rhs)
            #lhs.release_target_temp(env)
            #rhs.release_temp(env)
William Stein's avatar
William Stein committed
3009
        self.rhs.release_temp(env)
3010
    
William Stein's avatar
William Stein committed
3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021
    def generate_rhs_evaluation_code(self, code):
        self.rhs.generate_evaluation_code(code)
    
    def generate_assignment_code(self, code):
        for i in range(len(self.lhs_list)):
            lhs = self.lhs_list[i]
            rhs = self.coerced_rhs_list[i]
            rhs.generate_evaluation_code(code)
            lhs.generate_assignment_code(rhs, code)
            # Assignment has disposed of the cloned RHS
        self.rhs.generate_disposal_code(code)
3022
        self.rhs.free_temps(code)
William Stein's avatar
William Stein committed
3023

3024 3025 3026 3027 3028 3029 3030
    def annotate(self, code):
        for i in range(len(self.lhs_list)):
            lhs = self.lhs_list[i].annotate(code)
            rhs = self.coerced_rhs_list[i].annotate(code)
        self.rhs.annotate(code)
        

William Stein's avatar
William Stein committed
3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044
class ParallelAssignmentNode(AssignmentNode):
    #  A combined packing/unpacking assignment:
    #
    #    a, b, c =  d, e, f
    #
    #  This has been rearranged by the parser into
    #
    #    a = d ; b = e ; c = f
    #
    #  but we must evaluate all the right hand sides
    #  before assigning to any of the left hand sides.
    #
    #  stats     [AssignmentNode]   The constituent assignments
    
3045 3046
    child_attrs = ["stats"]

William Stein's avatar
William Stein committed
3047 3048 3049 3050 3051 3052
    def analyse_declarations(self, env):
        for stat in self.stats:
            stat.analyse_declarations(env)
    
    def analyse_expressions(self, env):
        for stat in self.stats:
3053 3054
            stat.analyse_types(env, use_temp = 1)
            stat.allocate_rhs_temps(env)
William Stein's avatar
William Stein committed
3055
        for stat in self.stats:
3056 3057
            stat.allocate_lhs_temps(env)

Robert Bradshaw's avatar
Robert Bradshaw committed
3058 3059 3060 3061 3062
#    def analyse_expressions(self, env):
#        for stat in self.stats:
#            stat.analyse_expressions_1(env, use_temp = 1)
#        for stat in self.stats:
#            stat.analyse_expressions_2(env)
William Stein's avatar
William Stein committed
3063 3064 3065 3066 3067 3068 3069
    
    def generate_execution_code(self, code):
        for stat in self.stats:
            stat.generate_rhs_evaluation_code(code)
        for stat in self.stats:
            stat.generate_assignment_code(code)

3070 3071 3072 3073 3074
    def annotate(self, code):
        for stat in self.stats:
            stat.annotate(code)


3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093
class InPlaceAssignmentNode(AssignmentNode):
    #  An in place arithmatic operand:
    #
    #    a += b
    #    a -= b
    #    ...
    #
    #  lhs      ExprNode      Left hand side
    #  rhs      ExprNode      Right hand side
    #  op       char          one of "+-*/%^&|"
    #  dup     (ExprNode)     copy of lhs used for operation (auto-generated)
    #
    #  This code is a bit tricky because in order to obey Python 
    #  semantics the sub-expressions (e.g. indices) of the lhs must 
    #  not be evaluated twice. So we must re-use the values calculated 
    #  in evaluation phase for the assignment phase as well. 
    #  Fortunately, the type of the lhs node is fairly constrained 
    #  (it must be a NameNode, AttributeNode, or IndexNode).     
    
3094
    child_attrs = ["lhs", "rhs"]
3095
    dup = None
3096

3097 3098
    def analyse_declarations(self, env):
        self.lhs.analyse_target_declaration(env)
3099 3100 3101
        
    def analyse_types(self, env):
        self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3102 3103
        self.rhs.analyse_types(env)
        self.lhs.analyse_target_types(env)
3104 3105
        if Options.incref_local_binop and self.dup.type.is_pyobject:
            self.dup = self.dup.coerce_to_temp(env)
3106 3107
        
    def allocate_rhs_temps(self, env):
3108
        import ExprNodes
3109 3110 3111
        if self.lhs.type.is_pyobject:
            self.rhs = self.rhs.coerce_to_pyobject(env)
        elif self.rhs.type.is_pyobject:
3112 3113
            self.rhs = self.rhs.coerce_to(self.lhs.type, env)
        if self.lhs.type.is_pyobject:
3114 3115
             self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
             self.result_value.allocate_temps(env)
3116 3117
#        if use_temp:
#            self.rhs = self.rhs.coerce_to_temp(env)
3118
        self.rhs.allocate_temps(env)
3119 3120 3121
        self.dup.allocate_subexpr_temps(env)
        self.dup.allocate_temp(env)
    
3122
    def allocate_lhs_temps(self, env):
3123 3124
        self.lhs.allocate_target_temps(env, self.rhs)
#        self.lhs.release_target_temp(env)
3125 3126 3127
        self.dup.release_temp(env)
        if self.dup.is_temp:
            self.dup.release_subexpr_temps(env)
3128
#        self.rhs.release_temp(env)
3129
        if self.lhs.type.is_pyobject:
3130
            self.result_value.release_temp(env)
3131 3132

    def generate_execution_code(self, code):
3133
        import ExprNodes
3134 3135
        self.rhs.generate_evaluation_code(code)
        self.dup.generate_subexpr_evaluation_code(code)
3136 3137 3138 3139
        if isinstance(self.dup, ExprNodes.NewTempExprNode):
            # This is because we're manually messing with subexpr nodes
            if self.dup.is_temp:
                self.dup.allocate_temp_result(code)
3140
        # self.dup.generate_result_code is run only if it is not buffer access
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
3141 3142 3143 3144
        if self.operator == "**":
            extra = ", Py_None"
        else:
            extra = ""
3145
        if self.lhs.type.is_pyobject:
3146 3147
            if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
                error(self.pos, "In-place operators not allowed on object buffers in this release.")
3148
            self.dup.generate_result_code(code)
3149
            code.putln(
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
3150
                "%s = %s(%s, %s%s); %s" % (
3151
                    self.result_value.result(), 
3152 3153 3154
                    self.py_operation_function(), 
                    self.dup.py_result(),
                    self.rhs.py_result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
3155
                    extra,
3156
                    code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3157
            code.put_gotref(self.result_value.py_result())
3158
            self.result_value.generate_evaluation_code(code) # May be a type check...
3159
            self.rhs.generate_disposal_code(code)
3160
            self.rhs.free_temps(code)
3161
            self.dup.generate_disposal_code(code)
3162
            self.dup.free_temps(code)
3163
            self.lhs.generate_assignment_code(self.result_value, code)
3164
        else: 
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
3165 3166 3167 3168
            c_op = self.operator
            if c_op == "//":
                c_op = "/"
            elif c_op == "**":
3169 3170 3171 3172
                error(self.pos, "No C inplace power operator")
            elif self.lhs.type.is_complex and not code.globalstate.directives['c99_complex']:
                error(self.pos, "Inplace operators not implemented for complex types.")
                
3173
            # have to do assignment directly to avoid side-effects
3174 3175 3176 3177
            if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
                self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
            else:
                self.dup.generate_result_code(code)
3178
                code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3179
            self.rhs.generate_disposal_code(code)
3180
            self.rhs.free_temps(code)
3181 3182
        if self.dup.is_temp:
            self.dup.generate_subexpr_disposal_code(code)
3183
            self.dup.free_subexpr_temps(code)
3184 3185 3186 3187 3188 3189
            
    def create_dup_node(self, env): 
        import ExprNodes
        self.dup = self.lhs
        self.dup.analyse_types(env)
        if isinstance(self.lhs, ExprNodes.NameNode):
3190 3191 3192
            target_lhs = ExprNodes.NameNode(self.dup.pos,
                                            name = self.dup.name,
                                            is_temp = self.dup.is_temp,
3193
                                            entry = self.dup.entry)
3194
        elif isinstance(self.lhs, ExprNodes.AttributeNode):
3195 3196 3197
            target_lhs = ExprNodes.AttributeNode(self.dup.pos,
                                                 obj = ExprNodes.CloneNode(self.lhs.obj),
                                                 attribute = self.dup.attribute,
3198
                                                 is_temp = self.dup.is_temp)
3199
        elif isinstance(self.lhs, ExprNodes.IndexNode):
3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211
            if self.lhs.index:
                index = ExprNodes.CloneNode(self.lhs.index)
            else:
                index = None
            if self.lhs.indices:
                indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
            else:
                indices = []
            target_lhs = ExprNodes.IndexNode(self.dup.pos,
                                             base = ExprNodes.CloneNode(self.dup.base),
                                             index = index,
                                             indices = indices,
3212
                                             is_temp = self.dup.is_temp)
3213 3214
        else:
            assert False
3215
        self.lhs = target_lhs
3216
        return self.dup
3217 3218 3219 3220 3221
    
    def py_operation_function(self):
        return self.py_functions[self.operator]

    py_functions = {
Robert Bradshaw's avatar
Robert Bradshaw committed
3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233
        "|":        "PyNumber_InPlaceOr",
        "^":        "PyNumber_InPlaceXor",
        "&":        "PyNumber_InPlaceAnd",
        "+":        "PyNumber_InPlaceAdd",
        "-":        "PyNumber_InPlaceSubtract",
        "*":        "PyNumber_InPlaceMultiply",
        "/":        "PyNumber_InPlaceDivide",
        "%":        "PyNumber_InPlaceRemainder",
        "<<":        "PyNumber_InPlaceLshift",
        ">>":        "PyNumber_InPlaceRshift",
        "**":        "PyNumber_InPlacePower",
        "//":        "PyNumber_InPlaceFloorDivide",
3234 3235
    }

3236 3237 3238 3239 3240
    def annotate(self, code):
        self.lhs.annotate(code)
        self.rhs.annotate(code)
        self.dup.annotate(code)

William Stein's avatar
William Stein committed
3241 3242 3243 3244

class PrintStatNode(StatNode):
    #  print statement
    #
3245
    #  arg_tuple         TupleNode
3246
    #  append_newline    boolean
3247 3248 3249

    child_attrs = ["arg_tuple"]

William Stein's avatar
William Stein committed
3250
    def analyse_expressions(self, env):
3251
        self.arg_tuple.analyse_expressions(env)
3252 3253
        self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
        self.arg_tuple.release_temp(env)
3254
        env.use_utility_code(printing_utility_code)
3255 3256
        if len(self.arg_tuple.args) == 1 and self.append_newline:
            env.use_utility_code(printing_one_utility_code)
3257 3258 3259
        self.gil_check(env)

    gil_message = "Python print statement"
3260

William Stein's avatar
William Stein committed
3261
    def generate_execution_code(self, code):
3262 3263 3264
        if len(self.arg_tuple.args) == 1 and self.append_newline:
            arg = self.arg_tuple.args[0]
            arg.generate_evaluation_code(code)
3265
            
3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280
            code.putln(
                "if (__Pyx_PrintOne(%s) < 0) %s" % (
                    arg.py_result(),
                    code.error_goto(self.pos)))
            arg.generate_disposal_code(code)
            arg.free_temps(code)
        else:
            self.arg_tuple.generate_evaluation_code(code)
            code.putln(
                "if (__Pyx_Print(%s, %d) < 0) %s" % (
                    self.arg_tuple.py_result(),
                    self.append_newline,
                    code.error_goto(self.pos)))
            self.arg_tuple.generate_disposal_code(code)
            self.arg_tuple.free_temps(code)
3281

3282
    def annotate(self, code):
3283
        self.arg_tuple.annotate(code)
William Stein's avatar
William Stein committed
3284 3285


3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315
class ExecStatNode(StatNode):
    #  exec statement
    #
    #  args     [ExprNode]

    child_attrs = ["args"]

    def analyse_expressions(self, env):
        for i, arg in enumerate(self.args):
            arg.analyse_expressions(env)
            arg = arg.coerce_to_pyobject(env)
            arg.release_temp(env)
            self.args[i] = arg
        self.temp_result = env.allocate_temp_pyobject()
        env.release_temp(self.temp_result)
        env.use_utility_code(Builtin.pyexec_utility_code)
        self.gil_check(env)

    gil_message = "Python exec statement"

    def generate_execution_code(self, code):
        args = []
        for arg in self.args:
            arg.generate_evaluation_code(code)
            args.append( arg.py_result() )
        args = tuple(args + ['0', '0'][:3-len(args)])
        code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
                (self.temp_result,) + args))
        for arg in self.args:
            arg.generate_disposal_code(code)
3316
            arg.free_temps(code)
3317 3318
        code.putln(
            code.error_goto_if_null(self.temp_result, self.pos))
3319
        code.put_gotref(self.temp_result)
3320 3321 3322 3323 3324 3325 3326
        code.put_decref_clear(self.temp_result, py_object_type)

    def annotate(self, code):
        for arg in self.args:
            arg.annotate(code)


William Stein's avatar
William Stein committed
3327 3328 3329 3330 3331
class DelStatNode(StatNode):
    #  del statement
    #
    #  args     [ExprNode]
    
3332 3333
    child_attrs = ["args"]

William Stein's avatar
William Stein committed
3334 3335 3336 3337 3338 3339
    def analyse_declarations(self, env):
        for arg in self.args:
            arg.analyse_target_declaration(env)
    
    def analyse_expressions(self, env):
        for arg in self.args:
3340
            arg.analyse_target_expression(env, None)
3341 3342 3343
            if arg.type.is_pyobject:
                self.gil_check(env)
            else:
William Stein's avatar
William Stein committed
3344
                error(arg.pos, "Deletion of non-Python object")
3345
            #arg.release_target_temp(env)
3346 3347 3348

    gil_message = "Deleting Python object"

William Stein's avatar
William Stein committed
3349 3350 3351 3352 3353 3354
    def generate_execution_code(self, code):
        for arg in self.args:
            if arg.type.is_pyobject:
                arg.generate_deletion_code(code)
            # else error reported earlier

3355 3356 3357 3358
    def annotate(self, code):
        for arg in self.args:
            arg.annotate(code)

William Stein's avatar
William Stein committed
3359 3360 3361

class PassStatNode(StatNode):
    #  pass statement
3362 3363

    child_attrs = []
William Stein's avatar
William Stein committed
3364 3365 3366 3367 3368 3369 3370 3371 3372 3373
    
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        pass


class BreakStatNode(StatNode):

3374 3375
    child_attrs = []

William Stein's avatar
William Stein committed
3376 3377 3378 3379 3380 3381 3382
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        if not code.break_label:
            error(self.pos, "break statement not inside loop")
        else:
3383
            code.put_goto(code.break_label)
William Stein's avatar
William Stein committed
3384 3385 3386 3387


class ContinueStatNode(StatNode):

3388 3389
    child_attrs = []

William Stein's avatar
William Stein committed
3390 3391 3392 3393
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
3394
        if code.funcstate.in_try_finally:
William Stein's avatar
William Stein committed
3395 3396 3397 3398
            error(self.pos, "continue statement inside try of try...finally")
        elif not code.continue_label:
            error(self.pos, "continue statement not inside loop")
        else:
3399
            code.put_goto(code.continue_label)
William Stein's avatar
William Stein committed
3400 3401 3402 3403 3404 3405 3406 3407 3408


class ReturnStatNode(StatNode):
    #  return statement
    #
    #  value         ExprNode or None
    #  return_type   PyrexType
    #  temps_in_use  [Entry]            Temps in use at time of return
    
3409 3410
    child_attrs = ["value"]

William Stein's avatar
William Stein committed
3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431
    def analyse_expressions(self, env):
        return_type = env.return_type
        self.return_type = return_type
        self.temps_in_use = env.temps_in_use()
        if not return_type:
            error(self.pos, "Return not inside a function body")
            return
        if self.value:
            self.value.analyse_types(env)
            if return_type.is_void or return_type.is_returncode:
                error(self.value.pos, 
                    "Return with value in void function")
            else:
                self.value = self.value.coerce_to(env.return_type, env)
            self.value.allocate_temps(env)
            self.value.release_temp(env)
        else:
            if (not return_type.is_void
                and not return_type.is_pyobject
                and not return_type.is_returncode):
                    error(self.pos, "Return value required")
3432 3433 3434 3435 3436
        if return_type.is_pyobject:
            self.gil_check(env)

    gil_message = "Returning Python object"

William Stein's avatar
William Stein committed
3437
    def generate_execution_code(self, code):
3438
        code.mark_pos(self.pos)
William Stein's avatar
William Stein committed
3439 3440 3441
        if not self.return_type:
            # error reported earlier
            return
3442 3443 3444
        if self.return_type.is_pyobject:
            code.put_xdecref(Naming.retval_cname,
                             self.return_type)
William Stein's avatar
William Stein committed
3445 3446 3447 3448 3449 3450 3451 3452
        if self.value:
            self.value.generate_evaluation_code(code)
            self.value.make_owned_reference(code)
            code.putln(
                "%s = %s;" % (
                    Naming.retval_cname,
                    self.value.result_as(self.return_type)))
            self.value.generate_post_assignment_code(code)
3453
            self.value.free_temps(code)
William Stein's avatar
William Stein committed
3454 3455 3456 3457 3458 3459 3460 3461
        else:
            if self.return_type.is_pyobject:
                code.put_init_to_py_none(Naming.retval_cname, self.return_type)
            elif self.return_type.is_returncode:
                code.putln(
                    "%s = %s;" % (
                        Naming.retval_cname,
                        self.return_type.default_value))
3462
        # free temps the old way
3463 3464
        for entry in self.temps_in_use:
            code.put_var_decref_clear(entry)
3465
        # free temps the new way
3466
        for cname, type in code.funcstate.temps_holding_reference():
3467
            code.put_decref_clear(cname, type)
3468
        #code.putln(
3469 3470
        #    "goto %s;" %
        #        code.return_label)
3471
        code.put_goto(code.return_label)
3472 3473 3474 3475
        
    def annotate(self, code):
        if self.value:
            self.value.annotate(code)
William Stein's avatar
William Stein committed
3476 3477 3478 3479 3480 3481 3482 3483 3484


class RaiseStatNode(StatNode):
    #  raise statement
    #
    #  exc_type    ExprNode or None
    #  exc_value   ExprNode or None
    #  exc_tb      ExprNode or None
    
3485 3486
    child_attrs = ["exc_type", "exc_value", "exc_tb"]

William Stein's avatar
William Stein committed
3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505
    def analyse_expressions(self, env):
        if self.exc_type:
            self.exc_type.analyse_types(env)
            self.exc_type = self.exc_type.coerce_to_pyobject(env)
            self.exc_type.allocate_temps(env)
        if self.exc_value:
            self.exc_value.analyse_types(env)
            self.exc_value = self.exc_value.coerce_to_pyobject(env)
            self.exc_value.allocate_temps(env)
        if self.exc_tb:
            self.exc_tb.analyse_types(env)
            self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
            self.exc_tb.allocate_temps(env)
        if self.exc_type:
            self.exc_type.release_temp(env)
        if self.exc_value:
            self.exc_value.release_temp(env)
        if self.exc_tb:
            self.exc_tb.release_temp(env)
3506
        env.use_utility_code(raise_utility_code)
3507
        env.use_utility_code(restore_exception_utility_code)
3508 3509 3510 3511
        self.gil_check(env)

    gil_message = "Raising exception"

William Stein's avatar
William Stein committed
3512 3513 3514 3515 3516
    def generate_execution_code(self, code):
        if self.exc_type:
            self.exc_type.generate_evaluation_code(code)
            type_code = self.exc_type.py_result()
        else:
Stefan Behnel's avatar
Stefan Behnel committed
3517
            type_code = "0"
William Stein's avatar
William Stein committed
3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536
        if self.exc_value:
            self.exc_value.generate_evaluation_code(code)
            value_code = self.exc_value.py_result()
        else:
            value_code = "0"
        if self.exc_tb:
            self.exc_tb.generate_evaluation_code(code)
            tb_code = self.exc_tb.py_result()
        else:
            tb_code = "0"
        if self.exc_type or self.exc_value or self.exc_tb:
            code.putln(
                "__Pyx_Raise(%s, %s, %s);" % (
                    type_code,
                    value_code,
                    tb_code))
        else:
            code.putln(
                "__Pyx_ReRaise();")
3537 3538 3539 3540
        for obj in (self.exc_type, self.exc_value, self.exc_tb):
            if obj:
                obj.generate_disposal_code(code)
                obj.free_temps(code)
William Stein's avatar
William Stein committed
3541 3542 3543
        code.putln(
            code.error_goto(self.pos))

3544 3545 3546 3547 3548 3549 3550 3551
    def annotate(self, code):
        if self.exc_type:
            self.exc_type.annotate(code)
        if self.exc_value:
            self.exc_value.annotate(code)
        if self.exc_tb:
            self.exc_tb.annotate(code)

William Stein's avatar
William Stein committed
3552

3553 3554
class ReraiseStatNode(StatNode):

3555 3556
    child_attrs = []

3557
    def analyse_expressions(self, env):
3558
        self.gil_check(env)
3559
        env.use_utility_code(raise_utility_code)
3560
        env.use_utility_code(restore_exception_utility_code)
3561

3562 3563
    gil_message = "Raising exception"

3564
    def generate_execution_code(self, code):
3565
        vars = code.funcstate.exc_vars
3566 3567 3568 3569 3570 3571 3572
        if vars:
            code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
            code.putln(code.error_goto(self.pos))
        else:
            error(self.pos, "Reraise not inside except clause")
        

William Stein's avatar
William Stein committed
3573 3574 3575 3576 3577 3578
class AssertStatNode(StatNode):
    #  assert statement
    #
    #  cond    ExprNode
    #  value   ExprNode or None
    
3579 3580
    child_attrs = ["cond", "value"]

William Stein's avatar
William Stein committed
3581 3582 3583 3584 3585 3586 3587 3588 3589
    def analyse_expressions(self, env):
        self.cond = self.cond.analyse_boolean_expression(env)
        if self.value:
            self.value.analyse_types(env)
            self.value = self.value.coerce_to_pyobject(env)
            self.value.allocate_temps(env)
        self.cond.release_temp(env)
        if self.value:
            self.value.release_temp(env)
3590
        self.gil_check(env)
William Stein's avatar
William Stein committed
3591
        #env.recycle_pending_temps() # TEMPORARY
3592 3593

    gil_message = "Raising exception"
William Stein's avatar
William Stein committed
3594 3595
    
    def generate_execution_code(self, code):
3596
        code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
William Stein's avatar
William Stein committed
3597 3598
        self.cond.generate_evaluation_code(code)
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3599
            "if (unlikely(!%s)) {" %
3600
                self.cond.result())
William Stein's avatar
William Stein committed
3601
        if self.value:
3602
            self.value.generate_evaluation_code(code)
William Stein's avatar
William Stein committed
3603 3604 3605
            code.putln(
                "PyErr_SetObject(PyExc_AssertionError, %s);" %
                    self.value.py_result())
3606
            self.value.generate_disposal_code(code)
3607
            self.value.free_temps(code)
William Stein's avatar
William Stein committed
3608 3609 3610 3611 3612 3613 3614 3615
        else:
            code.putln(
                "PyErr_SetNone(PyExc_AssertionError);")
        code.putln(
                code.error_goto(self.pos))
        code.putln(
            "}")
        self.cond.generate_disposal_code(code)
3616
        self.cond.free_temps(code)
3617
        code.putln("#endif")
William Stein's avatar
William Stein committed
3618

3619 3620 3621 3622 3623 3624
    def annotate(self, code):
        self.cond.annotate(code)
        if self.value:
            self.value.annotate(code)


William Stein's avatar
William Stein committed
3625 3626 3627 3628 3629
class IfStatNode(StatNode):
    #  if statement
    #
    #  if_clauses   [IfClauseNode]
    #  else_clause  StatNode or None
3630 3631

    child_attrs = ["if_clauses", "else_clause"]
William Stein's avatar
William Stein committed
3632
    
3633 3634 3635 3636 3637 3638 3639 3640 3641
    def analyse_control_flow(self, env):
        env.start_branching(self.pos)
        for if_clause in self.if_clauses:
            if_clause.analyse_control_flow(env)
            env.next_branch(if_clause.end_pos())
        if self.else_clause:
            self.else_clause.analyse_control_flow(env)
        env.finish_branching(self.end_pos())

William Stein's avatar
William Stein committed
3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654
    def analyse_declarations(self, env):
        for if_clause in self.if_clauses:
            if_clause.analyse_declarations(env)
        if self.else_clause:
            self.else_clause.analyse_declarations(env)
    
    def analyse_expressions(self, env):
        for if_clause in self.if_clauses:
            if_clause.analyse_expressions(env)
        if self.else_clause:
            self.else_clause.analyse_expressions(env)
    
    def generate_execution_code(self, code):
3655
        code.mark_pos(self.pos)
William Stein's avatar
William Stein committed
3656 3657 3658 3659 3660 3661 3662 3663
        end_label = code.new_label()
        for if_clause in self.if_clauses:
            if_clause.generate_execution_code(code, end_label)
        if self.else_clause:
            code.putln("/*else*/ {")
            self.else_clause.generate_execution_code(code)
            code.putln("}")
        code.put_label(end_label)
3664 3665 3666 3667 3668 3669
        
    def annotate(self, code):
        for if_clause in self.if_clauses:
            if_clause.annotate(code)
        if self.else_clause:
            self.else_clause.annotate(code)
William Stein's avatar
William Stein committed
3670 3671 3672 3673 3674 3675 3676 3677


class IfClauseNode(Node):
    #  if or elif clause in an if statement
    #
    #  condition   ExprNode
    #  body        StatNode
    
3678 3679
    child_attrs = ["condition", "body"]

3680 3681 3682
    def analyse_control_flow(self, env):
        self.body.analyse_control_flow(env)
        
William Stein's avatar
William Stein committed
3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696
    def analyse_declarations(self, env):
        self.condition.analyse_declarations(env)
        self.body.analyse_declarations(env)
    
    def analyse_expressions(self, env):
        self.condition = \
            self.condition.analyse_temp_boolean_expression(env)
        self.condition.release_temp(env)
        self.body.analyse_expressions(env)
    
    def generate_execution_code(self, code, end_label):
        self.condition.generate_evaluation_code(code)
        code.putln(
            "if (%s) {" %
3697
                self.condition.result())
3698 3699
        self.condition.generate_disposal_code(code)
        self.condition.free_temps(code)
William Stein's avatar
William Stein committed
3700
        self.body.generate_execution_code(code)
3701
        #code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3702 3703
        #    "goto %s;" %
        #        end_label)
3704
        code.put_goto(end_label)
William Stein's avatar
William Stein committed
3705
        code.putln("}")
3706 3707 3708 3709

    def annotate(self, code):
        self.condition.annotate(code)
        self.body.annotate(code)
William Stein's avatar
William Stein committed
3710
        
3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721

class SwitchCaseNode(StatNode):
    # Generated in the optimization of an if-elif-else node
    #
    # conditions    [ExprNode]
    # body          StatNode
    
    child_attrs = ['conditions', 'body']
    
    def generate_execution_code(self, code):
        for cond in self.conditions:
3722
            code.mark_pos(cond.pos)
3723 3724 3725
            code.putln("case %s:" % cond.calculate_result_code())
        self.body.generate_execution_code(code)
        code.putln("break;")
3726
        
3727 3728 3729
    def annotate(self, code):
        for cond in self.conditions:
            cond.annotate(code)
3730
        self.body.annotate(code)
3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747

class SwitchStatNode(StatNode):
    # Generated in the optimization of an if-elif-else node
    #
    # test          ExprNode
    # cases         [SwitchCaseNode]
    # else_clause   StatNode or None
    
    child_attrs = ['test', 'cases', 'else_clause']
    
    def generate_execution_code(self, code):
        code.putln("switch (%s) {" % self.test.calculate_result_code())
        for case in self.cases:
            case.generate_execution_code(code)
        if self.else_clause is not None:
            code.putln("default:")
            self.else_clause.generate_execution_code(code)
3748
            code.putln("break;")
3749 3750 3751 3752 3753 3754
        code.putln("}")

    def annotate(self, code):
        self.test.annotate(code)
        for case in self.cases:
            case.annotate(code)
3755 3756
        if self.else_clause is not None:
            self.else_clause.annotate(code)
3757
            
3758
class LoopNode(object):
3759 3760 3761 3762 3763 3764 3765 3766 3767
    
    def analyse_control_flow(self, env):
        env.start_branching(self.pos)
        self.body.analyse_control_flow(env)
        env.next_branch(self.body.end_pos())
        if self.else_clause:
            self.else_clause.analyse_control_flow(env)
        env.finish_branching(self.end_pos())

William Stein's avatar
William Stein committed
3768
    
3769
class WhileStatNode(LoopNode, StatNode):
William Stein's avatar
William Stein committed
3770 3771 3772 3773 3774
    #  while statement
    #
    #  condition    ExprNode
    #  body         StatNode
    #  else_clause  StatNode
3775 3776

    child_attrs = ["condition", "body", "else_clause"]
3777

William Stein's avatar
William Stein committed
3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796
    def analyse_declarations(self, env):
        self.body.analyse_declarations(env)
        if self.else_clause:
            self.else_clause.analyse_declarations(env)
    
    def analyse_expressions(self, env):
        self.condition = \
            self.condition.analyse_temp_boolean_expression(env)
        self.condition.release_temp(env)
        #env.recycle_pending_temps() # TEMPORARY
        self.body.analyse_expressions(env)
        if self.else_clause:
            self.else_clause.analyse_expressions(env)
    
    def generate_execution_code(self, code):
        old_loop_labels = code.new_loop_labels()
        code.putln(
            "while (1) {")
        self.condition.generate_evaluation_code(code)
3797
        self.condition.generate_disposal_code(code)
William Stein's avatar
William Stein committed
3798 3799
        code.putln(
            "if (!%s) break;" %
3800
                self.condition.result())
3801
        self.condition.free_temps(code)
William Stein's avatar
William Stein committed
3802
        self.body.generate_execution_code(code)
3803
        code.put_label(code.continue_label)
William Stein's avatar
William Stein committed
3804 3805 3806 3807 3808 3809 3810 3811 3812
        code.putln("}")
        break_label = code.break_label
        code.set_loop_labels(old_loop_labels)
        if self.else_clause:
            code.putln("/*else*/ {")
            self.else_clause.generate_execution_code(code)
            code.putln("}")
        code.put_label(break_label)

3813 3814 3815 3816 3817 3818
    def annotate(self, code):
        self.condition.annotate(code)
        self.body.annotate(code)
        if self.else_clause:
            self.else_clause.annotate(code)

William Stein's avatar
William Stein committed
3819

Robert Bradshaw's avatar
Robert Bradshaw committed
3820
def ForStatNode(pos, **kw):
3821
    if 'iterator' in kw:
Robert Bradshaw's avatar
Robert Bradshaw committed
3822 3823 3824 3825
        return ForInStatNode(pos, **kw)
    else:
        return ForFromStatNode(pos, **kw)

3826
class ForInStatNode(LoopNode, StatNode):
William Stein's avatar
William Stein committed
3827 3828 3829 3830 3831 3832 3833 3834
    #  for statement
    #
    #  target        ExprNode
    #  iterator      IteratorNode
    #  body          StatNode
    #  else_clause   StatNode
    #  item          NextNode       used internally
    
3835
    child_attrs = ["target", "iterator", "body", "else_clause"]
3836
    item = None
3837
    
William Stein's avatar
William Stein committed
3838 3839 3840 3841 3842
    def analyse_declarations(self, env):
        self.target.analyse_target_declaration(env)
        self.body.analyse_declarations(env)
        if self.else_clause:
            self.else_clause.analyse_declarations(env)
3843

William Stein's avatar
William Stein committed
3844 3845 3846
    def analyse_expressions(self, env):
        import ExprNodes
        self.target.analyse_target_types(env)
3847
        self.iterator.analyse_expressions(env)
William Stein's avatar
William Stein committed
3848 3849 3850
        self.item = ExprNodes.NextNode(self.iterator, env)
        self.item = self.item.coerce_to(self.target.type, env)
        self.item.allocate_temps(env)
3851 3852 3853
        self.target.allocate_target_temps(env, self.item)
        #self.item.release_temp(env)
        #self.target.release_target_temp(env)
William Stein's avatar
William Stein committed
3854 3855 3856 3857 3858 3859 3860
        self.body.analyse_expressions(env)
        if self.else_clause:
            self.else_clause.analyse_expressions(env)
        self.iterator.release_temp(env)

    def generate_execution_code(self, code):
        old_loop_labels = code.new_loop_labels()
3861
        self.iterator.allocate_counter_temp(code)
William Stein's avatar
William Stein committed
3862 3863 3864 3865 3866 3867
        self.iterator.generate_evaluation_code(code)
        code.putln(
            "for (;;) {")
        self.item.generate_evaluation_code(code)
        self.target.generate_assignment_code(self.item, code)
        self.body.generate_execution_code(code)
3868
        code.put_label(code.continue_label)
William Stein's avatar
William Stein committed
3869 3870 3871 3872 3873 3874 3875 3876 3877
        code.putln(
            "}")
        break_label = code.break_label
        code.set_loop_labels(old_loop_labels)
        if self.else_clause:
            code.putln("/*else*/ {")
            self.else_clause.generate_execution_code(code)
            code.putln("}")
        code.put_label(break_label)
3878
        self.iterator.release_counter_temp(code)
William Stein's avatar
William Stein committed
3879
        self.iterator.generate_disposal_code(code)
3880
        self.iterator.free_temps(code)
William Stein's avatar
William Stein committed
3881

3882 3883 3884 3885 3886 3887 3888 3889
    def annotate(self, code):
        self.target.annotate(code)
        self.iterator.annotate(code)
        self.body.annotate(code)
        if self.else_clause:
            self.else_clause.annotate(code)
        self.item.annotate(code)

William Stein's avatar
William Stein committed
3890

3891
class ForFromStatNode(LoopNode, StatNode):
William Stein's avatar
William Stein committed
3892 3893 3894 3895 3896 3897 3898
    #  for name from expr rel name rel expr
    #
    #  target        NameNode
    #  bound1        ExprNode
    #  relation1     string
    #  relation2     string
    #  bound2        ExprNode
3899
    #  step          ExprNode or None
William Stein's avatar
William Stein committed
3900 3901 3902 3903 3904
    #  body          StatNode
    #  else_clause   StatNode or None
    #
    #  Used internally:
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
3905
    #  from_range         bool
3906
    #  is_py_target       bool
3907
    #  loopvar_node       ExprNode (usually a NameNode or temp node)
William Stein's avatar
William Stein committed
3908
    #  py_loopvar_node    PyTempNode or None
3909
    child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3910 3911

    is_py_target = False
3912
    loopvar_node = None
3913
    py_loopvar_node = None
Robert Bradshaw's avatar
Robert Bradshaw committed
3914
    from_range = False
3915

Robert Bradshaw's avatar
Robert Bradshaw committed
3916 3917 3918 3919 3920
    def analyse_declarations(self, env):
        self.target.analyse_target_declaration(env)
        self.body.analyse_declarations(env)
        if self.else_clause:
            self.else_clause.analyse_declarations(env)
3921

William Stein's avatar
William Stein committed
3922 3923 3924 3925 3926
    def analyse_expressions(self, env):
        import ExprNodes
        self.target.analyse_target_types(env)
        self.bound1.analyse_types(env)
        self.bound2.analyse_types(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
3927 3928 3929 3930 3931 3932
        if self.step is not None:
            if isinstance(self.step, ExprNodes.UnaryMinusNode):
                warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
            self.step.analyse_types(env)
        
        target_type = self.target.type
3933
        if self.target.type.is_numeric:
Robert Bradshaw's avatar
Robert Bradshaw committed
3934
            loop_type = self.target.type
3935
        else:
Robert Bradshaw's avatar
Robert Bradshaw committed
3936 3937 3938 3939 3940 3941 3942 3943 3944
            loop_type = PyrexTypes.c_int_type
            if not self.bound1.type.is_pyobject:
                loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
            if not self.bound2.type.is_pyobject:
                loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
            if self.step is not None and not self.step.type.is_pyobject:
                loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
        self.bound1 = self.bound1.coerce_to(loop_type, env)
        self.bound2 = self.bound2.coerce_to(loop_type, env)
Robert Bradshaw's avatar
Robert Bradshaw committed
3945 3946
        if not self.bound2.is_literal:
            self.bound2 = self.bound2.coerce_to_temp(env)
3947
        if self.step is not None:
Robert Bradshaw's avatar
Robert Bradshaw committed
3948
            self.step = self.step.coerce_to(loop_type, env)            
Robert Bradshaw's avatar
Robert Bradshaw committed
3949 3950
            if not self.step.is_literal:
                self.step = self.step.coerce_to_temp(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
3951

William Stein's avatar
William Stein committed
3952
        target_type = self.target.type
3953
        if not (target_type.is_pyobject or target_type.is_numeric):
3954
            error(self.target.pos,
Robert Bradshaw's avatar
Robert Bradshaw committed
3955
                "for-from loop variable must be c numeric type or Python object")
3956
        if target_type.is_numeric:
Robert Bradshaw's avatar
Robert Bradshaw committed
3957
            self.is_py_target = False
3958 3959
            if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
                raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3960
            self.loopvar_node = self.target
William Stein's avatar
William Stein committed
3961 3962
            self.py_loopvar_node = None
        else:
Robert Bradshaw's avatar
Robert Bradshaw committed
3963 3964
            self.is_py_target = True
            c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
William Stein's avatar
William Stein committed
3965
            c_loopvar_node.allocate_temps(env)
3966
            self.loopvar_node = c_loopvar_node
William Stein's avatar
William Stein committed
3967 3968 3969 3970
            self.py_loopvar_node = \
                ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
        self.bound1.allocate_temps(env)
        self.bound2.allocate_temps(env)
3971 3972
        if self.step is not None:
            self.step.allocate_temps(env)
3973
        if self.is_py_target:
William Stein's avatar
William Stein committed
3974
            self.py_loopvar_node.allocate_temps(env)
3975 3976 3977
            self.target.allocate_target_temps(env, self.py_loopvar_node)
            #self.target.release_target_temp(env)
            #self.py_loopvar_node.release_temp(env)
William Stein's avatar
William Stein committed
3978
        self.body.analyse_expressions(env)
3979
        if self.is_py_target:
William Stein's avatar
William Stein committed
3980 3981 3982 3983 3984
            c_loopvar_node.release_temp(env)
        if self.else_clause:
            self.else_clause.analyse_expressions(env)
        self.bound1.release_temp(env)
        self.bound2.release_temp(env)
3985 3986
        if self.step is not None:
            self.step.release_temp(env)
William Stein's avatar
William Stein committed
3987 3988 3989
            
    def generate_execution_code(self, code):
        old_loop_labels = code.new_loop_labels()
Robert Bradshaw's avatar
Robert Bradshaw committed
3990
        from_range = self.from_range
William Stein's avatar
William Stein committed
3991 3992 3993
        self.bound1.generate_evaluation_code(code)
        self.bound2.generate_evaluation_code(code)
        offset, incop = self.relation_table[self.relation1]
3994 3995
        if self.step is not None:
            self.step.generate_evaluation_code(code)
Magnus Lie Hetland's avatar
Magnus Lie Hetland committed
3996 3997
            step = self.step.result()
            incop = "%s=%s" % (incop[0], step)
3998
        if from_range:
Robert Bradshaw's avatar
Robert Bradshaw committed
3999
            loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
4000
        else:
Robert Bradshaw's avatar
Robert Bradshaw committed
4001
            loopvar_name = self.loopvar_node.result()
4002 4003 4004 4005
        code.putln(
            "for (%s = %s%s; %s %s %s; %s%s) {" % (
                loopvar_name,
                self.bound1.result(), offset,
Robert Bradshaw's avatar
Robert Bradshaw committed
4006
                loopvar_name, self.relation2, self.bound2.result(),
4007
                loopvar_name, incop))
William Stein's avatar
William Stein committed
4008 4009 4010
        if self.py_loopvar_node:
            self.py_loopvar_node.generate_evaluation_code(code)
            self.target.generate_assignment_code(self.py_loopvar_node, code)
Robert Bradshaw's avatar
Robert Bradshaw committed
4011 4012 4013
        elif from_range:
            code.putln("%s = %s;" % (
                            self.target.result(), loopvar_name))
William Stein's avatar
William Stein committed
4014 4015
        self.body.generate_execution_code(code)
        code.put_label(code.continue_label)
Robert Bradshaw's avatar
Robert Bradshaw committed
4016
        if self.py_loopvar_node:
4017 4018 4019
            # This mess is to make for..from loops with python targets behave 
            # exactly like those with C targets with regards to re-assignment 
            # of the loop variable. 
4020
            import ExprNodes
4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033
            if self.target.entry.is_pyglobal:
                # We know target is a NameNode, this is the only ugly case. 
                target_node = ExprNodes.PyTempNode(self.target.pos, None)
                target_node.result_code = code.funcstate.allocate_temp(py_object_type, False)
                code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
                                target_node.result_code,
                                Naming.module_cname, 
                                self.target.entry.interned_cname,
                                code.error_goto_if_null(target_node.result_code, self.target.pos)))
                code.put_gotref(target_node.result_code)
            else:
                target_node = self.target
            from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
4034 4035
            from_py_node.temp_code = loopvar_name
            from_py_node.generate_result_code(code)
4036 4037 4038
            if self.target.entry.is_pyglobal:
                code.put_decref_clear(target_node.result_code, py_object_type)
                code.funcstate.release_temp(target_node.result_code)
Robert Bradshaw's avatar
Robert Bradshaw committed
4039
        code.putln("}")
4040 4041 4042 4043 4044
        if self.py_loopvar_node:
            # This is potentially wasteful, but we don't want the semantics to 
            # depend on whether or not the loop is a python type. 
            self.py_loopvar_node.generate_evaluation_code(code)
            self.target.generate_assignment_code(self.py_loopvar_node, code)
William Stein's avatar
William Stein committed
4045 4046 4047 4048 4049 4050 4051 4052
        break_label = code.break_label
        code.set_loop_labels(old_loop_labels)
        if self.else_clause:
            code.putln("/*else*/ {")
            self.else_clause.generate_execution_code(code)
            code.putln("}")
        code.put_label(break_label)
        self.bound1.generate_disposal_code(code)
4053
        self.bound1.free_temps(code)
William Stein's avatar
William Stein committed
4054
        self.bound2.generate_disposal_code(code)
4055
        self.bound2.free_temps(code)
4056 4057
        if self.step is not None:
            self.step.generate_disposal_code(code)
4058
            self.step.free_temps(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
4059 4060
        if from_range:
            code.funcstate.release_temp(loopvar_name)
William Stein's avatar
William Stein committed
4061 4062 4063 4064 4065 4066 4067 4068
    
    relation_table = {
        # {relop : (initial offset, increment op)}
        '<=': ("",   "++"),
        '<' : ("+1", "++"),
        '>=': ("",   "--"),
        '>' : ("-1", "--")
    }
4069 4070 4071 4072 4073 4074 4075 4076 4077 4078
    
    def annotate(self, code):
        self.target.annotate(code)
        self.bound1.annotate(code)
        self.bound2.annotate(code)
        if self.step:
            self.bound2.annotate(code)
        self.body.annotate(code)
        if self.else_clause:
            self.else_clause.annotate(code)
William Stein's avatar
William Stein committed
4079 4080


4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092
class WithStatNode(StatNode):
    """
    Represents a Python with statement.
    
    This is only used at parse tree level; and is not present in
    analysis or generation phases.
    """
    #  manager          The with statement manager object
    #  target            Node (lhs expression)
    #  body             StatNode
    child_attrs = ["manager", "target", "body"]

William Stein's avatar
William Stein committed
4093 4094 4095 4096 4097 4098
class TryExceptStatNode(StatNode):
    #  try .. except statement
    #
    #  body             StatNode
    #  except_clauses   [ExceptClauseNode]
    #  else_clause      StatNode or None
4099
    #  cleanup_list     [Entry]            old style temps to clean up on error
4100

4101
    child_attrs = ["body", "except_clauses", "else_clause"]
William Stein's avatar
William Stein committed
4102
    
4103 4104 4105
    def analyse_control_flow(self, env):
        env.start_branching(self.pos)
        self.body.analyse_control_flow(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
4106 4107 4108 4109 4110
        successful_try = env.control_flow # grab this for later
        env.next_branch(self.body.end_pos())
        env.finish_branching(self.body.end_pos())
        
        env.start_branching(self.except_clauses[0].pos)
4111 4112
        for except_clause in self.except_clauses:
            except_clause.analyse_control_flow(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
4113 4114 4115 4116
            env.next_branch(except_clause.end_pos())
            
        # the else cause it executed only when the try clause finishes
        env.control_flow.incoming = successful_try
4117 4118 4119 4120
        if self.else_clause:
            self.else_clause.analyse_control_flow(env)
        env.finish_branching(self.end_pos())

William Stein's avatar
William Stein committed
4121 4122 4123 4124 4125 4126
    def analyse_declarations(self, env):
        self.body.analyse_declarations(env)
        for except_clause in self.except_clauses:
            except_clause.analyse_declarations(env)
        if self.else_clause:
            self.else_clause.analyse_declarations(env)
4127
        self.gil_check(env)
4128
        env.use_utility_code(reset_exception_utility_code)
William Stein's avatar
William Stein committed
4129 4130 4131 4132
    
    def analyse_expressions(self, env):
        self.body.analyse_expressions(env)
        self.cleanup_list = env.free_temp_entries[:]
4133
        default_clause_seen = 0
William Stein's avatar
William Stein committed
4134 4135
        for except_clause in self.except_clauses:
            except_clause.analyse_expressions(env)
4136 4137 4138 4139 4140
            if default_clause_seen:
                error(except_clause.pos, "default 'except:' must be last")
            if not except_clause.pattern:
                default_clause_seen = 1
        self.has_default_clause = default_clause_seen
William Stein's avatar
William Stein committed
4141 4142
        if self.else_clause:
            self.else_clause.analyse_expressions(env)
4143 4144 4145 4146
        self.gil_check(env)

    gil_message = "Try-except statement"

William Stein's avatar
William Stein committed
4147
    def generate_execution_code(self, code):
4148
        old_return_label = code.return_label
4149
        old_break_label = code.break_label
4150
        old_continue_label = code.continue_label
William Stein's avatar
William Stein committed
4151 4152
        old_error_label = code.new_error_label()
        our_error_label = code.error_label
4153 4154 4155
        except_end_label = code.new_label('exception_handled')
        except_error_label = code.new_label('except_error')
        except_return_label = code.new_label('except_return')
4156
        try_return_label = code.new_label('try_return')
4157
        try_break_label = code.new_label('try_break')
4158
        try_continue_label = code.new_label('try_continue')
4159
        try_end_label = code.new_label('try_end')
4160 4161 4162 4163 4164 4165

        code.putln("{")
        code.putln("PyObject %s;" %
                   ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
        code.putln("__Pyx_ExceptionSave(%s);" %
                   ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
4166 4167
        for var in Naming.exc_save_vars:
            code.put_xgotref(var)
William Stein's avatar
William Stein committed
4168 4169
        code.putln(
            "/*try:*/ {")
4170
        code.return_label = try_return_label
4171
        code.break_label = try_break_label
4172
        code.continue_label = try_continue_label
William Stein's avatar
William Stein committed
4173 4174 4175
        self.body.generate_execution_code(code)
        code.putln(
            "}")
4176
        temps_to_clean_up = code.funcstate.all_free_managed_temps()
4177 4178
        code.error_label = except_error_label
        code.return_label = except_return_label
William Stein's avatar
William Stein committed
4179 4180 4181 4182 4183 4184
        if self.else_clause:
            code.putln(
                "/*else:*/ {")
            self.else_clause.generate_execution_code(code)
            code.putln(
                "}")
4185 4186
        for var in Naming.exc_save_vars:
            code.put_xdecref_clear(var, py_object_type)
4187
        code.put_goto(try_end_label)
4188 4189 4190 4191 4192
        if code.label_used(try_return_label):
            code.put_label(try_return_label)
            for var in Naming.exc_save_vars:
                code.put_xdecref_clear(var, py_object_type)
            code.put_goto(old_return_label)
William Stein's avatar
William Stein committed
4193 4194
        code.put_label(our_error_label)
        code.put_var_xdecrefs_clear(self.cleanup_list)
4195 4196
        for temp_name, type in temps_to_clean_up:
            code.put_xdecref_clear(temp_name, type)
William Stein's avatar
William Stein committed
4197
        for except_clause in self.except_clauses:
4198 4199
            except_clause.generate_handling_code(code, except_end_label)

4200 4201 4202 4203
        error_label_used = code.label_used(except_error_label)
        if error_label_used or not self.has_default_clause:
            if error_label_used:
                code.put_label(except_error_label)
4204 4205 4206
            for var in Naming.exc_save_vars:
                code.put_xdecref(var, py_object_type)
            code.put_goto(old_error_label)
4207 4208 4209 4210 4211 4212 4213
            
        if code.label_used(try_break_label):
            code.put_label(try_break_label)
            for var in Naming.exc_save_vars: code.put_xgiveref(var)
            code.putln("__Pyx_ExceptionReset(%s);" %
                       ', '.join(Naming.exc_save_vars))
            code.put_goto(old_break_label)
4214 4215 4216 4217 4218 4219 4220
            
        if code.label_used(try_continue_label):
            code.put_label(try_continue_label)
            for var in Naming.exc_save_vars: code.put_xgiveref(var)
            code.putln("__Pyx_ExceptionReset(%s);" %
                       ', '.join(Naming.exc_save_vars))
            code.put_goto(old_continue_label)
4221 4222 4223

        if code.label_used(except_return_label):
            code.put_label(except_return_label)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
4224
            for var in Naming.exc_save_vars: code.put_xgiveref(var)
4225 4226 4227 4228 4229 4230
            code.putln("__Pyx_ExceptionReset(%s);" %
                       ', '.join(Naming.exc_save_vars))
            code.put_goto(old_return_label)

        if code.label_used(except_end_label):
            code.put_label(except_end_label)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
4231
            for var in Naming.exc_save_vars: code.put_xgiveref(var)
4232 4233 4234 4235 4236 4237
            code.putln("__Pyx_ExceptionReset(%s);" %
                       ', '.join(Naming.exc_save_vars))
        code.put_label(try_end_label)
        code.putln("}")

        code.return_label = old_return_label
4238
        code.break_label = old_break_label
4239
        code.continue_label = old_continue_label
4240
        code.error_label = old_error_label
William Stein's avatar
William Stein committed
4241

4242 4243 4244 4245 4246 4247 4248
    def annotate(self, code):
        self.body.annotate(code)
        for except_node in self.except_clauses:
            except_node.annotate(code)
        if self.else_clause:
            self.else_clause.annotate(code)

William Stein's avatar
William Stein committed
4249 4250 4251 4252 4253 4254 4255

class ExceptClauseNode(Node):
    #  Part of try ... except statement.
    #
    #  pattern        ExprNode
    #  target         ExprNode or None
    #  body           StatNode
4256
    #  excinfo_target NameNode or None   optional target for exception info
William Stein's avatar
William Stein committed
4257 4258 4259
    #  match_flag     string             result of exception match
    #  exc_value      ExcValueNode       used internally
    #  function_name  string             qualified name of enclosing function
4260
    #  exc_vars       (string * 3)       local exception variables
4261 4262 4263 4264

    # excinfo_target is never set by the parser, but can be set by a transform
    # in order to extract more extensive information about the exception as a
    # sys.exc_info()-style tuple into a target variable
William Stein's avatar
William Stein committed
4265
    
4266
    child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4267

4268
    exc_value = None
4269
    excinfo_target = None
4270

William Stein's avatar
William Stein committed
4271 4272 4273
    def analyse_declarations(self, env):
        if self.target:
            self.target.analyse_target_declaration(env)
4274 4275
        if self.excinfo_target is not None:
            self.excinfo_target.analyse_target_declaration(env)
William Stein's avatar
William Stein committed
4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287
        self.body.analyse_declarations(env)
    
    def analyse_expressions(self, env):
        import ExprNodes
        genv = env.global_scope()
        self.function_name = env.qualified_name
        if self.pattern:
            self.pattern.analyse_expressions(env)
            self.pattern = self.pattern.coerce_to_pyobject(env)
            self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
            self.pattern.release_temp(env)
            env.release_temp(self.match_flag)
4288

4289
        if self.target or self.excinfo_target:
4290 4291
            self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
        else:
4292
            self.exc_vars = None
4293

William Stein's avatar
William Stein committed
4294
        if self.target:
4295 4296
            self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
            self.exc_value.allocate_temps(env)
4297
            self.target.analyse_target_expression(env, self.exc_value)
4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308
        if self.excinfo_target is not None:
            import ExprNodes
            self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
                ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
                ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
                ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
            ])
            self.excinfo_tuple.analyse_expressions(env)
            self.excinfo_tuple.allocate_temps(env)
            self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)

William Stein's avatar
William Stein committed
4309
        self.body.analyse_expressions(env)
4310 4311 4312 4313

        if self.exc_vars:
            for var in self.exc_vars:
                env.release_temp(var)
William Stein's avatar
William Stein committed
4314 4315 4316 4317 4318 4319 4320 4321 4322 4323
    
    def generate_handling_code(self, code, end_label):
        code.mark_pos(self.pos)
        if self.pattern:
            self.pattern.generate_evaluation_code(code)
            code.putln(
                "%s = PyErr_ExceptionMatches(%s);" % (
                    self.match_flag,
                    self.pattern.py_result()))
            self.pattern.generate_disposal_code(code)
4324
            self.pattern.free_temps(code)
William Stein's avatar
William Stein committed
4325 4326 4327 4328
            code.putln(
                "if (%s) {" %
                    self.match_flag)
        else:
4329
            code.putln("/*except:*/ {")
4330

Stefan Behnel's avatar
Stefan Behnel committed
4331 4332 4333 4334 4335
        if self.exc_vars:
            exc_vars = self.exc_vars
        elif not getattr(self.body, 'stats', True):
            # most simple case: no exception variable, empty body (pass)
            # => reset the exception state, done
4336 4337 4338 4339
            code.putln("PyErr_Restore(0,0,0);")
            code.put_goto(end_label)
            code.putln("}")
            return
4340
        else:
Stefan Behnel's avatar
Stefan Behnel committed
4341 4342
            # during type analysis, we didn't know if we need the
            # exception value, but apparently, we do
4343 4344 4345 4346
            exc_vars = [code.funcstate.allocate_temp(py_object_type,
                                                     manage_ref=True)
                        for i in xrange(3)]

4347
        code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
William Stein's avatar
William Stein committed
4348 4349 4350
        # We always have to fetch the exception value even if
        # there is no target, because this also normalises the 
        # exception and stores it in the thread state.
4351 4352
        code.globalstate.use_utility_code(get_exception_utility_code)
        exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4353 4354
        code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
            code.error_goto(self.pos)))
4355
        for x in exc_vars:
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
4356
            code.put_gotref(x)
William Stein's avatar
William Stein committed
4357
        if self.target:
4358
            self.exc_value.generate_evaluation_code(code)
William Stein's avatar
William Stein committed
4359
            self.target.generate_assignment_code(self.exc_value, code)
4360 4361 4362 4363
        if self.excinfo_target is not None:
            self.excinfo_tuple.generate_evaluation_code(code)
            self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)

4364 4365 4366 4367 4368

        old_break_label, old_continue_label = code.break_label, code.continue_label
        code.break_label = code.new_label('except_break')
        code.continue_label = code.new_label('except_continue')

4369
        old_exc_vars = code.funcstate.exc_vars
4370
        code.funcstate.exc_vars = exc_vars
William Stein's avatar
William Stein committed
4371
        self.body.generate_execution_code(code)
4372
        code.funcstate.exc_vars = old_exc_vars
4373
        for var in exc_vars:
4374
            code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4375
        code.put_goto(end_label)
Robert Bradshaw's avatar
Robert Bradshaw committed
4376 4377 4378
        
        if code.label_used(code.break_label):
            code.put_label(code.break_label)
4379
            for var in exc_vars:
Robert Bradshaw's avatar
Robert Bradshaw committed
4380 4381 4382
                code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
            code.put_goto(old_break_label)
        code.break_label = old_break_label
4383 4384 4385

        if code.label_used(code.continue_label):
            code.put_label(code.continue_label)
4386
            for var in exc_vars:
4387 4388 4389
                code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
            code.put_goto(old_continue_label)
        code.continue_label = old_continue_label
4390 4391 4392 4393 4394 4395

        if not self.exc_vars:
            # clean up locally allocated temps
            for temp in exc_vars:
                code.funcstate.release_temp(temp)

William Stein's avatar
William Stein committed
4396 4397 4398
        code.putln(
            "}")

4399
    def annotate(self, code):
4400 4401
        if self.pattern:
            self.pattern.annotate(code)
4402 4403 4404 4405
        if self.target:
            self.target.annotate(code)
        self.body.annotate(code)

William Stein's avatar
William Stein committed
4406 4407 4408 4409 4410 4411

class TryFinallyStatNode(StatNode):
    #  try ... finally statement
    #
    #  body             StatNode
    #  finally_clause   StatNode
4412
    #
4413
    #  cleanup_list     [Entry]     old_style temps to clean up on error
William Stein's avatar
William Stein committed
4414 4415 4416 4417 4418 4419 4420 4421 4422
    #
    #  The plan is that we funnel all continue, break
    #  return and error gotos into the beginning of the
    #  finally block, setting a variable to remember which
    #  one we're doing. At the end of the finally block, we
    #  switch on the variable to figure out where to go.
    #  In addition, if we're doing an error, we save the
    #  exception on entry to the finally block and restore
    #  it on exit.
4423

4424
    child_attrs = ["body", "finally_clause"]
William Stein's avatar
William Stein committed
4425
    
4426 4427
    preserve_exception = 1
    
William Stein's avatar
William Stein committed
4428 4429 4430 4431
    disallow_continue_in_try_finally = 0
    # There doesn't seem to be any point in disallowing
    # continue in the try block, since we have no problem
    # handling it.
4432 4433 4434 4435 4436 4437

    def create_analysed(pos, env, body, finally_clause):
        node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
        node.cleanup_list = []
        return node
    create_analysed = staticmethod(create_analysed)
William Stein's avatar
William Stein committed
4438
    
4439 4440 4441 4442
    def analyse_control_flow(self, env):
        env.start_branching(self.pos)
        self.body.analyse_control_flow(env)
        env.next_branch(self.body.end_pos())
Robert Bradshaw's avatar
Robert Bradshaw committed
4443
        env.finish_branching(self.body.end_pos())
4444 4445
        self.finally_clause.analyse_control_flow(env)

William Stein's avatar
William Stein committed
4446 4447 4448 4449 4450 4451 4452 4453
    def analyse_declarations(self, env):
        self.body.analyse_declarations(env)
        self.finally_clause.analyse_declarations(env)
    
    def analyse_expressions(self, env):
        self.body.analyse_expressions(env)
        self.cleanup_list = env.free_temp_entries[:]
        self.finally_clause.analyse_expressions(env)
4454 4455 4456 4457
        self.gil_check(env)

    gil_message = "Try-finally statement"

William Stein's avatar
William Stein committed
4458 4459 4460 4461 4462 4463 4464 4465 4466
    def generate_execution_code(self, code):
        old_error_label = code.error_label
        old_labels = code.all_new_labels()
        new_labels = code.get_all_labels()
        new_error_label = code.error_label
        catch_label = code.new_label()
        code.putln(
            "/*try:*/ {")
        if self.disallow_continue_in_try_finally:
4467 4468
            was_in_try_finally = code.funcstate.in_try_finally
            code.funcstate.in_try_finally = 1
William Stein's avatar
William Stein committed
4469 4470
        self.body.generate_execution_code(code)
        if self.disallow_continue_in_try_finally:
4471
            code.funcstate.in_try_finally = was_in_try_finally
William Stein's avatar
William Stein committed
4472 4473
        code.putln(
            "}")
4474
        temps_to_clean_up = code.funcstate.all_free_managed_temps()
William Stein's avatar
William Stein committed
4475 4476
        code.putln(
            "/*finally:*/ {")
4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492
        cases_used = []
        error_label_used = 0
        for i, new_label in enumerate(new_labels):
            if new_label in code.labels_used:
                cases_used.append(i)
                if new_label == new_error_label:
                    error_label_used = 1
                    error_label_case = i
        if cases_used:
            code.putln(
                    "int __pyx_why;")
            if error_label_used and self.preserve_exception:
                code.putln(
                    "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
                code.putln(
                    "int %s;" % Naming.exc_lineno_name)
4493 4494 4495 4496 4497
                exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
                exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
                code.putln(exc_var_init_zero)
            else:
                exc_var_init_zero = None
4498 4499 4500 4501 4502
            code.use_label(catch_label)
            code.putln(
                    "__pyx_why = 0; goto %s;" % catch_label)
            for i in cases_used:
                new_label = new_labels[i]
Stefan Behnel's avatar
Stefan Behnel committed
4503
                #if new_label and new_label != "<try>":
4504 4505
                if new_label == new_error_label and self.preserve_exception:
                    self.put_error_catcher(code, 
4506
                        new_error_label, i+1, catch_label, temps_to_clean_up)
4507
                else:
4508 4509 4510 4511
                    code.put('%s: ' % new_label)
                    if exc_var_init_zero:
                        code.putln(exc_var_init_zero)
                    code.putln("__pyx_why = %s; goto %s;" % (
4512 4513 4514
                            i+1,
                            catch_label))
            code.put_label(catch_label)
William Stein's avatar
William Stein committed
4515
        code.set_all_labels(old_labels)
4516 4517 4518
        if error_label_used:
            code.new_error_label()
            finally_error_label = code.error_label
William Stein's avatar
William Stein committed
4519
        self.finally_clause.generate_execution_code(code)
4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533
        if error_label_used:
            if finally_error_label in code.labels_used and self.preserve_exception:
                over_label = code.new_label()
                code.put_goto(over_label);
                code.put_label(finally_error_label)
                code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
                for var in Naming.exc_vars:
                    code.putln("Py_XDECREF(%s);" % var)
                code.putln("}")
                code.put_goto(old_error_label)
                code.put_label(over_label)
            code.error_label = old_error_label
        if cases_used:
            code.putln(
William Stein's avatar
William Stein committed
4534
                "switch (__pyx_why) {")
4535 4536 4537
            for i in cases_used:
                old_label = old_labels[i]
                if old_label == old_error_label and self.preserve_exception:
William Stein's avatar
William Stein committed
4538 4539
                    self.put_error_uncatcher(code, i+1, old_error_label)
                else:
4540
                    code.use_label(old_label)
William Stein's avatar
William Stein committed
4541 4542 4543
                    code.putln(
                        "case %s: goto %s;" % (
                            i+1,
4544 4545
                            old_label))
            code.putln(
4546
                "}")
William Stein's avatar
William Stein committed
4547 4548 4549
        code.putln(
            "}")

4550
    def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4551
        code.globalstate.use_utility_code(restore_exception_utility_code)
William Stein's avatar
William Stein committed
4552 4553 4554 4555 4556 4557 4558
        code.putln(
            "%s: {" %
                error_label)
        code.putln(
                "__pyx_why = %s;" %
                    i)
        code.put_var_xdecrefs_clear(self.cleanup_list)
4559 4560
        for temp_name, type in temps_to_clean_up:
            code.put_xdecref_clear(temp_name, type)
William Stein's avatar
William Stein committed
4561
        code.putln(
4562
                "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4563
                    Naming.exc_vars)
William Stein's avatar
William Stein committed
4564 4565
        code.putln(
                "%s = %s;" % (
4566
                    Naming.exc_lineno_name, Naming.lineno_cname))
4567
        #code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
4568 4569
        #        "goto %s;" %
        #            catch_label)
4570
        code.put_goto(catch_label)
William Stein's avatar
William Stein committed
4571 4572 4573 4574
        code.putln(
            "}")
            
    def put_error_uncatcher(self, code, i, error_label):
4575
        code.globalstate.use_utility_code(restore_exception_utility_code)
William Stein's avatar
William Stein committed
4576 4577 4578 4579
        code.putln(
            "case %s: {" %
                i)
        code.putln(
4580
                "__Pyx_ErrRestore(%s, %s, %s);" %
4581
                    Naming.exc_vars)
William Stein's avatar
William Stein committed
4582 4583
        code.putln(
                "%s = %s;" % (
4584 4585
                    Naming.lineno_cname, Naming.exc_lineno_name))
        for var in Naming.exc_vars:
William Stein's avatar
William Stein committed
4586 4587 4588
            code.putln(
                "%s = 0;" %
                    var)
4589
        code.put_goto(error_label)
William Stein's avatar
William Stein committed
4590 4591 4592
        code.putln(
            "}")

4593 4594 4595 4596
    def annotate(self, code):
        self.body.annotate(code)
        self.finally_clause.annotate(code)

William Stein's avatar
William Stein committed
4597

4598 4599 4600 4601 4602
class GILStatNode(TryFinallyStatNode):
    #  'with gil' or 'with nogil' statement
    #
    #   state   string   'gil' or 'nogil'
        
4603 4604
    child_attrs = []
    
4605 4606 4607 4608 4609 4610 4611 4612
    preserve_exception = 0

    def __init__(self, pos, state, body):
        self.state = state
        TryFinallyStatNode.__init__(self, pos,
            body = body,
            finally_clause = GILExitNode(pos, state = state))

4613
    def analyse_expressions(self, env):
Stefan Behnel's avatar
Stefan Behnel committed
4614
        env.use_utility_code(force_init_threads_utility_code)
4615 4616 4617 4618 4619 4620 4621 4622
        was_nogil = env.nogil
        env.nogil = 1
        TryFinallyStatNode.analyse_expressions(self, env)
        env.nogil = was_nogil

    def gil_check(self, env):
        pass

4623
    def generate_execution_code(self, code):
Stefan Behnel's avatar
Stefan Behnel committed
4624
        code.mark_pos(self.pos)
4625
        if self.state == 'gil':
Stefan Behnel's avatar
Stefan Behnel committed
4626
            code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4627
        else:
Stefan Behnel's avatar
Stefan Behnel committed
4628
            code.putln("{ PyThreadState *_save;")
4629 4630 4631 4632 4633 4634 4635 4636 4637 4638
            code.putln("Py_UNBLOCK_THREADS")
        TryFinallyStatNode.generate_execution_code(self, code)
        code.putln("}")


class GILExitNode(StatNode):
    #  Used as the 'finally' block in a GILStatNode
    #
    #  state   string   'gil' or 'nogil'

4639 4640
    child_attrs = []

4641 4642 4643 4644 4645 4646 4647 4648 4649 4650
    def analyse_expressions(self, env):
        pass

    def generate_execution_code(self, code):
        if self.state == 'gil':
            code.putln("PyGILState_Release();")
        else:
            code.putln("Py_BLOCK_THREADS")


William Stein's avatar
William Stein committed
4651 4652 4653 4654 4655
class CImportStatNode(StatNode):
    #  cimport statement
    #
    #  module_name   string           Qualified name of module being imported
    #  as_name       string or None   Name specified in "as" clause, if any
4656 4657

    child_attrs = []
William Stein's avatar
William Stein committed
4658 4659
    
    def analyse_declarations(self, env):
4660 4661 4662
        if not env.is_module_scope:
            error(self.pos, "cimport only allowed at module level")
            return
William Stein's avatar
William Stein committed
4663 4664
        module_scope = env.find_module(self.module_name, self.pos)
        if "." in self.module_name:
4665
            names = [EncodedString(name) for name in self.module_name.split(".")]
William Stein's avatar
William Stein committed
4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690
            top_name = names[0]
            top_module_scope = env.context.find_submodule(top_name)
            module_scope = top_module_scope
            for name in names[1:]:
                submodule_scope = module_scope.find_submodule(name)
                module_scope.declare_module(name, submodule_scope, self.pos)
                module_scope = submodule_scope
            if self.as_name:
                env.declare_module(self.as_name, module_scope, self.pos)
            else:
                env.declare_module(top_name, top_module_scope, self.pos)
        else:
            name = self.as_name or self.module_name
            env.declare_module(name, module_scope, self.pos)

    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        pass
    

class FromCImportStatNode(StatNode):
    #  from ... cimport statement
    #
4691 4692
    #  module_name     string                        Qualified name of module
    #  imported_names  [(pos, name, as_name, kind)]  Names to be imported
William Stein's avatar
William Stein committed
4693
    
4694 4695
    child_attrs = []

William Stein's avatar
William Stein committed
4696
    def analyse_declarations(self, env):
4697 4698 4699
        if not env.is_module_scope:
            error(self.pos, "cimport only allowed at module level")
            return
William Stein's avatar
William Stein committed
4700 4701
        module_scope = env.find_module(self.module_name, self.pos)
        env.add_imported_module(module_scope)
4702
        for pos, name, as_name, kind in self.imported_names:
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4703 4704 4705 4706
            if name == "*":
                for local_name, entry in module_scope.entries.items():
                    env.add_imported_entry(local_name, entry, pos)
            else:
4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718
                entry = module_scope.lookup(name)
                if entry:
                    if kind and not self.declaration_matches(entry, kind):
                        entry.redeclared(pos)
                else:
                    if kind == 'struct' or kind == 'union':
                        entry = module_scope.declare_struct_or_union(name,
                            kind = kind, scope = None, typedef_flag = 0, pos = pos)
                    elif kind == 'class':
                        entry = module_scope.declare_c_class(name, pos = pos,
                            module_name = self.module_name)
                    else:
4719 4720 4721 4722 4723 4724
                        submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
                        if submodule_scope.parent_module is module_scope:
                            env.declare_module(as_name or name, submodule_scope, self.pos)
                        else:
                            error(pos, "Name '%s' not declared in module '%s'"
                                % (name, self.module_name))
4725
                        
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4726 4727 4728
                if entry:
                    local_name = as_name or name
                    env.add_imported_entry(local_name, entry, pos)
4729 4730
    
    def declaration_matches(self, entry, kind):
4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742
        if not entry.is_type:
            return 0
        type = entry.type
        if kind == 'class':
            if not type.is_extension_type:
                return 0
        else:
            if not type.is_struct_or_union:
                return 0
            if kind != type.kind:
                return 0
        return 1
William Stein's avatar
William Stein committed
4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755

    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        pass


class FromImportStatNode(StatNode):
    #  from ... import statement
    #
    #  module           ImportNode
    #  items            [(string, NameNode)]
4756
    #  interned_items   [(string, NameNode, ExprNode)]
William Stein's avatar
William Stein committed
4757
    #  item             PyTempNode            used internally
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4758
    #  import_star      boolean               used internally
4759 4760

    child_attrs = ["module"]
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4761
    import_star = 0
William Stein's avatar
William Stein committed
4762 4763
    
    def analyse_declarations(self, env):
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4764 4765 4766 4767 4768 4769 4770 4771 4772
        for name, target in self.items:
            if name == "*":
                if not env.is_module_scope:
                    error(self.pos, "import * only allowed at module level")
                    return
                env.has_import_star = 1
                self.import_star = 1
            else:
                target.analyse_target_declaration(env)
William Stein's avatar
William Stein committed
4773 4774 4775 4776 4777 4778 4779 4780
    
    def analyse_expressions(self, env):
        import ExprNodes
        self.module.analyse_expressions(env)
        self.item = ExprNodes.PyTempNode(self.pos, env)
        self.item.allocate_temp(env)
        self.interned_items = []
        for name, target in self.items:
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4781 4782 4783 4784 4785 4786
            if name == '*':
                for _, entry in env.entries.items():
                    if not entry.is_type and entry.type.is_extension_type:
                        env.use_utility_code(ExprNodes.type_test_utility_code)
                        break
            else:
4787 4788 4789
                entry =  env.lookup(target.name)
                if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
                    continue # already cimported
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4790
                target.analyse_target_expression(env, None)
4791 4792 4793 4794 4795 4796
                if target.type is py_object_type:
                    coerced_item = None
                else:
                    coerced_item = self.item.coerce_to(target.type, env)
                self.interned_items.append(
                    (env.intern_identifier(name), target, coerced_item))
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4797
                #target.release_target_temp(env) # was release_temp ?!?
William Stein's avatar
William Stein committed
4798 4799 4800 4801 4802
        self.module.release_temp(env)
        self.item.release_temp(env)
    
    def generate_execution_code(self, code):
        self.module.generate_evaluation_code(code)
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4803 4804 4805 4806 4807 4808
        if self.import_star:
            code.putln(
                'if (%s(%s) < 0) %s;' % (
                    Naming.import_star,
                    self.module.py_result(),
                    code.error_goto(self.pos)))
4809
        for cname, target, coerced_item in self.interned_items:
4810 4811
            code.putln(
                '%s = PyObject_GetAttr(%s, %s); %s' % (
4812
                    self.item.result(), 
4813 4814
                    self.module.py_result(),
                    cname,
4815
                    code.error_goto_if_null(self.item.result(), self.pos)))
4816
            code.put_gotref(self.item.py_result())
4817 4818 4819 4820 4821 4822 4823 4824
            if coerced_item is None:
                target.generate_assignment_code(self.item, code)
            else:
                coerced_item.allocate_temp_result(code)
                coerced_item.generate_result_code(code)
                target.generate_assignment_code(coerced_item, code)
                if self.item.result() != coerced_item.result():
                    code.put_decref_clear(self.item.result(), self.item.type)
William Stein's avatar
William Stein committed
4825
        self.module.generate_disposal_code(code)
4826
        self.module.free_temps(code)
William Stein's avatar
William Stein committed
4827

4828

4829

William Stein's avatar
William Stein committed
4830 4831 4832 4833 4834 4835 4836 4837
#------------------------------------------------------------------------------------
#
#  Runtime support code
#
#------------------------------------------------------------------------------------

utility_function_predeclarations = \
"""
4838 4839 4840
#ifdef __GNUC__
#define INLINE __inline__
#elif _WIN32
4841
#define INLINE __inline
4842 4843 4844 4845
#else
#define INLINE 
#endif

4846
typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4847

4848 4849 4850 4851 4852
""" + """

static int %(skip_dispatch_cname)s = 0;

""" % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
Robert Bradshaw's avatar
Robert Bradshaw committed
4853 4854 4855 4856

if Options.gcc_branch_hints:
    branch_prediction_macros = \
    """
4857
#ifdef __GNUC__
4858 4859 4860
/* Test for GCC > 2.95 */
#if __GNUC__ > 2 || \
              (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) 
Robert Bradshaw's avatar
Robert Bradshaw committed
4861 4862
#define likely(x)   __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
4863 4864 4865 4866
#else /* __GNUC__ > 2 ... */
#define likely(x)   (x)
#define unlikely(x) (x)
#endif /* __GNUC__ > 2 ... */
4867 4868 4869 4870
#else /* __GNUC__ */
#define likely(x)   (x)
#define unlikely(x) (x)
#endif /* __GNUC__ */
Robert Bradshaw's avatar
Robert Bradshaw committed
4871 4872 4873 4874 4875 4876 4877
    """
else:
    branch_prediction_macros = \
    """
#define likely(x)   (x)
#define unlikely(x) (x)
    """
William Stein's avatar
William Stein committed
4878

4879 4880
#get_name_predeclaration = \
#"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
William Stein's avatar
William Stein committed
4881

4882 4883
#get_name_interned_predeclaration = \
#"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
William Stein's avatar
William Stein committed
4884 4885 4886

#------------------------------------------------------------------------------------

4887 4888
printing_utility_code = UtilityCode(
proto = """
4889 4890
static int __Pyx_Print(PyObject *, int); /*proto*/
#if PY_MAJOR_VERSION >= 3
4891 4892 4893
static PyObject* %s = 0;
static PyObject* %s = 0;
#endif
4894 4895
""" % (Naming.print_function, Naming.print_function_kwargs),
impl = r"""
4896
#if PY_MAJOR_VERSION < 3
William Stein's avatar
William Stein committed
4897
static PyObject *__Pyx_GetStdout(void) {
4898
    PyObject *f = PySys_GetObject((char *)"stdout");
William Stein's avatar
William Stein committed
4899 4900 4901 4902 4903 4904
    if (!f) {
        PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
    }
    return f;
}

4905
static int __Pyx_Print(PyObject *arg_tuple, int newline) {
William Stein's avatar
William Stein committed
4906
    PyObject *f;
4907 4908
    PyObject* v;
    int i;
4909

William Stein's avatar
William Stein committed
4910 4911
    if (!(f = __Pyx_GetStdout()))
        return -1;
4912 4913 4914 4915 4916 4917 4918
    for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
        if (PyFile_SoftSpace(f, 1)) {
            if (PyFile_WriteString(" ", f) < 0)
                return -1;
        }
        v = PyTuple_GET_ITEM(arg_tuple, i);
        if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
William Stein's avatar
William Stein committed
4919
            return -1;
4920 4921 4922 4923 4924 4925 4926 4927
        if (PyString_Check(v)) {
            char *s = PyString_AsString(v);
            Py_ssize_t len = PyString_Size(v);
            if (len > 0 &&
                isspace(Py_CHARMASK(s[len-1])) &&
                s[len-1] != ' ')
                    PyFile_SoftSpace(f, 0);
        }
William Stein's avatar
William Stein committed
4928
    }
4929 4930 4931 4932
    if (newline) {
        if (PyFile_WriteString("\n", f) < 0)
            return -1;
        PyFile_SoftSpace(f, 0);
William Stein's avatar
William Stein committed
4933 4934 4935 4936
    }
    return 0;
}

4937
#else /* Python 3 has a print function */
4938

4939 4940 4941 4942 4943
static int __Pyx_Print(PyObject *arg_tuple, int newline) {
    PyObject* kwargs = 0;
    PyObject* result = 0;
    PyObject* end_string;
    if (!%(PRINT_FUNCTION)s) {
4944
        %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4945
        if (!%(PRINT_FUNCTION)s)
4946
            return -1;
4947 4948 4949 4950 4951
    }
    if (!newline) {
        if (!%(PRINT_KWARGS)s) {
            %(PRINT_KWARGS)s = PyDict_New();
            if (!%(PRINT_KWARGS)s)
4952
                return -1;
4953 4954
            end_string = PyUnicode_FromStringAndSize(" ", 1);
            if (!end_string)
4955
                return -1;
4956 4957
            if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
                Py_DECREF(end_string);
4958
                return -1;
4959 4960 4961 4962 4963 4964 4965
            }
            Py_DECREF(end_string);
        }
        kwargs = %(PRINT_KWARGS)s;
    }
    result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
    if (!result)
William Stein's avatar
William Stein committed
4966
        return -1;
4967
    Py_DECREF(result);
William Stein's avatar
William Stein committed
4968 4969
    return 0;
}
4970

4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997
#endif
""" % {'BUILTINS'       : Naming.builtins_cname,
       'PRINT_FUNCTION' : Naming.print_function,
       'PRINT_KWARGS'   : Naming.print_function_kwargs}
)


printing_one_utility_code = UtilityCode(
proto = """
static int __Pyx_PrintOne(PyObject *o); /*proto*/
""",
impl = r"""
#if PY_MAJOR_VERSION < 3

static int __Pyx_PrintOne(PyObject *o) {
    PyObject *f;
    if (!(f = __Pyx_GetStdout()))
        return -1;
    if (PyFile_SoftSpace(f, 0)) {
        if (PyFile_WriteString(" ", f) < 0)
            return -1;
    }
    if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
        return -1;
    if (PyFile_WriteString("\n", f) < 0)
        return -1;
    return 0;
4998 4999
    /* the line below is just to avoid compiler
     * compiler warnings about unused functions */
Robert Bradshaw's avatar
Robert Bradshaw committed
5000
    return __Pyx_Print(NULL, 0);
5001 5002 5003 5004
}

#else /* Python 3 has a print function */

5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016
static int __Pyx_PrintOne(PyObject *o) {
    int res;
    PyObject* arg_tuple = PyTuple_New(1);
    if (unlikely(!arg_tuple))
        return -1;
    Py_INCREF(o);
    PyTuple_SET_ITEM(arg_tuple, 0, o);
    res = __Pyx_Print(arg_tuple, 1);
    Py_DECREF(arg_tuple);
    return res;
}

5017
#endif
Robert Bradshaw's avatar
Robert Bradshaw committed
5018 5019
""",
requires=[printing_utility_code])
5020 5021


William Stein's avatar
William Stein committed
5022 5023 5024 5025 5026

#------------------------------------------------------------------------------------

# The following function is based on do_raise() from ceval.c.

5027 5028
raise_utility_code = UtilityCode(
proto = """
5029
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5030 5031
""",
impl = """
William Stein's avatar
William Stein committed
5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
    Py_XINCREF(type);
    Py_XINCREF(value);
    Py_XINCREF(tb);
    /* First, check the traceback argument, replacing None with NULL. */
    if (tb == Py_None) {
        Py_DECREF(tb);
        tb = 0;
    }
    else if (tb != NULL && !PyTraceBack_Check(tb)) {
        PyErr_SetString(PyExc_TypeError,
            "raise: arg 3 must be a traceback or None");
        goto raise_error;
    }
    /* Next, replace a missing value with None */
    if (value == NULL) {
        value = Py_None;
        Py_INCREF(value);
    }
5051 5052 5053 5054 5055 5056
    #if PY_VERSION_HEX < 0x02050000
    if (!PyClass_Check(type))
    #else
    if (!PyType_Check(type))
    #endif
    {
William Stein's avatar
William Stein committed
5057 5058 5059
        /* Raising an instance.  The value should be a dummy. */
        if (value != Py_None) {
            PyErr_SetString(PyExc_TypeError,
5060
                "instance exception may not have a separate value");
William Stein's avatar
William Stein committed
5061 5062
            goto raise_error;
        }
5063 5064 5065
        /* Normalize to raise <class>, <instance> */
        Py_DECREF(value);
        value = type;
5066 5067 5068 5069 5070 5071
        #if PY_VERSION_HEX < 0x02050000
            if (PyInstance_Check(type)) {
                type = (PyObject*) ((PyInstanceObject*)type)->in_class;
                Py_INCREF(type);
            }
            else {
5072
                type = 0;
5073 5074 5075 5076 5077
                PyErr_SetString(PyExc_TypeError,
                    "raise: exception must be an old-style class or instance");
                goto raise_error;
            }
        #else
5078
            type = (PyObject*) Py_TYPE(type);
5079 5080 5081 5082 5083 5084 5085
            Py_INCREF(type);
            if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
                PyErr_SetString(PyExc_TypeError,
                    "raise: exception class must be a subclass of BaseException");
                goto raise_error;
            }
        #endif
William Stein's avatar
William Stein committed
5086
    }
5087
    __Pyx_ErrRestore(type, value, tb);
5088 5089 5090
    return;
raise_error:
    Py_XDECREF(value);
William Stein's avatar
William Stein committed
5091 5092 5093 5094
    Py_XDECREF(type);
    Py_XDECREF(tb);
    return;
}
5095
""")
William Stein's avatar
William Stein committed
5096 5097 5098

#------------------------------------------------------------------------------------

5099 5100
reraise_utility_code = UtilityCode(
proto = """
5101
static void __Pyx_ReRaise(void); /*proto*/
5102 5103
""",
impl = """
William Stein's avatar
William Stein committed
5104
static void __Pyx_ReRaise(void) {
5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117
    PyThreadState *tstate = PyThreadState_GET();
    PyObject* tmp_type = tstate->curexc_type;
    PyObject* tmp_value = tstate->curexc_value;
    PyObject* tmp_tb = tstate->curexc_traceback;
    tstate->curexc_type = tstate->exc_type;
    tstate->curexc_value = tstate->exc_value;
    tstate->curexc_traceback = tstate->exc_traceback;
    tstate->exc_type = 0;
    tstate->exc_value = 0;
    tstate->exc_traceback = 0;
    Py_XDECREF(tmp_type);
    Py_XDECREF(tmp_value);
    Py_XDECREF(tmp_tb);
William Stein's avatar
William Stein committed
5118
}
5119
""")
William Stein's avatar
William Stein committed
5120 5121 5122

#------------------------------------------------------------------------------------

5123 5124
arg_type_test_utility_code = UtilityCode(
proto = """
5125 5126
static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
    const char *name, int exact); /*proto*/
5127 5128
""",
impl = """
5129 5130 5131
static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
    const char *name, int exact)
{
William Stein's avatar
William Stein committed
5132 5133 5134 5135
    if (!type) {
        PyErr_Format(PyExc_SystemError, "Missing type object");
        return 0;
    }
Robert Bradshaw's avatar
Robert Bradshaw committed
5136 5137
    if (none_allowed && obj == Py_None) return 1;
    else if (exact) {
5138
        if (Py_TYPE(obj) == type) return 1;
Robert Bradshaw's avatar
Robert Bradshaw committed
5139 5140
    }
    else {
Robert Bradshaw's avatar
Robert Bradshaw committed
5141
        if (PyObject_TypeCheck(obj, type)) return 1;
Robert Bradshaw's avatar
Robert Bradshaw committed
5142
    }
William Stein's avatar
William Stein committed
5143 5144
    PyErr_Format(PyExc_TypeError,
        "Argument '%s' has incorrect type (expected %s, got %s)",
5145
        name, type->tp_name, Py_TYPE(obj)->tp_name);
William Stein's avatar
William Stein committed
5146 5147
    return 0;
}
5148
""")
William Stein's avatar
William Stein committed
5149 5150 5151

#------------------------------------------------------------------------------------
#
5152 5153 5154
#  __Pyx_RaiseArgtupleInvalid raises the correct exception when too
#  many or too few positional arguments were found.  This handles
#  Py_ssize_t formatting correctly.
5155

5156 5157
raise_argtuple_invalid_utility_code = UtilityCode(
proto = """
5158
static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5159
    Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5160 5161
""",
impl = """
5162
static void __Pyx_RaiseArgtupleInvalid(
5163
    const char* func_name,
5164
    int exact,
5165 5166
    Py_ssize_t num_min,
    Py_ssize_t num_max,
5167
    Py_ssize_t num_found)
William Stein's avatar
William Stein committed
5168
{
5169
    Py_ssize_t num_expected;
Stefan Behnel's avatar
Stefan Behnel committed
5170
    const char *number, *more_or_less;
5171 5172 5173 5174

    if (num_found < num_min) {
        num_expected = num_min;
        more_or_less = "at least";
5175
    } else {
5176
        num_expected = num_max;
5177
        more_or_less = "at most";
5178
    }
5179 5180
    if (exact) {
        more_or_less = "exactly";
5181
    }
5182
    number = (num_expected == 1) ? "" : "s";
Stefan Behnel's avatar
Stefan Behnel committed
5183 5184 5185 5186 5187 5188 5189
    PyErr_Format(PyExc_TypeError,
        #if PY_VERSION_HEX < 0x02050000
            "%s() takes %s %d positional argument%s (%d given)",
        #else
            "%s() takes %s %zd positional argument%s (%zd given)",
        #endif
        func_name, more_or_less, num_expected, number, num_found);
5190
}
5191
""")
5192

5193 5194
raise_keyword_required_utility_code = UtilityCode(
proto = """
5195
static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5196 5197
""",
impl = """
5198
static INLINE void __Pyx_RaiseKeywordRequired(
5199
    const char* func_name,
5200
    PyObject* kw_name)
5201 5202
{
    PyErr_Format(PyExc_TypeError,
5203 5204 5205 5206 5207 5208
        #if PY_MAJOR_VERSION >= 3
        "%s() needs keyword-only argument %U", func_name, kw_name);
        #else
        "%s() needs keyword-only argument %s", func_name,
        PyString_AS_STRING(kw_name));
        #endif
5209
}
5210
""")
5211

5212 5213
raise_double_keywords_utility_code = UtilityCode(
proto = """
5214
static void __Pyx_RaiseDoubleKeywordsError(
5215
    const char* func_name, PyObject* kw_name); /*proto*/
5216 5217
""",
impl = """
5218
static void __Pyx_RaiseDoubleKeywordsError(
5219
    const char* func_name,
5220
    PyObject* kw_name)
5221
{
5222
    PyErr_Format(PyExc_TypeError,
5223 5224 5225 5226 5227 5228
        #if PY_MAJOR_VERSION >= 3
        "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
        #else
        "%s() got multiple values for keyword argument '%s'", func_name,
        PyString_AS_STRING(kw_name));
        #endif
5229
}
5230
""")
5231

5232 5233
#------------------------------------------------------------------------------------
#
5234 5235 5236
#  __Pyx_CheckKeywordStrings raises an error if non-string keywords
#  were passed to a function, or if any keywords were passed to a
#  function that does not accept them.
5237

5238 5239
keyword_string_check_utility_code = UtilityCode(
proto = """
5240
static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5241
    const char* function_name, int kw_allowed); /*proto*/
5242 5243
""",
impl = """
5244
static INLINE int __Pyx_CheckKeywordStrings(
5245 5246 5247 5248
    PyObject *kwdict,
    const char* function_name,
    int kw_allowed)
{
5249 5250
    PyObject* key = 0;
    Py_ssize_t pos = 0;
5251
    while (PyDict_Next(kwdict, &pos, &key, 0)) {
5252
        #if PY_MAJOR_VERSION < 3
5253
        if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5254
        #else
5255
        if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5256
        #endif
5257
            goto invalid_keyword_type;
5258
    }
5259 5260
    if ((!kw_allowed) && unlikely(key))
        goto invalid_keyword;
5261
    return 1;
5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275
invalid_keyword_type:
    PyErr_Format(PyExc_TypeError,
        "%s() keywords must be strings", function_name);
    return 0;
invalid_keyword:
    PyErr_Format(PyExc_TypeError,
    #if PY_MAJOR_VERSION < 3
        "%s() got an unexpected keyword argument '%s'",
        function_name, PyString_AsString(key));
    #else
        "%s() got an unexpected keyword argument '%U'",
        function_name, key);
    #endif
    return 0;
5276
}
5277
""")
5278

5279 5280
#------------------------------------------------------------------------------------
#
5281 5282 5283
#  __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
#  arguments from the kwds dict into kwds2.  If kwds2 is NULL, unknown
#  keywords will raise an invalid keyword error.
5284
#
Stefan Behnel's avatar
Stefan Behnel committed
5285 5286
#  Three kinds of errors are checked: 1) non-string keywords, 2)
#  unexpected keywords and 3) overlap with positional arguments.
5287
#
Stefan Behnel's avatar
Stefan Behnel committed
5288 5289 5290 5291 5292
#  If num_posargs is greater 0, it denotes the number of positional
#  arguments that were passed and that must therefore not appear
#  amongst the keywords as well.
#
#  This method does not check for required keyword arguments.
5293 5294
#

5295
parse_keywords_utility_code = UtilityCode(
5296
proto = """
5297
static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5298 5299
    PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
    const char* function_name); /*proto*/
5300 5301
""",
impl = """
5302
static int __Pyx_ParseOptionalKeywords(
5303
    PyObject *kwds,
Stefan Behnel's avatar
Stefan Behnel committed
5304 5305
    PyObject **argnames[],
    PyObject *kwds2,
5306
    PyObject *values[],
Stefan Behnel's avatar
Stefan Behnel committed
5307
    Py_ssize_t num_pos_args,
5308
    const char* function_name)
5309
{
5310
    PyObject *key = 0, *value = 0;
5311
    Py_ssize_t pos = 0;
5312
    PyObject*** name;
5313
    PyObject*** first_kw_arg = argnames + num_pos_args;
5314

Stefan Behnel's avatar
Stefan Behnel committed
5315
    while (PyDict_Next(kwds, &pos, &key, &value)) {
5316 5317
        name = first_kw_arg;
        while (*name && (**name != key)) name++;
5318
        if (*name) {
5319
            values[name-argnames] = value;
Stefan Behnel's avatar
Stefan Behnel committed
5320
        } else {
5321 5322 5323 5324 5325 5326
            #if PY_MAJOR_VERSION < 3
            if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
            #else
            if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
            #endif
                goto invalid_keyword_type;
5327 5328
            } else {
                for (name = first_kw_arg; *name; name++) {
5329
                    #if PY_MAJOR_VERSION >= 3
Stefan Behnel's avatar
Stefan Behnel committed
5330
                    if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5331
                        PyUnicode_Compare(**name, key) == 0) break;
5332
                    #else
5333
                    if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5334
                        _PyString_Eq(**name, key)) break;
5335 5336
                    #endif
                }
5337
                if (*name) {
5338 5339 5340 5341 5342 5343 5344 5345 5346 5347
                    values[name-argnames] = value;
                } else {
                    /* unexpected keyword found */
                    for (name=argnames; name != first_kw_arg; name++) {
                        if (**name == key) goto arg_passed_twice;
                        #if PY_MAJOR_VERSION >= 3
                        if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
                            PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
                        #else
                        if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5348
                            _PyString_Eq(**name, key)) goto arg_passed_twice;
5349 5350
                        #endif
                    }
Stefan Behnel's avatar
Stefan Behnel committed
5351 5352 5353
                    if (kwds2) {
                        if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
                    } else {
5354
                        goto invalid_keyword;
Stefan Behnel's avatar
Stefan Behnel committed
5355 5356
                    }
                }
5357
            }
5358
        }
5359
    }
5360
    return 0;
5361
arg_passed_twice:
Stefan Behnel's avatar
Stefan Behnel committed
5362 5363
    __Pyx_RaiseDoubleKeywordsError(function_name, **name);
    goto bad;
5364 5365 5366 5367 5368
invalid_keyword_type:
    PyErr_Format(PyExc_TypeError,
        "%s() keywords must be strings", function_name);
    goto bad;
invalid_keyword:
5369
    PyErr_Format(PyExc_TypeError,
5370
    #if PY_MAJOR_VERSION < 3
5371 5372
        "%s() got an unexpected keyword argument '%s'",
        function_name, PyString_AsString(key));
5373
    #else
5374 5375
        "%s() got an unexpected keyword argument '%U'",
        function_name, key);
5376
    #endif
William Stein's avatar
William Stein committed
5377 5378 5379
bad:
    return -1;
}
5380
""")
William Stein's avatar
William Stein committed
5381 5382 5383

#------------------------------------------------------------------------------------

5384 5385
traceback_utility_code = UtilityCode(
proto = """
5386
static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5387 5388
""",
impl = """
William Stein's avatar
William Stein committed
5389 5390 5391 5392
#include "compile.h"
#include "frameobject.h"
#include "traceback.h"

5393
static void __Pyx_AddTraceback(const char *funcname) {
William Stein's avatar
William Stein committed
5394 5395 5396 5397 5398 5399
    PyObject *py_srcfile = 0;
    PyObject *py_funcname = 0;
    PyObject *py_globals = 0;
    PyObject *empty_string = 0;
    PyCodeObject *py_code = 0;
    PyFrameObject *py_frame = 0;
5400 5401

    #if PY_MAJOR_VERSION < 3
William Stein's avatar
William Stein committed
5402
    py_srcfile = PyString_FromString(%(FILENAME)s);
5403 5404 5405
    #else
    py_srcfile = PyUnicode_FromString(%(FILENAME)s);
    #endif
William Stein's avatar
William Stein committed
5406
    if (!py_srcfile) goto bad;
Robert Bradshaw's avatar
Robert Bradshaw committed
5407
    if (%(CLINENO)s) {
5408
        #if PY_MAJOR_VERSION < 3
5409
        py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5410
        #else
5411
        py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5412
        #endif
Robert Bradshaw's avatar
Robert Bradshaw committed
5413 5414
    }
    else {
5415
        #if PY_MAJOR_VERSION < 3
Robert Bradshaw's avatar
Robert Bradshaw committed
5416
        py_funcname = PyString_FromString(funcname);
5417 5418 5419
        #else
        py_funcname = PyUnicode_FromString(funcname);
        #endif
Robert Bradshaw's avatar
Robert Bradshaw committed
5420
    }
William Stein's avatar
William Stein committed
5421 5422 5423
    if (!py_funcname) goto bad;
    py_globals = PyModule_GetDict(%(GLOBALS)s);
    if (!py_globals) goto bad;
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
5424
    #if PY_MAJOR_VERSION < 3
Stefan Behnel's avatar
Stefan Behnel committed
5425
    empty_string = PyString_FromStringAndSize("", 0);
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
5426 5427 5428
    #else
    empty_string = PyBytes_FromStringAndSize("", 0);
    #endif
William Stein's avatar
William Stein committed
5429 5430 5431
    if (!empty_string) goto bad;
    py_code = PyCode_New(
        0,            /*int argcount,*/
5432 5433 5434
        #if PY_MAJOR_VERSION >= 3
        0,            /*int kwonlyargcount,*/
        #endif
William Stein's avatar
William Stein committed
5435 5436 5437 5438
        0,            /*int nlocals,*/
        0,            /*int stacksize,*/
        0,            /*int flags,*/
        empty_string, /*PyObject *code,*/
Stefan Behnel's avatar
Stefan Behnel committed
5439 5440 5441 5442 5443
        %(EMPTY_TUPLE)s,  /*PyObject *consts,*/
        %(EMPTY_TUPLE)s,  /*PyObject *names,*/
        %(EMPTY_TUPLE)s,  /*PyObject *varnames,*/
        %(EMPTY_TUPLE)s,  /*PyObject *freevars,*/
        %(EMPTY_TUPLE)s,  /*PyObject *cellvars,*/
William Stein's avatar
William Stein committed
5444 5445 5446 5447 5448 5449 5450
        py_srcfile,   /*PyObject *filename,*/
        py_funcname,  /*PyObject *name,*/
        %(LINENO)s,   /*int firstlineno,*/
        empty_string  /*PyObject *lnotab*/
    );
    if (!py_code) goto bad;
    py_frame = PyFrame_New(
5451
        PyThreadState_GET(), /*PyThreadState *tstate,*/
William Stein's avatar
William Stein committed
5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468
        py_code,             /*PyCodeObject *code,*/
        py_globals,          /*PyObject *globals,*/
        0                    /*PyObject *locals*/
    );
    if (!py_frame) goto bad;
    py_frame->f_lineno = %(LINENO)s;
    PyTraceBack_Here(py_frame);
bad:
    Py_XDECREF(py_srcfile);
    Py_XDECREF(py_funcname);
    Py_XDECREF(empty_string);
    Py_XDECREF(py_code);
    Py_XDECREF(py_frame);
}
""" % {
    'FILENAME': Naming.filename_cname,
    'LINENO':  Naming.lineno_cname,
Robert Bradshaw's avatar
Robert Bradshaw committed
5469 5470
    'CFILENAME': Naming.cfilenm_cname,
    'CLINENO':  Naming.clineno_cname,
Stefan Behnel's avatar
Stefan Behnel committed
5471 5472
    'GLOBALS': Naming.module_cname,
    'EMPTY_TUPLE' : Naming.empty_tuple,
5473
})
William Stein's avatar
William Stein committed
5474

5475 5476
restore_exception_utility_code = UtilityCode(
proto = """
5477 5478
static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5479 5480
""",
impl = """
5481
static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5482 5483 5484
    PyObject *tmp_type, *tmp_value, *tmp_tb;
    PyThreadState *tstate = PyThreadState_GET();

5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500
#if PY_MAJOR_VERSION >= 3
    /* Note: this is a temporary work-around to prevent crashes in Python 3.0 */
    if ((tstate->exc_type != NULL) & (tstate->exc_type != Py_None)) {
        tmp_type = tstate->exc_type;
        tmp_value = tstate->exc_value;
        tmp_tb = tstate->exc_traceback;
        PyErr_NormalizeException(&type, &value, &tb);
        PyErr_NormalizeException(&tmp_type, &tmp_value, &tmp_tb);
        tstate->exc_type = 0;
        tstate->exc_value = 0;
        tstate->exc_traceback = 0;
        PyException_SetContext(value, tmp_value);
        Py_DECREF(tmp_type);
        Py_XDECREF(tmp_tb);
    }
#endif
5501

5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512
    tmp_type = tstate->curexc_type;
    tmp_value = tstate->curexc_value;
    tmp_tb = tstate->curexc_traceback;
    tstate->curexc_type = type;
    tstate->curexc_value = value;
    tstate->curexc_traceback = tb;
    Py_XDECREF(tmp_type);
    Py_XDECREF(tmp_value);
    Py_XDECREF(tmp_tb);
}

5513
static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5514 5515 5516 5517 5518 5519 5520 5521 5522 5523
    PyThreadState *tstate = PyThreadState_GET();
    *type = tstate->curexc_type;
    *value = tstate->curexc_value;
    *tb = tstate->curexc_traceback;

    tstate->curexc_type = 0;
    tstate->curexc_value = 0;
    tstate->curexc_traceback = 0;
}

5524
""")
5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551

#------------------------------------------------------------------------------------

unraisable_exception_utility_code = UtilityCode(
proto = """
static void __Pyx_WriteUnraisable(const char *name); /*proto*/
""",
impl = """
static void __Pyx_WriteUnraisable(const char *name) {
    PyObject *old_exc, *old_val, *old_tb;
    PyObject *ctx;
    __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
    #if PY_MAJOR_VERSION < 3
    ctx = PyString_FromString(name);
    #else
    ctx = PyUnicode_FromString(name);
    #endif
    __Pyx_ErrRestore(old_exc, old_val, old_tb);
    if (!ctx) {
        PyErr_WriteUnraisable(Py_None);
    } else {
        PyErr_WriteUnraisable(ctx);
        Py_DECREF(ctx);
    }
}
""",
requires=[restore_exception_utility_code])
5552

William Stein's avatar
William Stein committed
5553 5554
#------------------------------------------------------------------------------------

5555 5556
set_vtable_utility_code = UtilityCode(
proto = """
5557
static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5558 5559
""",
impl = """
William Stein's avatar
William Stein committed
5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577
static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
    PyObject *pycobj = 0;
    int result;
    
    pycobj = PyCObject_FromVoidPtr(vtable, 0);
    if (!pycobj)
        goto bad;
    if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
        goto bad;
    result = 0;
    goto done;

bad:
    result = -1;
done:
    Py_XDECREF(pycobj);
    return result;
}
5578
""")
William Stein's avatar
William Stein committed
5579 5580 5581

#------------------------------------------------------------------------------------

5582 5583
get_vtable_utility_code = UtilityCode(
proto = """
5584
static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5585 5586
""",
impl = r"""
William Stein's avatar
William Stein committed
5587 5588 5589
static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
    int result;
    PyObject *pycobj;
5590 5591

    pycobj = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
William Stein's avatar
William Stein committed
5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605
    if (!pycobj)
        goto bad;
    *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
    if (!*(void **)vtabptr)
        goto bad;
    result = 0;
    goto done;

bad:
    result = -1;
done:
    Py_XDECREF(pycobj);
    return result;
}
5606
""")
William Stein's avatar
William Stein committed
5607 5608 5609

#------------------------------------------------------------------------------------

5610 5611
init_string_tab_utility_code = UtilityCode(
proto = """
5612
static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5613 5614
""",
impl = """
William Stein's avatar
William Stein committed
5615 5616
static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
    while (t->p) {
5617
        #if PY_MAJOR_VERSION < 3
5618
        if (t->is_unicode && (!t->is_identifier)) {
5619
            *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5620 5621
        } else if (t->intern) {
            *t->p = PyString_InternFromString(t->s);
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
5622 5623
        } else {
            *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
Stefan Behnel's avatar
Stefan Behnel committed
5624
        }
5625 5626 5627 5628 5629
        #else  /* Python 3+ has unicode identifiers */
        if (t->is_identifier || (t->is_unicode && t->intern)) {
            *t->p = PyUnicode_InternFromString(t->s);
        } else if (t->is_unicode) {
            *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
5630 5631
        } else {
            *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
Stefan Behnel's avatar
Stefan Behnel committed
5632
        }
5633
        #endif
William Stein's avatar
William Stein committed
5634 5635 5636 5637 5638 5639
        if (!*t->p)
            return -1;
        ++t;
    }
    return 0;
}
5640
""")
William Stein's avatar
William Stein committed
5641 5642

#------------------------------------------------------------------------------------
5643

5644 5645
get_exception_utility_code = UtilityCode(
proto = """
5646
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5647 5648
""",
impl = """
5649
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5650
    PyObject *tmp_type, *tmp_value, *tmp_tb;
5651
    PyThreadState *tstate = PyThreadState_GET();
5652 5653 5654 5655 5656 5657
    *type = tstate->curexc_type;
    *value = tstate->curexc_value;
    *tb = tstate->curexc_traceback;
    tstate->curexc_type = 0;
    tstate->curexc_value = 0;
    tstate->curexc_traceback = 0;
5658 5659 5660 5661 5662 5663
    PyErr_NormalizeException(type, value, tb);
    if (PyErr_Occurred())
        goto bad;
    Py_INCREF(*type);
    Py_INCREF(*value);
    Py_INCREF(*tb);
5664 5665 5666
    tmp_type = tstate->exc_type;
    tmp_value = tstate->exc_value;
    tmp_tb = tstate->exc_traceback;
5667 5668 5669
    tstate->exc_type = *type;
    tstate->exc_value = *value;
    tstate->exc_traceback = *tb;
5670 5671 5672 5673 5674
    /* Make sure tstate is in a consistent state when we XDECREF
    these objects (XDECREF may run arbitrary code). */
    Py_XDECREF(tmp_type);
    Py_XDECREF(tmp_value);
    Py_XDECREF(tmp_tb);
5675
    return 0;
5676 5677 5678 5679 5680
bad:
    Py_XDECREF(*type);
    Py_XDECREF(*value);
    Py_XDECREF(*tb);
    return -1;
5681
}
5682

5683
""")
5684 5685

#------------------------------------------------------------------------------------
5686

5687 5688
reset_exception_utility_code = UtilityCode(
proto = """
5689
static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5690
static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5691 5692
""",
impl = """
5693
static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5694 5695 5696 5697
    PyThreadState *tstate = PyThreadState_GET();
    *type = tstate->exc_type;
    *value = tstate->exc_value;
    *tb = tstate->exc_traceback;
Stefan Behnel's avatar
Stefan Behnel committed
5698 5699 5700
    Py_XINCREF(*type);
    Py_XINCREF(*value);
    Py_XINCREF(*tb);
5701 5702
}

5703
static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715
    PyObject *tmp_type, *tmp_value, *tmp_tb;
    PyThreadState *tstate = PyThreadState_GET();
    tmp_type = tstate->exc_type;
    tmp_value = tstate->exc_value;
    tmp_tb = tstate->exc_traceback;
    tstate->exc_type = type;
    tstate->exc_value = value;
    tstate->exc_traceback = tb;
    Py_XDECREF(tmp_type);
    Py_XDECREF(tmp_value);
    Py_XDECREF(tmp_tb);
}
5716
""")
5717 5718

#------------------------------------------------------------------------------------
5719

Stefan Behnel's avatar
Stefan Behnel committed
5720
force_init_threads_utility_code = UtilityCode(
5721 5722
proto="""
#ifndef __PYX_FORCE_INIT_THREADS
5723
#if PY_VERSION_HEX < 0x02040200
5724
#define __PYX_FORCE_INIT_THREADS 1
5725 5726
#else
#define __PYX_FORCE_INIT_THREADS 0
5727 5728 5729 5730 5731
#endif
#endif
""")

#------------------------------------------------------------------------------------