Nodes.py 219 KB
Newer Older
1

William Stein's avatar
William Stein committed
2 3 4 5
#
#   Pyrex - Parse tree nodes
#

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

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

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

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
41 42 43
    global absolute_path_length
    if absolute_path_length==0:
        absolute_path_length = len(os.path.abspath(os.getcwd())) 
44
    return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
45 46 47 48

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

    # 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
65
        doc = EncodedString(pos_line)
66
    else:
67
        doc = EncodedString(pos_line + u'\n' + docstring)
68 69
    doc.encoding = encoding
    return doc
70

71 72 73 74 75 76 77

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
78 79
            # here we annotate the code with this function call
            # but only if new code is generated
80
            node, code = args[:2]
Robert Bradshaw's avatar
Robert Bradshaw committed
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
            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)
100 101 102 103
    return f

class VerboseCodeWriter(type):
    # Set this as a metaclass to trace function calls in code.
Robert Bradshaw's avatar
Robert Bradshaw committed
104
    # This slows down code generation and makes much larger files. 
105 106 107 108 109 110 111 112
    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
113
class Node(object):
William Stein's avatar
William Stein committed
114 115 116
    #  pos         (string, int, int)   Source file position
    #  is_name     boolean              Is a NameNode
    #  is_literal  boolean              Is a ConstNode
117

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

125 126 127
    # 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.
128
    child_attrs = None
William Stein's avatar
William Stein committed
129 130 131 132 133
    
    def __init__(self, pos, **kw):
        self.pos = pos
        self.__dict__.update(kw)
    
134 135 136 137 138 139 140 141 142
    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)

143 144 145 146 147 148
    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."""
149 150 151
        result = copy.copy(self)
        for attrname in result.child_attrs:
            value = getattr(result, attrname)
152
            if isinstance(value, list):
153
                setattr(result, attrname, [x for x in value])
154
        return result
155
    
156
    
William Stein's avatar
William Stein committed
157
    #
158
    #  There are 4 phases of parse tree processing, applied in order to
William Stein's avatar
William Stein committed
159 160
    #  all the statements in a given scope-block:
    #
161 162 163 164
    #  (0) analyse_control_flow
    #        Create the control flow tree into which state can be asserted and
    #        queried.
    #
William Stein's avatar
William Stein committed
165 166 167 168 169
    #  (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).
    #
170
    #  (2) analyse_expressions
William Stein's avatar
William Stein committed
171 172 173 174 175 176 177
    #         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.
    #
178
    #  (3) generate_code
William Stein's avatar
William Stein committed
179 180 181 182 183
    #         Emit C code for all declarations, statements and expressions.
    #         Recursively applies the 3 processing phases to the bodies of
    #         functions.
    #
    
184 185 186
    def analyse_control_flow(self, env):
        pass
    
William Stein's avatar
William Stein committed
187 188 189 190 191 192 193 194 195 196
    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__)
197 198 199 200 201
            
    def annotate(self, code):
        # mro does the wrong thing
        if isinstance(self, BlockNode):
            self.body.annotate(code)
202 203 204 205 206
            
    def end_pos(self):
        try:
            return self._end_pos
        except AttributeError:
Stefan Behnel's avatar
Stefan Behnel committed
207
            pos = self.pos
208 209 210
            if not self.child_attrs:
                self._end_pos = pos
                return pos
211
            for attr in self.child_attrs:
212
                child = getattr(self, attr)
213
                # Sometimes lists, sometimes nodes
214 215 216
                if child is None:
                    pass
                elif isinstance(child, list):
Stefan Behnel's avatar
Stefan Behnel committed
217 218
                    for c in child:
                        pos = max(pos, c.end_pos())
219
                else:
Stefan Behnel's avatar
Stefan Behnel committed
220 221 222
                    pos = max(pos, child.end_pos())
            self._end_pos = pos
            return pos
William Stein's avatar
William Stein committed
223

224
    def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
225 226
        if cutoff == 0:
            return "<...nesting level cutoff...>"
227 228 229 230 231
        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))
232
        
233 234
        def dump_child(x, level):
            if isinstance(x, Node):
235
                return x.dump(level, filter_out, cutoff-1, encountered)
236
            elif isinstance(x, list):
Robert Bradshaw's avatar
Robert Bradshaw committed
237
                return "[%s]" % ", ".join([dump_child(item, level) for item in x])
238 239 240 241 242 243
            else:
                return repr(x)
            
        
        attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
        if len(attrs) == 0:
244
            return "<%s (%d)>" % (self.__class__.__name__, id(self))
245 246
        else:
            indent = "  " * level
247
            res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
248 249 250 251
            for key, value in attrs:
                res += "%s  %s: %s\n" % (indent, key, dump_child(value, level + 1))
            res += "%s>" % indent
            return res
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 298

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
299
        
Stefan Behnel's avatar
Stefan Behnel committed
300
class BlockNode(object):
William Stein's avatar
William Stein committed
301 302 303 304 305 306
    #  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:
307
                    code.globalstate.add_const_definition(entry)
308 309 310 311 312

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

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

325 326 327 328 329 330 331
    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:
332
                code.globalstate.add_interned_num_decl(entry)
333
            del entries[:]
William Stein's avatar
William Stein committed
334

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

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

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

William Stein's avatar
William Stein committed
356 357 358 359 360 361 362
    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" ###
DaniloFreitas's avatar
DaniloFreitas committed
363
        entry = env.entries.get("cpp_sum", None)
William Stein's avatar
William Stein committed
364 365 366
        for stat in self.stats:
            stat.analyse_expressions(env)
    
367
    def generate_function_definitions(self, env, code):
William Stein's avatar
William Stein committed
368 369
        #print "StatListNode.generate_function_definitions" ###
        for stat in self.stats:
370
            stat.generate_function_definitions(env, code)
William Stein's avatar
William Stein committed
371 372 373 374 375 376
            
    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)
377 378 379 380
            
    def annotate(self, code):
        for stat in self.stats:
            stat.annotate(code)
William Stein's avatar
William Stein committed
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
    

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.
    #
    
396
    def generate_function_definitions(self, env, code):
William Stein's avatar
William Stein committed
397 398 399 400 401 402 403 404 405 406 407
        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
    
408 409
    child_attrs = ["body"]
    
William Stein's avatar
William Stein committed
410 411 412 413 414 415 416 417 418 419 420 421 422
    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
423 424 425

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

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.
    #
438 439 440
    #  calling_convention  string   Calling convention of CFuncDeclaratorNode
    #                               for which this is a base 

441 442
    child_attrs = []

443 444
    calling_convention = ""

William Stein's avatar
William Stein committed
445 446

class CNameDeclaratorNode(CDeclaratorNode):
Robert Bradshaw's avatar
Robert Bradshaw committed
447 448 449
    #  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
450
    
Robert Bradshaw's avatar
Robert Bradshaw committed
451
    child_attrs = ['default']
452
    
453
    default = None
454
    
455 456
    def analyse(self, base_type, env, nonempty = 0):
        if nonempty and self.name == '':
457 458
            # May have mistaken the name for the type. 
            if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
459
                error(self.pos, "Missing argument name")
460 461
            elif base_type.is_void:
                error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
462 463 464
            else:
                self.name = base_type.declaration_code("", for_display=1, pyrex=1)
                base_type = py_object_type
465
        self.type = base_type
William Stein's avatar
William Stein committed
466
        return self, base_type
467
        
William Stein's avatar
William Stein committed
468 469 470
class CPtrDeclaratorNode(CDeclaratorNode):
    # base     CDeclaratorNode
    
471 472
    child_attrs = ["base"]

473
    def analyse(self, base_type, env, nonempty = 0):
William Stein's avatar
William Stein committed
474 475 476 477
        if base_type.is_pyobject:
            error(self.pos,
                "Pointer base type cannot be a Python object")
        ptr_type = PyrexTypes.c_ptr_type(base_type)
478
        return self.base.analyse(ptr_type, env, nonempty = nonempty)
Danilo Freitas's avatar
Danilo Freitas committed
479 480 481 482 483 484 485 486 487 488

class CReferenceDeclaratorNode(CDeclaratorNode):
    # base     CDeclaratorNode

    child_attrs = ["base"]

    def analyse(self, base_type, env, nonempty = 0):
        if base_type.is_pyobject:
            error(self.pos,
                  "Reference base type cannot be a Python object")
489
        ref_type = PyrexTypes.c_ref_type(base_type)
Danilo Freitas's avatar
Danilo Freitas committed
490 491
        return self.base.analyse(ref_type, env, nonempty = nonempty)

William Stein's avatar
William Stein committed
492 493 494
class CArrayDeclaratorNode(CDeclaratorNode):
    # base        CDeclaratorNode
    # dimension   ExprNode
495 496

    child_attrs = ["base", "dimension"]
William Stein's avatar
William Stein committed
497
    
498
    def analyse(self, base_type, env, nonempty = 0):
William Stein's avatar
William Stein committed
499 500 501 502
        if self.dimension:
            self.dimension.analyse_const_expression(env)
            if not self.dimension.type.is_int:
                error(self.dimension.pos, "Array dimension not integer")
503
            size = self.dimension.result()
504 505 506 507 508
            try:
                size = int(size)
            except ValueError:
                # runtime constant?
                pass
William Stein's avatar
William Stein committed
509 510 511 512 513 514 515 516
        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")
517 518 519
        if base_type.is_cfunction:
            error(self.pos,
                "Array element cannot be a function")
William Stein's avatar
William Stein committed
520
        array_type = PyrexTypes.c_array_type(base_type, size)
521
        return self.base.analyse(array_type, env, nonempty = nonempty)
William Stein's avatar
William Stein committed
522 523 524 525 526 527 528 529


class CFuncDeclaratorNode(CDeclaratorNode):
    # base             CDeclaratorNode
    # args             [CArgDeclNode]
    # has_varargs      boolean
    # exception_value  ConstNode
    # exception_check  boolean    True if PyErr_Occurred check needed
530 531
    # nogil            boolean    Can be called without gil
    # with_gil         boolean    Acquire gil around function body
532
    
533 534
    child_attrs = ["base", "args", "exception_value"]

535
    overridable = 0
536
    optional_arg_count = 0
William Stein's avatar
William Stein committed
537

538
    def analyse(self, return_type, env, nonempty = 0):
539 540
        if nonempty:
            nonempty -= 1
William Stein's avatar
William Stein committed
541 542
        func_type_args = []
        for arg_node in self.args:
543
            name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
William Stein's avatar
William Stein committed
544 545 546 547 548 549 550 551 552
            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
553
                error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
554 555 556
#            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
557 558 559
            func_type_args.append(
                PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
            if arg_node.default:
560
                self.optional_arg_count += 1
561 562
            elif self.optional_arg_count:
                error(self.pos, "Non-default argument follows default argument")
563 564 565
        
        if self.optional_arg_count:
            scope = StructOrUnionScope()
566
            arg_count_member = '%sn' % Naming.pyrex_prefix
Robert Bradshaw's avatar
Robert Bradshaw committed
567
            scope.declare_var(arg_count_member, PyrexTypes.c_int_type, self.pos)
568 569
            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)
570
            struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
571 572 573 574 575 576
            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)
577
            self.op_args_struct.defined_in_pxd = 1
578 579
            self.op_args_struct.used = 1
        
William Stein's avatar
William Stein committed
580 581
        exc_val = None
        exc_check = 0
582 583
        if self.exception_check == '+':
            env.add_include_file('stdexcept')
William Stein's avatar
William Stein committed
584
        if return_type.is_pyobject \
Robert Bradshaw's avatar
Robert Bradshaw committed
585 586
            and (self.exception_value or self.exception_check) \
            and self.exception_check != '+':
William Stein's avatar
William Stein committed
587 588 589 590 591
                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
592 593 594 595 596 597 598 599 600
                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:
601
                    exc_val = self.exception_value.result()
Robert Bradshaw's avatar
Robert Bradshaw committed
602 603 604
                    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
605
            exc_check = self.exception_check
606 607 608 609 610 611
        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
612 613
        func_type = PyrexTypes.CFuncType(
            return_type, func_type_args, self.has_varargs, 
614
            optional_arg_count = self.optional_arg_count,
615
            exception_value = exc_val, exception_check = exc_check,
616
            calling_convention = self.base.calling_convention,
617
            nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
618
        if self.optional_arg_count:
619
            func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
620 621 622 623 624 625 626
        callspec = env.directives['callspec']
        if callspec:
            current = func_type.calling_convention
            if current and current != callspec:
                error(self.pos, "cannot have both '%s' and '%s' "
                      "calling conventions" % (current, callspec))
            func_type.calling_convention = callspec
William Stein's avatar
William Stein committed
627 628 629 630 631 632 633 634 635 636 637
        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
638
    # default_result_code string        cname or code fragment for default value
William Stein's avatar
William Stein committed
639
    # is_self_arg    boolean            Is the "self" arg of an extension type method
640 641
    # is_kw_only     boolean            Is a keyword-only argument

642 643
    child_attrs = ["base_type", "declarator", "default"]

William Stein's avatar
William Stein committed
644
    is_self_arg = 0
645
    is_generic = 1
646 647
    type = None
    name_declarator = None
648

649
    def analyse(self, env, nonempty = 0):
650
        #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
651 652 653 654 655 656 657 658 659 660 661 662
        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
663
            if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
664 665
                self.declarator.name = self.base_type.arg_name
            return self.declarator.analyse(base_type, env, nonempty = nonempty)
666
        else:
667
            return self.name_declarator, self.type
William Stein's avatar
William Stein committed
668

669 670 671 672
    def annotate(self, code):
        if self.default:
            self.default.annotate(code)

William Stein's avatar
William Stein committed
673 674 675 676 677 678 679 680 681 682

class CBaseTypeNode(Node):
    # Abstract base class for C base type nodes.
    #
    # Processing during analyse_declarations phase:
    #
    #   analyse
    #     Returns the type.
    
    pass
683
    
684 685 686
    def analyse_as_type(self, env):
        return self.analyse(env)
    
687 688 689 690 691 692 693
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
694 695 696 697 698 699 700

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

704
    child_attrs = []
705
    arg_name = None   # in case the argument name was interpreted as a type
706
    
707
    def analyse(self, env, could_be_name = False):
William Stein's avatar
William Stein committed
708
        # Return type descriptor.
709
        #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
William Stein's avatar
William Stein committed
710 711 712 713 714 715 716 717 718
        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:
719
                #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
William Stein's avatar
William Stein committed
720 721 722 723
                type = env.parent_type
            else:
                type = py_object_type
        else:
724 725 726 727
            if self.module_path:
                scope = env.find_imported_module(self.module_path, self.pos)
            else:
                scope = env
William Stein's avatar
William Stein committed
728
            if scope:
729 730
                if scope.is_c_class_scope:
                    scope = scope.global_scope()
731
                entry = scope.lookup(self.name)
William Stein's avatar
William Stein committed
732 733
                if entry and entry.is_type:
                    type = entry.type
734 735 736 737 738 739
                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
740
                else:
Danilo Freitas's avatar
Danilo Freitas committed
741 742 743
                    if self.templates:
                        if not self.name in self.templates:
                            error(self.pos, "'%s' is not a type identifier" % self.name)
744
                        type = PyrexTypes.TemplatePlaceholderType(self.name)
Danilo Freitas's avatar
Danilo Freitas committed
745 746
                    else:
                        error(self.pos, "'%s' is not a type identifier" % self.name)
747
        if self.complex:
748 749 750
            if not type.is_numeric or type.is_complex:
                error(self.pos, "can only complexify c numeric types")
            type = PyrexTypes.CComplexType(type)
751
            type.create_declaration_utility_code(env)
William Stein's avatar
William Stein committed
752 753 754 755 756
        if type:
            return type
        else:
            return PyrexTypes.error_type

Danilo Freitas's avatar
Danilo Freitas committed
757
class TemplatedTypeNode(CBaseTypeNode):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
758
    #  After parsing:
759 760
    #  positional_args  [ExprNode]        List of positional arguments
    #  keyword_args     DictNode          Keyword arguments
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
761 762 763
    #  base_type_node   CBaseTypeNode

    #  After analysis:
764
    #  type             PyrexTypes.BufferType or PyrexTypes.CppClassType  ...containing the right options
765

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
766

767 768
    child_attrs = ["base_type_node", "positional_args",
                   "keyword_args", "dtype_node"]
769

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
770
    dtype_node = None
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
771 772

    name = None
773
    
774 775 776
    def analyse(self, env, could_be_name = False, base_type = None):
        if base_type is None:
            base_type = self.base_type_node.analyse(env)
777
        if base_type.is_error: return base_type
778
        
779 780 781 782 783 784 785 786
        if base_type.is_cpp_class:
            if len(self.keyword_args.key_value_pairs) != 0:
                error(self.pos, "c++ templates cannot take keyword arguments");
                self.type = PyrexTypes.error_type
            else:
                template_types = []
                for template_node in self.positional_args:
                    template_types.append(template_node.analyse_as_type(env))
787
                self.type = base_type.specialize_here(self.pos, template_types)
788 789 790 791 792 793 794 795 796 797 798 799 800 801
        
        else:
        
            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
802
        return self.type
William Stein's avatar
William Stein committed
803 804 805 806 807

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

810 811
    def analyse(self, env, could_be_name = False):
        base = self.base_type.analyse(env, could_be_name)
William Stein's avatar
William Stein committed
812 813 814 815 816 817 818 819 820 821
        _, 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]
822
    #  in_pxd        boolean
Stefan Behnel's avatar
Stefan Behnel committed
823
    #  api           boolean
824
    #  need_properties [entry]
825

Robert Bradshaw's avatar
Robert Bradshaw committed
826
    #  decorators    [cython.locals(...)] or None 
827
    #  directive_locals { string : NameNode } locals defined by cython.locals(...)
828 829

    child_attrs = ["base_type", "declarators"]
Robert Bradshaw's avatar
Robert Bradshaw committed
830
    need_properties = ()
Robert Bradshaw's avatar
Robert Bradshaw committed
831 832
    
    decorators = None
833
    directive_locals = {}
William Stein's avatar
William Stein committed
834 835 836 837
    
    def analyse_declarations(self, env, dest_scope = None):
        if not dest_scope:
            dest_scope = env
838
        self.dest_scope = dest_scope
William Stein's avatar
William Stein committed
839
        base_type = self.base_type.analyse(env)
840

841 842 843
        # If the field is an external typedef, we cannot be sure about the type,
        # so do conversion ourself rather than rely on the CPython mechanism (through
        # a property; made in AnalyseDeclarationsTransform).
844
        if (dest_scope.is_c_class_scope
845 846 847 848
                and self.visibility == 'public' 
                and base_type.is_pyobject 
                and (base_type.is_builtin_type or base_type.is_extension_type)):
            self.need_properties = []
849 850 851
            need_property = True
            visibility = 'private'
        else:
852
            need_property = False
853 854
            visibility = self.visibility
            
William Stein's avatar
William Stein committed
855 856 857 858 859 860 861 862 863 864 865
        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
866 867 868
            if name == '':
                error(declarator.pos, "Missing name in declaration.")
                return
William Stein's avatar
William Stein committed
869
            if type.is_cfunction:
870
                entry = dest_scope.declare_cfunction(name, type, declarator.pos,
Stefan Behnel's avatar
Stefan Behnel committed
871 872
                    cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
                    api = self.api)
Robert Bradshaw's avatar
Robert Bradshaw committed
873
                if entry is not None:
874
                    entry.directive_locals = self.directive_locals
William Stein's avatar
William Stein committed
875
            else:
876 877
                if self.directive_locals:
                    s.error("Decorators can only be followed by functions")
878 879 880
                if self.in_pxd and self.visibility != 'extern':
                    error(self.pos, 
                        "Only 'extern' C variable declaration allowed in .pxd file")
881 882 883 884
                entry = dest_scope.declare_var(name, type, declarator.pos,
                            cname = cname, visibility = visibility, is_cdef = 1)
                if need_property:
                    self.need_properties.append(entry)
885
                    entry.needs_property = 1
William Stein's avatar
William Stein committed
886 887 888 889 890 891 892
    

class CStructOrUnionDefNode(StatNode):
    #  name          string
    #  cname         string or None
    #  kind          "struct" or "union"
    #  typedef_flag  boolean
893
    #  visibility    "public" or "private"
Stefan Behnel's avatar
Stefan Behnel committed
894
    #  in_pxd        boolean
William Stein's avatar
William Stein committed
895 896
    #  attributes    [CVarDefNode] or None
    #  entry         Entry
897
    #  packed        boolean
William Stein's avatar
William Stein committed
898
    
899 900
    child_attrs = ["attributes"]

William Stein's avatar
William Stein committed
901 902
    def analyse_declarations(self, env):
        scope = None
903 904
        if self.visibility == 'extern' and self.packed:
            error(self.pos, "Cannot declare extern struct as 'packed'")
William Stein's avatar
William Stein committed
905
        if self.attributes is not None:
906
            scope = StructOrUnionScope(self.name)
William Stein's avatar
William Stein committed
907 908
        self.entry = env.declare_struct_or_union(
            self.name, self.kind, scope, self.typedef_flag, self.pos,
909
            self.cname, visibility = self.visibility, packed = self.packed)
William Stein's avatar
William Stein committed
910
        if self.attributes is not None:
Stefan Behnel's avatar
Stefan Behnel committed
911 912
            if self.in_pxd and not env.in_cinclude:
                self.entry.defined_in_pxd = 1
William Stein's avatar
William Stein committed
913 914
            for attr in self.attributes:
                attr.analyse_declarations(env, scope)
915
            if self.visibility != 'extern':
Stefan Behnel's avatar
Stefan Behnel committed
916
                need_typedef_indirection = False
917 918 919
                for attr in scope.var_entries:
                    type = attr.type
                    while type.is_array:
920 921
                        type = type.base_type
                    if type == self.entry.type:
922 923 924 925 926 927
                        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
928 929 930 931 932 933 934
                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
935 936 937 938 939 940 941 942
    
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        pass


Robert Bradshaw's avatar
Robert Bradshaw committed
943 944 945 946
class CppClassNode(CStructOrUnionDefNode):

    #  name          string
    #  cname         string or None
947
    #  visibility    "extern"
Robert Bradshaw's avatar
Robert Bradshaw committed
948 949 950
    #  in_pxd        boolean
    #  attributes    [CVarDefNode] or None
    #  entry         Entry
DaniloFreitas's avatar
DaniloFreitas committed
951
    #  base_classes  [string]
Danilo Freitas's avatar
Danilo Freitas committed
952
    #  templates     [string] or None
Robert Bradshaw's avatar
Robert Bradshaw committed
953 954 955

    def analyse_declarations(self, env):
        scope = None
956
        if len(self.attributes) != 0:
Robert Bradshaw's avatar
Robert Bradshaw committed
957
            scope = CppClassScope(self.name, env)
958 959
        else:
            self.attributes = None
960 961 962 963 964 965 966 967 968
        base_class_types = []
        for base_class_name in self.base_classes:
            base_class_entry = env.lookup(base_class_name)
            if base_class_entry is None:
                error(self.pos, "'%s' not found" % base_class_name)
            elif not base_class_entry.is_type or not base_class_entry.type.is_cpp_class:
                error(self.pos, "'%s' is not a cpp class type" % base_class_name)
            else:
                base_class_types.append(base_class_entry.type)
969 970 971 972
        if self.templates is None:
            template_types = None
        else:
            template_types = [PyrexTypes.TemplatePlaceholderType(template_name) for template_name in self.templates]
973
        self.entry = env.declare_cpp_class(
974
            self.name, scope, self.pos,
975
            self.cname, base_class_types, visibility = self.visibility, templates = template_types)
Danilo Freitas's avatar
Danilo Freitas committed
976
        self.entry.is_cpp_class = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
977 978 979 980
        if self.attributes is not None:
            if self.in_pxd and not env.in_cinclude:
                self.entry.defined_in_pxd = 1
            for attr in self.attributes:
Robert Bradshaw's avatar
Robert Bradshaw committed
981
                attr.analyse_declarations(scope)
Robert Bradshaw's avatar
Robert Bradshaw committed
982

William Stein's avatar
William Stein committed
983 984 985 986 987
class CEnumDefNode(StatNode):
    #  name           string or None
    #  cname          string or None
    #  items          [CEnumDefItemNode]
    #  typedef_flag   boolean
Stefan Behnel's avatar
Stefan Behnel committed
988 989
    #  visibility     "public" or "private"
    #  in_pxd         boolean
William Stein's avatar
William Stein committed
990 991
    #  entry          Entry
    
992 993
    child_attrs = ["items"]
    
William Stein's avatar
William Stein committed
994 995
    def analyse_declarations(self, env):
        self.entry = env.declare_enum(self.name, self.pos,
996 997
            cname = self.cname, typedef_flag = self.typedef_flag,
            visibility = self.visibility)
Stefan Behnel's avatar
Stefan Behnel committed
998 999 1000 1001 1002
        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
1003 1004

    def analyse_expressions(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
1005 1006 1007
        if self.visibility == 'public':
            self.temp = env.allocate_temp_pyobject()
            env.release_temp(self.temp)
William Stein's avatar
William Stein committed
1008 1009
    
    def generate_execution_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
1010 1011 1012 1013 1014 1015
        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)))
1016
                code.put_gotref(self.temp)
1017
                code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
Robert Bradshaw's avatar
Robert Bradshaw committed
1018 1019 1020 1021
                        Naming.module_cname, 
                        item.name, 
                        self.temp,
                        code.error_goto(item.pos)))
1022
                code.put_decref_clear(self.temp, PyrexTypes.py_object_type)
William Stein's avatar
William Stein committed
1023 1024 1025 1026 1027 1028 1029


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

William Stein's avatar
William Stein committed
1032 1033 1034
    def analyse_declarations(self, env, enum_entry):
        if self.value:
            self.value.analyse_const_expression(env)
1035 1036 1037
            if not self.value.type.is_int:
                self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
                self.value.analyse_const_expression(env)
1038
            value = self.value.result()
William Stein's avatar
William Stein committed
1039 1040 1041
        else:
            value = self.name
        entry = env.declare_const(self.name, enum_entry.type, 
Robert Bradshaw's avatar
Robert Bradshaw committed
1042
            value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
William Stein's avatar
William Stein committed
1043 1044 1045 1046
        enum_entry.enum_values.append(entry)


class CTypeDefNode(StatNode):
Stefan Behnel's avatar
Stefan Behnel committed
1047 1048 1049 1050
    #  base_type    CBaseTypeNode
    #  declarator   CDeclaratorNode
    #  visibility   "public" or "private"
    #  in_pxd       boolean
1051 1052

    child_attrs = ["base_type", "declarator"]
William Stein's avatar
William Stein committed
1053 1054 1055 1056 1057 1058
    
    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
1059
        entry = env.declare_typedef(name, type, self.pos,
1060
            cname = cname, visibility = self.visibility)
Stefan Behnel's avatar
Stefan Behnel committed
1061 1062
        if self.in_pxd and not env.in_cinclude:
            entry.defined_in_pxd = 1
William Stein's avatar
William Stein committed
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
    
    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
1076
    #  needs_closure   boolean        Whether or not this function has inner functions/classes/yield
1077
    #  directive_locals { string : NameNode } locals defined by cython.locals(...)
William Stein's avatar
William Stein committed
1078
    
1079
    py_func = None
1080
    assmt = None
1081
    needs_closure = False
1082 1083 1084 1085 1086 1087 1088
    
    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'):
1089
                        arg.default.analyse_types(env)
1090
                        arg.default = arg.default.coerce_to(arg.type, genv)
1091 1092 1093
                        if arg.default.is_literal:
                            arg.default_entry = arg.default
                            arg.default_result_code = arg.default.calculate_result_code()
1094 1095
                            if arg.default.type != arg.type and not arg.type.is_int:
                                arg.default_result_code = arg.type.cast_code(arg.default_result_code)
1096 1097 1098
                        else:
                            arg.default.allocate_temps(genv)
                            arg.default_entry = genv.add_default_value(arg.type)
1099 1100
                            if arg.type.is_pyobject:
                                arg.default_entry.init = 0
1101 1102
                            arg.default_entry.used = 1
                            arg.default_result_code = arg.default_entry.cname
1103 1104 1105 1106
                else:
                    error(arg.pos,
                        "This argument cannot have a default value")
                    arg.default = None
1107
    
1108 1109
    def need_gil_acquisition(self, lenv):
        return 0
1110 1111 1112 1113 1114
        
    def create_local_scope(self, env):
        genv = env
        while env.is_py_class_scope or env.is_c_class_scope:
            env = env.outer_scope
1115
        if self.needs_closure:
1116
            lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
1117 1118
        else:
            lenv = LocalScope(name = self.entry.name, outer_scope = genv)
William Stein's avatar
William Stein committed
1119
        lenv.return_type = self.return_type
1120 1121 1122
        type = self.entry.type
        if type.is_cfunction:
            lenv.nogil = type.nogil and not type.with_gil
1123
        self.local_scope = lenv
1124
        lenv.directives = env.directives
1125 1126
        return lenv
                
1127
    def generate_function_definitions(self, env, code):
1128
        import Buffer
1129 1130 1131

        lenv = self.local_scope

1132 1133 1134
        is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
                             self.entry.scope.is_c_class_scope)

1135
        # Generate C code for header and body of function
1136
        code.enter_cfunc_scope()
1137 1138
        code.return_from_error_cleanup_label = code.new_label()
            
William Stein's avatar
William Stein committed
1139
        # ----- Top-level constants used by this function
1140
        code.mark_pos(self.pos)
1141
        self.generate_interned_num_decls(lenv, code)
1142
        self.generate_interned_string_decls(lenv, code)
William Stein's avatar
William Stein committed
1143
        self.generate_py_string_decls(lenv, code)
1144
        self.generate_cached_builtins_decls(lenv, code)
William Stein's avatar
William Stein committed
1145 1146 1147 1148 1149
        #code.putln("")
        #code.put_var_declarations(lenv.const_entries, static = 1)
        self.generate_const_definitions(lenv, code)
        # ----- Function header
        code.putln("")
1150 1151 1152 1153
        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
1154 1155 1156
        self.generate_function_header(code,
            with_pymethdef = env.is_py_class_scope)
        # ----- Local variable declarations
1157
        lenv.mangle_closure_cnames(Naming.cur_scope_cname)
William Stein's avatar
William Stein committed
1158
        self.generate_argument_declarations(lenv, code)
1159 1160
        if self.needs_closure:
            code.putln("/* TODO: declare and create scope object */")
William Stein's avatar
William Stein committed
1161 1162 1163
        code.put_var_declarations(lenv.var_entries)
        init = ""
        if not self.return_type.is_void:
1164 1165
            if self.return_type.is_pyobject:
                init = " = NULL"
William Stein's avatar
William Stein committed
1166 1167 1168 1169 1170
            code.putln(
                "%s%s;" % 
                    (self.return_type.declaration_code(
                        Naming.retval_cname),
                    init))
1171
        tempvardecl_code = code.insertion_point()
William Stein's avatar
William Stein committed
1172 1173 1174
        self.generate_keyword_list(code)
        # ----- Extern library function declarations
        lenv.generate_library_function_declarations(code)
1175 1176 1177
        # ----- GIL acquisition
        acquire_gil = self.need_gil_acquisition(lenv)
        if acquire_gil:
Stefan Behnel's avatar
Stefan Behnel committed
1178
            env.use_utility_code(force_init_threads_utility_code)
1179
            code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1180
        # ----- Automatic lead-ins for certain special functions
1181 1182
        if not lenv.nogil:
            code.put_setup_refcount_context(self.entry.name)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1183 1184
        if is_getbuffer_slot:
            self.getbuffer_init(code)
William Stein's avatar
William Stein committed
1185
        # ----- Fetch arguments
1186
        self.generate_argument_parsing_code(env, code)
Robert Bradshaw's avatar
Robert Bradshaw committed
1187 1188 1189 1190 1191
        # 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)
1192
        # ----- Initialise local variables 
William Stein's avatar
William Stein committed
1193
        for entry in lenv.var_entries:
1194
            if entry.type.is_pyobject and entry.init_to_none and entry.used:
William Stein's avatar
William Stein committed
1195
                code.put_init_var_to_py_none(entry)
1196 1197
        # ----- Initialise local buffer auxiliary variables
        for entry in lenv.var_entries + lenv.arg_entries:
1198 1199
            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)
1200
        # ----- Check and convert arguments
William Stein's avatar
William Stein committed
1201
        self.generate_argument_type_tests(code)
1202 1203 1204 1205
        # ----- 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
1206 1207 1208 1209 1210 1211
        # ----- 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:
1212
            #    lhs = "(PyObject *)%s" % Naming.retval_cname
William Stein's avatar
William Stein committed
1213 1214 1215 1216 1217 1218 1219 1220
            #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
1221 1222 1223
        if code.error_label in code.labels_used:
            code.put_goto(code.return_label)
            code.put_label(code.error_label)
1224
            # cleanup temps the old way
1225
            code.put_var_xdecrefs(lenv.temp_entries)
1226
            # cleanup temps the new way
1227 1228
            for cname, type in code.funcstate.all_managed_temps():
                code.put_xdecref(cname, type)
1229 1230 1231 1232 1233

            # 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:
1234
                code.globalstate.use_utility_code(restore_exception_utility_code)
1235
                code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1236
                code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1237 1238 1239
                for entry in lenv.buffer_entries:
                    code.putln("%s;" % Buffer.get_release_buffer_code(entry))
                    #code.putln("%s = 0;" % entry.cname)
1240
                code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1241

1242 1243 1244
            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
1245
                code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1246
            else:
1247 1248
                warning(self.entry.pos, "Unraisable exception in function '%s'." \
                            % self.entry.qualified_name, 0)
1249 1250 1251 1252
                code.putln(
                    '__Pyx_WriteUnraisable("%s");' % 
                        self.entry.qualified_name)
                env.use_utility_code(unraisable_exception_utility_code)
1253
                env.use_utility_code(restore_exception_utility_code)
1254 1255 1256 1257 1258 1259 1260 1261
            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))
1262 1263 1264 1265 1266 1267 1268 1269

            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:
1270 1271
                code.put_goto(code.return_from_error_cleanup_label)

1272

1273
        # ----- Non-error return cleanup
1274 1275 1276
        # 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
1277
        code.put_label(code.return_label)
1278
        for entry in lenv.buffer_entries:
1279 1280
            if entry.used:
                code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1281 1282
        if is_getbuffer_slot:
            self.getbuffer_normal_cleanup(code)
1283 1284
        # ----- 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
1285 1286 1287 1288
        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
1289
        code.put_var_decrefs(lenv.var_entries, used_only = 1)
Robert Bradshaw's avatar
Robert Bradshaw committed
1290
        # Decref any increfed args
1291
        for entry in lenv.arg_entries:
Robert Bradshaw's avatar
Robert Bradshaw committed
1292
            if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1293
                code.put_var_decref(entry)
1294

1295
        # code.putln("/* TODO: decref scope object */")
1296
        # ----- Return
1297
        # This code is duplicated in ModuleNode.generate_module_init_func
1298 1299 1300 1301 1302 1303 1304
        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))
1305

1306
            code.put_finish_refcount_context()
1307

1308 1309 1310
        if acquire_gil:
            code.putln("PyGILState_Release(_save);")

William Stein's avatar
William Stein committed
1311
        if not self.return_type.is_void:
1312
            code.putln("return %s;" % Naming.retval_cname)
1313
            
William Stein's avatar
William Stein committed
1314
        code.putln("}")
1315 1316
        # ----- Go back and insert temp variable declarations
        tempvardecl_code.put_var_declarations(lenv.temp_entries)
1317
        tempvardecl_code.put_temp_declarations(code.funcstate)
1318
        # ----- Python version
1319
        code.exit_cfunc_scope()
1320
        if self.py_func:
1321
            self.py_func.generate_function_definitions(env, code)
1322
        self.generate_wrapper_functions(code)
William Stein's avatar
William Stein committed
1323 1324 1325 1326 1327 1328 1329 1330

    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)
1331 1332
        
    def generate_wrapper_functions(self, code):
William Stein's avatar
William Stein committed
1333 1334 1335
        pass

    def generate_execution_code(self, code):
1336 1337 1338 1339
        # Evaluate and store argument default values
        for arg in self.args:
            default = arg.default
            if default:
1340 1341 1342
                if not default.is_literal:
                    default.generate_evaluation_code(code)
                    default.make_owned_reference(code)
1343
                    code.putln(
1344
                        "%s = %s;" % (
1345
                            arg.default_entry.cname,
1346
                            default.result_as(arg.default_entry.type)))
1347 1348
                    if default.is_temp and default.type.is_pyobject:
                        code.putln("%s = 0;" % default.result())
1349
                    default.free_temps(code)
1350
                    code.put_var_giveref(arg.default_entry)
1351 1352 1353
        # 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
1354

1355
    #
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1356
    # Special code for the __getbuffer__ function
1357 1358 1359 1360 1361 1362 1363
    #
    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) 
1364
        code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1365
        code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1366 1367 1368

    def getbuffer_error_cleanup(self, code):
        info = self.local_scope.arg_entries[1].cname
1369
        code.put_gotref("%s->obj" % info)
1370
        code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1371 1372 1373 1374
                   (info, info))

    def getbuffer_normal_cleanup(self, code):
        info = self.local_scope.arg_entries[1].cname
1375 1376 1377 1378
        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
1379 1380 1381 1382

class CFuncDefNode(FuncDefNode):
    #  C function definition.
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
1383
    #  modifiers     ['inline']
William Stein's avatar
William Stein committed
1384 1385 1386 1387
    #  visibility    'private' or 'public' or 'extern'
    #  base_type     CBaseTypeNode
    #  declarator    CDeclaratorNode
    #  body          StatListNode
1388
    #  api           boolean
1389
    #  decorators    [DecoratorNode]        list of decorators
William Stein's avatar
William Stein committed
1390
    #
1391
    #  with_gil      boolean    Acquire GIL around body
William Stein's avatar
William Stein committed
1392
    #  type          CFuncType
1393
    #  py_func       wrapper for calling from Python
1394
    #  overridable   whether or not this is a cpdef function
1395
    #  inline_in_pxd whether this is an inline function in a pxd file
William Stein's avatar
William Stein committed
1396
    
1397
    child_attrs = ["base_type", "declarator", "body", "py_func"]
1398 1399

    inline_in_pxd = False
1400 1401
    decorators = None
    directive_locals = {}
1402

William Stein's avatar
William Stein committed
1403 1404 1405 1406
    def unqualified_name(self):
        return self.entry.name
        
    def analyse_declarations(self, env):
1407
        directive_locals = self.directive_locals = env.directives['locals']
William Stein's avatar
William Stein committed
1408
        base_type = self.base_type.analyse(env)
1409 1410
        # 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))
1411 1412 1413
        if not type.is_cfunction:
            error(self.pos, 
                "Suite attached to non-function declaration")
William Stein's avatar
William Stein committed
1414 1415 1416 1417 1418
        # 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
1419
        type.is_overridable = self.overridable
1420 1421 1422 1423 1424
        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):
1425
            formal_arg.type = type_arg.type
1426
            formal_arg.name = type_arg.name
1427
            formal_arg.cname = type_arg.cname
William Stein's avatar
William Stein committed
1428 1429 1430 1431 1432
        name = name_declarator.name
        cname = name_declarator.cname
        self.entry = env.declare_cfunction(
            name, type, self.pos, 
            cname = cname, visibility = self.visibility,
1433
            defining = self.body is not None,
1434
            api = self.api, modifiers = self.modifiers)
1435
        self.entry.inline_func_in_pxd = self.inline_in_pxd
William Stein's avatar
William Stein committed
1436
        self.return_type = type.return_type
1437
        
1438 1439 1440 1441 1442 1443
        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:
1444
            import ExprNodes
1445
            py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1446
            self.py_func = DefNode(pos = self.pos, 
1447 1448
                                   name = self.entry.name,
                                   args = self.args,
1449 1450
                                   star_arg = None,
                                   starstar_arg = None,
1451
                                   doc = self.doc,
1452 1453
                                   body = py_func_body,
                                   is_wrapper = 1)
1454
            self.py_func.is_module_scope = env.is_module_scope
1455
            self.py_func.analyse_declarations(env)
1456
            self.entry.as_variable = self.py_func.entry
1457 1458
            # Reset scope entry the above cfunction
            env.entries[name] = self.entry
1459 1460
            self.py_func.interned_attr_cname = env.intern_identifier(
                self.py_func.entry.name)
1461 1462 1463
            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])
1464
    
1465
    def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1466 1467 1468 1469 1470
        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]
1471
        if is_module_scope:
1472
            cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1473 1474
        else:
            self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1475
            cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1476 1477
        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)
1478
        return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1479
    
William Stein's avatar
William Stein committed
1480 1481 1482 1483 1484 1485
    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)
            
1486
    def need_gil_acquisition(self, lenv):
1487
        type = self.type
1488
        with_gil = self.type.with_gil
1489 1490 1491 1492
        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")
1493 1494 1495 1496 1497
            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

1498
    def analyse_expressions(self, env):
1499
        self.local_scope.directives = env.directives
1500
        self.analyse_default_values(env)
1501
        if self.py_func is not None:
1502 1503
            self.py_func.analyse_expressions(env)

1504
    def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
William Stein's avatar
William Stein committed
1505 1506
        arg_decls = []
        type = self.type
Stefan Behnel's avatar
Stefan Behnel committed
1507
        visibility = self.entry.visibility
1508
        for arg in type.args[:len(type.args)-type.optional_arg_count]:
William Stein's avatar
William Stein committed
1509
            arg_decls.append(arg.declaration_code())
1510 1511
        if with_dispatch and self.overridable:
            arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1512 1513
        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
1514 1515 1516 1517
        if type.has_varargs:
            arg_decls.append("...")
        if not arg_decls:
            arg_decls = ["void"]
1518 1519
        if cname is None:
            cname = self.entry.func_cname
1520
        entity = type.function_header_code(cname, ', '.join(arg_decls))
Stefan Behnel's avatar
Stefan Behnel committed
1521
        if visibility == 'public':
William Stein's avatar
William Stein committed
1522 1523 1524 1525 1526
            dll_linkage = "DL_EXPORT"
        else:
            dll_linkage = None
        header = self.return_type.declaration_code(entity,
            dll_linkage = dll_linkage)
1527
        if visibility == 'extern':
William Stein's avatar
William Stein committed
1528
            storage_class = "%s " % Naming.extern_c_macro
1529 1530
        elif visibility == 'public':
            storage_class = ""
William Stein's avatar
William Stein committed
1531
        else:
Stefan Behnel's avatar
Stefan Behnel committed
1532
            storage_class = "static "
Robert Bradshaw's avatar
Robert Bradshaw committed
1533
        code.putln("%s%s %s {" % (
William Stein's avatar
William Stein committed
1534
            storage_class,
1535
            ' '.join(self.modifiers).upper(), # macro forms 
William Stein's avatar
William Stein committed
1536 1537 1538
            header))

    def generate_argument_declarations(self, env, code):
1539
        for arg in self.args:
1540
            if arg.default:
1541
                    code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1542

William Stein's avatar
William Stein committed
1543 1544 1545
    def generate_keyword_list(self, code):
        pass
        
1546
    def generate_argument_parsing_code(self, env, code):
1547
        i = 0
1548 1549
        if self.type.optional_arg_count:
            code.putln('if (%s) {' % Naming.optional_args_cname)
1550
            for arg in self.args:
1551
                if arg.default:
1552 1553
                    # FIXME: simple name prefixing doesn't work when
                    # argument name mangling is in place
1554
                    code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1555 1556 1557 1558
                    declarator = arg.declarator
                    while not hasattr(declarator, 'name'):
                        declarator = declarator.base
                    code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1559 1560 1561
                    i += 1
            for _ in range(self.type.optional_arg_count):
                code.putln('}')
1562
            code.putln('}')
William Stein's avatar
William Stein committed
1563 1564 1565 1566 1567
    
    def generate_argument_conversion_code(self, code):
        pass
    
    def generate_argument_type_tests(self, code):
1568 1569 1570 1571 1572 1573 1574 1575 1576 1577
        # 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
1578
            arg_code = "((PyObject *)%s)" % arg.cname
1579
            code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
1580
                'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1581 1582 1583 1584
                    arg_code, 
                    typeptr_cname,
                    not arg.not_none,
                    arg.name,
Robert Bradshaw's avatar
Robert Bradshaw committed
1585
                    type.is_builtin_type,
1586 1587 1588 1589
                    code.error_goto(arg.pos)))
        else:
            error(arg.pos, "Cannot test type of extern C class "
                "without type object name specification")
1590

William Stein's avatar
William Stein committed
1591 1592 1593 1594
    def error_value(self):
        if self.return_type.is_pyobject:
            return "0"
        else:
1595 1596
            #return None
            return self.entry.type.exception_value
William Stein's avatar
William Stein committed
1597 1598
            
    def caller_will_check_exceptions(self):
1599
        return self.entry.type.exception_check
1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610
        
    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)
1611
            code.putln()
1612 1613 1614 1615 1616
            self.generate_function_header(code, 
                                          0,
                                          with_dispatch = entry.type.is_overridable, 
                                          with_opt_args = entry.type.optional_arg_count, 
                                          cname = entry.func_cname)
1617 1618 1619 1620
            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]]
1621 1622 1623 1624 1625 1626 1627 1628
            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')
1629 1630
            code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
            code.putln('}')
1631
        
William Stein's avatar
William Stein committed
1632 1633 1634 1635 1636 1637 1638

class PyArgDeclNode(Node):
    # Argument which must be a Python object (used
    # for * and ** arguments).
    #
    # name   string
    # entry  Symtab.Entry
1639
    child_attrs = []
William Stein's avatar
William Stein committed
1640
    
1641 1642 1643 1644 1645 1646 1647

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

William Stein's avatar
William Stein committed
1648 1649 1650 1651 1652

class DefNode(FuncDefNode):
    # A Python function definition.
    #
    # name          string                 the Python name of the function
1653
    # decorators    [DecoratorNode]        list of decorators
William Stein's avatar
William Stein committed
1654 1655 1656
    # args          [CArgDeclNode]         formal arguments
    # star_arg      PyArgDeclNode or None  * argument
    # starstar_arg  PyArgDeclNode or None  ** argument
1657
    # doc           EncodedString or None
William Stein's avatar
William Stein committed
1658 1659 1660 1661 1662 1663 1664
    # body          StatListNode
    #
    #  The following subnode is constructed internally
    #  when the def statement is inside a Python class definition.
    #
    #  assmt   AssignmentNode   Function construction/assignment
    
1665
    child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1666

William Stein's avatar
William Stein committed
1667
    assmt = None
1668
    num_kwonly_args = 0
1669
    num_required_kw_args = 0
1670
    reqd_kw_flags_cname = "0"
1671
    is_wrapper = 0
1672
    decorators = None
1673 1674
    entry = None
    
1675

1676 1677
    def __init__(self, pos, **kwds):
        FuncDefNode.__init__(self, pos, **kwds)
1678
        k = rk = r = 0
1679 1680
        for arg in self.args:
            if arg.kw_only:
1681
                k += 1
1682
                if not arg.default:
1683 1684 1685 1686 1687 1688
                    rk += 1
            if not arg.default:
                r += 1
        self.num_kwonly_args = k
        self.num_required_kw_args = rk
        self.num_required_args = r
1689
        
1690
    def as_cfunction(self, cfunc=None, scope=None):
1691 1692 1693 1694
        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")
1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710
        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)
1711
            cfunc = CVarDefNode(self.pos, type=cfunc_type)
1712 1713 1714 1715 1716 1717 1718 1719 1720 1721
        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
1722
        import ExprNodes
1723
        if cfunc_type.exception_value is None:
1724 1725
            exception_value = None
        else:
1726
            exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1727 1728 1729 1730
        declarator = CFuncDeclaratorNode(self.pos, 
                                         base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
                                         args = self.args,
                                         has_varargs = False,
1731
                                         exception_check = cfunc_type.exception_check,
1732
                                         exception_value = exception_value,
1733 1734
                                         with_gil = cfunc_type.with_gil,
                                         nogil = cfunc_type.nogil)
1735 1736
        return CFuncDefNode(self.pos, 
                            modifiers = [],
1737
                            base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1738 1739 1740
                            declarator = declarator,
                            body = self.body,
                            doc = self.doc,
1741 1742 1743 1744
                            overridable = cfunc_type.is_overridable,
                            type = cfunc_type,
                            with_gil = cfunc_type.with_gil,
                            nogil = cfunc_type.nogil,
1745
                            visibility = 'private',
1746
                            api = False,
1747
                            directive_locals = getattr(cfunc, 'directive_locals', {}))
1748
    
William Stein's avatar
William Stein committed
1749
    def analyse_declarations(self, env):
1750
        directive_locals = self.directive_locals = env.directives['locals']
William Stein's avatar
William Stein committed
1751
        for arg in self.args:
1752 1753 1754 1755 1756 1757 1758 1759
            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
1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770
            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
1771
            if name_declarator and name_declarator.cname:
William Stein's avatar
William Stein committed
1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784
                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()
1785

William Stein's avatar
William Stein committed
1786 1787
    def analyse_signature(self, env):
        any_type_tests_needed = 0
1788 1789 1790 1791 1792
        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:
1793 1794
                if len(self.args) == 0:
                    self.entry.signature = TypeSlots.pyfunction_noargs
1795 1796 1797
                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
1798 1799 1800
            elif self.entry.signature is TypeSlots.pymethod_signature:
                if len(self.args) == 1:
                    self.entry.signature = TypeSlots.unaryfunc
1801 1802 1803
                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
1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832
        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
1833 1834
                if arg.is_generic and \
                        (arg.type.is_extension_type or arg.type.is_builtin_type):
William Stein's avatar
William Stein committed
1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853
                    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))
1854 1855 1856

    def signature_has_nongeneric_args(self):
        argcount = len(self.args)
Stefan Behnel's avatar
Stefan Behnel committed
1857
        if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1858 1859 1860 1861 1862
            return 0
        return 1

    def signature_has_generic_args(self):
        return self.entry.signature.has_generic_args
William Stein's avatar
William Stein committed
1863 1864
    
    def declare_pyfunction(self, env):
1865 1866
        #print "DefNode.declare_pyfunction:", self.name, "in", env ###
        name = self.name
1867 1868 1869
        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)
1870 1871 1872 1873
        entry = env.declare_pyfunction(self.name, self.pos)
        self.entry = entry
        prefix = env.scope_prefix
        entry.func_cname = \
1874
            Naming.pyfunc_prefix + prefix + name
1875 1876
        entry.pymethdef_cname = \
            Naming.pymethdef_prefix + prefix + name
1877 1878
        if Options.docstrings:
            entry.doc = embed_position(self.pos, self.doc)
1879 1880
            entry.doc_cname = \
                Naming.funcdoc_prefix + prefix + name
1881 1882
        else:
            entry.doc = None
1883

William Stein's avatar
William Stein committed
1884 1885 1886 1887 1888 1889
    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)
1890 1891
                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
1892 1893 1894 1895 1896
                if arg.type.is_pyobject:
                    arg.entry.init = "0"
                arg.entry.init_to_none = 0
            else:
                arg.entry = self.declare_argument(env, arg)
1897
            arg.entry.used = 1
William Stein's avatar
William Stein committed
1898
            arg.entry.is_self_arg = arg.is_self_arg
1899 1900 1901 1902
            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
1903 1904 1905 1906 1907 1908 1909 1910 1911
            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:
1912
            entry = env.declare_var(arg.name, 
William Stein's avatar
William Stein committed
1913
                PyrexTypes.py_object_type, arg.pos)
1914 1915 1916 1917 1918
            entry.used = 1
            entry.init = "0"
            entry.init_to_none = 0
            entry.xdecref_cleanup = 1
            arg.entry = entry
1919
            env.control_flow.set_state((), (arg.name, 'initalized'), True)
William Stein's avatar
William Stein committed
1920 1921
            
    def analyse_expressions(self, env):
1922
        self.local_scope.directives = env.directives
William Stein's avatar
William Stein committed
1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937
        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)
            
1938
    def generate_function_header(self, code, with_pymethdef, proto_only=0):
William Stein's avatar
William Stein committed
1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950
        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))
1951
        if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1952
            arg_code_list.append("PyObject *unused")
William Stein's avatar
William Stein committed
1953 1954 1955 1956 1957 1958 1959 1960
        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)
1961 1962
        if proto_only:
            return
1963
        if self.entry.doc and Options.docstrings:
1964 1965 1966
            docstr = self.entry.doc
            if not isinstance(docstr, str):
                docstr = docstr.utf8encode()
William Stein's avatar
William Stein committed
1967 1968 1969
            code.putln(
                'static char %s[] = "%s";' % (
                    self.entry.doc_cname,
1970
                    split_docstring(escape_byte_string(docstr))))
William Stein's avatar
William Stein committed
1971 1972 1973 1974 1975 1976 1977 1978 1979 1980
        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:
1981 1982 1983 1984
                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
1985 1986
    
    def generate_keyword_list(self, code):
1987 1988
        if self.signature_has_generic_args() and \
                self.signature_has_nongeneric_args():
William Stein's avatar
William Stein committed
1989
            code.put(
1990 1991
                "static PyObject **%s[] = {" %
                    Naming.pykwdlist_cname)
William Stein's avatar
William Stein committed
1992 1993
            for arg in self.args:
                if arg.is_generic:
1994
                    code.put('&%s,' % arg.name_entry.pystring_cname)
1995
            code.putln("0};")
1996

1997
    def generate_argument_parsing_code(self, env, code):
William Stein's avatar
William Stein committed
1998 1999
        # Generate PyArg_ParseTuple call for generic
        # arguments, if any.
2000 2001 2002 2003
        if self.entry.signature.has_dummy_arg:
            # get rid of unused argument warning
            code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))

2004 2005
        old_error_label = code.new_error_label()
        our_error_label = code.error_label
Stefan Behnel's avatar
Stefan Behnel committed
2006
        end_label = code.new_label("argument_unpacking_done")
2007

2008 2009 2010
        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
2011

2012 2013 2014 2015
        for arg in self.args:
            if not arg.type.is_pyobject and arg.type.from_py_function is None:
                arg.type.create_from_py_utility_code(env)

2016
        if not self.signature_has_generic_args():
2017 2018
            if has_star_or_kw_args:
                error(self.pos, "This method cannot have * or keyword arguments")
2019
            self.generate_argument_conversion_code(code)
2020

2021 2022
        elif not self.signature_has_nongeneric_args():
            # func(*args) or func(**kw) or func(*args, **kw)
2023
            self.generate_stararg_copy_code(code)
2024

2025
        else:
2026
            positional_args = []
2027
            kw_only_args = []
William Stein's avatar
William Stein committed
2028 2029 2030 2031 2032 2033
            default_seen = 0
            for arg in self.args:
                arg_entry = arg.entry
                if arg.is_generic:
                    if arg.default:
                        default_seen = 1
2034 2035 2036 2037 2038
                        if not arg.is_self_arg:
                            if arg.kw_only:
                                kw_only_args.append(arg)
                            else:
                                positional_args.append(arg)
2039
                    elif arg.kw_only:
2040
                        kw_only_args.append(arg)
2041
                        default_seen = 1
2042
                    elif default_seen:
William Stein's avatar
William Stein committed
2043
                        error(arg.pos, "Non-default argument following default argument")
2044 2045
                    elif not arg.is_self_arg:
                        positional_args.append(arg)
2046

2047
            self.generate_tuple_and_keyword_parsing_code(
2048
                positional_args, kw_only_args, end_label, code)
2049

2050 2051
        code.error_label = old_error_label
        if code.label_used(our_error_label):
2052 2053
            if not code.label_used(end_label):
                code.put_goto(end_label)
2054 2055 2056 2057 2058 2059 2060 2061
            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)
2062
            code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
2063
            code.putln("return %s;" % self.error_value())
2064
        if code.label_used(end_label):
2065 2066
            code.put_label(end_label)

2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079
    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)))
2080
            else:
2081
                error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
William Stein's avatar
William Stein committed
2082 2083 2084 2085 2086
    
    def generate_arg_xdecref(self, arg, code):
        if arg:
            code.put_var_xdecref(arg.entry)
    
2087 2088 2089
    def generate_arg_decref(self, arg, code):
        if arg:
            code.put_var_decref(arg.entry)
William Stein's avatar
William Stein committed
2090

2091 2092
    def generate_stararg_copy_code(self, code):
        if not self.star_arg:
2093 2094 2095 2096 2097 2098
            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("}")
2099

2100 2101
        code.globalstate.use_utility_code(keyword_string_check_utility_code)

2102 2103 2104 2105 2106 2107 2108 2109
        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)
2110
        code.putln(
2111 2112
            "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
                kwarg_check, Naming.kwds_cname, self.name,
2113
                bool(self.starstar_arg), self.error_value()))
2114

2115
        if self.starstar_arg:
2116
            code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2117 2118 2119
                    self.starstar_arg.entry.cname,
                    Naming.kwds_cname,
                    Naming.kwds_cname))
2120 2121
            code.putln("if (unlikely(!%s)) return %s;" % (
                    self.starstar_arg.entry.cname, self.error_value()))
2122
            self.starstar_arg.entry.xdecref_cleanup = 0
2123 2124
            code.put_gotref(self.starstar_arg.entry.cname)
            
2125

2126 2127 2128 2129 2130 2131 2132
        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

2133
    def generate_tuple_and_keyword_parsing_code(self, positional_args,
2134 2135
                                                kw_only_args, success_label, code):
        argtuple_error_label = code.new_label("argtuple_error")
2136

2137 2138 2139 2140
        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)
2141 2142
        has_fixed_positional_count = not self.star_arg and \
            min_positional_args == max_positional_args
2143

2144
        code.globalstate.use_utility_code(raise_double_keywords_utility_code)
Stefan Behnel's avatar
Stefan Behnel committed
2145 2146 2147 2148
        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)

2149 2150 2151 2152 2153
        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:
2154
            likely_hint = "likely"
2155
        else:
2156 2157
            likely_hint = "unlikely"
        code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2158 2159
        self.generate_keyword_unpacking_code(
            min_positional_args, max_positional_args,
2160
            has_fixed_positional_count,
2161 2162 2163
            positional_args, kw_only_args, argtuple_error_label, code)

        # --- optimised code when we do not receive any keyword arguments
2164
        if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2165 2166 2167 2168 2169 2170 2171 2172 2173
            # 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)
2174

2175 2176 2177 2178 2179 2180 2181 2182 2183 2184
        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
2185 2186 2187
                    code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
                            self.name.utf8encode(),
                            arg.name_entry.pystring_cname))
2188 2189
                    code.putln(code.error_goto(self.pos))
                    break
2190

2191 2192 2193
        elif min_positional_args == max_positional_args:
            # parse the exact number of positional arguments from the
            # args tuple
2194 2195 2196 2197 2198
            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)
2199

2200 2201 2202 2203
        else:
            # parse the positional arguments from the variable length
            # args tuple
            code.putln('} else {')
2204
            self.generate_arg_default_assignments(code)
2205
            code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2206 2207
            if self.star_arg:
                code.putln('default:')
2208 2209 2210 2211 2212 2213 2214 2215 2216
            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
2217 2218 2219
            if min_positional_args == 0:
                code.put('case  0: ')
            code.putln('break;')
2220 2221 2222 2223 2224 2225
            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:
2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240
                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))

2241 2242 2243 2244 2245 2246 2247 2248
    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))

2249
    def generate_stararg_init_code(self, max_positional_args, code):
2250
        if self.starstar_arg:
2251
            self.starstar_arg.entry.xdecref_cleanup = 0
Stefan Behnel's avatar
Stefan Behnel committed
2252 2253 2254 2255
            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
2256
            code.put_gotref(self.starstar_arg.entry.cname)
Stefan Behnel's avatar
Stefan Behnel committed
2257 2258 2259 2260 2261 2262 2263 2264
        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
2265
            code.put_gotref(self.star_arg.entry.cname)
Stefan Behnel's avatar
Stefan Behnel committed
2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278
            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('}')
2279

2280
    def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2281 2282
                                        has_fixed_positional_count, positional_args,
                                        kw_only_args, argtuple_error_label, code):
2283 2284 2285
        all_args = tuple(positional_args) + tuple(kw_only_args)
        max_args = len(all_args)

2286
        default_args = []
2287
        for i, arg in enumerate(all_args):
2288 2289 2290 2291
            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
2292
                default_args.append((i, default_value))
2293

2294 2295
        code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
                   Naming.kwds_cname)
2296 2297 2298 2299 2300 2301
        # 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))
2302

Stefan Behnel's avatar
Stefan Behnel committed
2303
        # parse the tuple and check that it's not too long
2304
        code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
Stefan Behnel's avatar
Stefan Behnel committed
2305 2306
        if self.star_arg:
            code.putln('default:')
2307
        for i in range(max_positional_args-1, -1, -1):
2308
            code.put('case %2d: ' % (i+1))
2309 2310
            code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
                    i, Naming.args_cname, i))
2311
        code.putln('case  0: break;')
2312
        if not self.star_arg:
Stefan Behnel's avatar
Stefan Behnel committed
2313
            code.put('default: ') # more arguments than allowed
2314
            code.put_goto(argtuple_error_label)
2315 2316
        code.putln('}')

Stefan Behnel's avatar
Stefan Behnel committed
2317 2318
        # now fill up the positional/required arguments with values
        # from the kw dict
2319
        if self.num_required_args or max_positional_args > 0:
Stefan Behnel's avatar
Stefan Behnel committed
2320 2321 2322 2323
            last_required_arg = -1
            for i, arg in enumerate(all_args):
                if not arg.default:
                    last_required_arg = i
2324 2325 2326
            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
2327 2328
            if max_positional_args > 0:
                code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2329
            for i, arg in enumerate(all_args[:last_required_arg+1]):
Stefan Behnel's avatar
Stefan Behnel committed
2330
                if max_positional_args > 0 and i <= max_positional_args:
2331 2332 2333 2334 2335
                    if self.star_arg and i == max_positional_args:
                        code.putln('default:')
                    else:
                        code.putln('case %2d:' % i)
                if arg.default:
2336 2337 2338 2339 2340 2341
                    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
2342
                    code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2343 2344 2345 2346
                    code.putln('}')
                else:
                    num_required_args -= 1
                    code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2347
                        i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364
                    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:
2365
                        code.putln('else {')
2366 2367
                        code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
                                self.name.utf8encode(), arg.name_entry.pystring_cname))
2368 2369
                        code.putln(code.error_goto(self.pos))
                        code.putln('}')
Stefan Behnel's avatar
Stefan Behnel committed
2370 2371
            if max_positional_args > 0:
                code.putln('}')
2372

2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394
        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('}')

2395
        code.putln('if (unlikely(kw_args > 0)) {')
2396 2397
        # non-positional/-required kw args left in dict: default args,
        # kw-only args, **kwargs or error
Stefan Behnel's avatar
Stefan Behnel committed
2398 2399 2400 2401 2402
        #
        # 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.
2403 2404 2405
        if max_positional_args == 0:
            pos_arg_count = "0"
        elif self.star_arg:
Stefan Behnel's avatar
Stefan Behnel committed
2406 2407 2408 2409 2410 2411
            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
2412
        code.globalstate.use_utility_code(parse_keywords_utility_code)
Stefan Behnel's avatar
Stefan Behnel committed
2413
        code.put(
2414
            'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
Stefan Behnel's avatar
Stefan Behnel committed
2415 2416 2417 2418 2419
                Naming.kwds_cname,
                Naming.pykwdlist_cname,
                self.starstar_arg and self.starstar_arg.entry.cname or '0',
                pos_arg_count,
                self.name.utf8encode()))
2420
        code.putln(code.error_goto(self.pos))
2421
        code.putln('}')
2422

2423
        # convert arg values to their final type and assign them
2424
        for i, arg in enumerate(all_args):
2425
            if arg.default and not arg.type.is_pyobject:
2426 2427
                code.putln("if (values[%d]) {" % i)
            self.generate_arg_assignment(arg, "values[%d]" % i, code)
2428
            if arg.default and not arg.type.is_pyobject:
2429 2430 2431 2432 2433
                code.putln('} else {')
                code.putln(
                    "%s = %s;" % (
                        arg.entry.cname,
                        arg.default_result_code))
2434
                code.putln('}')
2435

William Stein's avatar
William Stein committed
2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447
    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
2448 2449 2450 2451
            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
2452
            self.generate_arg_conversion_from_pyobject(arg, code)
Robert Bradshaw's avatar
Robert Bradshaw committed
2453
            code.putln("}")
William Stein's avatar
William Stein committed
2454 2455 2456 2457 2458 2459 2460 2461
        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,
2462
                    "Cannot convert 1 argument from '%s' to '%s'" %
William Stein's avatar
William Stein committed
2463 2464 2465 2466 2467
                        (old_type, new_type))
    
    def generate_arg_conversion_from_pyobject(self, arg, code):
        new_type = arg.type
        func = new_type.from_py_function
2468
        # copied from CoerceFromPyTypeNode
William Stein's avatar
William Stein committed
2469
        if func:
Robert Bradshaw's avatar
Robert Bradshaw committed
2470
            code.putln("%s = %s(%s); %s" % (
William Stein's avatar
William Stein committed
2471 2472 2473
                arg.entry.cname,
                func,
                arg.hdr_cname,
2474
                code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
William Stein's avatar
William Stein committed
2475 2476 2477 2478 2479 2480 2481 2482 2483
        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
2484
            code.putln("%s = %s(%s); %s" % (
William Stein's avatar
William Stein committed
2485 2486 2487
                arg.entry.cname,
                func,
                arg.hdr_cname,
Robert Bradshaw's avatar
Robert Bradshaw committed
2488
                code.error_goto_if_null(arg.entry.cname, arg.pos)))
2489
            code.put_var_gotref(arg.entry)
William Stein's avatar
William Stein committed
2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508
        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
2509
                'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
William Stein's avatar
William Stein committed
2510 2511 2512 2513
                    arg_code, 
                    typeptr_cname,
                    not arg.not_none,
                    arg.name,
Robert Bradshaw's avatar
Robert Bradshaw committed
2514
                    arg.type.is_builtin_type,
William Stein's avatar
William Stein committed
2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525
                    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
            
2526 2527 2528 2529 2530 2531 2532 2533 2534 2535
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
2536
    child_attrs = ['body']
2537 2538
    
    body = None
Robert Bradshaw's avatar
Robert Bradshaw committed
2539

2540 2541
    def analyse_expressions(self, env):
        self.args = env.arg_entries
2542 2543 2544 2545
        if self.py_func.is_module_scope:
            first_arg = 0
        else:
            first_arg = 1
2546 2547
        import ExprNodes
        self.func_node = ExprNodes.PyTempNode(self.pos, env)
2548
        call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2549 2550
        call_node = ExprNodes.SimpleCallNode(self.pos,
                                             function=self.func_node, 
2551
                                             args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2552 2553 2554 2555 2556
        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
2557 2558 2559 2560
        if self.py_func.is_module_scope:
            self_arg = "((PyObject *)%s)" % Naming.module_cname
        else:
            self_arg = "((PyObject *)%s)" % self.args[0].cname
2561
        code.putln("/* Check if called by wrapper */")
2562
        code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2563
        code.putln("/* Check if overriden in Python */")
2564 2565 2566
        if self.py_func.is_module_scope:
            code.putln("else {")
        else:
2567
            code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2568
        err = code.error_goto_if_null(self.func_node.result(), self.pos)
2569
        # need to get attribute manually--scope would return cdef method
2570
        code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2571
        code.put_gotref(self.func_node.py_result())
2572
        is_builtin_function_or_method = 'PyCFunction_Check(%s)' % self.func_node.result()
2573
        is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2574 2575 2576
        code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
        self.body.generate_execution_code(code)
        code.putln('}')
2577
        code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2578 2579
        code.putln("}")

Robert Bradshaw's avatar
Robert Bradshaw committed
2580 2581
class ClassDefNode(StatNode, BlockNode):
    pass
2582

Robert Bradshaw's avatar
Robert Bradshaw committed
2583
class PyClassDefNode(ClassDefNode):
William Stein's avatar
William Stein committed
2584 2585
    #  A Python class definition.
    #
Stefan Behnel's avatar
Stefan Behnel committed
2586
    #  name     EncodedString   Name of the class
William Stein's avatar
William Stein committed
2587 2588 2589 2590 2591 2592 2593 2594 2595 2596
    #  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
2597 2598

    child_attrs = ["body", "dict", "classobj", "target"]
William Stein's avatar
William Stein committed
2599 2600 2601 2602 2603 2604 2605 2606
    
    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 = [])
2607
        if self.doc and Options.docstrings:
2608
            doc = embed_position(self.pos, self.doc)
2609
            doc_node = ExprNodes.StringNode(pos, value = doc)
William Stein's avatar
William Stein committed
2610 2611
        else:
            doc_node = None
2612
        self.classobj = ExprNodes.ClassNode(pos, name = name,
William Stein's avatar
William Stein committed
2613 2614
            bases = bases, dict = self.dict, doc = doc_node)
        self.target = ExprNodes.NameNode(pos, name = name)
2615
        
2616 2617
    def as_cclass(self):
        """
2618
        Return this node as if it were declared as an extension class
2619 2620 2621 2622 2623 2624 2625 2626
        """
        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 = []
2627 2628
            from ExprNodes import AttributeNode, NameNode
            while isinstance(base, AttributeNode):
2629 2630
                path.insert(0, base.attribute)
                base = base.obj
2631
            if isinstance(base, NameNode):
2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653
                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)
        
2654 2655 2656 2657 2658 2659
    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
2660 2661 2662
    
    def analyse_declarations(self, env):
        self.target.analyse_target_declaration(env)
2663
        cenv = self.create_scope(env)
2664
        cenv.directives = env.directives
2665 2666
        cenv.class_obj_cname = self.target.entry.cname
        self.body.analyse_declarations(cenv)
William Stein's avatar
William Stein committed
2667 2668 2669 2670 2671
    
    def analyse_expressions(self, env):
        self.dict.analyse_expressions(env)
        self.classobj.analyse_expressions(env)
        genv = env.global_scope()
2672
        cenv = self.scope
2673 2674
        cenv.class_dict_cname = self.dict.result()
        cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
William Stein's avatar
William Stein committed
2675
        self.body.analyse_expressions(cenv)
2676
        self.target.analyse_target_expression(env, self.classobj)
William Stein's avatar
William Stein committed
2677
        self.dict.release_temp(env)
2678 2679
        #self.classobj.release_temp(env)
        #self.target.release_target_temp(env)
William Stein's avatar
William Stein committed
2680
    
2681
    def generate_function_definitions(self, env, code):
William Stein's avatar
William Stein committed
2682
        self.generate_py_string_decls(self.scope, code)
2683
        self.body.generate_function_definitions(self.scope, code)
William Stein's avatar
William Stein committed
2684 2685 2686 2687 2688 2689 2690
    
    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)
2691
        self.dict.free_temps(code)
William Stein's avatar
William Stein committed
2692 2693


Robert Bradshaw's avatar
Robert Bradshaw committed
2694
class CClassDefNode(ClassDefNode):
William Stein's avatar
William Stein committed
2695 2696 2697 2698
    #  An extension type definition.
    #
    #  visibility         'private' or 'public' or 'extern'
    #  typedef_flag       boolean
Stefan Behnel's avatar
Stefan Behnel committed
2699
    #  api                boolean
William Stein's avatar
William Stein committed
2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711
    #  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
2712 2713
    #  buffer_defaults_node DictNode or None Declares defaults for a buffer
    #  buffer_defaults_pos
2714

2715
    child_attrs = ["body"]
2716 2717
    buffer_defaults_node = None
    buffer_defaults_pos = None
2718 2719 2720 2721
    typedef_flag = False
    api = False
    objstruct_name = None
    typeobj_name = None
2722

William Stein's avatar
William Stein committed
2723 2724 2725 2726
    def analyse_declarations(self, env):
        #print "CClassDefNode.analyse_declarations:", self.class_name
        #print "...visibility =", self.visibility
        #print "...module_name =", self.module_name
2727 2728 2729 2730 2731 2732 2733 2734 2735

        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
2736 2737 2738 2739
        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
2740 2741 2742 2743 2744 2745 2746 2747 2748
        # 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)
2749
                self.module.has_extern_class = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2750
                env.add_imported_module(self.module)
2751

William Stein's avatar
William Stein committed
2752 2753 2754 2755 2756
        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
2757 2758 2759 2760 2761 2762
            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
2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774
            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
2775
        if self.module_name and self.visibility != 'extern':
2776 2777 2778 2779 2780 2781
            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
2782 2783 2784

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

2787
        self.entry = home_scope.declare_c_class(
William Stein's avatar
William Stein committed
2788 2789 2790 2791 2792 2793 2794 2795 2796
            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
2797
            typedef_flag = self.typedef_flag,
2798 2799
            api = self.api,
            buffer_defaults = buffer_defaults)
2800 2801
        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
2802
        scope = self.entry.type.scope
2803 2804
        if scope is not None:
            scope.directives = env.directives
2805

2806
        if self.doc and Options.docstrings:
2807
            scope.doc = embed_position(self.pos, self.doc)
2808
            
William Stein's avatar
William Stein committed
2809 2810 2811 2812 2813 2814 2815 2816 2817 2818
        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
2819 2820
            scope = self.entry.type.scope
            self.body.analyse_expressions(scope)
William Stein's avatar
William Stein committed
2821
    
2822
    def generate_function_definitions(self, env, code):
2823
        self.generate_py_string_decls(self.entry.type.scope, code)
William Stein's avatar
William Stein committed
2824 2825
        if self.body:
            self.body.generate_function_definitions(
2826
                self.entry.type.scope, code)
William Stein's avatar
William Stein committed
2827 2828 2829 2830 2831 2832
    
    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)
2833 2834 2835 2836
            
    def annotate(self, code):
        if self.body:
            self.body.annotate(code)
William Stein's avatar
William Stein committed
2837 2838 2839 2840 2841 2842


class PropertyNode(StatNode):
    #  Definition of a property in an extension type.
    #
    #  name   string
2843
    #  doc    EncodedString or None    Doc string
William Stein's avatar
William Stein committed
2844 2845
    #  body   StatListNode
    
2846 2847
    child_attrs = ["body"]

William Stein's avatar
William Stein committed
2848 2849 2850
    def analyse_declarations(self, env):
        entry = env.declare_property(self.name, self.doc, self.pos)
        if entry:
2851
            if self.doc and Options.docstrings:
2852 2853
                doc_entry = env.get_string_const(
                    self.doc, identifier = False)
William Stein's avatar
William Stein committed
2854
                entry.doc_cname = doc_entry.cname
2855
            entry.scope.directives = env.directives
William Stein's avatar
William Stein committed
2856
            self.body.analyse_declarations(entry.scope)
2857

William Stein's avatar
William Stein committed
2858 2859 2860
    def analyse_expressions(self, env):
        self.body.analyse_expressions(env)
    
2861 2862
    def generate_function_definitions(self, env, code):
        self.body.generate_function_definitions(env, code)
William Stein's avatar
William Stein committed
2863 2864 2865 2866

    def generate_execution_code(self, code):
        pass

2867 2868 2869
    def annotate(self, code):
        self.body.annotate(code)

William Stein's avatar
William Stein committed
2870 2871 2872 2873 2874 2875

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

William Stein's avatar
William Stein committed
2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892
    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
2893 2894

    child_attrs = ["expr"]
William Stein's avatar
William Stein committed
2895
    
Robert Bradshaw's avatar
Robert Bradshaw committed
2896 2897 2898
    def analyse_declarations(self, env):
        import ExprNodes
        if isinstance(self.expr, ExprNodes.GeneralCallNode):
2899
            func = self.expr.function.as_cython_attribute()
Robert Bradshaw's avatar
Robert Bradshaw committed
2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911
            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
2912 2913 2914 2915 2916 2917
    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)
2918 2919
        if not self.expr.is_temp and self.expr.result():
            code.putln("%s;" % self.expr.result())
William Stein's avatar
William Stein committed
2920
        self.expr.generate_disposal_code(code)
2921
        self.expr.free_temps(code)
William Stein's avatar
William Stein committed
2922

2923 2924 2925
    def annotate(self, code):
        self.expr.annotate(code)

William Stein's avatar
William Stein committed
2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936

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):
2937 2938 2939 2940
        self.analyse_types(env)
        self.allocate_rhs_temps(env)
        self.allocate_lhs_temps(env)

2941 2942 2943
#       def analyse_expressions(self, env):
#           self.analyse_expressions_1(env)
#           self.analyse_expressions_2(env)
William Stein's avatar
William Stein committed
2944 2945 2946 2947

    def generate_execution_code(self, code):
        self.generate_rhs_evaluation_code(code)
        self.generate_assignment_code(code)
2948
        
William Stein's avatar
William Stein committed
2949 2950 2951 2952 2953 2954 2955 2956

class SingleAssignmentNode(AssignmentNode):
    #  The simplest case:
    #
    #    a = b
    #
    #  lhs      ExprNode      Left hand side
    #  rhs      ExprNode      Right hand side
2957
    #  first    bool          Is this guaranteed the first assignment to lhs?
2958 2959
    
    child_attrs = ["lhs", "rhs"]
2960
    first = False
2961
    declaration_only = False
William Stein's avatar
William Stein committed
2962 2963

    def analyse_declarations(self, env):
2964 2965 2966 2967
        import ExprNodes
        
        # handle declarations of the form x = cython.foo()
        if isinstance(self.rhs, ExprNodes.CallNode):
2968
            func_name = self.rhs.function.as_cython_attribute()
2969 2970 2971 2972
            if func_name:
                args, kwds = self.rhs.explicit_args_kwds()
                
                if func_name in ['declare', 'typedef']:
Robert Bradshaw's avatar
Robert Bradshaw committed
2973
                    if len(args) > 2 or kwds is not None:
2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990
                        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
2991 2992 2993 2994 2995
                        if len(args) == 2:
                            # we have a value
                            self.rhs = args[1]
                        else:
                            self.declaration_only = True
2996
                    else:
Robert Bradshaw's avatar
Robert Bradshaw committed
2997
                        self.declaration_only = True
2998 2999
                        if not isinstance(lhs, ExprNodes.NameNode):
                            error(lhs.pos, "Invalid declaration.")
3000
                        env.declare_typedef(lhs.name, type, self.pos, visibility='private')
3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027
                    
                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
3028
    
3029
    def analyse_types(self, env, use_temp = 0):
William Stein's avatar
William Stein committed
3030 3031
        self.rhs.analyse_types(env)
        self.lhs.analyse_target_types(env)
3032
        self.lhs.gil_assignment_check(env)
William Stein's avatar
William Stein committed
3033 3034 3035
        self.rhs = self.rhs.coerce_to(self.lhs.type, env)
        if use_temp:
            self.rhs = self.rhs.coerce_to_temp(env)
3036 3037
    
    def allocate_rhs_temps(self, env):
William Stein's avatar
William Stein committed
3038
        self.rhs.allocate_temps(env)
3039 3040 3041 3042

    def allocate_lhs_temps(self, env):
        self.lhs.allocate_target_temps(env, self.rhs)
        #self.lhs.release_target_temp(env)
3043 3044
        #self.rhs.release_temp(env)

William Stein's avatar
William Stein committed
3045 3046 3047 3048 3049 3050
    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)

3051 3052 3053 3054
    def annotate(self, code):
        self.lhs.annotate(code)
        self.rhs.annotate(code)

William Stein's avatar
William Stein committed
3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067

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
    
3068
    child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
3069
    coerced_rhs_list = None
3070

William Stein's avatar
William Stein committed
3071 3072 3073 3074
    def analyse_declarations(self, env):
        for lhs in self.lhs_list:
            lhs.analyse_target_declaration(env)
    
3075
    def analyse_types(self, env, use_temp = 0):
William Stein's avatar
William Stein committed
3076 3077 3078 3079 3080 3081 3082 3083 3084
        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)
3085
            lhs.gil_assignment_check(env)
William Stein's avatar
William Stein committed
3086 3087 3088
            rhs = CloneNode(self.rhs)
            rhs = rhs.coerce_to(lhs.type, env)
            self.coerced_rhs_list.append(rhs)
3089 3090 3091 3092 3093 3094

    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
3095
            rhs.allocate_temps(env)
3096 3097 3098
            lhs.allocate_target_temps(env, rhs)
            #lhs.release_target_temp(env)
            #rhs.release_temp(env)
William Stein's avatar
William Stein committed
3099
        self.rhs.release_temp(env)
3100
    
William Stein's avatar
William Stein committed
3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111
    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)
3112
        self.rhs.free_temps(code)
William Stein's avatar
William Stein committed
3113

3114 3115 3116 3117 3118 3119 3120
    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
3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134
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
    
3135 3136
    child_attrs = ["stats"]

William Stein's avatar
William Stein committed
3137 3138 3139 3140 3141 3142
    def analyse_declarations(self, env):
        for stat in self.stats:
            stat.analyse_declarations(env)
    
    def analyse_expressions(self, env):
        for stat in self.stats:
3143 3144
            stat.analyse_types(env, use_temp = 1)
            stat.allocate_rhs_temps(env)
William Stein's avatar
William Stein committed
3145
        for stat in self.stats:
3146 3147
            stat.allocate_lhs_temps(env)

Robert Bradshaw's avatar
Robert Bradshaw committed
3148 3149 3150 3151 3152
#    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
3153 3154 3155 3156 3157 3158 3159
    
    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)

3160 3161 3162 3163 3164
    def annotate(self, code):
        for stat in self.stats:
            stat.annotate(code)


3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183
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).     
    
3184
    child_attrs = ["lhs", "rhs"]
3185
    dup = None
3186

3187 3188
    def analyse_declarations(self, env):
        self.lhs.analyse_target_declaration(env)
3189 3190 3191
        
    def analyse_types(self, env):
        self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3192 3193
        self.rhs.analyse_types(env)
        self.lhs.analyse_target_types(env)
3194 3195
        if Options.incref_local_binop and self.dup.type.is_pyobject:
            self.dup = self.dup.coerce_to_temp(env)
3196 3197
        
    def allocate_rhs_temps(self, env):
3198
        import ExprNodes
3199 3200 3201
        if self.lhs.type.is_pyobject:
            self.rhs = self.rhs.coerce_to_pyobject(env)
        elif self.rhs.type.is_pyobject:
3202 3203
            self.rhs = self.rhs.coerce_to(self.lhs.type, env)
        if self.lhs.type.is_pyobject:
3204 3205
             self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
             self.result_value.allocate_temps(env)
3206 3207
#        if use_temp:
#            self.rhs = self.rhs.coerce_to_temp(env)
3208
        self.rhs.allocate_temps(env)
3209 3210 3211
        self.dup.allocate_subexpr_temps(env)
        self.dup.allocate_temp(env)
    
3212
    def allocate_lhs_temps(self, env):
3213 3214
        self.lhs.allocate_target_temps(env, self.rhs)
#        self.lhs.release_target_temp(env)
3215 3216 3217
        self.dup.release_temp(env)
        if self.dup.is_temp:
            self.dup.release_subexpr_temps(env)
3218
#        self.rhs.release_temp(env)
3219
        if self.lhs.type.is_pyobject:
3220
            self.result_value.release_temp(env)
3221 3222

    def generate_execution_code(self, code):
3223
        import ExprNodes
3224 3225
        self.rhs.generate_evaluation_code(code)
        self.dup.generate_subexpr_evaluation_code(code)
3226 3227 3228 3229
        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)
3230
        # self.dup.generate_result_code is run only if it is not buffer access
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
3231 3232 3233 3234
        if self.operator == "**":
            extra = ", Py_None"
        else:
            extra = ""
3235
        if self.lhs.type.is_pyobject:
3236 3237
            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.")
3238
            self.dup.generate_result_code(code)
3239
            code.putln(
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
3240
                "%s = %s(%s, %s%s); %s" % (
3241
                    self.result_value.result(), 
3242 3243 3244
                    self.py_operation_function(), 
                    self.dup.py_result(),
                    self.rhs.py_result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
3245
                    extra,
3246
                    code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3247
            code.put_gotref(self.result_value.py_result())
3248
            self.result_value.generate_evaluation_code(code) # May be a type check...
3249
            self.rhs.generate_disposal_code(code)
3250
            self.rhs.free_temps(code)
3251
            self.dup.generate_disposal_code(code)
3252
            self.dup.free_temps(code)
3253
            self.lhs.generate_assignment_code(self.result_value, code)
3254
        else: 
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
3255 3256 3257 3258
            c_op = self.operator
            if c_op == "//":
                c_op = "/"
            elif c_op == "**":
3259 3260 3261 3262
                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.")
                
3263
            # have to do assignment directly to avoid side-effects
3264 3265 3266 3267
            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)
3268
                code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3269
            self.rhs.generate_disposal_code(code)
3270
            self.rhs.free_temps(code)
3271 3272
        if self.dup.is_temp:
            self.dup.generate_subexpr_disposal_code(code)
3273
            self.dup.free_subexpr_temps(code)
3274 3275 3276 3277 3278 3279
            
    def create_dup_node(self, env): 
        import ExprNodes
        self.dup = self.lhs
        self.dup.analyse_types(env)
        if isinstance(self.lhs, ExprNodes.NameNode):
3280 3281 3282
            target_lhs = ExprNodes.NameNode(self.dup.pos,
                                            name = self.dup.name,
                                            is_temp = self.dup.is_temp,
3283
                                            entry = self.dup.entry)
3284
        elif isinstance(self.lhs, ExprNodes.AttributeNode):
3285 3286 3287
            target_lhs = ExprNodes.AttributeNode(self.dup.pos,
                                                 obj = ExprNodes.CloneNode(self.lhs.obj),
                                                 attribute = self.dup.attribute,
3288
                                                 is_temp = self.dup.is_temp)
3289
        elif isinstance(self.lhs, ExprNodes.IndexNode):
3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301
            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,
3302
                                             is_temp = self.dup.is_temp)
3303 3304
        else:
            assert False
3305
        self.lhs = target_lhs
3306
        return self.dup
3307 3308 3309 3310 3311
    
    def py_operation_function(self):
        return self.py_functions[self.operator]

    py_functions = {
Robert Bradshaw's avatar
Robert Bradshaw committed
3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323
        "|":        "PyNumber_InPlaceOr",
        "^":        "PyNumber_InPlaceXor",
        "&":        "PyNumber_InPlaceAnd",
        "+":        "PyNumber_InPlaceAdd",
        "-":        "PyNumber_InPlaceSubtract",
        "*":        "PyNumber_InPlaceMultiply",
        "/":        "PyNumber_InPlaceDivide",
        "%":        "PyNumber_InPlaceRemainder",
        "<<":        "PyNumber_InPlaceLshift",
        ">>":        "PyNumber_InPlaceRshift",
        "**":        "PyNumber_InPlacePower",
        "//":        "PyNumber_InPlaceFloorDivide",
3324 3325
    }

3326 3327 3328 3329 3330
    def annotate(self, code):
        self.lhs.annotate(code)
        self.rhs.annotate(code)
        self.dup.annotate(code)

William Stein's avatar
William Stein committed
3331 3332 3333 3334

class PrintStatNode(StatNode):
    #  print statement
    #
3335
    #  arg_tuple         TupleNode
3336
    #  append_newline    boolean
3337 3338 3339

    child_attrs = ["arg_tuple"]

William Stein's avatar
William Stein committed
3340
    def analyse_expressions(self, env):
3341
        self.arg_tuple.analyse_expressions(env)
3342 3343
        self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
        self.arg_tuple.release_temp(env)
3344
        env.use_utility_code(printing_utility_code)
3345 3346
        if len(self.arg_tuple.args) == 1 and self.append_newline:
            env.use_utility_code(printing_one_utility_code)
3347 3348 3349
        self.gil_check(env)

    gil_message = "Python print statement"
3350

William Stein's avatar
William Stein committed
3351
    def generate_execution_code(self, code):
3352 3353 3354
        if len(self.arg_tuple.args) == 1 and self.append_newline:
            arg = self.arg_tuple.args[0]
            arg.generate_evaluation_code(code)
3355
            
3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370
            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)
3371

3372
    def annotate(self, code):
3373
        self.arg_tuple.annotate(code)
William Stein's avatar
William Stein committed
3374 3375


3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405
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)
3406
            arg.free_temps(code)
3407 3408
        code.putln(
            code.error_goto_if_null(self.temp_result, self.pos))
3409
        code.put_gotref(self.temp_result)
3410 3411 3412 3413 3414 3415 3416
        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
3417 3418 3419 3420 3421
class DelStatNode(StatNode):
    #  del statement
    #
    #  args     [ExprNode]
    
3422 3423
    child_attrs = ["args"]

William Stein's avatar
William Stein committed
3424 3425 3426 3427 3428 3429
    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:
3430
            arg.analyse_target_expression(env, None)
Robert Bradshaw's avatar
Robert Bradshaw committed
3431
            if arg.type.is_pyobject:
3432
                self.gil_check(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
3433 3434
            elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
                pass
3435
            elif arg.type.is_cpp_class:
Robert Bradshaw's avatar
merge  
Robert Bradshaw committed
3436
                error(arg.pos, "Deletion of non-heap C++ object")
3437
            else:
Robert Bradshaw's avatar
Robert Bradshaw committed
3438
                error(arg.pos, "Deletion of non-Python, non-C++ object")
3439
            #arg.release_target_temp(env)
3440 3441 3442

    gil_message = "Deleting Python object"

William Stein's avatar
William Stein committed
3443 3444 3445 3446
    def generate_execution_code(self, code):
        for arg in self.args:
            if arg.type.is_pyobject:
                arg.generate_deletion_code(code)
3447
            elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
Robert Bradshaw's avatar
Robert Bradshaw committed
3448
                arg.generate_result_code(code)
Robert Bradshaw's avatar
merge  
Robert Bradshaw committed
3449
                code.putln("delete %s;" % arg.result())
William Stein's avatar
William Stein committed
3450 3451
            # else error reported earlier

3452 3453 3454 3455
    def annotate(self, code):
        for arg in self.args:
            arg.annotate(code)

William Stein's avatar
William Stein committed
3456 3457 3458

class PassStatNode(StatNode):
    #  pass statement
3459 3460

    child_attrs = []
William Stein's avatar
William Stein committed
3461 3462 3463 3464 3465 3466 3467 3468 3469 3470
    
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        pass


class BreakStatNode(StatNode):

3471 3472
    child_attrs = []

William Stein's avatar
William Stein committed
3473 3474 3475 3476 3477 3478 3479
    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:
3480
            code.put_goto(code.break_label)
William Stein's avatar
William Stein committed
3481 3482 3483 3484


class ContinueStatNode(StatNode):

3485 3486
    child_attrs = []

William Stein's avatar
William Stein committed
3487 3488 3489 3490
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
3491
        if code.funcstate.in_try_finally:
William Stein's avatar
William Stein committed
3492 3493 3494 3495
            error(self.pos, "continue statement inside try of try...finally")
        elif not code.continue_label:
            error(self.pos, "continue statement not inside loop")
        else:
3496
            code.put_goto(code.continue_label)
William Stein's avatar
William Stein committed
3497 3498 3499 3500 3501 3502 3503 3504 3505


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

William Stein's avatar
William Stein committed
3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528
    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")
3529 3530 3531 3532 3533
        if return_type.is_pyobject:
            self.gil_check(env)

    gil_message = "Returning Python object"

William Stein's avatar
William Stein committed
3534
    def generate_execution_code(self, code):
3535
        code.mark_pos(self.pos)
William Stein's avatar
William Stein committed
3536 3537 3538
        if not self.return_type:
            # error reported earlier
            return
3539 3540 3541
        if self.return_type.is_pyobject:
            code.put_xdecref(Naming.retval_cname,
                             self.return_type)
William Stein's avatar
William Stein committed
3542 3543 3544 3545 3546 3547 3548 3549
        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)
3550
            self.value.free_temps(code)
William Stein's avatar
William Stein committed
3551 3552 3553 3554 3555 3556 3557 3558
        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))
3559
        # free temps the old way
3560 3561
        for entry in self.temps_in_use:
            code.put_var_decref_clear(entry)
3562
        # free temps the new way
3563
        for cname, type in code.funcstate.temps_holding_reference():
3564
            code.put_decref_clear(cname, type)
3565
        #code.putln(
3566 3567
        #    "goto %s;" %
        #        code.return_label)
3568
        code.put_goto(code.return_label)
3569 3570 3571 3572
        
    def annotate(self, code):
        if self.value:
            self.value.annotate(code)
William Stein's avatar
William Stein committed
3573 3574 3575 3576 3577 3578 3579 3580 3581


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

William Stein's avatar
William Stein committed
3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602
    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)
3603
        env.use_utility_code(raise_utility_code)
3604
        env.use_utility_code(restore_exception_utility_code)
3605 3606 3607 3608
        self.gil_check(env)

    gil_message = "Raising exception"

William Stein's avatar
William Stein committed
3609 3610 3611 3612 3613
    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
3614
            type_code = "0"
William Stein's avatar
William Stein committed
3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633
        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();")
3634 3635 3636 3637
        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
3638 3639 3640
        code.putln(
            code.error_goto(self.pos))

3641 3642 3643 3644 3645 3646 3647 3648
    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
3649

3650 3651
class ReraiseStatNode(StatNode):

3652 3653
    child_attrs = []

3654
    def analyse_expressions(self, env):
3655
        self.gil_check(env)
3656
        env.use_utility_code(raise_utility_code)
3657
        env.use_utility_code(restore_exception_utility_code)
3658

3659 3660
    gil_message = "Raising exception"

3661
    def generate_execution_code(self, code):
3662
        vars = code.funcstate.exc_vars
3663 3664 3665 3666 3667 3668 3669
        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
3670 3671 3672 3673 3674 3675
class AssertStatNode(StatNode):
    #  assert statement
    #
    #  cond    ExprNode
    #  value   ExprNode or None
    
3676 3677
    child_attrs = ["cond", "value"]

William Stein's avatar
William Stein committed
3678 3679 3680 3681 3682 3683 3684 3685 3686
    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)
3687
        self.gil_check(env)
William Stein's avatar
William Stein committed
3688
        #env.recycle_pending_temps() # TEMPORARY
3689 3690

    gil_message = "Raising exception"
William Stein's avatar
William Stein committed
3691 3692
    
    def generate_execution_code(self, code):
3693
        code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
William Stein's avatar
William Stein committed
3694 3695
        self.cond.generate_evaluation_code(code)
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3696
            "if (unlikely(!%s)) {" %
3697
                self.cond.result())
William Stein's avatar
William Stein committed
3698
        if self.value:
3699
            self.value.generate_evaluation_code(code)
William Stein's avatar
William Stein committed
3700 3701 3702
            code.putln(
                "PyErr_SetObject(PyExc_AssertionError, %s);" %
                    self.value.py_result())
3703
            self.value.generate_disposal_code(code)
3704
            self.value.free_temps(code)
William Stein's avatar
William Stein committed
3705 3706 3707 3708 3709 3710 3711 3712
        else:
            code.putln(
                "PyErr_SetNone(PyExc_AssertionError);")
        code.putln(
                code.error_goto(self.pos))
        code.putln(
            "}")
        self.cond.generate_disposal_code(code)
3713
        self.cond.free_temps(code)
3714
        code.putln("#endif")
William Stein's avatar
William Stein committed
3715

3716 3717 3718 3719 3720 3721
    def annotate(self, code):
        self.cond.annotate(code)
        if self.value:
            self.value.annotate(code)


William Stein's avatar
William Stein committed
3722 3723 3724 3725 3726
class IfStatNode(StatNode):
    #  if statement
    #
    #  if_clauses   [IfClauseNode]
    #  else_clause  StatNode or None
3727 3728

    child_attrs = ["if_clauses", "else_clause"]
William Stein's avatar
William Stein committed
3729
    
3730 3731 3732 3733 3734 3735 3736 3737 3738
    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
3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751
    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):
3752
        code.mark_pos(self.pos)
William Stein's avatar
William Stein committed
3753 3754 3755 3756 3757 3758 3759 3760
        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)
3761 3762 3763 3764 3765 3766
        
    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
3767 3768 3769 3770 3771 3772 3773 3774


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

3777 3778 3779
    def analyse_control_flow(self, env):
        self.body.analyse_control_flow(env)
        
William Stein's avatar
William Stein committed
3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793
    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) {" %
3794
                self.condition.result())
3795 3796
        self.condition.generate_disposal_code(code)
        self.condition.free_temps(code)
William Stein's avatar
William Stein committed
3797
        self.body.generate_execution_code(code)
3798
        #code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3799 3800
        #    "goto %s;" %
        #        end_label)
3801
        code.put_goto(end_label)
William Stein's avatar
William Stein committed
3802
        code.putln("}")
3803 3804 3805 3806

    def annotate(self, code):
        self.condition.annotate(code)
        self.body.annotate(code)
William Stein's avatar
William Stein committed
3807
        
3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818

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:
3819
            code.mark_pos(cond.pos)
3820 3821 3822
            code.putln("case %s:" % cond.calculate_result_code())
        self.body.generate_execution_code(code)
        code.putln("break;")
3823
        
3824 3825 3826
    def annotate(self, code):
        for cond in self.conditions:
            cond.annotate(code)
3827
        self.body.annotate(code)
3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844

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)
3845
            code.putln("break;")
3846 3847 3848 3849 3850 3851
        code.putln("}")

    def annotate(self, code):
        self.test.annotate(code)
        for case in self.cases:
            case.annotate(code)
3852 3853
        if self.else_clause is not None:
            self.else_clause.annotate(code)
3854
            
3855
class LoopNode(object):
3856 3857 3858 3859 3860 3861 3862 3863 3864
    
    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
3865
    
3866
class WhileStatNode(LoopNode, StatNode):
William Stein's avatar
William Stein committed
3867 3868 3869 3870 3871
    #  while statement
    #
    #  condition    ExprNode
    #  body         StatNode
    #  else_clause  StatNode
3872 3873

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

William Stein's avatar
William Stein committed
3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893
    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)
3894
        self.condition.generate_disposal_code(code)
William Stein's avatar
William Stein committed
3895 3896
        code.putln(
            "if (!%s) break;" %
3897
                self.condition.result())
3898
        self.condition.free_temps(code)
William Stein's avatar
William Stein committed
3899
        self.body.generate_execution_code(code)
3900
        code.put_label(code.continue_label)
William Stein's avatar
William Stein committed
3901 3902 3903 3904 3905 3906 3907 3908 3909
        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)

3910 3911 3912 3913 3914 3915
    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
3916

Robert Bradshaw's avatar
Robert Bradshaw committed
3917
def ForStatNode(pos, **kw):
3918
    if 'iterator' in kw:
Robert Bradshaw's avatar
Robert Bradshaw committed
3919 3920 3921 3922
        return ForInStatNode(pos, **kw)
    else:
        return ForFromStatNode(pos, **kw)

3923
class ForInStatNode(LoopNode, StatNode):
William Stein's avatar
William Stein committed
3924 3925 3926 3927 3928 3929 3930 3931
    #  for statement
    #
    #  target        ExprNode
    #  iterator      IteratorNode
    #  body          StatNode
    #  else_clause   StatNode
    #  item          NextNode       used internally
    
3932
    child_attrs = ["target", "iterator", "body", "else_clause"]
3933
    item = None
3934
    
William Stein's avatar
William Stein committed
3935 3936 3937 3938 3939
    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)
3940

William Stein's avatar
William Stein committed
3941 3942 3943
    def analyse_expressions(self, env):
        import ExprNodes
        self.target.analyse_target_types(env)
3944
        self.iterator.analyse_expressions(env)
William Stein's avatar
William Stein committed
3945 3946 3947
        self.item = ExprNodes.NextNode(self.iterator, env)
        self.item = self.item.coerce_to(self.target.type, env)
        self.item.allocate_temps(env)
3948 3949 3950
        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
3951 3952 3953 3954 3955 3956 3957
        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()
3958
        self.iterator.allocate_counter_temp(code)
William Stein's avatar
William Stein committed
3959 3960 3961 3962 3963 3964
        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)
3965
        code.put_label(code.continue_label)
William Stein's avatar
William Stein committed
3966 3967 3968 3969 3970 3971 3972 3973 3974
        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)
3975
        self.iterator.release_counter_temp(code)
William Stein's avatar
William Stein committed
3976
        self.iterator.generate_disposal_code(code)
3977
        self.iterator.free_temps(code)
William Stein's avatar
William Stein committed
3978

3979 3980 3981 3982 3983 3984 3985 3986
    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
3987

3988
class ForFromStatNode(LoopNode, StatNode):
William Stein's avatar
William Stein committed
3989 3990 3991 3992 3993 3994 3995
    #  for name from expr rel name rel expr
    #
    #  target        NameNode
    #  bound1        ExprNode
    #  relation1     string
    #  relation2     string
    #  bound2        ExprNode
3996
    #  step          ExprNode or None
William Stein's avatar
William Stein committed
3997 3998 3999 4000 4001
    #  body          StatNode
    #  else_clause   StatNode or None
    #
    #  Used internally:
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
4002
    #  from_range         bool
4003
    #  is_py_target       bool
4004
    #  loopvar_node       ExprNode (usually a NameNode or temp node)
William Stein's avatar
William Stein committed
4005
    #  py_loopvar_node    PyTempNode or None
4006
    child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
4007 4008

    is_py_target = False
4009
    loopvar_node = None
4010
    py_loopvar_node = None
Robert Bradshaw's avatar
Robert Bradshaw committed
4011
    from_range = False
4012

Robert Bradshaw's avatar
Robert Bradshaw committed
4013 4014 4015 4016 4017
    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)
4018

William Stein's avatar
William Stein committed
4019 4020 4021 4022 4023
    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
4024 4025 4026 4027 4028 4029
        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
4030
        if self.target.type.is_numeric:
Robert Bradshaw's avatar
Robert Bradshaw committed
4031
            loop_type = self.target.type
4032
        else:
Robert Bradshaw's avatar
Robert Bradshaw committed
4033 4034 4035 4036 4037 4038 4039 4040 4041
            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
4042 4043
        if not self.bound2.is_literal:
            self.bound2 = self.bound2.coerce_to_temp(env)
4044
        if self.step is not None:
Robert Bradshaw's avatar
Robert Bradshaw committed
4045
            self.step = self.step.coerce_to(loop_type, env)            
Robert Bradshaw's avatar
Robert Bradshaw committed
4046 4047
            if not self.step.is_literal:
                self.step = self.step.coerce_to_temp(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
4048

William Stein's avatar
William Stein committed
4049
        target_type = self.target.type
4050
        if not (target_type.is_pyobject or target_type.is_numeric):
4051
            error(self.target.pos,
Robert Bradshaw's avatar
Robert Bradshaw committed
4052
                "for-from loop variable must be c numeric type or Python object")
4053
        if target_type.is_numeric:
Robert Bradshaw's avatar
Robert Bradshaw committed
4054
            self.is_py_target = False
4055 4056
            if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
                raise error(self.pos, "Buffer indexing not allowed as for loop target.")
4057
            self.loopvar_node = self.target
William Stein's avatar
William Stein committed
4058 4059
            self.py_loopvar_node = None
        else:
Robert Bradshaw's avatar
Robert Bradshaw committed
4060 4061
            self.is_py_target = True
            c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
William Stein's avatar
William Stein committed
4062
            c_loopvar_node.allocate_temps(env)
4063
            self.loopvar_node = c_loopvar_node
William Stein's avatar
William Stein committed
4064 4065 4066 4067
            self.py_loopvar_node = \
                ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
        self.bound1.allocate_temps(env)
        self.bound2.allocate_temps(env)
4068 4069
        if self.step is not None:
            self.step.allocate_temps(env)
4070
        if self.is_py_target:
William Stein's avatar
William Stein committed
4071
            self.py_loopvar_node.allocate_temps(env)
4072 4073 4074
            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
4075
        self.body.analyse_expressions(env)
4076
        if self.is_py_target:
William Stein's avatar
William Stein committed
4077 4078 4079 4080 4081
            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)
4082 4083
        if self.step is not None:
            self.step.release_temp(env)
William Stein's avatar
William Stein committed
4084 4085 4086
            
    def generate_execution_code(self, code):
        old_loop_labels = code.new_loop_labels()
Robert Bradshaw's avatar
Robert Bradshaw committed
4087
        from_range = self.from_range
William Stein's avatar
William Stein committed
4088 4089 4090
        self.bound1.generate_evaluation_code(code)
        self.bound2.generate_evaluation_code(code)
        offset, incop = self.relation_table[self.relation1]
4091 4092
        if self.step is not None:
            self.step.generate_evaluation_code(code)
Magnus Lie Hetland's avatar
Magnus Lie Hetland committed
4093 4094
            step = self.step.result()
            incop = "%s=%s" % (incop[0], step)
4095
        if from_range:
Robert Bradshaw's avatar
Robert Bradshaw committed
4096
            loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
4097
        else:
Robert Bradshaw's avatar
Robert Bradshaw committed
4098
            loopvar_name = self.loopvar_node.result()
4099 4100 4101 4102
        code.putln(
            "for (%s = %s%s; %s %s %s; %s%s) {" % (
                loopvar_name,
                self.bound1.result(), offset,
Robert Bradshaw's avatar
Robert Bradshaw committed
4103
                loopvar_name, self.relation2, self.bound2.result(),
4104
                loopvar_name, incop))
William Stein's avatar
William Stein committed
4105 4106 4107
        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
4108 4109 4110
        elif from_range:
            code.putln("%s = %s;" % (
                            self.target.result(), loopvar_name))
William Stein's avatar
William Stein committed
4111 4112
        self.body.generate_execution_code(code)
        code.put_label(code.continue_label)
Robert Bradshaw's avatar
Robert Bradshaw committed
4113
        if self.py_loopvar_node:
4114 4115 4116
            # 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. 
4117
            import ExprNodes
4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130
            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)
4131 4132
            from_py_node.temp_code = loopvar_name
            from_py_node.generate_result_code(code)
4133 4134 4135
            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
4136
        code.putln("}")
4137 4138 4139 4140 4141
        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
4142 4143 4144 4145 4146 4147 4148 4149
        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)
4150
        self.bound1.free_temps(code)
William Stein's avatar
William Stein committed
4151
        self.bound2.generate_disposal_code(code)
4152
        self.bound2.free_temps(code)
4153 4154
        if self.step is not None:
            self.step.generate_disposal_code(code)
4155
            self.step.free_temps(code)
Robert Bradshaw's avatar
Robert Bradshaw committed
4156 4157
        if from_range:
            code.funcstate.release_temp(loopvar_name)
William Stein's avatar
William Stein committed
4158 4159 4160 4161 4162 4163 4164 4165
    
    relation_table = {
        # {relop : (initial offset, increment op)}
        '<=': ("",   "++"),
        '<' : ("+1", "++"),
        '>=': ("",   "--"),
        '>' : ("-1", "--")
    }
4166 4167 4168 4169 4170 4171 4172 4173 4174 4175
    
    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
4176 4177


4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189
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
4190 4191 4192 4193 4194 4195
class TryExceptStatNode(StatNode):
    #  try .. except statement
    #
    #  body             StatNode
    #  except_clauses   [ExceptClauseNode]
    #  else_clause      StatNode or None
4196
    #  cleanup_list     [Entry]            old style temps to clean up on error
4197

4198
    child_attrs = ["body", "except_clauses", "else_clause"]
William Stein's avatar
William Stein committed
4199
    
4200 4201 4202
    def analyse_control_flow(self, env):
        env.start_branching(self.pos)
        self.body.analyse_control_flow(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
4203 4204 4205 4206 4207
        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)
4208 4209
        for except_clause in self.except_clauses:
            except_clause.analyse_control_flow(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
4210 4211 4212 4213
            env.next_branch(except_clause.end_pos())
            
        # the else cause it executed only when the try clause finishes
        env.control_flow.incoming = successful_try
4214 4215 4216 4217
        if self.else_clause:
            self.else_clause.analyse_control_flow(env)
        env.finish_branching(self.end_pos())

William Stein's avatar
William Stein committed
4218 4219 4220 4221 4222 4223
    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)
4224
        self.gil_check(env)
4225
        env.use_utility_code(reset_exception_utility_code)
William Stein's avatar
William Stein committed
4226 4227 4228 4229
    
    def analyse_expressions(self, env):
        self.body.analyse_expressions(env)
        self.cleanup_list = env.free_temp_entries[:]
4230
        default_clause_seen = 0
William Stein's avatar
William Stein committed
4231 4232
        for except_clause in self.except_clauses:
            except_clause.analyse_expressions(env)
4233 4234 4235 4236 4237
            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
4238 4239
        if self.else_clause:
            self.else_clause.analyse_expressions(env)
4240 4241 4242 4243
        self.gil_check(env)

    gil_message = "Try-except statement"

William Stein's avatar
William Stein committed
4244
    def generate_execution_code(self, code):
4245
        old_return_label = code.return_label
4246
        old_break_label = code.break_label
4247
        old_continue_label = code.continue_label
William Stein's avatar
William Stein committed
4248 4249
        old_error_label = code.new_error_label()
        our_error_label = code.error_label
4250 4251 4252
        except_end_label = code.new_label('exception_handled')
        except_error_label = code.new_label('except_error')
        except_return_label = code.new_label('except_return')
4253
        try_return_label = code.new_label('try_return')
4254
        try_break_label = code.new_label('try_break')
4255
        try_continue_label = code.new_label('try_continue')
4256
        try_end_label = code.new_label('try_end')
4257 4258 4259 4260 4261 4262

        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
4263 4264
        for var in Naming.exc_save_vars:
            code.put_xgotref(var)
William Stein's avatar
William Stein committed
4265 4266
        code.putln(
            "/*try:*/ {")
4267
        code.return_label = try_return_label
4268
        code.break_label = try_break_label
4269
        code.continue_label = try_continue_label
William Stein's avatar
William Stein committed
4270 4271 4272
        self.body.generate_execution_code(code)
        code.putln(
            "}")
4273
        temps_to_clean_up = code.funcstate.all_free_managed_temps()
4274 4275
        code.error_label = except_error_label
        code.return_label = except_return_label
William Stein's avatar
William Stein committed
4276 4277 4278 4279 4280 4281
        if self.else_clause:
            code.putln(
                "/*else:*/ {")
            self.else_clause.generate_execution_code(code)
            code.putln(
                "}")
4282 4283
        for var in Naming.exc_save_vars:
            code.put_xdecref_clear(var, py_object_type)
4284
        code.put_goto(try_end_label)
4285 4286 4287 4288 4289
        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
4290 4291
        code.put_label(our_error_label)
        code.put_var_xdecrefs_clear(self.cleanup_list)
4292 4293
        for temp_name, type in temps_to_clean_up:
            code.put_xdecref_clear(temp_name, type)
William Stein's avatar
William Stein committed
4294
        for except_clause in self.except_clauses:
4295 4296
            except_clause.generate_handling_code(code, except_end_label)

4297 4298 4299 4300
        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)
4301 4302 4303
            for var in Naming.exc_save_vars:
                code.put_xdecref(var, py_object_type)
            code.put_goto(old_error_label)
4304 4305 4306 4307 4308 4309 4310
            
        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)
4311 4312 4313 4314 4315 4316 4317
            
        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)
4318 4319 4320

        if code.label_used(except_return_label):
            code.put_label(except_return_label)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
4321
            for var in Naming.exc_save_vars: code.put_xgiveref(var)
4322 4323 4324 4325 4326 4327
            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
4328
            for var in Naming.exc_save_vars: code.put_xgiveref(var)
4329 4330 4331 4332 4333 4334
            code.putln("__Pyx_ExceptionReset(%s);" %
                       ', '.join(Naming.exc_save_vars))
        code.put_label(try_end_label)
        code.putln("}")

        code.return_label = old_return_label
4335
        code.break_label = old_break_label
4336
        code.continue_label = old_continue_label
4337
        code.error_label = old_error_label
William Stein's avatar
William Stein committed
4338

4339 4340 4341 4342 4343 4344 4345
    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
4346 4347 4348 4349 4350 4351 4352

class ExceptClauseNode(Node):
    #  Part of try ... except statement.
    #
    #  pattern        ExprNode
    #  target         ExprNode or None
    #  body           StatNode
4353
    #  excinfo_target NameNode or None   optional target for exception info
William Stein's avatar
William Stein committed
4354 4355 4356
    #  match_flag     string             result of exception match
    #  exc_value      ExcValueNode       used internally
    #  function_name  string             qualified name of enclosing function
4357
    #  exc_vars       (string * 3)       local exception variables
4358 4359 4360 4361

    # 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
4362
    
4363
    child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4364

4365
    exc_value = None
4366
    excinfo_target = None
4367

William Stein's avatar
William Stein committed
4368 4369 4370
    def analyse_declarations(self, env):
        if self.target:
            self.target.analyse_target_declaration(env)
4371 4372
        if self.excinfo_target is not None:
            self.excinfo_target.analyse_target_declaration(env)
William Stein's avatar
William Stein committed
4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384
        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)
4385

4386
        if self.target or self.excinfo_target:
4387 4388
            self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
        else:
4389
            self.exc_vars = None
4390

William Stein's avatar
William Stein committed
4391
        if self.target:
4392 4393
            self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
            self.exc_value.allocate_temps(env)
4394
            self.target.analyse_target_expression(env, self.exc_value)
4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405
        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
4406
        self.body.analyse_expressions(env)
4407 4408 4409 4410

        if self.exc_vars:
            for var in self.exc_vars:
                env.release_temp(var)
William Stein's avatar
William Stein committed
4411 4412 4413 4414 4415 4416 4417 4418 4419 4420
    
    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)
4421
            self.pattern.free_temps(code)
William Stein's avatar
William Stein committed
4422 4423 4424 4425
            code.putln(
                "if (%s) {" %
                    self.match_flag)
        else:
4426
            code.putln("/*except:*/ {")
4427

Stefan Behnel's avatar
Stefan Behnel committed
4428 4429 4430 4431 4432
        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
4433 4434 4435 4436
            code.putln("PyErr_Restore(0,0,0);")
            code.put_goto(end_label)
            code.putln("}")
            return
4437
        else:
Stefan Behnel's avatar
Stefan Behnel committed
4438 4439
            # during type analysis, we didn't know if we need the
            # exception value, but apparently, we do
4440 4441 4442 4443
            exc_vars = [code.funcstate.allocate_temp(py_object_type,
                                                     manage_ref=True)
                        for i in xrange(3)]

4444
        code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
William Stein's avatar
William Stein committed
4445 4446 4447
        # 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.
4448 4449
        code.globalstate.use_utility_code(get_exception_utility_code)
        exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4450 4451
        code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
            code.error_goto(self.pos)))
4452
        for x in exc_vars:
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
4453
            code.put_gotref(x)
William Stein's avatar
William Stein committed
4454
        if self.target:
4455
            self.exc_value.generate_evaluation_code(code)
William Stein's avatar
William Stein committed
4456
            self.target.generate_assignment_code(self.exc_value, code)
4457 4458 4459 4460
        if self.excinfo_target is not None:
            self.excinfo_tuple.generate_evaluation_code(code)
            self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)

4461 4462 4463 4464 4465

        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')

4466
        old_exc_vars = code.funcstate.exc_vars
4467
        code.funcstate.exc_vars = exc_vars
William Stein's avatar
William Stein committed
4468
        self.body.generate_execution_code(code)
4469
        code.funcstate.exc_vars = old_exc_vars
4470
        for var in exc_vars:
4471
            code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4472
        code.put_goto(end_label)
Robert Bradshaw's avatar
Robert Bradshaw committed
4473 4474 4475
        
        if code.label_used(code.break_label):
            code.put_label(code.break_label)
4476
            for var in exc_vars:
Robert Bradshaw's avatar
Robert Bradshaw committed
4477 4478 4479
                code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
            code.put_goto(old_break_label)
        code.break_label = old_break_label
4480 4481 4482

        if code.label_used(code.continue_label):
            code.put_label(code.continue_label)
4483
            for var in exc_vars:
4484 4485 4486
                code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
            code.put_goto(old_continue_label)
        code.continue_label = old_continue_label
4487 4488 4489 4490 4491 4492

        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
4493 4494 4495
        code.putln(
            "}")

4496
    def annotate(self, code):
4497 4498
        if self.pattern:
            self.pattern.annotate(code)
4499 4500 4501 4502
        if self.target:
            self.target.annotate(code)
        self.body.annotate(code)

William Stein's avatar
William Stein committed
4503 4504 4505 4506 4507 4508

class TryFinallyStatNode(StatNode):
    #  try ... finally statement
    #
    #  body             StatNode
    #  finally_clause   StatNode
4509
    #
4510
    #  cleanup_list     [Entry]     old_style temps to clean up on error
William Stein's avatar
William Stein committed
4511 4512 4513 4514 4515 4516 4517 4518 4519
    #
    #  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.
4520

4521
    child_attrs = ["body", "finally_clause"]
William Stein's avatar
William Stein committed
4522
    
4523 4524
    preserve_exception = 1
    
William Stein's avatar
William Stein committed
4525 4526 4527 4528
    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.
4529 4530 4531 4532 4533 4534

    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
4535
    
4536 4537 4538 4539
    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
4540
        env.finish_branching(self.body.end_pos())
4541 4542
        self.finally_clause.analyse_control_flow(env)

William Stein's avatar
William Stein committed
4543 4544 4545 4546 4547 4548 4549 4550
    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)
4551 4552 4553 4554
        self.gil_check(env)

    gil_message = "Try-finally statement"

William Stein's avatar
William Stein committed
4555 4556 4557 4558 4559 4560 4561 4562 4563
    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:
4564 4565
            was_in_try_finally = code.funcstate.in_try_finally
            code.funcstate.in_try_finally = 1
William Stein's avatar
William Stein committed
4566 4567
        self.body.generate_execution_code(code)
        if self.disallow_continue_in_try_finally:
4568
            code.funcstate.in_try_finally = was_in_try_finally
William Stein's avatar
William Stein committed
4569 4570
        code.putln(
            "}")
4571
        temps_to_clean_up = code.funcstate.all_free_managed_temps()
William Stein's avatar
William Stein committed
4572 4573
        code.putln(
            "/*finally:*/ {")
4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589
        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)
4590 4591 4592 4593 4594
                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
4595 4596 4597 4598 4599
            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
4600
                #if new_label and new_label != "<try>":
4601 4602
                if new_label == new_error_label and self.preserve_exception:
                    self.put_error_catcher(code, 
4603
                        new_error_label, i+1, catch_label, temps_to_clean_up)
4604
                else:
4605 4606 4607 4608
                    code.put('%s: ' % new_label)
                    if exc_var_init_zero:
                        code.putln(exc_var_init_zero)
                    code.putln("__pyx_why = %s; goto %s;" % (
4609 4610 4611
                            i+1,
                            catch_label))
            code.put_label(catch_label)
William Stein's avatar
William Stein committed
4612
        code.set_all_labels(old_labels)
4613 4614 4615
        if error_label_used:
            code.new_error_label()
            finally_error_label = code.error_label
William Stein's avatar
William Stein committed
4616
        self.finally_clause.generate_execution_code(code)
4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630
        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
4631
                "switch (__pyx_why) {")
4632 4633 4634
            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
4635 4636
                    self.put_error_uncatcher(code, i+1, old_error_label)
                else:
4637
                    code.use_label(old_label)
William Stein's avatar
William Stein committed
4638 4639 4640
                    code.putln(
                        "case %s: goto %s;" % (
                            i+1,
4641 4642
                            old_label))
            code.putln(
4643
                "}")
William Stein's avatar
William Stein committed
4644 4645 4646
        code.putln(
            "}")

4647
    def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4648
        code.globalstate.use_utility_code(restore_exception_utility_code)
William Stein's avatar
William Stein committed
4649 4650 4651 4652 4653 4654 4655
        code.putln(
            "%s: {" %
                error_label)
        code.putln(
                "__pyx_why = %s;" %
                    i)
        code.put_var_xdecrefs_clear(self.cleanup_list)
4656 4657
        for temp_name, type in temps_to_clean_up:
            code.put_xdecref_clear(temp_name, type)
William Stein's avatar
William Stein committed
4658
        code.putln(
4659
                "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4660
                    Naming.exc_vars)
William Stein's avatar
William Stein committed
4661 4662
        code.putln(
                "%s = %s;" % (
4663
                    Naming.exc_lineno_name, Naming.lineno_cname))
4664
        #code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
4665 4666
        #        "goto %s;" %
        #            catch_label)
4667
        code.put_goto(catch_label)
William Stein's avatar
William Stein committed
4668 4669 4670 4671
        code.putln(
            "}")
            
    def put_error_uncatcher(self, code, i, error_label):
4672
        code.globalstate.use_utility_code(restore_exception_utility_code)
William Stein's avatar
William Stein committed
4673 4674 4675 4676
        code.putln(
            "case %s: {" %
                i)
        code.putln(
4677
                "__Pyx_ErrRestore(%s, %s, %s);" %
4678
                    Naming.exc_vars)
William Stein's avatar
William Stein committed
4679 4680
        code.putln(
                "%s = %s;" % (
4681 4682
                    Naming.lineno_cname, Naming.exc_lineno_name))
        for var in Naming.exc_vars:
William Stein's avatar
William Stein committed
4683 4684 4685
            code.putln(
                "%s = 0;" %
                    var)
4686
        code.put_goto(error_label)
William Stein's avatar
William Stein committed
4687 4688 4689
        code.putln(
            "}")

4690 4691 4692 4693
    def annotate(self, code):
        self.body.annotate(code)
        self.finally_clause.annotate(code)

William Stein's avatar
William Stein committed
4694

4695 4696 4697 4698 4699
class GILStatNode(TryFinallyStatNode):
    #  'with gil' or 'with nogil' statement
    #
    #   state   string   'gil' or 'nogil'
        
4700 4701
    child_attrs = []
    
4702 4703 4704 4705 4706 4707 4708 4709
    preserve_exception = 0

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

4710
    def analyse_expressions(self, env):
Stefan Behnel's avatar
Stefan Behnel committed
4711
        env.use_utility_code(force_init_threads_utility_code)
4712 4713 4714 4715 4716 4717 4718 4719
        was_nogil = env.nogil
        env.nogil = 1
        TryFinallyStatNode.analyse_expressions(self, env)
        env.nogil = was_nogil

    def gil_check(self, env):
        pass

4720
    def generate_execution_code(self, code):
Stefan Behnel's avatar
Stefan Behnel committed
4721
        code.mark_pos(self.pos)
4722
        if self.state == 'gil':
Stefan Behnel's avatar
Stefan Behnel committed
4723
            code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4724
        else:
Stefan Behnel's avatar
Stefan Behnel committed
4725
            code.putln("{ PyThreadState *_save;")
4726 4727 4728 4729 4730 4731 4732 4733 4734 4735
            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'

4736 4737
    child_attrs = []

4738 4739 4740 4741 4742 4743 4744 4745 4746 4747
    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
4748 4749 4750 4751 4752
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
4753 4754

    child_attrs = []
William Stein's avatar
William Stein committed
4755 4756
    
    def analyse_declarations(self, env):
4757 4758 4759
        if not env.is_module_scope:
            error(self.pos, "cimport only allowed at module level")
            return
William Stein's avatar
William Stein committed
4760 4761
        module_scope = env.find_module(self.module_name, self.pos)
        if "." in self.module_name:
4762
            names = [EncodedString(name) for name in self.module_name.split(".")]
William Stein's avatar
William Stein committed
4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787
            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
    #
4788 4789
    #  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
4790
    
4791 4792
    child_attrs = []

William Stein's avatar
William Stein committed
4793
    def analyse_declarations(self, env):
4794 4795 4796
        if not env.is_module_scope:
            error(self.pos, "cimport only allowed at module level")
            return
William Stein's avatar
William Stein committed
4797 4798
        module_scope = env.find_module(self.module_name, self.pos)
        env.add_imported_module(module_scope)
4799
        for pos, name, as_name, kind in self.imported_names:
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4800 4801 4802 4803
            if name == "*":
                for local_name, entry in module_scope.entries.items():
                    env.add_imported_entry(local_name, entry, pos)
            else:
4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815
                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:
4816 4817 4818 4819 4820 4821
                        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))
4822
                        
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4823 4824 4825
                if entry:
                    local_name = as_name or name
                    env.add_imported_entry(local_name, entry, pos)
4826 4827
    
    def declaration_matches(self, entry, kind):
4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839
        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
4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852

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


class FromImportStatNode(StatNode):
    #  from ... import statement
    #
    #  module           ImportNode
    #  items            [(string, NameNode)]
4853
    #  interned_items   [(string, NameNode, ExprNode)]
William Stein's avatar
William Stein committed
4854
    #  item             PyTempNode            used internally
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4855
    #  import_star      boolean               used internally
4856 4857

    child_attrs = ["module"]
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4858
    import_star = 0
William Stein's avatar
William Stein committed
4859 4860
    
    def analyse_declarations(self, env):
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4861 4862 4863 4864 4865 4866 4867 4868 4869
        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
4870 4871 4872 4873 4874 4875 4876 4877
    
    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
4878 4879 4880 4881 4882 4883
            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:
4884 4885 4886
                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
4887
                target.analyse_target_expression(env, None)
4888 4889 4890 4891 4892 4893
                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
4894
                #target.release_target_temp(env) # was release_temp ?!?
William Stein's avatar
William Stein committed
4895 4896 4897 4898 4899
        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
4900 4901 4902 4903 4904 4905
        if self.import_star:
            code.putln(
                'if (%s(%s) < 0) %s;' % (
                    Naming.import_star,
                    self.module.py_result(),
                    code.error_goto(self.pos)))
4906
        for cname, target, coerced_item in self.interned_items:
4907 4908
            code.putln(
                '%s = PyObject_GetAttr(%s, %s); %s' % (
4909
                    self.item.result(), 
4910 4911
                    self.module.py_result(),
                    cname,
4912
                    code.error_goto_if_null(self.item.result(), self.pos)))
4913
            code.put_gotref(self.item.py_result())
4914 4915 4916 4917 4918 4919 4920 4921
            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
4922
        self.module.generate_disposal_code(code)
4923
        self.module.free_temps(code)
William Stein's avatar
William Stein committed
4924

4925

4926

William Stein's avatar
William Stein committed
4927 4928 4929 4930 4931 4932 4933 4934
#------------------------------------------------------------------------------------
#
#  Runtime support code
#
#------------------------------------------------------------------------------------

utility_function_predeclarations = \
"""
4935 4936 4937
#ifdef __GNUC__
#define INLINE __inline__
#elif _WIN32
4938
#define INLINE __inline
4939 4940 4941 4942
#else
#define INLINE 
#endif

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

4945 4946 4947 4948 4949
""" + """

static int %(skip_dispatch_cname)s = 0;

""" % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
Robert Bradshaw's avatar
Robert Bradshaw committed
4950 4951 4952 4953

if Options.gcc_branch_hints:
    branch_prediction_macros = \
    """
4954
#ifdef __GNUC__
4955 4956 4957
/* Test for GCC > 2.95 */
#if __GNUC__ > 2 || \
              (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) 
Robert Bradshaw's avatar
Robert Bradshaw committed
4958 4959
#define likely(x)   __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
4960 4961 4962 4963
#else /* __GNUC__ > 2 ... */
#define likely(x)   (x)
#define unlikely(x) (x)
#endif /* __GNUC__ > 2 ... */
4964 4965 4966 4967
#else /* __GNUC__ */
#define likely(x)   (x)
#define unlikely(x) (x)
#endif /* __GNUC__ */
Robert Bradshaw's avatar
Robert Bradshaw committed
4968 4969 4970 4971 4972 4973 4974
    """
else:
    branch_prediction_macros = \
    """
#define likely(x)   (x)
#define unlikely(x) (x)
    """
William Stein's avatar
William Stein committed
4975

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

4979 4980
#get_name_interned_predeclaration = \
#"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
William Stein's avatar
William Stein committed
4981 4982 4983

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

4984 4985
printing_utility_code = UtilityCode(
proto = """
4986 4987
static int __Pyx_Print(PyObject *, int); /*proto*/
#if PY_MAJOR_VERSION >= 3
4988 4989 4990
static PyObject* %s = 0;
static PyObject* %s = 0;
#endif
4991 4992
""" % (Naming.print_function, Naming.print_function_kwargs),
impl = r"""
4993
#if PY_MAJOR_VERSION < 3
William Stein's avatar
William Stein committed
4994
static PyObject *__Pyx_GetStdout(void) {
4995
    PyObject *f = PySys_GetObject((char *)"stdout");
William Stein's avatar
William Stein committed
4996 4997 4998 4999 5000 5001
    if (!f) {
        PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
    }
    return f;
}

5002
static int __Pyx_Print(PyObject *arg_tuple, int newline) {
William Stein's avatar
William Stein committed
5003
    PyObject *f;
5004 5005
    PyObject* v;
    int i;
5006

William Stein's avatar
William Stein committed
5007 5008
    if (!(f = __Pyx_GetStdout()))
        return -1;
5009 5010 5011 5012 5013 5014 5015
    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
5016
            return -1;
5017 5018 5019 5020 5021 5022 5023 5024
        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
5025
    }
5026 5027 5028 5029
    if (newline) {
        if (PyFile_WriteString("\n", f) < 0)
            return -1;
        PyFile_SoftSpace(f, 0);
William Stein's avatar
William Stein committed
5030 5031 5032 5033
    }
    return 0;
}

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

5036 5037 5038 5039 5040
static int __Pyx_Print(PyObject *arg_tuple, int newline) {
    PyObject* kwargs = 0;
    PyObject* result = 0;
    PyObject* end_string;
    if (!%(PRINT_FUNCTION)s) {
5041
        %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
5042
        if (!%(PRINT_FUNCTION)s)
5043
            return -1;
5044 5045 5046 5047 5048
    }
    if (!newline) {
        if (!%(PRINT_KWARGS)s) {
            %(PRINT_KWARGS)s = PyDict_New();
            if (!%(PRINT_KWARGS)s)
5049
                return -1;
5050 5051
            end_string = PyUnicode_FromStringAndSize(" ", 1);
            if (!end_string)
5052
                return -1;
5053 5054
            if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
                Py_DECREF(end_string);
5055
                return -1;
5056 5057 5058 5059 5060 5061 5062
            }
            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
5063
        return -1;
5064
    Py_DECREF(result);
William Stein's avatar
William Stein committed
5065 5066
    return 0;
}
5067

5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094
#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;
5095 5096
    /* the line below is just to avoid compiler
     * compiler warnings about unused functions */
Robert Bradshaw's avatar
Robert Bradshaw committed
5097
    return __Pyx_Print(NULL, 0);
5098 5099 5100 5101
}

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

5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113
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;
}

5114
#endif
Robert Bradshaw's avatar
Robert Bradshaw committed
5115 5116
""",
requires=[printing_utility_code])
5117 5118


William Stein's avatar
William Stein committed
5119 5120 5121 5122 5123

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

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

5124 5125
raise_utility_code = UtilityCode(
proto = """
5126
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5127 5128
""",
impl = """
William Stein's avatar
William Stein committed
5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147
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);
    }
5148 5149 5150 5151 5152 5153
    #if PY_VERSION_HEX < 0x02050000
    if (!PyClass_Check(type))
    #else
    if (!PyType_Check(type))
    #endif
    {
William Stein's avatar
William Stein committed
5154 5155 5156
        /* Raising an instance.  The value should be a dummy. */
        if (value != Py_None) {
            PyErr_SetString(PyExc_TypeError,
5157
                "instance exception may not have a separate value");
William Stein's avatar
William Stein committed
5158 5159
            goto raise_error;
        }
5160 5161 5162
        /* Normalize to raise <class>, <instance> */
        Py_DECREF(value);
        value = type;
5163 5164 5165 5166 5167 5168
        #if PY_VERSION_HEX < 0x02050000
            if (PyInstance_Check(type)) {
                type = (PyObject*) ((PyInstanceObject*)type)->in_class;
                Py_INCREF(type);
            }
            else {
5169
                type = 0;
5170 5171 5172 5173 5174
                PyErr_SetString(PyExc_TypeError,
                    "raise: exception must be an old-style class or instance");
                goto raise_error;
            }
        #else
5175
            type = (PyObject*) Py_TYPE(type);
5176 5177 5178 5179 5180 5181 5182
            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
5183
    }
5184
    __Pyx_ErrRestore(type, value, tb);
5185 5186 5187
    return;
raise_error:
    Py_XDECREF(value);
William Stein's avatar
William Stein committed
5188 5189 5190 5191
    Py_XDECREF(type);
    Py_XDECREF(tb);
    return;
}
5192
""")
William Stein's avatar
William Stein committed
5193 5194 5195

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

5196 5197
reraise_utility_code = UtilityCode(
proto = """
5198
static void __Pyx_ReRaise(void); /*proto*/
5199 5200
""",
impl = """
William Stein's avatar
William Stein committed
5201
static void __Pyx_ReRaise(void) {
5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214
    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
5215
}
5216
""")
William Stein's avatar
William Stein committed
5217 5218 5219

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

5220 5221
arg_type_test_utility_code = UtilityCode(
proto = """
5222 5223
static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
    const char *name, int exact); /*proto*/
5224 5225
""",
impl = """
5226 5227 5228
static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
    const char *name, int exact)
{
William Stein's avatar
William Stein committed
5229 5230 5231 5232
    if (!type) {
        PyErr_Format(PyExc_SystemError, "Missing type object");
        return 0;
    }
Robert Bradshaw's avatar
Robert Bradshaw committed
5233 5234
    if (none_allowed && obj == Py_None) return 1;
    else if (exact) {
5235
        if (Py_TYPE(obj) == type) return 1;
Robert Bradshaw's avatar
Robert Bradshaw committed
5236 5237
    }
    else {
Robert Bradshaw's avatar
Robert Bradshaw committed
5238
        if (PyObject_TypeCheck(obj, type)) return 1;
Robert Bradshaw's avatar
Robert Bradshaw committed
5239
    }
William Stein's avatar
William Stein committed
5240 5241
    PyErr_Format(PyExc_TypeError,
        "Argument '%s' has incorrect type (expected %s, got %s)",
5242
        name, type->tp_name, Py_TYPE(obj)->tp_name);
William Stein's avatar
William Stein committed
5243 5244
    return 0;
}
5245
""")
William Stein's avatar
William Stein committed
5246 5247 5248

#------------------------------------------------------------------------------------
#
5249 5250 5251
#  __Pyx_RaiseArgtupleInvalid raises the correct exception when too
#  many or too few positional arguments were found.  This handles
#  Py_ssize_t formatting correctly.
5252

5253 5254
raise_argtuple_invalid_utility_code = UtilityCode(
proto = """
5255
static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5256
    Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5257 5258
""",
impl = """
5259
static void __Pyx_RaiseArgtupleInvalid(
5260
    const char* func_name,
5261
    int exact,
5262 5263
    Py_ssize_t num_min,
    Py_ssize_t num_max,
5264
    Py_ssize_t num_found)
William Stein's avatar
William Stein committed
5265
{
5266
    Py_ssize_t num_expected;
Stefan Behnel's avatar
Stefan Behnel committed
5267
    const char *number, *more_or_less;
5268 5269 5270 5271

    if (num_found < num_min) {
        num_expected = num_min;
        more_or_less = "at least";
5272
    } else {
5273
        num_expected = num_max;
5274
        more_or_less = "at most";
5275
    }
5276 5277
    if (exact) {
        more_or_less = "exactly";
5278
    }
5279
    number = (num_expected == 1) ? "" : "s";
Stefan Behnel's avatar
Stefan Behnel committed
5280 5281 5282 5283 5284 5285 5286
    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);
5287
}
5288
""")
5289

5290 5291
raise_keyword_required_utility_code = UtilityCode(
proto = """
5292
static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5293 5294
""",
impl = """
5295
static INLINE void __Pyx_RaiseKeywordRequired(
5296
    const char* func_name,
5297
    PyObject* kw_name)
5298 5299
{
    PyErr_Format(PyExc_TypeError,
5300 5301 5302 5303 5304 5305
        #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
5306
}
5307
""")
5308

5309 5310
raise_double_keywords_utility_code = UtilityCode(
proto = """
5311
static void __Pyx_RaiseDoubleKeywordsError(
5312
    const char* func_name, PyObject* kw_name); /*proto*/
5313 5314
""",
impl = """
5315
static void __Pyx_RaiseDoubleKeywordsError(
5316
    const char* func_name,
5317
    PyObject* kw_name)
5318
{
5319
    PyErr_Format(PyExc_TypeError,
5320 5321 5322 5323 5324 5325
        #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
5326
}
5327
""")
5328

5329 5330
#------------------------------------------------------------------------------------
#
5331 5332 5333
#  __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.
5334

5335 5336
keyword_string_check_utility_code = UtilityCode(
proto = """
5337
static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5338
    const char* function_name, int kw_allowed); /*proto*/
5339 5340
""",
impl = """
5341
static INLINE int __Pyx_CheckKeywordStrings(
5342 5343 5344 5345
    PyObject *kwdict,
    const char* function_name,
    int kw_allowed)
{
5346 5347
    PyObject* key = 0;
    Py_ssize_t pos = 0;
5348
    while (PyDict_Next(kwdict, &pos, &key, 0)) {
5349
        #if PY_MAJOR_VERSION < 3
5350
        if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5351
        #else
5352
        if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5353
        #endif
5354
            goto invalid_keyword_type;
5355
    }
5356 5357
    if ((!kw_allowed) && unlikely(key))
        goto invalid_keyword;
5358
    return 1;
5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372
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;
5373
}
5374
""")
5375

5376 5377
#------------------------------------------------------------------------------------
#
5378 5379 5380
#  __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.
5381
#
Stefan Behnel's avatar
Stefan Behnel committed
5382 5383
#  Three kinds of errors are checked: 1) non-string keywords, 2)
#  unexpected keywords and 3) overlap with positional arguments.
5384
#
Stefan Behnel's avatar
Stefan Behnel committed
5385 5386 5387 5388 5389
#  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.
5390 5391
#

5392
parse_keywords_utility_code = UtilityCode(
5393
proto = """
5394
static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5395 5396
    PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
    const char* function_name); /*proto*/
5397 5398
""",
impl = """
5399
static int __Pyx_ParseOptionalKeywords(
5400
    PyObject *kwds,
Stefan Behnel's avatar
Stefan Behnel committed
5401 5402
    PyObject **argnames[],
    PyObject *kwds2,
5403
    PyObject *values[],
Stefan Behnel's avatar
Stefan Behnel committed
5404
    Py_ssize_t num_pos_args,
5405
    const char* function_name)
5406
{
5407
    PyObject *key = 0, *value = 0;
5408
    Py_ssize_t pos = 0;
5409
    PyObject*** name;
5410
    PyObject*** first_kw_arg = argnames + num_pos_args;
5411

Stefan Behnel's avatar
Stefan Behnel committed
5412
    while (PyDict_Next(kwds, &pos, &key, &value)) {
5413 5414
        name = first_kw_arg;
        while (*name && (**name != key)) name++;
5415
        if (*name) {
5416
            values[name-argnames] = value;
Stefan Behnel's avatar
Stefan Behnel committed
5417
        } else {
5418 5419 5420 5421 5422 5423
            #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;
5424 5425
            } else {
                for (name = first_kw_arg; *name; name++) {
5426
                    #if PY_MAJOR_VERSION >= 3
Stefan Behnel's avatar
Stefan Behnel committed
5427
                    if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5428
                        PyUnicode_Compare(**name, key) == 0) break;
5429
                    #else
5430
                    if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5431
                        _PyString_Eq(**name, key)) break;
5432 5433
                    #endif
                }
5434
                if (*name) {
5435 5436 5437 5438 5439 5440 5441 5442 5443 5444
                    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) &&
5445
                            _PyString_Eq(**name, key)) goto arg_passed_twice;
5446 5447
                        #endif
                    }
Stefan Behnel's avatar
Stefan Behnel committed
5448 5449 5450
                    if (kwds2) {
                        if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
                    } else {
5451
                        goto invalid_keyword;
Stefan Behnel's avatar
Stefan Behnel committed
5452 5453
                    }
                }
5454
            }
5455
        }
5456
    }
5457
    return 0;
5458
arg_passed_twice:
Stefan Behnel's avatar
Stefan Behnel committed
5459 5460
    __Pyx_RaiseDoubleKeywordsError(function_name, **name);
    goto bad;
5461 5462 5463 5464 5465
invalid_keyword_type:
    PyErr_Format(PyExc_TypeError,
        "%s() keywords must be strings", function_name);
    goto bad;
invalid_keyword:
5466
    PyErr_Format(PyExc_TypeError,
5467
    #if PY_MAJOR_VERSION < 3
5468 5469
        "%s() got an unexpected keyword argument '%s'",
        function_name, PyString_AsString(key));
5470
    #else
5471 5472
        "%s() got an unexpected keyword argument '%U'",
        function_name, key);
5473
    #endif
William Stein's avatar
William Stein committed
5474 5475 5476
bad:
    return -1;
}
5477
""")
William Stein's avatar
William Stein committed
5478 5479 5480

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

5481 5482
traceback_utility_code = UtilityCode(
proto = """
5483
static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5484 5485
""",
impl = """
William Stein's avatar
William Stein committed
5486 5487 5488 5489
#include "compile.h"
#include "frameobject.h"
#include "traceback.h"

5490
static void __Pyx_AddTraceback(const char *funcname) {
William Stein's avatar
William Stein committed
5491 5492 5493 5494 5495 5496
    PyObject *py_srcfile = 0;
    PyObject *py_funcname = 0;
    PyObject *py_globals = 0;
    PyObject *empty_string = 0;
    PyCodeObject *py_code = 0;
    PyFrameObject *py_frame = 0;
5497 5498

    #if PY_MAJOR_VERSION < 3
William Stein's avatar
William Stein committed
5499
    py_srcfile = PyString_FromString(%(FILENAME)s);
5500 5501 5502
    #else
    py_srcfile = PyUnicode_FromString(%(FILENAME)s);
    #endif
William Stein's avatar
William Stein committed
5503
    if (!py_srcfile) goto bad;
Robert Bradshaw's avatar
Robert Bradshaw committed
5504
    if (%(CLINENO)s) {
5505
        #if PY_MAJOR_VERSION < 3
5506
        py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5507
        #else
5508
        py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5509
        #endif
Robert Bradshaw's avatar
Robert Bradshaw committed
5510 5511
    }
    else {
5512
        #if PY_MAJOR_VERSION < 3
Robert Bradshaw's avatar
Robert Bradshaw committed
5513
        py_funcname = PyString_FromString(funcname);
5514 5515 5516
        #else
        py_funcname = PyUnicode_FromString(funcname);
        #endif
Robert Bradshaw's avatar
Robert Bradshaw committed
5517
    }
William Stein's avatar
William Stein committed
5518 5519 5520
    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
5521
    #if PY_MAJOR_VERSION < 3
Stefan Behnel's avatar
Stefan Behnel committed
5522
    empty_string = PyString_FromStringAndSize("", 0);
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
5523 5524 5525
    #else
    empty_string = PyBytes_FromStringAndSize("", 0);
    #endif
William Stein's avatar
William Stein committed
5526 5527 5528
    if (!empty_string) goto bad;
    py_code = PyCode_New(
        0,            /*int argcount,*/
5529 5530 5531
        #if PY_MAJOR_VERSION >= 3
        0,            /*int kwonlyargcount,*/
        #endif
William Stein's avatar
William Stein committed
5532 5533 5534 5535
        0,            /*int nlocals,*/
        0,            /*int stacksize,*/
        0,            /*int flags,*/
        empty_string, /*PyObject *code,*/
Stefan Behnel's avatar
Stefan Behnel committed
5536 5537 5538 5539 5540
        %(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
5541 5542 5543 5544 5545 5546 5547
        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(
5548
        PyThreadState_GET(), /*PyThreadState *tstate,*/
William Stein's avatar
William Stein committed
5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565
        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
5566 5567
    'CFILENAME': Naming.cfilenm_cname,
    'CLINENO':  Naming.clineno_cname,
Stefan Behnel's avatar
Stefan Behnel committed
5568 5569
    'GLOBALS': Naming.module_cname,
    'EMPTY_TUPLE' : Naming.empty_tuple,
5570
})
William Stein's avatar
William Stein committed
5571

5572 5573
restore_exception_utility_code = UtilityCode(
proto = """
5574 5575
static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5576 5577
""",
impl = """
5578
static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5579 5580 5581
    PyObject *tmp_type, *tmp_value, *tmp_tb;
    PyThreadState *tstate = PyThreadState_GET();

5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597
#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
5598

5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609
    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);
}

5610
static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5611 5612 5613 5614 5615 5616 5617 5618 5619 5620
    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;
}

5621
""")
5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648

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

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])
5649

William Stein's avatar
William Stein committed
5650 5651
#------------------------------------------------------------------------------------

5652 5653
set_vtable_utility_code = UtilityCode(
proto = """
5654
static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5655 5656
""",
impl = """
William Stein's avatar
William Stein committed
5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674
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;
}
5675
""")
William Stein's avatar
William Stein committed
5676 5677 5678

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

5679 5680
get_vtable_utility_code = UtilityCode(
proto = """
5681
static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5682 5683
""",
impl = r"""
William Stein's avatar
William Stein committed
5684 5685 5686
static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
    int result;
    PyObject *pycobj;
5687 5688

    pycobj = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
William Stein's avatar
William Stein committed
5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702
    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;
}
5703
""")
William Stein's avatar
William Stein committed
5704 5705 5706

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

5707 5708
init_string_tab_utility_code = UtilityCode(
proto = """
5709
static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5710 5711
""",
impl = """
William Stein's avatar
William Stein committed
5712 5713
static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
    while (t->p) {
5714
        #if PY_MAJOR_VERSION < 3
5715
        if (t->is_unicode && (!t->is_identifier)) {
5716
            *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5717 5718
        } else if (t->intern) {
            *t->p = PyString_InternFromString(t->s);
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
5719 5720
        } else {
            *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
Stefan Behnel's avatar
Stefan Behnel committed
5721
        }
5722 5723 5724 5725 5726
        #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
5727 5728
        } else {
            *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
Stefan Behnel's avatar
Stefan Behnel committed
5729
        }
5730
        #endif
William Stein's avatar
William Stein committed
5731 5732 5733 5734 5735 5736
        if (!*t->p)
            return -1;
        ++t;
    }
    return 0;
}
5737
""")
William Stein's avatar
William Stein committed
5738 5739

#------------------------------------------------------------------------------------
5740

5741 5742
get_exception_utility_code = UtilityCode(
proto = """
5743
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5744 5745
""",
impl = """
5746
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5747
    PyObject *tmp_type, *tmp_value, *tmp_tb;
5748
    PyThreadState *tstate = PyThreadState_GET();
5749 5750 5751 5752 5753 5754
    *type = tstate->curexc_type;
    *value = tstate->curexc_value;
    *tb = tstate->curexc_traceback;
    tstate->curexc_type = 0;
    tstate->curexc_value = 0;
    tstate->curexc_traceback = 0;
5755 5756 5757 5758 5759 5760
    PyErr_NormalizeException(type, value, tb);
    if (PyErr_Occurred())
        goto bad;
    Py_INCREF(*type);
    Py_INCREF(*value);
    Py_INCREF(*tb);
5761 5762 5763
    tmp_type = tstate->exc_type;
    tmp_value = tstate->exc_value;
    tmp_tb = tstate->exc_traceback;
5764 5765 5766
    tstate->exc_type = *type;
    tstate->exc_value = *value;
    tstate->exc_traceback = *tb;
5767 5768 5769 5770 5771
    /* 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);
5772
    return 0;
5773 5774 5775 5776 5777
bad:
    Py_XDECREF(*type);
    Py_XDECREF(*value);
    Py_XDECREF(*tb);
    return -1;
5778
}
5779

5780
""")
5781 5782

#------------------------------------------------------------------------------------
5783

5784 5785
reset_exception_utility_code = UtilityCode(
proto = """
5786
static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5787
static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5788 5789
""",
impl = """
5790
static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5791 5792 5793 5794
    PyThreadState *tstate = PyThreadState_GET();
    *type = tstate->exc_type;
    *value = tstate->exc_value;
    *tb = tstate->exc_traceback;
Stefan Behnel's avatar
Stefan Behnel committed
5795 5796 5797
    Py_XINCREF(*type);
    Py_XINCREF(*value);
    Py_XINCREF(*tb);
5798 5799
}

5800
static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812
    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);
}
5813
""")
5814 5815

#------------------------------------------------------------------------------------
5816

Stefan Behnel's avatar
Stefan Behnel committed
5817
force_init_threads_utility_code = UtilityCode(
5818 5819
proto="""
#ifndef __PYX_FORCE_INIT_THREADS
5820
#if PY_VERSION_HEX < 0x02040200
5821
#define __PYX_FORCE_INIT_THREADS 1
5822 5823
#else
#define __PYX_FORCE_INIT_THREADS 0
5824 5825 5826 5827 5828
#endif
#endif
""")

#------------------------------------------------------------------------------------
5829