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

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

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

from DebugFlags import debug_disposal_code

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

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

    OUTPUT:
        relative filename
        line number

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

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

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

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

Stefan Behnel's avatar
Stefan Behnel committed
70
class Node(object):
William Stein's avatar
William Stein committed
71 72 73 74 75 76
    #  pos         (string, int, int)   Source file position
    #  is_name     boolean              Is a NameNode
    #  is_literal  boolean              Is a ConstNode
    
    is_name = 0
    is_literal = 0
77
    temps = None
78

79 80 81
    # 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.
82
    child_attrs = None
William Stein's avatar
William Stein committed
83 84 85 86 87
    
    def __init__(self, pos, **kw):
        self.pos = pos
        self.__dict__.update(kw)
    
88 89 90 91 92 93 94 95 96
    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)

97 98 99 100 101 102
    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."""
103 104 105
        result = copy.copy(self)
        for attrname in result.child_attrs:
            value = getattr(result, attrname)
106
            if isinstance(value, list):
107
                setattr(result, attrname, [x for x in value])
108
        return result
109
    
110
    
William Stein's avatar
William Stein committed
111
    #
112
    #  There are 4 phases of parse tree processing, applied in order to
William Stein's avatar
William Stein committed
113 114
    #  all the statements in a given scope-block:
    #
115 116 117 118
    #  (0) analyse_control_flow
    #        Create the control flow tree into which state can be asserted and
    #        queried.
    #
William Stein's avatar
William Stein committed
119 120 121 122 123
    #  (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).
    #
124
    #  (2) analyse_expressions
William Stein's avatar
William Stein committed
125 126 127 128 129 130 131
    #         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.
    #
132
    #  (3) generate_code
William Stein's avatar
William Stein committed
133 134 135 136 137
    #         Emit C code for all declarations, statements and expressions.
    #         Recursively applies the 3 processing phases to the bodies of
    #         functions.
    #
    
138 139 140
    def analyse_control_flow(self, env):
        pass
    
William Stein's avatar
William Stein committed
141 142 143 144 145 146 147 148 149 150
    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__)
151 152 153 154 155
            
    def annotate(self, code):
        # mro does the wrong thing
        if isinstance(self, BlockNode):
            self.body.annotate(code)
156 157
            
    def end_pos(self):
Stefan Behnel's avatar
Stefan Behnel committed
158 159
        if not self.child_attrs:
            return self.pos
160 161 162
        try:
            return self._end_pos
        except AttributeError:
Stefan Behnel's avatar
Stefan Behnel committed
163
            pos = self.pos
164
            for attr in self.child_attrs:
165
                child = getattr(self, attr)
166
                # Sometimes lists, sometimes nodes
167 168 169
                if child is None:
                    pass
                elif isinstance(child, list):
Stefan Behnel's avatar
Stefan Behnel committed
170 171
                    for c in child:
                        pos = max(pos, c.end_pos())
172
                else:
Stefan Behnel's avatar
Stefan Behnel committed
173 174 175
                    pos = max(pos, child.end_pos())
            self._end_pos = pos
            return pos
William Stein's avatar
William Stein committed
176

177
    def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
178 179
        if cutoff == 0:
            return "<...nesting level cutoff...>"
180 181 182 183 184
        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))
185
        
186 187
        def dump_child(x, level):
            if isinstance(x, Node):
188
                return x.dump(level, filter_out, cutoff-1, encountered)
189
            elif isinstance(x, list):
Robert Bradshaw's avatar
Robert Bradshaw committed
190
                return "[%s]" % ", ".join([dump_child(item, level) for item in x])
191 192 193 194 195 196
            else:
                return repr(x)
            
        
        attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
        if len(attrs) == 0:
197
            return "<%s (%d)>" % (self.__class__.__name__, id(self))
198 199
        else:
            indent = "  " * level
200
            res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
201 202 203 204
            for key, value in attrs:
                res += "%s  %s: %s\n" % (indent, key, dump_child(value, level + 1))
            res += "%s>" % indent
            return res
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251

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
252
        
William Stein's avatar
William Stein committed
253 254 255 256 257 258 259
class BlockNode:
    #  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:
260
                    code.globalstate.add_const_definition(entry)
261 262 263 264 265

    def generate_interned_string_decls(self, env, code):
        entries = env.global_scope().new_interned_string_entries
        if entries:
            for entry in entries:
266
                code.globalstate.add_interned_string_decl(entry)
267 268
            del entries[:]

William Stein's avatar
William Stein committed
269
    def generate_py_string_decls(self, env, code):
270 271
        if env is None:
            return # earlier error
William Stein's avatar
William Stein committed
272 273 274
        entries = env.pystring_entries
        if entries:
            for entry in entries:
275
                if not entry.is_interned:
276
                    code.globalstate.add_py_string_decl(entry)
277

278 279 280 281 282 283 284
    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:
285
                code.globalstate.add_interned_num_decl(entry)
286
            del entries[:]
William Stein's avatar
William Stein committed
287

288
    def generate_cached_builtins_decls(self, env, code):
289
        entries = env.global_scope().undeclared_cached_builtins
290
        for entry in entries:
291
            code.globalstate.add_cached_builtin_decl(entry)
292
        del entries[:]
293
        
William Stein's avatar
William Stein committed
294 295 296 297

class StatListNode(Node):
    # stats     a list of StatNode
    
298
    child_attrs = ["stats"]
299 300 301 302 303

    def create_analysed(pos, env, *args, **kw):
        node = StatListNode(pos, *args, **kw)
        return node # No node-specific analysis necesarry
    create_analysed = staticmethod(create_analysed)
304
    
305 306 307 308
    def analyse_control_flow(self, env):
        for stat in self.stats:
            stat.analyse_control_flow(env)

William Stein's avatar
William Stein committed
309 310 311 312 313 314 315 316 317 318
    def analyse_declarations(self, env):
        #print "StatListNode.analyse_declarations" ###
        for stat in self.stats:
            stat.analyse_declarations(env)
    
    def analyse_expressions(self, env):
        #print "StatListNode.analyse_expressions" ###
        for stat in self.stats:
            stat.analyse_expressions(env)
    
319
    def generate_function_definitions(self, env, code):
William Stein's avatar
William Stein committed
320 321
        #print "StatListNode.generate_function_definitions" ###
        for stat in self.stats:
322
            stat.generate_function_definitions(env, code)
William Stein's avatar
William Stein committed
323 324 325 326 327 328
            
    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)
329 330 331 332
            
    def annotate(self, code):
        for stat in self.stats:
            stat.annotate(code)
William Stein's avatar
William Stein committed
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
    

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.
    #
    
348
    def generate_function_definitions(self, env, code):
William Stein's avatar
William Stein committed
349 350 351 352 353 354 355 356 357 358 359
        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
    
360 361
    child_attrs = ["body"]
    
William Stein's avatar
William Stein committed
362 363 364 365 366 367 368 369 370 371 372 373 374
    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
375 376 377

    def annotate(self, code):
        self.body.annotate(code)
William Stein's avatar
William Stein committed
378 379 380 381 382 383 384 385 386 387 388 389
        

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.
    #
390 391 392
    #  calling_convention  string   Calling convention of CFuncDeclaratorNode
    #                               for which this is a base 

393 394
    child_attrs = []

395 396
    calling_convention = ""

William Stein's avatar
William Stein committed
397 398

class CNameDeclaratorNode(CDeclaratorNode):
Robert Bradshaw's avatar
Robert Bradshaw committed
399 400 401
    #  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
402
    
Robert Bradshaw's avatar
Robert Bradshaw committed
403
    child_attrs = ['default']
404
    
405
    default = None
406
    
407 408
    def analyse(self, base_type, env, nonempty = 0):
        if nonempty and self.name == '':
409 410
            # May have mistaken the name for the type. 
            if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
411
                error(self.pos, "Missing argument name")
412 413
            elif base_type.is_void:
                error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
414 415 416
            else:
                self.name = base_type.declaration_code("", for_display=1, pyrex=1)
                base_type = py_object_type
417
        self.type = base_type
William Stein's avatar
William Stein committed
418
        return self, base_type
419
        
William Stein's avatar
William Stein committed
420 421 422
class CPtrDeclaratorNode(CDeclaratorNode):
    # base     CDeclaratorNode
    
423 424
    child_attrs = ["base"]

425
    def analyse(self, base_type, env, nonempty = 0):
William Stein's avatar
William Stein committed
426 427 428 429
        if base_type.is_pyobject:
            error(self.pos,
                "Pointer base type cannot be a Python object")
        ptr_type = PyrexTypes.c_ptr_type(base_type)
430
        return self.base.analyse(ptr_type, env, nonempty = nonempty)
William Stein's avatar
William Stein committed
431 432 433 434
        
class CArrayDeclaratorNode(CDeclaratorNode):
    # base        CDeclaratorNode
    # dimension   ExprNode
435 436

    child_attrs = ["base", "dimension"]
William Stein's avatar
William Stein committed
437
    
438
    def analyse(self, base_type, env, nonempty = 0):
William Stein's avatar
William Stein committed
439 440 441 442
        if self.dimension:
            self.dimension.analyse_const_expression(env)
            if not self.dimension.type.is_int:
                error(self.dimension.pos, "Array dimension not integer")
443
            size = self.dimension.result()
William Stein's avatar
William Stein committed
444 445 446 447 448 449 450 451
        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")
452 453 454
        if base_type.is_cfunction:
            error(self.pos,
                "Array element cannot be a function")
William Stein's avatar
William Stein committed
455
        array_type = PyrexTypes.c_array_type(base_type, size)
456
        return self.base.analyse(array_type, env, nonempty = nonempty)
William Stein's avatar
William Stein committed
457 458 459 460 461 462 463 464


class CFuncDeclaratorNode(CDeclaratorNode):
    # base             CDeclaratorNode
    # args             [CArgDeclNode]
    # has_varargs      boolean
    # exception_value  ConstNode
    # exception_check  boolean    True if PyErr_Occurred check needed
465 466
    # nogil            boolean    Can be called without gil
    # with_gil         boolean    Acquire gil around function body
467
    
468 469
    child_attrs = ["base", "args", "exception_value"]

470
    overridable = 0
471
    optional_arg_count = 0
William Stein's avatar
William Stein committed
472

473
    def analyse(self, return_type, env, nonempty = 0):
474 475
        if nonempty:
            nonempty -= 1
William Stein's avatar
William Stein committed
476 477
        func_type_args = []
        for arg_node in self.args:
478
            name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
William Stein's avatar
William Stein committed
479 480 481 482 483 484 485 486 487
            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
488
                error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
489 490 491
#            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
492 493 494
            func_type_args.append(
                PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
            if arg_node.default:
495
                self.optional_arg_count += 1
496 497
            elif self.optional_arg_count:
                error(self.pos, "Non-default argument follows default argument")
498 499 500
        
        if self.optional_arg_count:
            scope = StructOrUnionScope()
501
            scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
502 503
            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)
504
            struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
505 506 507 508 509 510
            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)
511
            self.op_args_struct.defined_in_pxd = 1
512 513
            self.op_args_struct.used = 1
        
William Stein's avatar
William Stein committed
514 515 516
        exc_val = None
        exc_check = 0
        if return_type.is_pyobject \
Robert Bradshaw's avatar
Robert Bradshaw committed
517 518
            and (self.exception_value or self.exception_check) \
            and self.exception_check != '+':
William Stein's avatar
William Stein committed
519 520 521 522 523
                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
524 525 526 527 528 529 530 531 532
                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:
533
                    exc_val = self.exception_value.result()
Robert Bradshaw's avatar
Robert Bradshaw committed
534 535 536
                    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
537
            exc_check = self.exception_check
538 539 540 541 542 543
        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
544 545
        func_type = PyrexTypes.CFuncType(
            return_type, func_type_args, self.has_varargs, 
546
            optional_arg_count = self.optional_arg_count,
547
            exception_value = exc_val, exception_check = exc_check,
548
            calling_convention = self.base.calling_convention,
549
            nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
550
        if self.optional_arg_count:
551
            func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
William Stein's avatar
William Stein committed
552 553 554 555 556 557 558 559 560 561 562
        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
563
    # default_result_code string        cname or code fragment for default value
William Stein's avatar
William Stein committed
564
    # is_self_arg    boolean            Is the "self" arg of an extension type method
565 566
    # is_kw_only     boolean            Is a keyword-only argument

567 568
    child_attrs = ["base_type", "declarator", "default"]

William Stein's avatar
William Stein committed
569
    is_self_arg = 0
570
    is_generic = 1
571 572
    type = None
    name_declarator = None
573

574
    def analyse(self, env, nonempty = 0):
575
        #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
        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)
            if self.base_type.arg_name:
                self.declarator.name = self.base_type.arg_name
            return self.declarator.analyse(base_type, env, nonempty = nonempty)
591
        else:
592
            return self.name_declarator, self.type
William Stein's avatar
William Stein committed
593

594 595 596 597
    def annotate(self, code):
        if self.default:
            self.default.annotate(code)

William Stein's avatar
William Stein committed
598 599 600 601 602 603 604 605 606 607

class CBaseTypeNode(Node):
    # Abstract base class for C base type nodes.
    #
    # Processing during analyse_declarations phase:
    #
    #   analyse
    #     Returns the type.
    
    pass
608 609 610 611 612 613 614 615
    
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
616 617 618 619 620 621 622 623 624

class CSimpleBaseTypeNode(CBaseTypeNode):
    # name             string
    # module_path      [string]     Qualifying name components
    # is_basic_c_type  boolean
    # signed           boolean
    # longness         integer
    # is_self_arg      boolean      Is self argument of C method

625
    child_attrs = []
626
    arg_name = None   # in case the argument name was interpreted as a type
627
    
628
    def analyse(self, env, could_be_name = False):
William Stein's avatar
William Stein committed
629
        # Return type descriptor.
630
        #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
William Stein's avatar
William Stein committed
631 632 633 634 635 636 637 638 639
        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:
640
                #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
William Stein's avatar
William Stein committed
641 642 643 644
                type = env.parent_type
            else:
                type = py_object_type
        else:
645 646 647 648
            if self.module_path:
                scope = env.find_imported_module(self.module_path, self.pos)
            else:
                scope = env
William Stein's avatar
William Stein committed
649
            if scope:
650 651
                if scope.is_c_class_scope:
                    scope = scope.global_scope()
652
                entry = scope.lookup(self.name)
William Stein's avatar
William Stein committed
653 654
                if entry and entry.is_type:
                    type = entry.type
655 656 657 658 659 660
                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
661 662 663 664 665 666 667
                else:
                    error(self.pos, "'%s' is not a type identifier" % self.name)
        if type:
            return type
        else:
            return PyrexTypes.error_type

668
class CBufferAccessTypeNode(CBaseTypeNode):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
669
    #  After parsing:
670 671
    #  positional_args  [ExprNode]        List of positional arguments
    #  keyword_args     DictNode          Keyword arguments
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
672 673 674
    #  base_type_node   CBaseTypeNode

    #  After analysis:
675 676
    #  type             PyrexType.BufferType   ...containing the right options

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
677

678 679
    child_attrs = ["base_type_node", "positional_args",
                   "keyword_args", "dtype_node"]
680

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
681
    dtype_node = None
682
    
683
    def analyse(self, env, could_be_name = False):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
684
        base_type = self.base_type_node.analyse(env)
685
        if base_type.is_error: return base_type
686 687 688 689 690 691 692 693 694 695
        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
696
        return self.type
William Stein's avatar
William Stein committed
697 698 699 700 701

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

704 705
    def analyse(self, env, could_be_name = False):
        base = self.base_type.analyse(env, could_be_name)
William Stein's avatar
William Stein committed
706 707 708 709 710 711 712 713 714 715
        _, 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]
716
    #  in_pxd        boolean
Stefan Behnel's avatar
Stefan Behnel committed
717
    #  api           boolean
718
    #  need_properties [entry]
719 720

    child_attrs = ["base_type", "declarators"]
Robert Bradshaw's avatar
Robert Bradshaw committed
721
    need_properties = ()
William Stein's avatar
William Stein committed
722 723 724 725
    
    def analyse_declarations(self, env, dest_scope = None):
        if not dest_scope:
            dest_scope = env
726
        self.dest_scope = dest_scope
William Stein's avatar
William Stein committed
727
        base_type = self.base_type.analyse(env)
728 729 730 731
        if (dest_scope.is_c_class_scope
                and self.visibility == 'public' 
                and base_type.is_pyobject 
                and (base_type.is_builtin_type or base_type.is_extension_type)):
Robert Bradshaw's avatar
Robert Bradshaw committed
732
            self.need_properties = []
733 734 735 736 737 738
            need_property = True
            visibility = 'private'
        else:
            need_property = False
            visibility = self.visibility
            
William Stein's avatar
William Stein committed
739 740 741 742 743 744 745 746 747 748 749
        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
750 751 752
            if name == '':
                error(declarator.pos, "Missing name in declaration.")
                return
William Stein's avatar
William Stein committed
753
            if type.is_cfunction:
754
                entry = dest_scope.declare_cfunction(name, type, declarator.pos,
Stefan Behnel's avatar
Stefan Behnel committed
755 756
                    cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
                    api = self.api)
William Stein's avatar
William Stein committed
757
            else:
758 759 760
                if self.in_pxd and self.visibility != 'extern':
                    error(self.pos, 
                        "Only 'extern' C variable declaration allowed in .pxd file")
761 762 763 764
                entry = dest_scope.declare_var(name, type, declarator.pos,
                            cname = cname, visibility = visibility, is_cdef = 1)
                if need_property:
                    self.need_properties.append(entry)
765
                    entry.needs_property = 1
William Stein's avatar
William Stein committed
766 767 768 769 770 771 772
    

class CStructOrUnionDefNode(StatNode):
    #  name          string
    #  cname         string or None
    #  kind          "struct" or "union"
    #  typedef_flag  boolean
773
    #  visibility    "public" or "private"
Stefan Behnel's avatar
Stefan Behnel committed
774
    #  in_pxd        boolean
William Stein's avatar
William Stein committed
775 776 777
    #  attributes    [CVarDefNode] or None
    #  entry         Entry
    
778 779
    child_attrs = ["attributes"]

William Stein's avatar
William Stein committed
780 781 782
    def analyse_declarations(self, env):
        scope = None
        if self.attributes is not None:
783
            scope = StructOrUnionScope(self.name)
William Stein's avatar
William Stein committed
784 785
        self.entry = env.declare_struct_or_union(
            self.name, self.kind, scope, self.typedef_flag, self.pos,
786
            self.cname, visibility = self.visibility)
William Stein's avatar
William Stein committed
787
        if self.attributes is not None:
Stefan Behnel's avatar
Stefan Behnel committed
788 789
            if self.in_pxd and not env.in_cinclude:
                self.entry.defined_in_pxd = 1
William Stein's avatar
William Stein committed
790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
            for attr in self.attributes:
                attr.analyse_declarations(env, scope)
    
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        pass


class CEnumDefNode(StatNode):
    #  name           string or None
    #  cname          string or None
    #  items          [CEnumDefItemNode]
    #  typedef_flag   boolean
Stefan Behnel's avatar
Stefan Behnel committed
805 806
    #  visibility     "public" or "private"
    #  in_pxd         boolean
William Stein's avatar
William Stein committed
807 808
    #  entry          Entry
    
809 810
    child_attrs = ["items"]
    
William Stein's avatar
William Stein committed
811 812
    def analyse_declarations(self, env):
        self.entry = env.declare_enum(self.name, self.pos,
813 814
            cname = self.cname, typedef_flag = self.typedef_flag,
            visibility = self.visibility)
Stefan Behnel's avatar
Stefan Behnel committed
815 816 817 818 819
        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
820 821

    def analyse_expressions(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
822 823 824
        if self.visibility == 'public':
            self.temp = env.allocate_temp_pyobject()
            env.release_temp(self.temp)
William Stein's avatar
William Stein committed
825 826
    
    def generate_execution_code(self, code):
Robert Bradshaw's avatar
Robert Bradshaw committed
827 828 829 830 831 832 833 834 835 836 837 838
        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)))
                code.putln('if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
                        Naming.module_cname, 
                        item.name, 
                        self.temp,
                        code.error_goto(item.pos)))
                code.putln("%s = 0;" % self.temp)
William Stein's avatar
William Stein committed
839 840 841 842 843 844 845


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

William Stein's avatar
William Stein committed
848 849 850
    def analyse_declarations(self, env, enum_entry):
        if self.value:
            self.value.analyse_const_expression(env)
851 852 853
            if not self.value.type.is_int:
                self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
                self.value.analyse_const_expression(env)
854
            value = self.value.result()
William Stein's avatar
William Stein committed
855 856 857
        else:
            value = self.name
        entry = env.declare_const(self.name, enum_entry.type, 
Robert Bradshaw's avatar
Robert Bradshaw committed
858
            value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
William Stein's avatar
William Stein committed
859 860 861 862
        enum_entry.enum_values.append(entry)


class CTypeDefNode(StatNode):
Stefan Behnel's avatar
Stefan Behnel committed
863 864 865 866
    #  base_type    CBaseTypeNode
    #  declarator   CDeclaratorNode
    #  visibility   "public" or "private"
    #  in_pxd       boolean
867 868

    child_attrs = ["base_type", "declarator"]
William Stein's avatar
William Stein committed
869 870 871 872 873 874
    
    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
875
        entry = env.declare_typedef(name, type, self.pos,
876
            cname = cname, visibility = self.visibility)
Stefan Behnel's avatar
Stefan Behnel committed
877 878
        if self.in_pxd and not env.in_cinclude:
            entry.defined_in_pxd = 1
William Stein's avatar
William Stein committed
879 880 881 882 883 884 885 886 887 888 889 890 891
    
    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
892
    #  needs_closure   boolean        Whether or not this function has inner functions/classes/yield
William Stein's avatar
William Stein committed
893
    
894
    py_func = None
895
    assmt = None
896
    needs_closure = False
897 898 899 900 901 902 903
    
    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'):
904
                        arg.default.analyse_types(env)
905
                        arg.default = arg.default.coerce_to(arg.type, genv)
906 907 908
                        if arg.default.is_literal:
                            arg.default_entry = arg.default
                            arg.default_result_code = arg.default.calculate_result_code()
909 910
                            if arg.default.type != arg.type and not arg.type.is_int:
                                arg.default_result_code = arg.type.cast_code(arg.default_result_code)
911 912 913 914 915
                        else:
                            arg.default.allocate_temps(genv)
                            arg.default_entry = genv.add_default_value(arg.type)
                            arg.default_entry.used = 1
                            arg.default_result_code = arg.default_entry.cname
916 917 918 919
                else:
                    error(arg.pos,
                        "This argument cannot have a default value")
                    arg.default = None
920
    
921 922
    def need_gil_acquisition(self, lenv):
        return 0
923 924 925 926 927
        
    def create_local_scope(self, env):
        genv = env
        while env.is_py_class_scope or env.is_c_class_scope:
            env = env.outer_scope
928
        if self.needs_closure:
929
            lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
930 931
        else:
            lenv = LocalScope(name = self.entry.name, outer_scope = genv)
William Stein's avatar
William Stein committed
932
        lenv.return_type = self.return_type
933 934 935
        type = self.entry.type
        if type.is_cfunction:
            lenv.nogil = type.nogil and not type.with_gil
936 937 938
        self.local_scope = lenv
        return lenv
                
939
    def generate_function_definitions(self, env, code):
940
        import Buffer
941 942 943

        lenv = self.local_scope

944 945 946
        is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
                             self.entry.scope.is_c_class_scope)

947
        # Generate C code for header and body of function
948
        code.enter_cfunc_scope()
949 950
        code.return_from_error_cleanup_label = code.new_label()
            
William Stein's avatar
William Stein committed
951
        # ----- Top-level constants used by this function
952
        code.mark_pos(self.pos)
953
        self.generate_interned_num_decls(lenv, code)
954
        self.generate_interned_string_decls(lenv, code)
William Stein's avatar
William Stein committed
955
        self.generate_py_string_decls(lenv, code)
956
        self.generate_cached_builtins_decls(lenv, code)
William Stein's avatar
William Stein committed
957 958 959 960 961
        #code.putln("")
        #code.put_var_declarations(lenv.const_entries, static = 1)
        self.generate_const_definitions(lenv, code)
        # ----- Function header
        code.putln("")
962 963 964 965
        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
966 967 968
        self.generate_function_header(code,
            with_pymethdef = env.is_py_class_scope)
        # ----- Local variable declarations
969
        lenv.mangle_closure_cnames(Naming.cur_scope_cname)
William Stein's avatar
William Stein committed
970
        self.generate_argument_declarations(lenv, code)
971 972
        if self.needs_closure:
            code.putln("/* TODO: declare and create scope object */")
William Stein's avatar
William Stein committed
973 974 975 976 977 978 979 980
        code.put_var_declarations(lenv.var_entries)
        init = ""
        if not self.return_type.is_void:
            code.putln(
                "%s%s;" % 
                    (self.return_type.declaration_code(
                        Naming.retval_cname),
                    init))
981
        tempvardecl_code = code.insertion_point()
William Stein's avatar
William Stein committed
982 983 984
        self.generate_keyword_list(code)
        # ----- Extern library function declarations
        lenv.generate_library_function_declarations(code)
985 986 987 988
        # ----- GIL acquisition
        acquire_gil = self.need_gil_acquisition(lenv)
        if acquire_gil:
            code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
989 990 991
        # ----- Automatic lead-ins for certain special functions
        if is_getbuffer_slot:
            self.getbuffer_init(code)
William Stein's avatar
William Stein committed
992
        # ----- Fetch arguments
993
        self.generate_argument_parsing_code(env, code)
Robert Bradshaw's avatar
Robert Bradshaw committed
994 995 996 997 998
        # 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)
999
        # ----- Initialise local variables 
William Stein's avatar
William Stein committed
1000
        for entry in lenv.var_entries:
1001
            if entry.type.is_pyobject and entry.init_to_none and entry.used:
William Stein's avatar
William Stein committed
1002
                code.put_init_var_to_py_none(entry)
1003 1004
        # ----- Initialise local buffer auxiliary variables
        for entry in lenv.var_entries + lenv.arg_entries:
1005 1006
            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)
1007
        # ----- Check and convert arguments
William Stein's avatar
William Stein committed
1008
        self.generate_argument_type_tests(code)
1009 1010 1011 1012
        # ----- 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
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
        # ----- 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:
            #	lhs = "(PyObject *)%s" % Naming.retval_cname
            #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
1028 1029 1030 1031
        if code.error_label in code.labels_used:
            code.put_goto(code.return_label)
            code.put_label(code.error_label)
            code.put_var_xdecrefs(lenv.temp_entries)
1032 1033 1034 1035 1036

            # 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:
1037
                code.globalstate.use_utility_code(restore_exception_utility_code)
1038
                code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1039
                code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1040 1041 1042
                for entry in lenv.buffer_entries:
                    code.putln("%s;" % Buffer.get_release_buffer_code(entry))
                    #code.putln("%s = 0;" % entry.cname)
1043
                code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1044

1045 1046 1047
            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
1048
                code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1049
            else:
1050 1051
                warning(self.entry.pos, "Unraisable exception in function '%s'." \
                            % self.entry.qualified_name, 0)
1052 1053 1054 1055
                code.putln(
                    '__Pyx_WriteUnraisable("%s");' % 
                        self.entry.qualified_name)
                env.use_utility_code(unraisable_exception_utility_code)
1056
                env.use_utility_code(restore_exception_utility_code)
1057 1058 1059 1060 1061 1062 1063 1064
            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))
1065 1066 1067 1068 1069 1070 1071 1072

            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:
1073 1074
                code.put_goto(code.return_from_error_cleanup_label)

1075

1076
        # ----- Non-error return cleanup
1077 1078 1079
        # 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
1080
        code.put_label(code.return_label)
1081
        for entry in lenv.buffer_entries:
1082 1083
            if entry.used:
                code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1084 1085
        if is_getbuffer_slot:
            self.getbuffer_normal_cleanup(code)
1086 1087
        # ----- 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
1088 1089 1090 1091
        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
1092
        code.put_var_decrefs(lenv.var_entries, used_only = 1)
Robert Bradshaw's avatar
Robert Bradshaw committed
1093
        # Decref any increfed args
1094
        for entry in lenv.arg_entries:
Robert Bradshaw's avatar
Robert Bradshaw committed
1095
            if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1096
                code.put_var_decref(entry)
1097 1098
        if acquire_gil:
            code.putln("PyGILState_Release(_save);")
1099
        # code.putln("/* TODO: decref scope object */")
1100
        # ----- Return
William Stein's avatar
William Stein committed
1101
        if not self.return_type.is_void:
1102
            code.putln("return %s;" % Naming.retval_cname)
William Stein's avatar
William Stein committed
1103
        code.putln("}")
1104 1105
        # ----- Go back and insert temp variable declarations
        tempvardecl_code.put_var_declarations(lenv.temp_entries)
1106
        tempvardecl_code.put_temp_declarations(code.funcstate)
1107
        # ----- Python version
1108
        code.exit_cfunc_scope()
1109
        if self.py_func:
1110
            self.py_func.generate_function_definitions(env, code)
1111
        self.generate_wrapper_functions(code)
William Stein's avatar
William Stein committed
1112 1113 1114 1115 1116 1117 1118 1119

    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)
1120 1121
        
    def generate_wrapper_functions(self, code):
William Stein's avatar
William Stein committed
1122 1123 1124
        pass

    def generate_execution_code(self, code):
1125 1126 1127 1128
        # Evaluate and store argument default values
        for arg in self.args:
            default = arg.default
            if default:
1129 1130 1131
                if not default.is_literal:
                    default.generate_evaluation_code(code)
                    default.make_owned_reference(code)
1132
                    code.putln(
1133 1134 1135 1136 1137 1138
                        "%s = %s;" % (
                            arg.default_entry.cname,
                            default.result_as(arg.default_entry.type)))
                    if default.is_temp and default.type.is_pyobject:
                        code.putln(
                            "%s = 0;" %
1139
                                default.result())
1140 1141 1142
        # 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
1143

1144
    #
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1145
    # Special code for the __getbuffer__ function
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
    #
    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) 
        code.putln("%s->obj = Py_None; Py_INCREF(Py_None);" % info)

    def getbuffer_error_cleanup(self, code):
        info = self.local_scope.arg_entries[1].cname
        code.putln("Py_DECREF(%s->obj); %s->obj = NULL;" %
                   (info, info))

    def getbuffer_normal_cleanup(self, code):
        info = self.local_scope.arg_entries[1].cname
        code.putln("if (%s->obj == Py_None) { Py_DECREF(Py_None); %s->obj = NULL; }" %
                   (info, info))
William Stein's avatar
William Stein committed
1164 1165 1166 1167

class CFuncDefNode(FuncDefNode):
    #  C function definition.
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
1168
    #  modifiers     ['inline']
William Stein's avatar
William Stein committed
1169 1170 1171 1172
    #  visibility    'private' or 'public' or 'extern'
    #  base_type     CBaseTypeNode
    #  declarator    CDeclaratorNode
    #  body          StatListNode
1173
    #  api           boolean
William Stein's avatar
William Stein committed
1174
    #
1175
    #  with_gil      boolean    Acquire GIL around body
William Stein's avatar
William Stein committed
1176
    #  type          CFuncType
1177
    #  py_func       wrapper for calling from Python
1178
    #  overridable   whether or not this is a cpdef function
William Stein's avatar
William Stein committed
1179
    
1180
    child_attrs = ["base_type", "declarator", "body", "py_func"]
1181
    
William Stein's avatar
William Stein committed
1182 1183 1184 1185
    def unqualified_name(self):
        return self.entry.name
        
    def analyse_declarations(self, env):
1186 1187 1188 1189 1190
        if 'locals' in env.directives:
            directive_locals = env.directives['locals']
        else:
            directive_locals = {}
        self.directive_locals = directive_locals
William Stein's avatar
William Stein committed
1191
        base_type = self.base_type.analyse(env)
1192 1193
        # 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))
1194 1195 1196
        if not type.is_cfunction:
            error(self.pos, 
                "Suite attached to non-function declaration")
William Stein's avatar
William Stein committed
1197 1198 1199 1200 1201
        # 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
1202
        type.is_overridable = self.overridable
1203 1204 1205 1206 1207
        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):
1208 1209
            formal_arg.type = type_arg.type
            formal_arg.cname = type_arg.cname
William Stein's avatar
William Stein committed
1210 1211 1212 1213 1214
        name = name_declarator.name
        cname = name_declarator.cname
        self.entry = env.declare_cfunction(
            name, type, self.pos, 
            cname = cname, visibility = self.visibility,
1215 1216
            defining = self.body is not None,
            api = self.api)
William Stein's avatar
William Stein committed
1217
        self.return_type = type.return_type
1218
        
1219
        if self.overridable:
1220
            import ExprNodes
1221
            py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1222
            self.py_func = DefNode(pos = self.pos, 
1223 1224
                                   name = self.entry.name,
                                   args = self.args,
1225 1226
                                   star_arg = None,
                                   starstar_arg = None,
1227
                                   doc = self.doc,
1228 1229
                                   body = py_func_body,
                                   is_wrapper = 1)
1230
            self.py_func.is_module_scope = env.is_module_scope
1231
            self.py_func.analyse_declarations(env)
1232
            self.entry.as_variable = self.py_func.entry
1233 1234
            # Reset scope entry the above cfunction
            env.entries[name] = self.entry
1235 1236
            self.py_func.interned_attr_cname = env.intern_identifier(
                self.py_func.entry.name)
1237 1238 1239
            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])
1240
    
1241
    def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1242 1243 1244 1245 1246
        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]
1247
        if is_module_scope:
1248
            cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1249 1250
        else:
            self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1251
            cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1252 1253
        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)
1254
        return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1255
    
William Stein's avatar
William Stein committed
1256 1257 1258 1259 1260 1261
    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)
            
1262
    def need_gil_acquisition(self, lenv):
1263
        type = self.type
1264
        with_gil = self.type.with_gil
1265 1266 1267 1268
        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")
1269 1270 1271 1272 1273
            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

1274 1275 1276 1277 1278
    def analyse_expressions(self, env):
        self.analyse_default_values(env)
        if self.overridable:
            self.py_func.analyse_expressions(env)

1279
    def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
William Stein's avatar
William Stein committed
1280 1281
        arg_decls = []
        type = self.type
Stefan Behnel's avatar
Stefan Behnel committed
1282
        visibility = self.entry.visibility
1283
        for arg in type.args[:len(type.args)-type.optional_arg_count]:
William Stein's avatar
William Stein committed
1284
            arg_decls.append(arg.declaration_code())
1285 1286
        if with_dispatch and self.overridable:
            arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1287 1288
        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
1289 1290 1291 1292
        if type.has_varargs:
            arg_decls.append("...")
        if not arg_decls:
            arg_decls = ["void"]
1293 1294
        if cname is None:
            cname = self.entry.func_cname
1295
        entity = type.function_header_code(cname, string.join(arg_decls, ", "))
Stefan Behnel's avatar
Stefan Behnel committed
1296
        if visibility == 'public':
William Stein's avatar
William Stein committed
1297 1298 1299 1300 1301
            dll_linkage = "DL_EXPORT"
        else:
            dll_linkage = None
        header = self.return_type.declaration_code(entity,
            dll_linkage = dll_linkage)
1302
        if visibility == 'extern':
William Stein's avatar
William Stein committed
1303
            storage_class = "%s " % Naming.extern_c_macro
1304 1305
        elif visibility == 'public':
            storage_class = ""
William Stein's avatar
William Stein committed
1306
        else:
Stefan Behnel's avatar
Stefan Behnel committed
1307
            storage_class = "static "
Robert Bradshaw's avatar
Robert Bradshaw committed
1308
        code.putln("%s%s %s {" % (
William Stein's avatar
William Stein committed
1309
            storage_class,
1310
            ' '.join(self.modifiers).upper(), # macro forms 
William Stein's avatar
William Stein committed
1311 1312 1313
            header))

    def generate_argument_declarations(self, env, code):
1314
        for arg in self.args:
1315
            if arg.default:
1316
                    code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1317

William Stein's avatar
William Stein committed
1318 1319 1320
    def generate_keyword_list(self, code):
        pass
        
1321
    def generate_argument_parsing_code(self, env, code):
1322
        i = 0
1323 1324
        if self.type.optional_arg_count:
            code.putln('if (%s) {' % Naming.optional_args_cname)
1325
            for arg in self.args:
1326
                if arg.default:
1327
                    code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1328 1329 1330 1331
                    declarator = arg.declarator
                    while not hasattr(declarator, 'name'):
                        declarator = declarator.base
                    code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1332 1333 1334
                    i += 1
            for _ in range(self.type.optional_arg_count):
                code.putln('}')
1335
            code.putln('}')
William Stein's avatar
William Stein committed
1336 1337 1338 1339 1340
    
    def generate_argument_conversion_code(self, code):
        pass
    
    def generate_argument_type_tests(self, code):
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
        # 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
1351
            arg_code = "((PyObject *)%s)" % arg.cname
1352
            code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
1353
                'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1354 1355 1356 1357
                    arg_code, 
                    typeptr_cname,
                    not arg.not_none,
                    arg.name,
Robert Bradshaw's avatar
Robert Bradshaw committed
1358
                    type.is_builtin_type,
1359 1360 1361 1362
                    code.error_goto(arg.pos)))
        else:
            error(arg.pos, "Cannot test type of extern C class "
                "without type object name specification")
1363

William Stein's avatar
William Stein committed
1364 1365 1366 1367
    def error_value(self):
        if self.return_type.is_pyobject:
            return "0"
        else:
1368 1369
            #return None
            return self.entry.type.exception_value
William Stein's avatar
William Stein committed
1370 1371
            
    def caller_will_check_exceptions(self):
1372
        return self.entry.type.exception_check
1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383
        
    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)
1384
            code.putln()
1385 1386 1387 1388 1389
            self.generate_function_header(code, 
                                          0,
                                          with_dispatch = entry.type.is_overridable, 
                                          with_opt_args = entry.type.optional_arg_count, 
                                          cname = entry.func_cname)
1390 1391 1392 1393
            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]]
1394 1395 1396 1397 1398 1399 1400 1401
            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')
1402 1403
            code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
            code.putln('}')
1404
        
William Stein's avatar
William Stein committed
1405 1406 1407 1408 1409 1410 1411

class PyArgDeclNode(Node):
    # Argument which must be a Python object (used
    # for * and ** arguments).
    #
    # name   string
    # entry  Symtab.Entry
1412
    child_attrs = []
William Stein's avatar
William Stein committed
1413
    
1414 1415 1416 1417 1418 1419 1420

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

William Stein's avatar
William Stein committed
1421 1422 1423 1424 1425

class DefNode(FuncDefNode):
    # A Python function definition.
    #
    # name          string                 the Python name of the function
1426
    # decorators    [DecoratorNode]        list of decorators
William Stein's avatar
William Stein committed
1427 1428 1429
    # args          [CArgDeclNode]         formal arguments
    # star_arg      PyArgDeclNode or None  * argument
    # starstar_arg  PyArgDeclNode or None  ** argument
1430
    # doc           EncodedString or None
William Stein's avatar
William Stein committed
1431 1432 1433 1434 1435 1436 1437
    # body          StatListNode
    #
    #  The following subnode is constructed internally
    #  when the def statement is inside a Python class definition.
    #
    #  assmt   AssignmentNode   Function construction/assignment
    
1438
    child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1439

William Stein's avatar
William Stein committed
1440
    assmt = None
1441
    num_kwonly_args = 0
1442
    num_required_kw_args = 0
1443
    reqd_kw_flags_cname = "0"
1444
    is_wrapper = 0
1445
    decorators = None
1446 1447
    entry = None
    
1448

1449 1450
    def __init__(self, pos, **kwds):
        FuncDefNode.__init__(self, pos, **kwds)
1451
        k = rk = r = 0
1452 1453
        for arg in self.args:
            if arg.kw_only:
1454
                k += 1
1455
                if not arg.default:
1456 1457 1458 1459 1460 1461
                    rk += 1
            if not arg.default:
                r += 1
        self.num_kwonly_args = k
        self.num_required_kw_args = rk
        self.num_required_args = r
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500
        
    def as_cfunction(self, cfunc):
        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")
        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 PyrexTypes.py_object_type or formal_arg.is_self:
                formal_arg.type = type_arg.type
                formal_arg.name_declarator = name_declarator
        import ExprNodes
        if cfunc.type.exception_value is None:
            exception_value = None
        else:
            exception_value = ExprNodes.ConstNode(self.pos, value=cfunc.type.exception_value, type=cfunc.type.return_type)
        declarator = CFuncDeclaratorNode(self.pos, 
                                         base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
                                         args = self.args,
                                         has_varargs = False,
                                         exception_check = cfunc.type.exception_check,
                                         exception_value = exception_value,
                                         with_gil = cfunc.type.with_gil,
                                         nogil = cfunc.type.nogil)
        return CFuncDefNode(self.pos, 
                            modifiers = [],
                            base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc.type.return_type),
                            declarator = declarator,
                            body = self.body,
                            doc = self.doc,
                            overridable = cfunc.type.is_overridable,
                            type = cfunc.type,
                            with_gil = cfunc.type.with_gil,
                            nogil = cfunc.type.nogil,
                            visibility = 'private',
                            api = False)
1501
    
William Stein's avatar
William Stein committed
1502
    def analyse_declarations(self, env):
1503 1504 1505 1506 1507
        if 'locals' in env.directives:
            directive_locals = env.directives['locals']
        else:
            directive_locals = {}
        self.directive_locals = directive_locals
William Stein's avatar
William Stein committed
1508 1509 1510 1511 1512
        for arg in self.args:
            base_type = arg.base_type.analyse(env)
            name_declarator, type = \
                arg.declarator.analyse(base_type, env)
            arg.name = name_declarator.name
1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523
            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
William Stein's avatar
William Stein committed
1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537
            if name_declarator.cname:
                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()
1538

William Stein's avatar
William Stein committed
1539 1540
    def analyse_signature(self, env):
        any_type_tests_needed = 0
1541
        # Use the simpler calling signature for zero- and one-argument functions.
1542
        if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1543
            if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1544 1545
                if len(self.args) == 0:
                    self.entry.signature = TypeSlots.pyfunction_noargs
1546 1547 1548
                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
1549 1550 1551
            elif self.entry.signature is TypeSlots.pymethod_signature:
                if len(self.args) == 1:
                    self.entry.signature = TypeSlots.unaryfunc
1552 1553 1554
                elif len(self.args) == 2:
                    if self.args[1].default is None and not self.args[1].kw_only:
                        self.entry.signature = TypeSlots.ibinaryfunc
1555 1556
        elif self.entry.is_special:
            self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
William Stein's avatar
William Stein committed
1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585
        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
1586 1587
                if arg.is_generic and \
                        (arg.type.is_extension_type or arg.type.is_builtin_type):
William Stein's avatar
William Stein committed
1588 1589
                    arg.needs_type_test = 1
                    any_type_tests_needed = 1
1590 1591 1592 1593 1594 1595
                elif arg.type is PyrexTypes.c_py_ssize_t_type:
                    # Want to use __index__ rather than __int__ method
                    # that PyArg_ParseTupleAndKeywords calls
                    arg.needs_conversion = 1
                    arg.hdr_type = PyrexTypes.py_object_type
                    arg.hdr_cname = Naming.arg_prefix + arg.name
William Stein's avatar
William Stein committed
1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612
        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))
1613 1614 1615

    def signature_has_nongeneric_args(self):
        argcount = len(self.args)
Stefan Behnel's avatar
Stefan Behnel committed
1616
        if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1617 1618 1619 1620 1621
            return 0
        return 1

    def signature_has_generic_args(self):
        return self.entry.signature.has_generic_args
William Stein's avatar
William Stein committed
1622 1623
    
    def declare_pyfunction(self, env):
1624 1625
        #print "DefNode.declare_pyfunction:", self.name, "in", env ###
        name = self.name
1626 1627 1628
        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)
1629 1630 1631 1632
        entry = env.declare_pyfunction(self.name, self.pos)
        self.entry = entry
        prefix = env.scope_prefix
        entry.func_cname = \
1633
            Naming.pyfunc_prefix + prefix + name
1634 1635
        entry.pymethdef_cname = \
            Naming.pymethdef_prefix + prefix + name
1636 1637
        if Options.docstrings:
            entry.doc = embed_position(self.pos, self.doc)
1638 1639
            entry.doc_cname = \
                Naming.funcdoc_prefix + prefix + name
1640 1641
        else:
            entry.doc = None
1642

William Stein's avatar
William Stein committed
1643 1644 1645 1646 1647 1648
    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)
1649 1650
                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
1651 1652 1653 1654 1655
                if arg.type.is_pyobject:
                    arg.entry.init = "0"
                arg.entry.init_to_none = 0
            else:
                arg.entry = self.declare_argument(env, arg)
1656
            arg.entry.used = 1
William Stein's avatar
William Stein committed
1657
            arg.entry.is_self_arg = arg.is_self_arg
1658 1659 1660 1661
            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
1662 1663 1664 1665 1666 1667 1668 1669 1670
            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:
1671
            entry = env.declare_var(arg.name, 
William Stein's avatar
William Stein committed
1672
                PyrexTypes.py_object_type, arg.pos)
1673 1674 1675 1676 1677
            entry.used = 1
            entry.init = "0"
            entry.init_to_none = 0
            entry.xdecref_cleanup = 1
            arg.entry = entry
1678
            env.control_flow.set_state((), (arg.name, 'initalized'), True)
William Stein's avatar
William Stein committed
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695
            
    def analyse_expressions(self, env):
        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)
            
1696
    def generate_function_header(self, code, with_pymethdef, proto_only=0):
William Stein's avatar
William Stein committed
1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708
        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))
1709
        if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1710
            arg_code_list.append("PyObject *unused")
William Stein's avatar
William Stein committed
1711 1712 1713 1714 1715 1716 1717 1718
        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)
1719 1720
        if proto_only:
            return
1721
        if self.entry.doc and Options.docstrings:
1722 1723 1724
            docstr = self.entry.doc
            if not isinstance(docstr, str):
                docstr = docstr.utf8encode()
William Stein's avatar
William Stein committed
1725 1726 1727
            code.putln(
                'static char %s[] = "%s";' % (
                    self.entry.doc_cname,
1728
                    split_docstring(escape_byte_string(docstr))))
William Stein's avatar
William Stein committed
1729 1730 1731 1732 1733 1734 1735 1736 1737 1738
        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:
1739 1740 1741 1742
                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
1743 1744
    
    def generate_keyword_list(self, code):
1745 1746
        if self.signature_has_generic_args() and \
                self.signature_has_nongeneric_args():
William Stein's avatar
William Stein committed
1747
            code.put(
1748 1749
                "static PyObject **%s[] = {" %
                    Naming.pykwdlist_cname)
William Stein's avatar
William Stein committed
1750 1751
            for arg in self.args:
                if arg.is_generic:
1752
                    code.put('&%s,' % arg.name_entry.pystring_cname)
1753
            code.putln("0};")
1754

1755
    def generate_argument_parsing_code(self, env, code):
William Stein's avatar
William Stein committed
1756 1757
        # Generate PyArg_ParseTuple call for generic
        # arguments, if any.
1758 1759 1760 1761
        if self.entry.signature.has_dummy_arg:
            # get rid of unused argument warning
            code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))

1762 1763
        old_error_label = code.new_error_label()
        our_error_label = code.error_label
Stefan Behnel's avatar
Stefan Behnel committed
1764
        end_label = code.new_label("argument_unpacking_done")
1765

1766 1767 1768
        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
1769

1770
        if not self.signature_has_generic_args():
1771 1772
            if has_star_or_kw_args:
                error(self.pos, "This method cannot have * or keyword arguments")
1773
            self.generate_argument_conversion_code(code)
1774

1775 1776
        elif not self.signature_has_nongeneric_args():
            # func(*args) or func(**kw) or func(*args, **kw)
1777
            self.generate_stararg_copy_code(code)
1778

1779
        else:
1780
            positional_args = []
1781
            kw_only_args = []
William Stein's avatar
William Stein committed
1782 1783 1784 1785 1786 1787 1788 1789
            default_seen = 0
            for arg in self.args:
                arg_entry = arg.entry
                if arg.is_generic:
                    if arg.default:
                        code.putln(
                            "%s = %s;" % (
                                arg_entry.cname,
1790
                                arg.default_result_code))
William Stein's avatar
William Stein committed
1791
                        default_seen = 1
1792 1793 1794 1795 1796
                        if not arg.is_self_arg:
                            if arg.kw_only:
                                kw_only_args.append(arg)
                            else:
                                positional_args.append(arg)
1797
                    elif arg.kw_only:
1798
                        kw_only_args.append(arg)
1799
                        default_seen = 1
1800
                    elif default_seen:
William Stein's avatar
William Stein committed
1801
                        error(arg.pos, "Non-default argument following default argument")
1802 1803
                    elif not arg.is_self_arg:
                        positional_args.append(arg)
1804 1805 1806 1807
                    if arg.needs_conversion:
                        format = arg.hdr_type.parsetuple_format
                    else:
                        format = arg_entry.type.parsetuple_format
1808 1809 1810 1811
                    if not format:
                        error(arg.pos,
                              "Cannot convert Python object argument to type '%s' (when parsing input arguments)"
                              % arg.type)
1812

1813
            self.generate_tuple_and_keyword_parsing_code(
1814
                positional_args, kw_only_args, end_label, code)
1815

1816 1817
        code.error_label = old_error_label
        if code.label_used(our_error_label):
1818 1819
            if not code.label_used(end_label):
                code.put_goto(end_label)
1820 1821 1822 1823 1824 1825 1826 1827
            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)
1828
            code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1829
            code.putln("return %s;" % self.error_value())
1830
        if code.label_used(end_label):
1831 1832
            code.put_label(end_label)

1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845
    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)))
1846
            else:
1847
                error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
William Stein's avatar
William Stein committed
1848 1849 1850 1851 1852
    
    def generate_arg_xdecref(self, arg, code):
        if arg:
            code.put_var_xdecref(arg.entry)
    
1853 1854 1855
    def generate_arg_decref(self, arg, code):
        if arg:
            code.put_var_decref(arg.entry)
William Stein's avatar
William Stein committed
1856

1857 1858
    def generate_stararg_copy_code(self, code):
        if not self.star_arg:
1859 1860 1861 1862 1863 1864
            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("}")
1865

1866 1867
        code.globalstate.use_utility_code(keyword_string_check_utility_code)

1868 1869 1870 1871 1872 1873 1874 1875
        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)
1876
        code.putln(
1877 1878
            "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
                kwarg_check, Naming.kwds_cname, self.name,
1879
                bool(self.starstar_arg), self.error_value()))
1880

1881
        if self.starstar_arg:
1882
            code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
1883 1884 1885
                    self.starstar_arg.entry.cname,
                    Naming.kwds_cname,
                    Naming.kwds_cname))
1886 1887
            code.putln("if (unlikely(!%s)) return %s;" % (
                    self.starstar_arg.entry.cname, self.error_value()))
1888 1889
            self.starstar_arg.entry.xdecref_cleanup = 0

1890 1891 1892 1893 1894 1895 1896
        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

1897
    def generate_tuple_and_keyword_parsing_code(self, positional_args,
1898 1899
                                                kw_only_args, success_label, code):
        argtuple_error_label = code.new_label("argtuple_error")
1900

1901 1902 1903 1904
        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)
1905 1906
        has_fixed_positional_count = not self.star_arg and \
            min_positional_args == max_positional_args
1907

1908
        code.globalstate.use_utility_code(raise_double_keywords_utility_code)
Stefan Behnel's avatar
Stefan Behnel committed
1909 1910 1911 1912
        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)

1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923
        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:
            code.putln("if (likely(%s)) {" % Naming.kwds_cname)
        else:
            code.putln("if (unlikely(%s) && (PyDict_Size(%s) > 0)) {" % (
                    Naming.kwds_cname, Naming.kwds_cname))
        self.generate_keyword_unpacking_code(
            min_positional_args, max_positional_args,
1924
            has_fixed_positional_count,
1925 1926 1927
            positional_args, kw_only_args, argtuple_error_label, code)

        # --- optimised code when we do not receive any keyword arguments
1928
        if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
1929 1930 1931 1932 1933 1934 1935 1936 1937
            # 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)
1938

1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953
        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
                    code.put('__Pyx_RaiseKeywordRequired("%s", *%s[%d]); ' % (
                            self.name.utf8encode(), Naming.pykwdlist_cname,
                            len(positional_args) + i))
                    code.putln(code.error_goto(self.pos))
                    break
1954

1955 1956 1957 1958 1959 1960 1961
        elif min_positional_args == max_positional_args:
            # parse the exact number of positional arguments from the
            # args tuple
            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)
1962

1963 1964 1965 1966 1967
        else:
            # parse the positional arguments from the variable length
            # args tuple
            code.putln('} else {')
            code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
1968 1969
            if self.star_arg:
                code.putln('default:')
1970 1971 1972 1973 1974 1975 1976 1977 1978
            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
1979 1980 1981
            if min_positional_args == 0:
                code.put('case  0: ')
            code.putln('break;')
1982 1983 1984 1985 1986 1987
            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:
1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003
                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))

    def generate_stararg_init_code(self, max_positional_args, code):
2004
        if self.starstar_arg:
2005
            self.starstar_arg.entry.xdecref_cleanup = 0
Stefan Behnel's avatar
Stefan Behnel committed
2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030
            code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
                    self.starstar_arg.entry.cname,
                    self.starstar_arg.entry.cname,
                    self.error_value()))
        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))
            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('}')
2031

2032
    def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2033 2034
                                        has_fixed_positional_count, positional_args,
                                        kw_only_args, argtuple_error_label, code):
2035 2036 2037
        all_args = tuple(positional_args) + tuple(kw_only_args)
        max_args = len(all_args)

2038 2039 2040
        code.putln("PyObject* values[%d] = {%s};" % (
                max_args, ('0,'*max_args)[:-1]))
        code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2041 2042
                   Naming.kwds_cname)

Stefan Behnel's avatar
Stefan Behnel committed
2043
        # parse the tuple and check that it's not too long
2044
        code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
Stefan Behnel's avatar
Stefan Behnel committed
2045 2046
        if self.star_arg:
            code.putln('default:')
2047
        for i in range(max_positional_args-1, -1, -1):
2048
            code.put('case %2d: ' % (i+1))
2049 2050
            code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
                    i, Naming.args_cname, i))
2051
        code.putln('case  0: break;')
2052
        if not self.star_arg:
Stefan Behnel's avatar
Stefan Behnel committed
2053
            code.put('default: ') # more arguments than allowed
2054
            code.put_goto(argtuple_error_label)
2055 2056
        code.putln('}')

2057 2058 2059 2060
        # now fill up the arguments with values from the kw dict
        code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
        for i, arg in enumerate(all_args):
            if i <= max_positional_args:
Stefan Behnel's avatar
Stefan Behnel committed
2061 2062 2063
                if self.star_arg and i == max_positional_args:
                    code.putln('default:')
                else:
2064
                    code.putln('case %2d:' % i)
2065 2066
            code.putln('values[%d] = PyDict_GetItem(%s, *%s[%d]);' % (
                    i, Naming.kwds_cname, Naming.pykwdlist_cname, i))
Stefan Behnel's avatar
Stefan Behnel committed
2067 2068
            if i < min_positional_args:
                code.putln('if (likely(values[%d])) kw_args--;' % i);
2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082
                if i == 0:
                    # special case: we know arg 0 is missing
                    code.put('else ')
                    code.put_goto(argtuple_error_label)
                else:
                    # provide 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('}')
2083
            else:
Stefan Behnel's avatar
Stefan Behnel committed
2084 2085 2086 2087 2088 2089 2090
                code.putln('if (values[%d]) kw_args--;' % i);
                if arg.kw_only and not arg.default:
                    code.putln('else {')
                    code.put('__Pyx_RaiseKeywordRequired("%s", *%s[%d]); ' %(
                            self.name.utf8encode(), Naming.pykwdlist_cname, i))
                    code.putln(code.error_goto(self.pos))
                    code.putln('}')
2091
        code.putln('}')
2092

2093
        code.putln('if (unlikely(kw_args > 0)) {')
Stefan Behnel's avatar
Stefan Behnel committed
2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109
        # non-positional kw args left in the dict: **kwargs or error
        if self.star_arg:
            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
        code.globalstate.use_utility_code(split_keywords_utility_code)
        code.put(
            'if (unlikely(__Pyx_SplitKeywords(%s, %s, %s, %s, "%s") < 0)) ' % (
                Naming.kwds_cname,
                Naming.pykwdlist_cname,
                self.starstar_arg and self.starstar_arg.entry.cname or '0',
                pos_arg_count,
                self.name.utf8encode()))
2110 2111 2112
        code.putln(code.error_goto(self.pos))
        code.putln('}')

2113
        # convert arg values to their final type and assign them
2114
        for i, arg in enumerate(all_args):
2115 2116 2117
            if arg.default:
                code.putln("if (values[%d]) {" % i)
            self.generate_arg_assignment(arg, "values[%d]" % i, code)
2118
            if arg.default:
2119
                code.putln('}')
2120

William Stein's avatar
William Stein committed
2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132
    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
2133 2134 2135 2136
            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
2137
            self.generate_arg_conversion_from_pyobject(arg, code)
Robert Bradshaw's avatar
Robert Bradshaw committed
2138
            code.putln("}")
William Stein's avatar
William Stein committed
2139 2140 2141 2142 2143 2144 2145 2146
        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,
2147
                    "Cannot convert 1 argument from '%s' to '%s'" %
William Stein's avatar
William Stein committed
2148 2149 2150 2151 2152
                        (old_type, new_type))
    
    def generate_arg_conversion_from_pyobject(self, arg, code):
        new_type = arg.type
        func = new_type.from_py_function
2153
        # copied from CoerceFromPyTypeNode
William Stein's avatar
William Stein committed
2154
        if func:
Robert Bradshaw's avatar
Robert Bradshaw committed
2155
            code.putln("%s = %s(%s); %s" % (
William Stein's avatar
William Stein committed
2156 2157 2158
                arg.entry.cname,
                func,
                arg.hdr_cname,
2159
                code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
William Stein's avatar
William Stein committed
2160 2161 2162 2163 2164 2165 2166 2167 2168
        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
2169
            code.putln("%s = %s(%s); %s" % (
William Stein's avatar
William Stein committed
2170 2171 2172
                arg.entry.cname,
                func,
                arg.hdr_cname,
Robert Bradshaw's avatar
Robert Bradshaw committed
2173
                code.error_goto_if_null(arg.entry.cname, arg.pos)))
William Stein's avatar
William Stein committed
2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192
        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
2193
                'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
William Stein's avatar
William Stein committed
2194 2195 2196 2197
                    arg_code, 
                    typeptr_cname,
                    not arg.not_none,
                    arg.name,
Robert Bradshaw's avatar
Robert Bradshaw committed
2198
                    arg.type.is_builtin_type,
William Stein's avatar
William Stein committed
2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209
                    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
            
2210 2211 2212 2213 2214 2215 2216 2217 2218 2219
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
2220
    child_attrs = ['body']
2221 2222
    
    body = None
Robert Bradshaw's avatar
Robert Bradshaw committed
2223

2224 2225
    def analyse_expressions(self, env):
        self.args = env.arg_entries
2226 2227 2228 2229
        if self.py_func.is_module_scope:
            first_arg = 0
        else:
            first_arg = 1
2230 2231
        import ExprNodes
        self.func_node = ExprNodes.PyTempNode(self.pos, env)
2232
        call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2233 2234
        call_node = ExprNodes.SimpleCallNode(self.pos,
                                             function=self.func_node, 
2235
                                             args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2236 2237 2238 2239 2240
        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
2241 2242 2243 2244
        if self.py_func.is_module_scope:
            self_arg = "((PyObject *)%s)" % Naming.module_cname
        else:
            self_arg = "((PyObject *)%s)" % self.args[0].cname
2245
        code.putln("/* Check if called by wrapper */")
2246
        code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2247
        code.putln("/* Check if overriden in Python */")
2248 2249 2250
        if self.py_func.is_module_scope:
            code.putln("else {")
        else:
2251
            code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2252
        err = code.error_goto_if_null(self.func_node.result(), self.pos)
2253
        # need to get attribute manually--scope would return cdef method
2254
        code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2255
        # It appears that this type is not anywhere exposed in the Python/C API
2256 2257
        is_builtin_function_or_method = '(strcmp(Py_TYPE(%s)->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result()
        is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2258 2259 2260
        code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
        self.body.generate_execution_code(code)
        code.putln('}')
2261
        code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2262 2263
        code.putln("}")

Robert Bradshaw's avatar
Robert Bradshaw committed
2264 2265
class ClassDefNode(StatNode, BlockNode):
    pass
2266

Robert Bradshaw's avatar
Robert Bradshaw committed
2267
class PyClassDefNode(ClassDefNode):
William Stein's avatar
William Stein committed
2268 2269
    #  A Python class definition.
    #
Stefan Behnel's avatar
Stefan Behnel committed
2270
    #  name     EncodedString   Name of the class
William Stein's avatar
William Stein committed
2271 2272 2273 2274 2275 2276 2277 2278 2279 2280
    #  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
2281 2282

    child_attrs = ["body", "dict", "classobj", "target"]
William Stein's avatar
William Stein committed
2283 2284 2285 2286 2287 2288 2289 2290
    
    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 = [])
2291
        if self.doc and Options.docstrings:
2292
            doc = embed_position(self.pos, self.doc)
2293
            doc_node = ExprNodes.StringNode(pos, value = doc)
William Stein's avatar
William Stein committed
2294 2295
        else:
            doc_node = None
2296
        self.classobj = ExprNodes.ClassNode(pos, name = name,
William Stein's avatar
William Stein committed
2297 2298
            bases = bases, dict = self.dict, doc = doc_node)
        self.target = ExprNodes.NameNode(pos, name = name)
2299
        
2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336
    def as_cclass(self):
        """
        Return this node as if it were declared as an extension class"
        """
        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 = []
            while isinstance(base, ExprNodes.AttributeNode):
                path.insert(0, base.attribute)
                base = base.obj
            if isinstance(base, ExprNodes.NameNode):
                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)
        
2337 2338 2339 2340 2341 2342
    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
2343 2344 2345
    
    def analyse_declarations(self, env):
        self.target.analyse_target_declaration(env)
2346 2347 2348
        cenv = self.create_scope(env)
        cenv.class_obj_cname = self.target.entry.cname
        self.body.analyse_declarations(cenv)
William Stein's avatar
William Stein committed
2349 2350 2351 2352 2353
    
    def analyse_expressions(self, env):
        self.dict.analyse_expressions(env)
        self.classobj.analyse_expressions(env)
        genv = env.global_scope()
2354
        cenv = self.scope
2355 2356
        cenv.class_dict_cname = self.dict.result()
        cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
William Stein's avatar
William Stein committed
2357
        self.body.analyse_expressions(cenv)
2358
        self.target.analyse_target_expression(env, self.classobj)
William Stein's avatar
William Stein committed
2359
        self.dict.release_temp(env)
2360 2361
        #self.classobj.release_temp(env)
        #self.target.release_target_temp(env)
William Stein's avatar
William Stein committed
2362
    
2363
    def generate_function_definitions(self, env, code):
William Stein's avatar
William Stein committed
2364
        self.generate_py_string_decls(self.scope, code)
2365
        self.body.generate_function_definitions(self.scope, code)
William Stein's avatar
William Stein committed
2366 2367 2368 2369 2370 2371 2372 2373 2374
    
    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)


Robert Bradshaw's avatar
Robert Bradshaw committed
2375
class CClassDefNode(ClassDefNode):
William Stein's avatar
William Stein committed
2376 2377 2378 2379
    #  An extension type definition.
    #
    #  visibility         'private' or 'public' or 'extern'
    #  typedef_flag       boolean
Stefan Behnel's avatar
Stefan Behnel committed
2380
    #  api                boolean
William Stein's avatar
William Stein committed
2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392
    #  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
2393 2394
    #  buffer_defaults_node DictNode or None Declares defaults for a buffer
    #  buffer_defaults_pos
2395

2396
    child_attrs = ["body"]
2397 2398
    buffer_defaults_node = None
    buffer_defaults_pos = None
2399 2400 2401 2402
    typedef_flag = False
    api = False
    objstruct_name = None
    typeobj_name = None
2403

William Stein's avatar
William Stein committed
2404 2405 2406 2407
    def analyse_declarations(self, env):
        #print "CClassDefNode.analyse_declarations:", self.class_name
        #print "...visibility =", self.visibility
        #print "...module_name =", self.module_name
2408 2409 2410 2411 2412 2413 2414 2415 2416

        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
2417 2418 2419 2420
        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
2421 2422 2423 2424 2425 2426 2427 2428 2429
        # 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)
2430
                self.module.has_extern_class = 1
2431
                env.cimported_modules.append(self.module)
2432

William Stein's avatar
William Stein committed
2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449
        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
            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
2450
        if self.module_name and self.visibility != 'extern':
2451 2452 2453 2454 2455 2456 2457
            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
        self.entry = home_scope.declare_c_class(
William Stein's avatar
William Stein committed
2458 2459 2460 2461 2462 2463 2464 2465 2466
            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
2467
            typedef_flag = self.typedef_flag,
2468 2469
            api = self.api,
            buffer_defaults = buffer_defaults)
2470 2471
        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
2472
        scope = self.entry.type.scope
2473

2474
        if self.doc and Options.docstrings:
2475
            scope.doc = embed_position(self.pos, self.doc)
2476
            
William Stein's avatar
William Stein committed
2477 2478 2479 2480 2481 2482 2483 2484 2485 2486
        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
2487 2488
            scope = self.entry.type.scope
            self.body.analyse_expressions(scope)
William Stein's avatar
William Stein committed
2489
    
2490
    def generate_function_definitions(self, env, code):
2491
        self.generate_py_string_decls(self.entry.type.scope, code)
William Stein's avatar
William Stein committed
2492 2493
        if self.body:
            self.body.generate_function_definitions(
2494
                self.entry.type.scope, code)
William Stein's avatar
William Stein committed
2495 2496 2497 2498 2499 2500
    
    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)
2501 2502 2503 2504
            
    def annotate(self, code):
        if self.body:
            self.body.annotate(code)
William Stein's avatar
William Stein committed
2505 2506 2507 2508 2509 2510


class PropertyNode(StatNode):
    #  Definition of a property in an extension type.
    #
    #  name   string
2511
    #  doc    EncodedString or None    Doc string
William Stein's avatar
William Stein committed
2512 2513
    #  body   StatListNode
    
2514 2515
    child_attrs = ["body"]

William Stein's avatar
William Stein committed
2516 2517 2518
    def analyse_declarations(self, env):
        entry = env.declare_property(self.name, self.doc, self.pos)
        if entry:
2519
            if self.doc and Options.docstrings:
2520 2521
                doc_entry = env.get_string_const(
                    self.doc, identifier = False)
William Stein's avatar
William Stein committed
2522 2523
                entry.doc_cname = doc_entry.cname
            self.body.analyse_declarations(entry.scope)
2524

William Stein's avatar
William Stein committed
2525 2526 2527
    def analyse_expressions(self, env):
        self.body.analyse_expressions(env)
    
2528 2529
    def generate_function_definitions(self, env, code):
        self.body.generate_function_definitions(env, code)
William Stein's avatar
William Stein committed
2530 2531 2532 2533

    def generate_execution_code(self, code):
        pass

2534 2535 2536
    def annotate(self, code):
        self.body.annotate(code)

William Stein's avatar
William Stein committed
2537 2538 2539 2540 2541 2542

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

William Stein's avatar
William Stein committed
2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559
    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
2560 2561

    child_attrs = ["expr"]
William Stein's avatar
William Stein committed
2562
    
Robert Bradshaw's avatar
Robert Bradshaw committed
2563 2564 2565
    def analyse_declarations(self, env):
        import ExprNodes
        if isinstance(self.expr, ExprNodes.GeneralCallNode):
2566
            func = self.expr.function.as_cython_attribute()
Robert Bradshaw's avatar
Robert Bradshaw committed
2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578
            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
2579 2580 2581 2582 2583 2584
    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)
2585 2586
        if not self.expr.is_temp and self.expr.result():
            code.putln("%s;" % self.expr.result())
William Stein's avatar
William Stein committed
2587 2588
        self.expr.generate_disposal_code(code)

2589 2590 2591
    def annotate(self, code):
        self.expr.annotate(code)

William Stein's avatar
William Stein committed
2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602

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):
2603 2604 2605 2606 2607 2608 2609
        self.analyse_types(env)
        self.allocate_rhs_temps(env)
        self.allocate_lhs_temps(env)

#	def analyse_expressions(self, env):
#		self.analyse_expressions_1(env)
#		self.analyse_expressions_2(env)
William Stein's avatar
William Stein committed
2610 2611 2612 2613

    def generate_execution_code(self, code):
        self.generate_rhs_evaluation_code(code)
        self.generate_assignment_code(code)
2614
        
William Stein's avatar
William Stein committed
2615 2616 2617 2618 2619 2620 2621 2622

class SingleAssignmentNode(AssignmentNode):
    #  The simplest case:
    #
    #    a = b
    #
    #  lhs      ExprNode      Left hand side
    #  rhs      ExprNode      Right hand side
2623
    #  first    bool          Is this guaranteed the first assignment to lhs?
2624 2625
    
    child_attrs = ["lhs", "rhs"]
2626
    first = False
2627
    declaration_only = False
William Stein's avatar
William Stein committed
2628 2629

    def analyse_declarations(self, env):
2630 2631 2632 2633
        import ExprNodes
        
        # handle declarations of the form x = cython.foo()
        if isinstance(self.rhs, ExprNodes.CallNode):
2634
            func_name = self.rhs.function.as_cython_attribute()
2635 2636 2637 2638
            if func_name:
                args, kwds = self.rhs.explicit_args_kwds()
                
                if func_name in ['declare', 'typedef']:
Robert Bradshaw's avatar
Robert Bradshaw committed
2639
                    if len(args) > 2 or kwds is not None:
2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656
                        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
2657 2658 2659 2660 2661
                        if len(args) == 2:
                            # we have a value
                            self.rhs = args[1]
                        else:
                            self.declaration_only = True
2662
                    else:
Robert Bradshaw's avatar
Robert Bradshaw committed
2663
                        self.declaration_only = True
2664 2665
                        if not isinstance(lhs, ExprNodes.NameNode):
                            error(lhs.pos, "Invalid declaration.")
2666
                        env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693
                    
                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
2694
    
2695
    def analyse_types(self, env, use_temp = 0):
William Stein's avatar
William Stein committed
2696 2697
        self.rhs.analyse_types(env)
        self.lhs.analyse_target_types(env)
2698
        self.lhs.gil_assignment_check(env)
William Stein's avatar
William Stein committed
2699 2700 2701
        self.rhs = self.rhs.coerce_to(self.lhs.type, env)
        if use_temp:
            self.rhs = self.rhs.coerce_to_temp(env)
2702 2703
    
    def allocate_rhs_temps(self, env):
William Stein's avatar
William Stein committed
2704
        self.rhs.allocate_temps(env)
2705 2706 2707 2708 2709

    def allocate_lhs_temps(self, env):
        self.lhs.allocate_target_temps(env, self.rhs)
        #self.lhs.release_target_temp(env)
        #self.rhs.release_temp(env)		
William Stein's avatar
William Stein committed
2710
    
2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722
#	def analyse_expressions_1(self, env, use_temp = 0):
#		self.rhs.analyse_types(env)
#		self.lhs.analyse_target_types(env)
#		self.rhs = self.rhs.coerce_to(self.lhs.type, env)
#		if use_temp:
#			self.rhs = self.rhs.coerce_to_temp(env)
#		self.rhs.allocate_temps(env)
#	
#	def analyse_expressions_2(self, env):
#		self.lhs.allocate_target_temps(env)
#		self.lhs.release_target_temp(env)
#		self.rhs.release_temp(env)		
2723
        
William Stein's avatar
William Stein committed
2724 2725 2726 2727 2728 2729
    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)

2730 2731 2732 2733
    def annotate(self, code):
        self.lhs.annotate(code)
        self.rhs.annotate(code)

William Stein's avatar
William Stein committed
2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746

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
    
2747
    child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2748
    coerced_rhs_list = None
2749

William Stein's avatar
William Stein committed
2750 2751 2752 2753
    def analyse_declarations(self, env):
        for lhs in self.lhs_list:
            lhs.analyse_target_declaration(env)
    
2754
    def analyse_types(self, env, use_temp = 0):
William Stein's avatar
William Stein committed
2755 2756 2757 2758 2759 2760 2761 2762 2763
        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)
2764
            lhs.gil_assignment_check(env)
William Stein's avatar
William Stein committed
2765 2766 2767
            rhs = CloneNode(self.rhs)
            rhs = rhs.coerce_to(lhs.type, env)
            self.coerced_rhs_list.append(rhs)
2768 2769 2770 2771 2772 2773

    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
2774
            rhs.allocate_temps(env)
2775 2776 2777
            lhs.allocate_target_temps(env, rhs)
            #lhs.release_target_temp(env)
            #rhs.release_temp(env)
William Stein's avatar
William Stein committed
2778
        self.rhs.release_temp(env)
2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800
    
#	def analyse_expressions_1(self, env, use_temp = 0):
#		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)
#		self.rhs.allocate_temps(env)
#	
#	def analyse_expressions_2(self, env):
#		from ExprNodes import CloneNode
#		self.coerced_rhs_list = []
#		for lhs in self.lhs_list:
#			lhs.analyse_target_types(env)
#			rhs = CloneNode(self.rhs)
#			rhs = rhs.coerce_to(lhs.type, env)
#			self.coerced_rhs_list.append(rhs)
#			rhs.allocate_temps(env)
#			lhs.allocate_target_temps(env)
#			lhs.release_target_temp(env)
#			rhs.release_temp(env)
#		self.rhs.release_temp(env)
William Stein's avatar
William Stein committed
2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813
    
    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)

2814 2815 2816 2817 2818 2819 2820
    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
2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834
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
    
2835 2836
    child_attrs = ["stats"]

William Stein's avatar
William Stein committed
2837 2838 2839 2840 2841 2842
    def analyse_declarations(self, env):
        for stat in self.stats:
            stat.analyse_declarations(env)
    
    def analyse_expressions(self, env):
        for stat in self.stats:
2843 2844
            stat.analyse_types(env, use_temp = 1)
            stat.allocate_rhs_temps(env)
William Stein's avatar
William Stein committed
2845
        for stat in self.stats:
2846 2847 2848 2849 2850 2851 2852
            stat.allocate_lhs_temps(env)

#	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
2853 2854 2855 2856 2857 2858 2859
    
    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)

2860 2861 2862 2863 2864
    def annotate(self, code):
        for stat in self.stats:
            stat.annotate(code)


2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883
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).     
    
2884
    child_attrs = ["lhs", "rhs"]
2885
    dup = None
2886

2887 2888
    def analyse_declarations(self, env):
        self.lhs.analyse_target_declaration(env)
2889 2890 2891
        
    def analyse_types(self, env):
        self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
2892 2893
        self.rhs.analyse_types(env)
        self.lhs.analyse_target_types(env)
2894 2895
        if Options.incref_local_binop and self.dup.type.is_pyobject:
            self.dup = self.dup.coerce_to_temp(env)
2896 2897
        
    def allocate_rhs_temps(self, env):
2898
        import ExprNodes
2899 2900 2901
        if self.lhs.type.is_pyobject:
            self.rhs = self.rhs.coerce_to_pyobject(env)
        elif self.rhs.type.is_pyobject:
2902 2903
            self.rhs = self.rhs.coerce_to(self.lhs.type, env)
        if self.lhs.type.is_pyobject:
2904 2905
             self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
             self.result_value.allocate_temps(env)
2906 2907
#        if use_temp:
#            self.rhs = self.rhs.coerce_to_temp(env)
2908
        self.rhs.allocate_temps(env)
2909 2910 2911
        self.dup.allocate_subexpr_temps(env)
        self.dup.allocate_temp(env)
    
2912
    def allocate_lhs_temps(self, env):
2913 2914
        self.lhs.allocate_target_temps(env, self.rhs)
#        self.lhs.release_target_temp(env)
2915 2916 2917
        self.dup.release_temp(env)
        if self.dup.is_temp:
            self.dup.release_subexpr_temps(env)
2918
#        self.rhs.release_temp(env)
2919
        if self.lhs.type.is_pyobject:
2920
            self.result_value.release_temp(env)
2921 2922 2923 2924

    def generate_execution_code(self, code):
        self.rhs.generate_evaluation_code(code)
        self.dup.generate_subexpr_evaluation_code(code)
2925
        # self.dup.generate_result_code is run only if it is not buffer access
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2926 2927 2928 2929
        if self.operator == "**":
            extra = ", Py_None"
        else:
            extra = ""
2930
        import ExprNodes
2931
        if self.lhs.type.is_pyobject:
2932 2933
            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.")
2934
            self.dup.generate_result_code(code)
2935
            code.putln(
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2936
                "%s = %s(%s, %s%s); %s" % (
2937
                    self.result_value.result(), 
2938 2939 2940
                    self.py_operation_function(), 
                    self.dup.py_result(),
                    self.rhs.py_result(),
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2941
                    extra,
2942 2943
                    code.error_goto_if_null(self.result_value.py_result(), self.pos)))
            self.result_value.generate_evaluation_code(code) # May be a type check...
2944 2945
            self.rhs.generate_disposal_code(code)
            self.dup.generate_disposal_code(code)
2946
            self.lhs.generate_assignment_code(self.result_value, code)
2947
        else: 
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
2948 2949 2950 2951 2952 2953 2954 2955
            c_op = self.operator
            if c_op == "//":
                c_op = "/"
            elif c_op == "**":
                if self.lhs.type.is_int and self.rhs.type.is_int:
                    error(self.pos, "** with two C int types is ambiguous")
                else:
                    error(self.pos, "No C inplace power operator")
2956
            # have to do assignment directly to avoid side-effects
2957 2958 2959 2960
            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)
2961
                code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
2962 2963 2964 2965 2966 2967 2968 2969 2970
            self.rhs.generate_disposal_code(code)
        if self.dup.is_temp:
            self.dup.generate_subexpr_disposal_code(code)
            
    def create_dup_node(self, env): 
        import ExprNodes
        self.dup = self.lhs
        self.dup.analyse_types(env)
        if isinstance(self.lhs, ExprNodes.NameNode):
2971 2972 2973
            target_lhs = ExprNodes.NameNode(self.dup.pos,
                                            name = self.dup.name,
                                            is_temp = self.dup.is_temp,
2974
                                            entry = self.dup.entry)
2975
        elif isinstance(self.lhs, ExprNodes.AttributeNode):
2976 2977 2978
            target_lhs = ExprNodes.AttributeNode(self.dup.pos,
                                                 obj = ExprNodes.CloneNode(self.lhs.obj),
                                                 attribute = self.dup.attribute,
2979
                                                 is_temp = self.dup.is_temp)
2980
        elif isinstance(self.lhs, ExprNodes.IndexNode):
2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992
            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,
2993
                                             is_temp = self.dup.is_temp)
2994
        self.lhs = target_lhs
2995
        return self.dup
2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008
    
    def py_operation_function(self):
        return self.py_functions[self.operator]

    py_functions = {
        "|":		"PyNumber_InPlaceOr",
        "^":		"PyNumber_InPlaceXor",
        "&":		"PyNumber_InPlaceAnd",
        "+":		"PyNumber_InPlaceAdd",
        "-":		"PyNumber_InPlaceSubtract",
        "*":		"PyNumber_InPlaceMultiply",
        "/":		"PyNumber_InPlaceDivide",
        "%":		"PyNumber_InPlaceRemainder",
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
3009 3010 3011 3012
        "<<":		"PyNumber_InPlaceLshift",
        ">>":		"PyNumber_InPlaceRshift",
        "**":		"PyNumber_InPlacePower",
        "//":		"PyNumber_InPlaceFloorDivide",
3013 3014
    }

3015 3016 3017 3018 3019
    def annotate(self, code):
        self.lhs.annotate(code)
        self.rhs.annotate(code)
        self.dup.annotate(code)

William Stein's avatar
William Stein committed
3020 3021 3022 3023

class PrintStatNode(StatNode):
    #  print statement
    #
3024
    #  arg_tuple         TupleNode
3025
    #  append_newline    boolean
3026 3027 3028

    child_attrs = ["arg_tuple"]

William Stein's avatar
William Stein committed
3029
    def analyse_expressions(self, env):
3030
        self.arg_tuple.analyse_expressions(env)
3031 3032
        self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
        self.arg_tuple.release_temp(env)
3033
        env.use_utility_code(printing_utility_code)
3034 3035 3036
        self.gil_check(env)

    gil_message = "Python print statement"
3037

William Stein's avatar
William Stein committed
3038
    def generate_execution_code(self, code):
3039
        self.arg_tuple.generate_evaluation_code(code)
3040 3041 3042
        code.putln(
            "if (__Pyx_Print(%s, %d) < 0) %s" % (
                self.arg_tuple.py_result(),
3043
                self.append_newline,
3044
                code.error_goto(self.pos)))
3045
        self.arg_tuple.generate_disposal_code(code)
3046

3047
    def annotate(self, code):
3048
        self.arg_tuple.annotate(code)
William Stein's avatar
William Stein committed
3049 3050 3051 3052 3053 3054 3055


class DelStatNode(StatNode):
    #  del statement
    #
    #  args     [ExprNode]
    
3056 3057
    child_attrs = ["args"]

William Stein's avatar
William Stein committed
3058 3059 3060 3061 3062 3063
    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:
3064
            arg.analyse_target_expression(env, None)
3065 3066 3067
            if arg.type.is_pyobject:
                self.gil_check(env)
            else:
William Stein's avatar
William Stein committed
3068
                error(arg.pos, "Deletion of non-Python object")
3069
            #arg.release_target_temp(env)
3070 3071 3072

    gil_message = "Deleting Python object"

William Stein's avatar
William Stein committed
3073 3074 3075 3076 3077 3078
    def generate_execution_code(self, code):
        for arg in self.args:
            if arg.type.is_pyobject:
                arg.generate_deletion_code(code)
            # else error reported earlier

3079 3080 3081 3082
    def annotate(self, code):
        for arg in self.args:
            arg.annotate(code)

William Stein's avatar
William Stein committed
3083 3084 3085

class PassStatNode(StatNode):
    #  pass statement
3086 3087

    child_attrs = []
William Stein's avatar
William Stein committed
3088 3089 3090 3091 3092 3093 3094 3095 3096 3097
    
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        pass


class BreakStatNode(StatNode):

3098 3099
    child_attrs = []

William Stein's avatar
William Stein committed
3100 3101 3102 3103 3104 3105 3106
    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:
3107 3108 3109 3110
            #code.putln(
            #	"goto %s;" %
            #		code.break_label)
            code.put_goto(code.break_label)
William Stein's avatar
William Stein committed
3111 3112 3113 3114


class ContinueStatNode(StatNode):

3115 3116
    child_attrs = []

William Stein's avatar
William Stein committed
3117 3118 3119 3120
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
3121
        if code.funcstate.in_try_finally:
William Stein's avatar
William Stein committed
3122 3123 3124 3125
            error(self.pos, "continue statement inside try of try...finally")
        elif not code.continue_label:
            error(self.pos, "continue statement not inside loop")
        else:
3126
            code.put_goto(code.continue_label)
William Stein's avatar
William Stein committed
3127 3128 3129 3130 3131 3132 3133 3134 3135


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

William Stein's avatar
William Stein committed
3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158
    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")
3159 3160 3161 3162 3163
        if return_type.is_pyobject:
            self.gil_check(env)

    gil_message = "Returning Python object"

William Stein's avatar
William Stein committed
3164
    def generate_execution_code(self, code):
3165
        code.mark_pos(self.pos)
William Stein's avatar
William Stein committed
3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184
        if not self.return_type:
            # error reported earlier
            return
        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)
        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))
3185 3186
        for entry in self.temps_in_use:
            code.put_var_decref_clear(entry)
3187 3188 3189 3190
        #code.putln(
        #	"goto %s;" %
        #		code.return_label)
        code.put_goto(code.return_label)
3191 3192 3193 3194
        
    def annotate(self, code):
        if self.value:
            self.value.annotate(code)
William Stein's avatar
William Stein committed
3195 3196 3197 3198 3199 3200 3201 3202 3203


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

William Stein's avatar
William Stein committed
3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224
    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)
3225
        env.use_utility_code(raise_utility_code)
3226
        env.use_utility_code(restore_exception_utility_code)
3227 3228 3229 3230
        self.gil_check(env)

    gil_message = "Raising exception"

William Stein's avatar
William Stein committed
3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264
    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:
            type_code = 0
        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();")
        if self.exc_type:
            self.exc_type.generate_disposal_code(code)
        if self.exc_value:
            self.exc_value.generate_disposal_code(code)
        if self.exc_tb:
            self.exc_tb.generate_disposal_code(code)
        code.putln(
            code.error_goto(self.pos))

3265 3266 3267 3268 3269 3270 3271 3272
    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
3273

3274 3275
class ReraiseStatNode(StatNode):

3276 3277
    child_attrs = []

3278
    def analyse_expressions(self, env):
3279
        self.gil_check(env)
3280
        env.use_utility_code(raise_utility_code)
3281
        env.use_utility_code(restore_exception_utility_code)
3282

3283 3284
    gil_message = "Raising exception"

3285
    def generate_execution_code(self, code):
3286
        vars = code.funcstate.exc_vars
3287 3288 3289 3290 3291 3292 3293
        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
3294 3295 3296 3297 3298 3299
class AssertStatNode(StatNode):
    #  assert statement
    #
    #  cond    ExprNode
    #  value   ExprNode or None
    
3300 3301
    child_attrs = ["cond", "value"]

William Stein's avatar
William Stein committed
3302 3303 3304 3305 3306 3307 3308 3309 3310
    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)
3311
        self.gil_check(env)
William Stein's avatar
William Stein committed
3312
        #env.recycle_pending_temps() # TEMPORARY
3313 3314

    gil_message = "Raising exception"
William Stein's avatar
William Stein committed
3315 3316
    
    def generate_execution_code(self, code):
3317
        code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
William Stein's avatar
William Stein committed
3318 3319
        self.cond.generate_evaluation_code(code)
        code.putln(
Robert Bradshaw's avatar
Robert Bradshaw committed
3320
            "if (unlikely(!%s)) {" %
3321
                self.cond.result())
William Stein's avatar
William Stein committed
3322
        if self.value:
3323
            self.value.generate_evaluation_code(code)
William Stein's avatar
William Stein committed
3324 3325 3326
            code.putln(
                "PyErr_SetObject(PyExc_AssertionError, %s);" %
                    self.value.py_result())
3327
            self.value.generate_disposal_code(code)
William Stein's avatar
William Stein committed
3328 3329 3330 3331 3332 3333 3334 3335
        else:
            code.putln(
                "PyErr_SetNone(PyExc_AssertionError);")
        code.putln(
                code.error_goto(self.pos))
        code.putln(
            "}")
        self.cond.generate_disposal_code(code)
3336
        code.putln("#endif")
William Stein's avatar
William Stein committed
3337

3338 3339 3340 3341 3342 3343
    def annotate(self, code):
        self.cond.annotate(code)
        if self.value:
            self.value.annotate(code)


William Stein's avatar
William Stein committed
3344 3345 3346 3347 3348
class IfStatNode(StatNode):
    #  if statement
    #
    #  if_clauses   [IfClauseNode]
    #  else_clause  StatNode or None
3349 3350

    child_attrs = ["if_clauses", "else_clause"]
William Stein's avatar
William Stein committed
3351
    
3352 3353 3354 3355 3356 3357 3358 3359 3360
    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
3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373
    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):
3374
        code.mark_pos(self.pos)
William Stein's avatar
William Stein committed
3375 3376 3377 3378 3379 3380 3381 3382
        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)
3383 3384 3385 3386 3387 3388
        
    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
3389 3390 3391 3392 3393 3394 3395 3396


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

3399 3400 3401
    def analyse_control_flow(self, env):
        self.body.analyse_control_flow(env)
        
William Stein's avatar
William Stein committed
3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415
    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) {" %
3416
                self.condition.result())
William Stein's avatar
William Stein committed
3417
        self.body.generate_execution_code(code)
3418 3419 3420 3421
        #code.putln(
        #	"goto %s;" %
        #		end_label)
        code.put_goto(end_label)
William Stein's avatar
William Stein committed
3422
        code.putln("}")
3423 3424 3425 3426

    def annotate(self, code):
        self.condition.annotate(code)
        self.body.annotate(code)
William Stein's avatar
William Stein committed
3427
        
3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441

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:
            code.putln("case %s:" % cond.calculate_result_code())
        self.body.generate_execution_code(code)
        code.putln("break;")
3442
        
3443 3444 3445
    def annotate(self, code):
        for cond in self.conditions:
            cond.annotate(code)
3446
        self.body.annotate(code)
3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469

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

    def annotate(self, code):
        self.test.annotate(code)
        for case in self.cases:
            case.annotate(code)
3470 3471
        if self.else_clause is not None:
            self.else_clause.annotate(code)
3472
            
3473 3474 3475 3476 3477 3478 3479 3480 3481 3482
class LoopNode:
    
    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
3483
    
3484
class WhileStatNode(LoopNode, StatNode):
William Stein's avatar
William Stein committed
3485 3486 3487 3488 3489
    #  while statement
    #
    #  condition    ExprNode
    #  body         StatNode
    #  else_clause  StatNode
3490 3491

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

William Stein's avatar
William Stein committed
3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513
    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)
        code.putln(
            "if (!%s) break;" %
3514
                self.condition.result())
William Stein's avatar
William Stein committed
3515
        self.body.generate_execution_code(code)
3516
        code.put_label(code.continue_label)
William Stein's avatar
William Stein committed
3517 3518 3519 3520 3521 3522 3523 3524 3525
        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)

3526 3527 3528 3529 3530 3531
    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
3532

Robert Bradshaw's avatar
Robert Bradshaw committed
3533 3534 3535 3536 3537 3538
def ForStatNode(pos, **kw):
    if kw.has_key('iterator'):
        return ForInStatNode(pos, **kw)
    else:
        return ForFromStatNode(pos, **kw)

3539
class ForInStatNode(LoopNode, StatNode):
William Stein's avatar
William Stein committed
3540 3541 3542 3543 3544 3545 3546 3547
    #  for statement
    #
    #  target        ExprNode
    #  iterator      IteratorNode
    #  body          StatNode
    #  else_clause   StatNode
    #  item          NextNode       used internally
    
3548
    child_attrs = ["target", "iterator", "body", "else_clause"]
3549
    item = None
3550
    
William Stein's avatar
William Stein committed
3551 3552 3553 3554 3555
    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)
3556 3557 3558 3559 3560 3561
            
    def analyse_range_step(self, args):
        import ExprNodes
        # The direction must be determined at compile time to set relations. 
        # Otherwise, return False. 
        if len(args) < 3:
3562
            self.step = ExprNodes.IntNode(pos = args[0].pos, value='1')
3563 3564 3565 3566 3567 3568
            self.relation1 = '<='
            self.relation2 = '<'
            return True
        else:
            step = args[2]
            if isinstance(step, ExprNodes.UnaryMinusNode) and isinstance(step.operand, ExprNodes.IntNode):
Stefan Behnel's avatar
Stefan Behnel committed
3569
                step = ExprNodes.IntNode(pos = step.pos, value=str(-int(step.operand.value, 0)))
3570
            if isinstance(step, ExprNodes.IntNode):
Stefan Behnel's avatar
Stefan Behnel committed
3571 3572
                step_value = int(step.value, 0)
                if step_value > 0:
3573 3574 3575 3576
                    self.step = step
                    self.relation1 = '<='
                    self.relation2 = '<'
                    return True
Stefan Behnel's avatar
Stefan Behnel committed
3577 3578
                elif step_value < 0:
                    self.step = ExprNodes.IntNode(pos = step.pos, value=str(-step_value))
3579 3580 3581 3582 3583
                    self.relation1 = '>='
                    self.relation2 = '>'
                    return True
        return False
                
William Stein's avatar
William Stein committed
3584 3585 3586 3587
    
    def analyse_expressions(self, env):
        import ExprNodes
        self.target.analyse_target_types(env)
3588 3589 3590 3591 3592
        if Options.convert_range and self.target.type.is_int:
            sequence = self.iterator.sequence
            if isinstance(sequence, ExprNodes.SimpleCallNode) \
                  and sequence.self is None \
                  and isinstance(sequence.function, ExprNodes.NameNode) \
Robert Bradshaw's avatar
Robert Bradshaw committed
3593
                  and (sequence.function.name == 'range' or sequence.function.name == 'xrange'):
3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608
                args = sequence.args
                # Make sure we can determine direction from step
                if self.analyse_range_step(args):
                    # Mutate to ForFrom loop type
                    self.__class__ = ForFromStatNode
                    if len(args) == 1:
                        self.bound1 = ExprNodes.IntNode(pos = sequence.pos, value='0')
                        self.bound2 = args[0]
                    else:
                        self.bound1 = args[0]
                        self.bound2 = args[1]
                    ForFromStatNode.analyse_expressions(self, env)
                    return
                    
        self.iterator.analyse_expressions(env)
William Stein's avatar
William Stein committed
3609 3610 3611
        self.item = ExprNodes.NextNode(self.iterator, env)
        self.item = self.item.coerce_to(self.target.type, env)
        self.item.allocate_temps(env)
3612 3613 3614
        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
3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627
        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()
        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)
3628
        code.put_label(code.continue_label)
William Stein's avatar
William Stein committed
3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639
        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)
        self.iterator.generate_disposal_code(code)

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

3649
class ForFromStatNode(LoopNode, StatNode):
William Stein's avatar
William Stein committed
3650 3651 3652 3653 3654 3655 3656
    #  for name from expr rel name rel expr
    #
    #  target        NameNode
    #  bound1        ExprNode
    #  relation1     string
    #  relation2     string
    #  bound2        ExprNode
3657
    #  step          ExprNode or None
William Stein's avatar
William Stein committed
3658 3659 3660 3661 3662
    #  body          StatNode
    #  else_clause   StatNode or None
    #
    #  Used internally:
    #
3663
    #  is_py_target       bool
William Stein's avatar
William Stein committed
3664 3665
    #  loopvar_name       string
    #  py_loopvar_node    PyTempNode or None
3666
    child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
William Stein's avatar
William Stein committed
3667
    
Robert Bradshaw's avatar
Robert Bradshaw committed
3668 3669 3670 3671 3672 3673
    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)
    
William Stein's avatar
William Stein committed
3674 3675 3676 3677 3678
    def analyse_expressions(self, env):
        import ExprNodes
        self.target.analyse_target_types(env)
        self.bound1.analyse_types(env)
        self.bound2.analyse_types(env)
3679 3680 3681 3682 3683 3684
        if self.target.type.is_numeric:
            self.bound1 = self.bound1.coerce_to(self.target.type, env)
            self.bound2 = self.bound2.coerce_to(self.target.type, env)
        else:
            self.bound1 = self.bound1.coerce_to_integer(env)
            self.bound2 = self.bound2.coerce_to_integer(env)
3685
        if self.step is not None:
3686 3687
            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)
3688 3689
            self.step.analyse_types(env)
            self.step = self.step.coerce_to_integer(env)
William Stein's avatar
William Stein committed
3690 3691 3692
        if not (self.bound2.is_name or self.bound2.is_literal):
            self.bound2 = self.bound2.coerce_to_temp(env)
        target_type = self.target.type
3693
        if not (target_type.is_pyobject or target_type.is_numeric):
3694 3695 3696 3697 3698 3699
            error(self.target.pos,
                "Integer for-loop variable must be of type int or Python object")
        #if not (target_type.is_pyobject
        #	or target_type.assignable_from(PyrexTypes.c_int_type)):
        #		error(self.target.pos,
        #			"Cannot assign integer to variable of type '%s'" % target_type)
3700
        if target_type.is_numeric:
3701
            self.is_py_target = 0
3702 3703
            if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
                raise error(self.pos, "Buffer indexing not allowed as for loop target.")
William Stein's avatar
William Stein committed
3704 3705 3706
            self.loopvar_name = self.target.entry.cname
            self.py_loopvar_node = None
        else:
3707
            self.is_py_target = 1
William Stein's avatar
William Stein committed
3708 3709 3710
            c_loopvar_node = ExprNodes.TempNode(self.pos, 
                PyrexTypes.c_long_type, env)
            c_loopvar_node.allocate_temps(env)
3711
            self.loopvar_name = c_loopvar_node.result()
William Stein's avatar
William Stein committed
3712 3713 3714 3715
            self.py_loopvar_node = \
                ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
        self.bound1.allocate_temps(env)
        self.bound2.allocate_temps(env)
3716 3717
        if self.step is not None:
            self.step.allocate_temps(env)
3718
        if self.is_py_target:
William Stein's avatar
William Stein committed
3719
            self.py_loopvar_node.allocate_temps(env)
3720 3721 3722
            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
3723
        self.body.analyse_expressions(env)
3724
        if self.is_py_target:
William Stein's avatar
William Stein committed
3725 3726 3727 3728 3729
            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)
3730 3731
        if self.step is not None:
            self.step.release_temp(env)
William Stein's avatar
William Stein committed
3732 3733 3734 3735 3736 3737
            
    def generate_execution_code(self, code):
        old_loop_labels = code.new_loop_labels()
        self.bound1.generate_evaluation_code(code)
        self.bound2.generate_evaluation_code(code)
        offset, incop = self.relation_table[self.relation1]
3738 3739
        if self.step is not None:
            self.step.generate_evaluation_code(code)
3740
            incop = "%s=%s" % (incop[0], self.step.result())
William Stein's avatar
William Stein committed
3741 3742 3743
        code.putln(
            "for (%s = %s%s; %s %s %s; %s%s) {" % (
                self.loopvar_name,
3744 3745
                self.bound1.result(), offset,
                self.loopvar_name, self.relation2, self.bound2.result(),
3746
                self.loopvar_name, incop))
William Stein's avatar
William Stein committed
3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761
        if self.py_loopvar_node:
            self.py_loopvar_node.generate_evaluation_code(code)
            self.target.generate_assignment_code(self.py_loopvar_node, code)
        self.body.generate_execution_code(code)
        code.put_label(code.continue_label)
        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)
        self.bound1.generate_disposal_code(code)
        self.bound2.generate_disposal_code(code)
3762 3763
        if self.step is not None:
            self.step.generate_disposal_code(code)
William Stein's avatar
William Stein committed
3764 3765 3766 3767 3768 3769 3770 3771
    
    relation_table = {
        # {relop : (initial offset, increment op)}
        '<=': ("",   "++"),
        '<' : ("+1", "++"),
        '>=': ("",   "--"),
        '>' : ("-1", "--")
    }
3772 3773 3774 3775 3776 3777 3778 3779 3780 3781
    
    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
3782 3783


3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795
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
3796 3797 3798 3799 3800 3801 3802
class TryExceptStatNode(StatNode):
    #  try .. except statement
    #
    #  body             StatNode
    #  except_clauses   [ExceptClauseNode]
    #  else_clause      StatNode or None
    #  cleanup_list     [Entry]            temps to clean up on error
3803

3804
    child_attrs = ["body", "except_clauses", "else_clause"]
William Stein's avatar
William Stein committed
3805
    
3806 3807 3808
    def analyse_control_flow(self, env):
        env.start_branching(self.pos)
        self.body.analyse_control_flow(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
3809 3810 3811 3812 3813
        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)
3814 3815
        for except_clause in self.except_clauses:
            except_clause.analyse_control_flow(env)
Robert Bradshaw's avatar
Robert Bradshaw committed
3816 3817 3818 3819
            env.next_branch(except_clause.end_pos())
            
        # the else cause it executed only when the try clause finishes
        env.control_flow.incoming = successful_try
3820 3821 3822 3823
        if self.else_clause:
            self.else_clause.analyse_control_flow(env)
        env.finish_branching(self.end_pos())

William Stein's avatar
William Stein committed
3824 3825 3826 3827 3828 3829
    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)
3830
        self.gil_check(env)
3831
        env.use_utility_code(reset_exception_utility_code)
William Stein's avatar
William Stein committed
3832 3833 3834 3835
    
    def analyse_expressions(self, env):
        self.body.analyse_expressions(env)
        self.cleanup_list = env.free_temp_entries[:]
3836
        default_clause_seen = 0
William Stein's avatar
William Stein committed
3837 3838
        for except_clause in self.except_clauses:
            except_clause.analyse_expressions(env)
3839 3840 3841 3842 3843
            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
3844 3845
        if self.else_clause:
            self.else_clause.analyse_expressions(env)
3846 3847 3848 3849
        self.gil_check(env)

    gil_message = "Try-except statement"

William Stein's avatar
William Stein committed
3850
    def generate_execution_code(self, code):
3851
        old_return_label = code.return_label
William Stein's avatar
William Stein committed
3852 3853
        old_error_label = code.new_error_label()
        our_error_label = code.error_label
3854 3855 3856 3857 3858 3859 3860 3861 3862 3863
        except_end_label = code.new_label('exception_handled')
        except_error_label = code.new_label('except_error')
        except_return_label = code.new_label('except_return')
        try_end_label = code.new_label('try')

        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]))
William Stein's avatar
William Stein committed
3864 3865 3866 3867 3868
        code.putln(
            "/*try:*/ {")
        self.body.generate_execution_code(code)
        code.putln(
            "}")
3869 3870
        code.error_label = except_error_label
        code.return_label = except_return_label
William Stein's avatar
William Stein committed
3871 3872 3873 3874 3875 3876
        if self.else_clause:
            code.putln(
                "/*else:*/ {")
            self.else_clause.generate_execution_code(code)
            code.putln(
                "}")
3877
        code.put_goto(try_end_label)
William Stein's avatar
William Stein committed
3878 3879 3880
        code.put_label(our_error_label)
        code.put_var_xdecrefs_clear(self.cleanup_list)
        for except_clause in self.except_clauses:
3881 3882
            except_clause.generate_handling_code(code, except_end_label)

3883 3884 3885 3886
        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)
3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905
            for var in Naming.exc_save_vars:
                code.put_xdecref(var, py_object_type)
            code.put_goto(old_error_label)

        if code.label_used(except_return_label):
            code.put_label(except_return_label)
            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)
            code.putln("__Pyx_ExceptionReset(%s);" %
                       ', '.join(Naming.exc_save_vars))
        code.put_label(try_end_label)
        code.putln("}")

        code.return_label = old_return_label
        code.error_label = old_error_label
William Stein's avatar
William Stein committed
3906

3907 3908 3909 3910 3911 3912 3913
    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
3914 3915 3916 3917 3918 3919 3920

class ExceptClauseNode(Node):
    #  Part of try ... except statement.
    #
    #  pattern        ExprNode
    #  target         ExprNode or None
    #  body           StatNode
3921
    #  excinfo_target NameNode or None   optional target for exception info
William Stein's avatar
William Stein committed
3922 3923 3924
    #  match_flag     string             result of exception match
    #  exc_value      ExcValueNode       used internally
    #  function_name  string             qualified name of enclosing function
3925
    #  exc_vars       (string * 3)       local exception variables
3926 3927 3928 3929

    # 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
3930
    
3931
    child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
3932

3933
    exc_value = None
3934
    excinfo_target = None
3935

William Stein's avatar
William Stein committed
3936 3937 3938
    def analyse_declarations(self, env):
        if self.target:
            self.target.analyse_target_declaration(env)
3939 3940
        if self.excinfo_target is not None:
            self.excinfo_target.analyse_target_declaration(env)
William Stein's avatar
William Stein committed
3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952
        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)
3953
        self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
William Stein's avatar
William Stein committed
3954
        if self.target:
3955 3956
            self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
            self.exc_value.allocate_temps(env)
3957
            self.target.analyse_target_expression(env, self.exc_value)
3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968
        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
3969
        self.body.analyse_expressions(env)
3970 3971 3972
        for var in self.exc_vars:
            env.release_temp(var)
        env.use_utility_code(get_exception_utility_code)
3973
        env.use_utility_code(restore_exception_utility_code)
William Stein's avatar
William Stein committed
3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987
    
    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)
            code.putln(
                "if (%s) {" %
                    self.match_flag)
        else:
3988 3989
            code.putln("/*except:*/ {")
        code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
William Stein's avatar
William Stein committed
3990 3991 3992
        # 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.
3993 3994 3995
        exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
        code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
            code.error_goto(self.pos)))
William Stein's avatar
William Stein committed
3996
        if self.target:
3997
            self.exc_value.generate_evaluation_code(code)
William Stein's avatar
William Stein committed
3998
            self.target.generate_assignment_code(self.exc_value, code)
3999 4000 4001 4002
        if self.excinfo_target is not None:
            self.excinfo_tuple.generate_evaluation_code(code)
            self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)

4003 4004
        old_exc_vars = code.funcstate.exc_vars
        code.funcstate.exc_vars = self.exc_vars
William Stein's avatar
William Stein committed
4005
        self.body.generate_execution_code(code)
4006
        code.funcstate.exc_vars = old_exc_vars
4007
        for var in self.exc_vars:
4008
            code.putln("Py_DECREF(%s); %s = 0;" % (var, var))
4009
        code.put_goto(end_label)
William Stein's avatar
William Stein committed
4010 4011 4012
        code.putln(
            "}")

4013
    def annotate(self, code):
4014 4015
        if self.pattern:
            self.pattern.annotate(code)
4016 4017 4018 4019
        if self.target:
            self.target.annotate(code)
        self.body.annotate(code)

William Stein's avatar
William Stein committed
4020 4021 4022 4023 4024 4025

class TryFinallyStatNode(StatNode):
    #  try ... finally statement
    #
    #  body             StatNode
    #  finally_clause   StatNode
4026
    #
William Stein's avatar
William Stein committed
4027 4028 4029 4030 4031 4032 4033 4034 4035 4036
    #  cleanup_list     [Entry]      temps to clean up on error
    #
    #  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.
4037

4038
    child_attrs = ["body", "finally_clause"]
William Stein's avatar
William Stein committed
4039
    
4040 4041
    preserve_exception = 1
    
William Stein's avatar
William Stein committed
4042 4043 4044 4045
    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.
4046 4047 4048 4049 4050 4051

    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
4052
    
4053 4054 4055 4056
    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
4057
        env.finish_branching(self.body.end_pos())
4058 4059
        self.finally_clause.analyse_control_flow(env)

William Stein's avatar
William Stein committed
4060 4061 4062 4063 4064 4065 4066 4067
    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)
4068 4069 4070 4071
        self.gil_check(env)

    gil_message = "Try-finally statement"

William Stein's avatar
William Stein committed
4072 4073 4074 4075 4076 4077 4078 4079 4080
    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:
4081 4082
            was_in_try_finally = code.funcstate.in_try_finally
            code.funcstate.in_try_finally = 1
William Stein's avatar
William Stein committed
4083 4084
        self.body.generate_execution_code(code)
        if self.disallow_continue_in_try_finally:
4085
            code.funcstate.in_try_finally = was_in_try_finally
William Stein's avatar
William Stein committed
4086 4087 4088 4089
        code.putln(
            "}")
        code.putln(
            "/*finally:*/ {")
4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105
        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)
4106 4107 4108 4109 4110
                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
4111 4112 4113 4114 4115
            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
4116
                #if new_label and new_label != "<try>":
4117 4118 4119 4120
                if new_label == new_error_label and self.preserve_exception:
                    self.put_error_catcher(code, 
                        new_error_label, i+1, catch_label)
                else:
4121 4122 4123 4124
                    code.put('%s: ' % new_label)
                    if exc_var_init_zero:
                        code.putln(exc_var_init_zero)
                    code.putln("__pyx_why = %s; goto %s;" % (
4125 4126 4127
                            i+1,
                            catch_label))
            code.put_label(catch_label)
William Stein's avatar
William Stein committed
4128
        code.set_all_labels(old_labels)
4129 4130 4131
        if error_label_used:
            code.new_error_label()
            finally_error_label = code.error_label
William Stein's avatar
William Stein committed
4132
        self.finally_clause.generate_execution_code(code)
4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146
        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
4147
                "switch (__pyx_why) {")
4148 4149 4150
            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
4151 4152
                    self.put_error_uncatcher(code, i+1, old_error_label)
                else:
4153
                    code.use_label(old_label)
William Stein's avatar
William Stein committed
4154 4155 4156
                    code.putln(
                        "case %s: goto %s;" % (
                            i+1,
4157 4158
                            old_label))
            code.putln(
William Stein's avatar
William Stein committed
4159 4160 4161 4162 4163
                "}")		
        code.putln(
            "}")

    def put_error_catcher(self, code, error_label, i, catch_label):
4164
        code.globalstate.use_utility_code(restore_exception_utility_code)
William Stein's avatar
William Stein committed
4165 4166 4167 4168 4169 4170 4171 4172
        code.putln(
            "%s: {" %
                error_label)
        code.putln(
                "__pyx_why = %s;" %
                    i)
        code.put_var_xdecrefs_clear(self.cleanup_list)
        code.putln(
4173
                "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4174
                    Naming.exc_vars)
William Stein's avatar
William Stein committed
4175 4176
        code.putln(
                "%s = %s;" % (
4177
                    Naming.exc_lineno_name, Naming.lineno_cname))
4178 4179 4180 4181
        #code.putln(
        #		"goto %s;" %
        #			catch_label)
        code.put_goto(catch_label)
William Stein's avatar
William Stein committed
4182 4183 4184 4185
        code.putln(
            "}")
            
    def put_error_uncatcher(self, code, i, error_label):
4186
        code.globalstate.use_utility_code(restore_exception_utility_code)
William Stein's avatar
William Stein committed
4187 4188 4189 4190
        code.putln(
            "case %s: {" %
                i)
        code.putln(
4191
                "__Pyx_ErrRestore(%s, %s, %s);" %
4192
                    Naming.exc_vars)
William Stein's avatar
William Stein committed
4193 4194
        code.putln(
                "%s = %s;" % (
4195 4196
                    Naming.lineno_cname, Naming.exc_lineno_name))
        for var in Naming.exc_vars:
William Stein's avatar
William Stein committed
4197 4198 4199
            code.putln(
                "%s = 0;" %
                    var)
4200
        code.put_goto(error_label)
William Stein's avatar
William Stein committed
4201 4202 4203
        code.putln(
            "}")

4204 4205 4206 4207
    def annotate(self, code):
        self.body.annotate(code)
        self.finally_clause.annotate(code)

William Stein's avatar
William Stein committed
4208

4209 4210 4211 4212 4213
class GILStatNode(TryFinallyStatNode):
    #  'with gil' or 'with nogil' statement
    #
    #   state   string   'gil' or 'nogil'
        
4214 4215
    child_attrs = []
    
4216 4217 4218 4219 4220 4221 4222 4223
    preserve_exception = 0

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

4224 4225 4226 4227 4228 4229 4230 4231 4232
    def analyse_expressions(self, env):
        was_nogil = env.nogil
        env.nogil = 1
        TryFinallyStatNode.analyse_expressions(self, env)
        env.nogil = was_nogil

    def gil_check(self, env):
        pass

4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248
    def generate_execution_code(self, code):
        code.putln("/*with %s:*/ {" % self.state)
        if self.state == 'gil':
            code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
        else:
            code.putln("PyThreadState *_save;")
            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'

4249 4250
    child_attrs = []

4251 4252 4253 4254 4255 4256 4257 4258 4259 4260
    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
4261 4262 4263 4264 4265
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
4266 4267

    child_attrs = []
William Stein's avatar
William Stein committed
4268 4269
    
    def analyse_declarations(self, env):
4270 4271 4272
        if not env.is_module_scope:
            error(self.pos, "cimport only allowed at module level")
            return
William Stein's avatar
William Stein committed
4273 4274
        module_scope = env.find_module(self.module_name, self.pos)
        if "." in self.module_name:
4275
            names = [EncodedString(name) for name in self.module_name.split(".")]
William Stein's avatar
William Stein committed
4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300
            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
    #
4301 4302
    #  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
4303
    
4304 4305
    child_attrs = []

William Stein's avatar
William Stein committed
4306
    def analyse_declarations(self, env):
4307 4308 4309
        if not env.is_module_scope:
            error(self.pos, "cimport only allowed at module level")
            return
William Stein's avatar
William Stein committed
4310 4311
        module_scope = env.find_module(self.module_name, self.pos)
        env.add_imported_module(module_scope)
4312
        for pos, name, as_name, kind in self.imported_names:
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4313 4314 4315 4316
            if name == "*":
                for local_name, entry in module_scope.entries.items():
                    env.add_imported_entry(local_name, entry, pos)
            else:
4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331
                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:
                        error(pos, "Name '%s' not declared in module '%s'"
                            % (name, self.module_name))
                        
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4332 4333 4334
                if entry:
                    local_name = as_name or name
                    env.add_imported_entry(local_name, entry, pos)
4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348
    
    def declaration_matches(self, entry, kind):
		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
4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363

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


class FromImportStatNode(StatNode):
    #  from ... import statement
    #
    #  module           ImportNode
    #  items            [(string, NameNode)]
    #  interned_items   [(string, NameNode)]
    #  item             PyTempNode            used internally
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4364
    #  import_star      boolean               used internally
4365 4366

    child_attrs = ["module"]
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4367
    import_star = 0
William Stein's avatar
William Stein committed
4368 4369
    
    def analyse_declarations(self, env):
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4370 4371 4372 4373 4374 4375 4376 4377 4378
        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
4379 4380 4381 4382 4383 4384 4385 4386
    
    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
4387 4388 4389 4390 4391 4392 4393 4394 4395 4396
            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:
                self.interned_items.append(
                    (env.intern_identifier(name), target))
                target.analyse_target_expression(env, None)
                #target.release_target_temp(env) # was release_temp ?!?
William Stein's avatar
William Stein committed
4397 4398 4399 4400 4401
        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
4402 4403 4404 4405 4406 4407
        if self.import_star:
            code.putln(
                'if (%s(%s) < 0) %s;' % (
                    Naming.import_star,
                    self.module.py_result(),
                    code.error_goto(self.pos)))
4408 4409 4410
        for cname, target in self.interned_items:
            code.putln(
                '%s = PyObject_GetAttr(%s, %s); %s' % (
4411
                    self.item.result(), 
4412 4413
                    self.module.py_result(),
                    cname,
4414
                    code.error_goto_if_null(self.item.result(), self.pos)))
4415
            target.generate_assignment_code(self.item, code)
William Stein's avatar
William Stein committed
4416 4417
        self.module.generate_disposal_code(code)

4418

4419

William Stein's avatar
William Stein committed
4420 4421 4422 4423 4424 4425 4426 4427
#------------------------------------------------------------------------------------
#
#  Runtime support code
#
#------------------------------------------------------------------------------------

utility_function_predeclarations = \
"""
4428 4429 4430
#ifdef __GNUC__
#define INLINE __inline__
#elif _WIN32
4431
#define INLINE __inline
4432 4433 4434 4435
#else
#define INLINE 
#endif

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

4438 4439 4440 4441 4442
""" + """

static int %(skip_dispatch_cname)s = 0;

""" % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
Robert Bradshaw's avatar
Robert Bradshaw committed
4443 4444 4445 4446

if Options.gcc_branch_hints:
    branch_prediction_macros = \
    """
4447
#ifdef __GNUC__
4448 4449 4450
/* Test for GCC > 2.95 */
#if __GNUC__ > 2 || \
              (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) 
Robert Bradshaw's avatar
Robert Bradshaw committed
4451 4452
#define likely(x)   __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
4453 4454 4455 4456
#else /* __GNUC__ > 2 ... */
#define likely(x)   (x)
#define unlikely(x) (x)
#endif /* __GNUC__ > 2 ... */
4457 4458 4459 4460
#else /* __GNUC__ */
#define likely(x)   (x)
#define unlikely(x) (x)
#endif /* __GNUC__ */
Robert Bradshaw's avatar
Robert Bradshaw committed
4461 4462 4463 4464 4465 4466 4467
    """
else:
    branch_prediction_macros = \
    """
#define likely(x)   (x)
#define unlikely(x) (x)
    """
William Stein's avatar
William Stein committed
4468

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

4472 4473
#get_name_interned_predeclaration = \
#"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
William Stein's avatar
William Stein committed
4474 4475 4476

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

4477 4478
printing_utility_code = UtilityCode(
proto = """
4479 4480
static int __Pyx_Print(PyObject *, int); /*proto*/
#if PY_MAJOR_VERSION >= 3
4481 4482 4483
static PyObject* %s = 0;
static PyObject* %s = 0;
#endif
4484 4485
""" % (Naming.print_function, Naming.print_function_kwargs),
impl = r"""
4486
#if PY_MAJOR_VERSION < 3
William Stein's avatar
William Stein committed
4487 4488 4489 4490 4491 4492 4493 4494
static PyObject *__Pyx_GetStdout(void) {
    PyObject *f = PySys_GetObject("stdout");
    if (!f) {
        PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
    }
    return f;
}

4495
static int __Pyx_Print(PyObject *arg_tuple, int newline) {
William Stein's avatar
William Stein committed
4496
    PyObject *f;
4497 4498
    PyObject* v;
    int i;
William Stein's avatar
William Stein committed
4499 4500 4501
    
    if (!(f = __Pyx_GetStdout()))
        return -1;
4502 4503 4504 4505 4506 4507 4508
    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
4509
            return -1;
4510 4511 4512 4513 4514 4515 4516 4517
        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
4518
    }
4519 4520 4521 4522
    if (newline) {
        if (PyFile_WriteString("\n", f) < 0)
            return -1;
        PyFile_SoftSpace(f, 0);
William Stein's avatar
William Stein committed
4523 4524 4525 4526
    }
    return 0;
}

4527 4528 4529 4530 4531 4532 4533 4534
#else /* Python 3 has a print function */
static int __Pyx_Print(PyObject *arg_tuple, int newline) {
    PyObject* kwargs = 0;
    PyObject* result = 0;
    PyObject* end_string;
    if (!%(PRINT_FUNCTION)s) {
        %(PRINT_FUNCTION)s = PyObject_GetAttrString(%(BUILTINS)s, "print");
        if (!%(PRINT_FUNCTION)s)
4535
            return -1;
4536 4537 4538 4539 4540
    }
    if (!newline) {
        if (!%(PRINT_KWARGS)s) {
            %(PRINT_KWARGS)s = PyDict_New();
            if (!%(PRINT_KWARGS)s)
4541
                return -1;
4542 4543
            end_string = PyUnicode_FromStringAndSize(" ", 1);
            if (!end_string)
4544
                return -1;
4545 4546
            if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
                Py_DECREF(end_string);
4547
                return -1;
4548 4549 4550 4551 4552 4553 4554
            }
            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
4555
        return -1;
4556
    Py_DECREF(result);
William Stein's avatar
William Stein committed
4557 4558
    return 0;
}
4559 4560 4561 4562
#endif
""" % {'BUILTINS'       : Naming.builtins_cname,
       'PRINT_FUNCTION' : Naming.print_function,
       'PRINT_KWARGS'   : Naming.print_function_kwargs}
4563
)
William Stein's avatar
William Stein committed
4564 4565 4566 4567 4568

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

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

4569 4570
raise_utility_code = UtilityCode(
proto = """
4571
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4572 4573
""",
impl = """
William Stein's avatar
William Stein committed
4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592
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);
    }
4593 4594 4595 4596 4597 4598
    #if PY_VERSION_HEX < 0x02050000
    if (!PyClass_Check(type))
    #else
    if (!PyType_Check(type))
    #endif
    {
William Stein's avatar
William Stein committed
4599 4600 4601
        /* Raising an instance.  The value should be a dummy. */
        if (value != Py_None) {
            PyErr_SetString(PyExc_TypeError,
4602
                "instance exception may not have a separate value");
William Stein's avatar
William Stein committed
4603 4604
            goto raise_error;
        }
4605 4606 4607
        /* Normalize to raise <class>, <instance> */
        Py_DECREF(value);
        value = type;
4608 4609 4610 4611 4612 4613
        #if PY_VERSION_HEX < 0x02050000
            if (PyInstance_Check(type)) {
                type = (PyObject*) ((PyInstanceObject*)type)->in_class;
                Py_INCREF(type);
            }
            else {
4614
                type = 0;
4615 4616 4617 4618 4619
                PyErr_SetString(PyExc_TypeError,
                    "raise: exception must be an old-style class or instance");
                goto raise_error;
            }
        #else
4620
            type = (PyObject*) Py_TYPE(type);
4621 4622 4623 4624 4625 4626 4627
            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
4628
    }
4629
    __Pyx_ErrRestore(type, value, tb);
4630 4631 4632
    return;
raise_error:
    Py_XDECREF(value);
William Stein's avatar
William Stein committed
4633 4634 4635 4636
    Py_XDECREF(type);
    Py_XDECREF(tb);
    return;
}
4637
""")
William Stein's avatar
William Stein committed
4638 4639 4640

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

4641 4642
reraise_utility_code = UtilityCode(
proto = """
4643
static void __Pyx_ReRaise(void); /*proto*/
4644 4645
""",
impl = """
William Stein's avatar
William Stein committed
4646 4647 4648 4649 4650 4651 4652 4653
static void __Pyx_ReRaise(void) {
    PyThreadState *tstate = PyThreadState_Get();
    PyObject *type = tstate->exc_type;
    PyObject *value = tstate->exc_value;
    PyObject *tb = tstate->exc_traceback;
    Py_XINCREF(type);
    Py_XINCREF(value);
    Py_XINCREF(tb);
4654
    __Pyx_ErrRestore(type, value, tb);
William Stein's avatar
William Stein committed
4655
}
4656
""")
William Stein's avatar
William Stein committed
4657 4658 4659

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

4660 4661
arg_type_test_utility_code = UtilityCode(
proto = """
4662 4663
static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
    const char *name, int exact); /*proto*/
4664 4665
""",
impl = """
4666 4667 4668
static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
    const char *name, int exact)
{
William Stein's avatar
William Stein committed
4669 4670 4671 4672
    if (!type) {
        PyErr_Format(PyExc_SystemError, "Missing type object");
        return 0;
    }
Robert Bradshaw's avatar
Robert Bradshaw committed
4673 4674
    if (none_allowed && obj == Py_None) return 1;
    else if (exact) {
4675
        if (Py_TYPE(obj) == type) return 1;
Robert Bradshaw's avatar
Robert Bradshaw committed
4676 4677
    }
    else {
Robert Bradshaw's avatar
Robert Bradshaw committed
4678
        if (PyObject_TypeCheck(obj, type)) return 1;
Robert Bradshaw's avatar
Robert Bradshaw committed
4679
    }
William Stein's avatar
William Stein committed
4680 4681
    PyErr_Format(PyExc_TypeError,
        "Argument '%s' has incorrect type (expected %s, got %s)",
4682
        name, type->tp_name, Py_TYPE(obj)->tp_name);
William Stein's avatar
William Stein committed
4683 4684
    return 0;
}
4685
""")
William Stein's avatar
William Stein committed
4686 4687 4688

#------------------------------------------------------------------------------------
#
4689 4690 4691
#  __Pyx_RaiseArgtupleInvalid raises the correct exception when too
#  many or too few positional arguments were found.  This handles
#  Py_ssize_t formatting correctly.
4692

4693 4694
raise_argtuple_invalid_utility_code = UtilityCode(
proto = """
4695
static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
4696
    Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
4697 4698
""",
impl = """
4699
static void __Pyx_RaiseArgtupleInvalid(
4700
    const char* func_name,
4701
    int exact,
4702 4703
    Py_ssize_t num_min,
    Py_ssize_t num_max,
4704
    Py_ssize_t num_found)
William Stein's avatar
William Stein committed
4705
{
4706
    Py_ssize_t num_expected;
Stefan Behnel's avatar
Stefan Behnel committed
4707
    const char *number, *more_or_less;
4708 4709 4710 4711

    if (num_found < num_min) {
        num_expected = num_min;
        more_or_less = "at least";
4712
    } else {
4713
        num_expected = num_max;
4714
        more_or_less = "at most";
4715
    }
4716 4717
    if (exact) {
        more_or_less = "exactly";
4718
    }
4719
    number = (num_expected == 1) ? "" : "s";
Stefan Behnel's avatar
Stefan Behnel committed
4720 4721 4722 4723 4724 4725 4726
    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);
4727
}
4728
""")
4729

4730 4731
raise_keyword_required_utility_code = UtilityCode(
proto = """
4732
static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
4733 4734
""",
impl = """
4735
static INLINE void __Pyx_RaiseKeywordRequired(
4736
    const char* func_name,
4737
    PyObject* kw_name)
4738 4739
{
    PyErr_Format(PyExc_TypeError,
4740 4741 4742 4743 4744 4745
        #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
4746
}
4747
""")
4748

4749 4750
raise_double_keywords_utility_code = UtilityCode(
proto = """
4751
static void __Pyx_RaiseDoubleKeywordsError(
4752
    const char* func_name, PyObject* kw_name); /*proto*/
4753 4754
""",
impl = """
4755
static void __Pyx_RaiseDoubleKeywordsError(
4756
    const char* func_name,
4757
    PyObject* kw_name)
4758
{
4759
    PyErr_Format(PyExc_TypeError,
4760 4761 4762 4763 4764 4765
        #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
4766
}
4767
""")
4768

4769 4770
#------------------------------------------------------------------------------------
#
4771 4772 4773
#  __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.
4774

4775 4776
keyword_string_check_utility_code = UtilityCode(
proto = """
4777
static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
4778
    const char* function_name, int kw_allowed); /*proto*/
4779 4780
""",
impl = """
4781
static INLINE int __Pyx_CheckKeywordStrings(
4782 4783 4784 4785
    PyObject *kwdict,
    const char* function_name,
    int kw_allowed)
{
4786 4787
    PyObject* key = 0;
    Py_ssize_t pos = 0;
4788
    while (PyDict_Next(kwdict, &pos, &key, 0)) {
4789
        #if PY_MAJOR_VERSION < 3
4790
        if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
4791
        #else
4792
        if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
4793
        #endif
4794
            goto invalid_keyword_type;
4795
    }
4796 4797
    if ((!kw_allowed) && unlikely(key))
        goto invalid_keyword;
4798
    return 1;
4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812
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;
4813
}
4814
""")
4815

4816 4817
#------------------------------------------------------------------------------------
#
Stefan Behnel's avatar
Stefan Behnel committed
4818 4819 4820
#  __Pyx_SplitKeywords copies the keyword arguments that are not named
#  in argnames[] from the kwds dict into kwds2.  If kwds2 is NULL,
#  these keywords will raise an invalid keyword error.
4821
#
Stefan Behnel's avatar
Stefan Behnel committed
4822 4823
#  Three kinds of errors are checked: 1) non-string keywords, 2)
#  unexpected keywords and 3) overlap with positional arguments.
4824
#
Stefan Behnel's avatar
Stefan Behnel committed
4825 4826 4827 4828 4829
#  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.
4830 4831
#

4832 4833
split_keywords_utility_code = UtilityCode(
proto = """
Stefan Behnel's avatar
Stefan Behnel committed
4834
static int __Pyx_SplitKeywords(PyObject *kwds, PyObject **argnames[], \
4835
    PyObject *kwds2, Py_ssize_t num_pos_args, const char* function_name); /*proto*/
4836 4837
""",
impl = """
4838
static int __Pyx_SplitKeywords(
4839
    PyObject *kwds,
Stefan Behnel's avatar
Stefan Behnel committed
4840 4841 4842
    PyObject **argnames[],
    PyObject *kwds2,
    Py_ssize_t num_pos_args,
4843
    const char* function_name)
4844
{
4845
    PyObject *key = 0, *value = 0;
4846
    Py_ssize_t pos = 0;
4847
    PyObject*** name;
4848

Stefan Behnel's avatar
Stefan Behnel committed
4849
    while (PyDict_Next(kwds, &pos, &key, &value)) {
4850
        #if PY_MAJOR_VERSION < 3
4851
        if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
4852
        #else
4853
        if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
4854
        #endif
4855
            goto invalid_keyword_type;
Stefan Behnel's avatar
Stefan Behnel committed
4856
        } else {
4857
            name = argnames;
4858
            while (*name && (**name != key)) name++;
4859
            if (!*name) {
4860 4861
                for (name = argnames; *name; name++) {
                    #if PY_MAJOR_VERSION >= 3
Stefan Behnel's avatar
Stefan Behnel committed
4862
                    if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
4863
                        PyUnicode_Compare(**name, key) == 0) break;
4864
                    #else
4865 4866
                    if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
                        strcmp(PyString_AS_STRING(**name),
4867 4868 4869
                               PyString_AS_STRING(key)) == 0) break;
                    #endif
                }
Stefan Behnel's avatar
Stefan Behnel committed
4870 4871 4872 4873
                if (!*name) {
                    if (kwds2) {
                        if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
                    } else {
4874
                        goto invalid_keyword;
Stefan Behnel's avatar
Stefan Behnel committed
4875 4876
                    }
                }
4877
            }
Stefan Behnel's avatar
Stefan Behnel committed
4878
            if (*name && ((name-argnames) < num_pos_args))
4879
                goto arg_passed_twice;
4880
            }
4881
    }
4882
    return 0;
4883
arg_passed_twice:
Stefan Behnel's avatar
Stefan Behnel committed
4884 4885
    __Pyx_RaiseDoubleKeywordsError(function_name, **name);
    goto bad;
4886 4887 4888 4889 4890
invalid_keyword_type:
    PyErr_Format(PyExc_TypeError,
        "%s() keywords must be strings", function_name);
    goto bad;
invalid_keyword:
4891
    PyErr_Format(PyExc_TypeError,
4892
    #if PY_MAJOR_VERSION < 3
4893 4894
        "%s() got an unexpected keyword argument '%s'",
        function_name, PyString_AsString(key));
4895
    #else
4896 4897
        "%s() got an unexpected keyword argument '%U'",
        function_name, key);
4898
    #endif
William Stein's avatar
William Stein committed
4899 4900 4901
bad:
    return -1;
}
4902
""")
William Stein's avatar
William Stein committed
4903 4904 4905

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

4906 4907
unraisable_exception_utility_code = UtilityCode(
proto = """
4908
static void __Pyx_WriteUnraisable(const char *name); /*proto*/
4909 4910
""",
impl = """
4911
static void __Pyx_WriteUnraisable(const char *name) {
William Stein's avatar
William Stein committed
4912 4913
    PyObject *old_exc, *old_val, *old_tb;
    PyObject *ctx;
4914
    __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
4915
    #if PY_MAJOR_VERSION < 3
William Stein's avatar
William Stein committed
4916
    ctx = PyString_FromString(name);
4917 4918 4919
    #else
    ctx = PyUnicode_FromString(name);
    #endif
4920
    __Pyx_ErrRestore(old_exc, old_val, old_tb);
4921 4922 4923 4924 4925 4926
    if (!ctx) {
        PyErr_WriteUnraisable(Py_None);
    } else {
        PyErr_WriteUnraisable(ctx);
        Py_DECREF(ctx);
    }
4927
}
4928
""")
William Stein's avatar
William Stein committed
4929 4930 4931

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

4932 4933
traceback_utility_code = UtilityCode(
proto = """
4934
static void __Pyx_AddTraceback(const char *funcname); /*proto*/
4935 4936
""",
impl = """
William Stein's avatar
William Stein committed
4937 4938 4939 4940
#include "compile.h"
#include "frameobject.h"
#include "traceback.h"

4941
static void __Pyx_AddTraceback(const char *funcname) {
William Stein's avatar
William Stein committed
4942 4943 4944 4945 4946 4947
    PyObject *py_srcfile = 0;
    PyObject *py_funcname = 0;
    PyObject *py_globals = 0;
    PyObject *empty_string = 0;
    PyCodeObject *py_code = 0;
    PyFrameObject *py_frame = 0;
4948 4949

    #if PY_MAJOR_VERSION < 3
William Stein's avatar
William Stein committed
4950
    py_srcfile = PyString_FromString(%(FILENAME)s);
4951 4952 4953
    #else
    py_srcfile = PyUnicode_FromString(%(FILENAME)s);
    #endif
William Stein's avatar
William Stein committed
4954
    if (!py_srcfile) goto bad;
Robert Bradshaw's avatar
Robert Bradshaw committed
4955
    if (%(CLINENO)s) {
4956
        #if PY_MAJOR_VERSION < 3
4957
        py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
4958
        #else
4959
        py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
4960
        #endif
Robert Bradshaw's avatar
Robert Bradshaw committed
4961 4962
    }
    else {
4963
        #if PY_MAJOR_VERSION < 3
Robert Bradshaw's avatar
Robert Bradshaw committed
4964
        py_funcname = PyString_FromString(funcname);
4965 4966 4967
        #else
        py_funcname = PyUnicode_FromString(funcname);
        #endif
Robert Bradshaw's avatar
Robert Bradshaw committed
4968
    }
William Stein's avatar
William Stein committed
4969 4970 4971
    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
4972
    #if PY_MAJOR_VERSION < 3
Stefan Behnel's avatar
Stefan Behnel committed
4973
    empty_string = PyString_FromStringAndSize("", 0);
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
4974 4975 4976
    #else
    empty_string = PyBytes_FromStringAndSize("", 0);
    #endif
William Stein's avatar
William Stein committed
4977 4978 4979
    if (!empty_string) goto bad;
    py_code = PyCode_New(
        0,            /*int argcount,*/
4980 4981 4982
        #if PY_MAJOR_VERSION >= 3
        0,            /*int kwonlyargcount,*/
        #endif
William Stein's avatar
William Stein committed
4983 4984 4985 4986
        0,            /*int nlocals,*/
        0,            /*int stacksize,*/
        0,            /*int flags,*/
        empty_string, /*PyObject *code,*/
Stefan Behnel's avatar
Stefan Behnel committed
4987 4988 4989 4990 4991
        %(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
4992 4993 4994 4995 4996 4997 4998
        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(
4999
        PyThreadState_GET(), /*PyThreadState *tstate,*/
William Stein's avatar
William Stein committed
5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016
        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
5017 5018
    'CFILENAME': Naming.cfilenm_cname,
    'CLINENO':  Naming.clineno_cname,
Stefan Behnel's avatar
Stefan Behnel committed
5019 5020
    'GLOBALS': Naming.module_cname,
    'EMPTY_TUPLE' : Naming.empty_tuple,
5021
})
William Stein's avatar
William Stein committed
5022

5023 5024
restore_exception_utility_code = UtilityCode(
proto = """
5025 5026
static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5027 5028
""",
impl = """
5029
static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043
    PyObject *tmp_type, *tmp_value, *tmp_tb;
    PyThreadState *tstate = PyThreadState_GET();

    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);
}

5044
static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5045 5046 5047 5048 5049 5050 5051 5052 5053 5054
    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;
}

5055
""")
5056

William Stein's avatar
William Stein committed
5057 5058
#------------------------------------------------------------------------------------

5059 5060
set_vtable_utility_code = UtilityCode(
proto = """
5061
static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5062 5063
""",
impl = """
William Stein's avatar
William Stein committed
5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081
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;
}
5082
""")
William Stein's avatar
William Stein committed
5083 5084 5085

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

5086 5087
get_vtable_utility_code = UtilityCode(
proto = """
5088
static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5089 5090
""",
impl = r"""
William Stein's avatar
William Stein committed
5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109
static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
    int result;
    PyObject *pycobj;
    
    pycobj = PyMapping_GetItemString(dict, "__pyx_vtable__");
    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;
}
5110
""")
William Stein's avatar
William Stein committed
5111 5112 5113

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

5114 5115
init_string_tab_utility_code = UtilityCode(
proto = """
5116
static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5117 5118
""",
impl = """
William Stein's avatar
William Stein committed
5119 5120
static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
    while (t->p) {
5121
        #if PY_MAJOR_VERSION < 3
5122
        if (t->is_unicode && (!t->is_identifier)) {
5123
            *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5124 5125
        } else if (t->intern) {
            *t->p = PyString_InternFromString(t->s);
Dag Sverre Seljebotn's avatar
Merge  
Dag Sverre Seljebotn committed
5126 5127
        } else {
            *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
Stefan Behnel's avatar
Stefan Behnel committed
5128
        }
5129 5130 5131 5132 5133
        #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
5134 5135
        } else {
            *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
Stefan Behnel's avatar
Stefan Behnel committed
5136
        }
5137
        #endif
William Stein's avatar
William Stein committed
5138 5139 5140 5141 5142 5143
        if (!*t->p)
            return -1;
        ++t;
    }
    return 0;
}
5144
""")
William Stein's avatar
William Stein committed
5145 5146

#------------------------------------------------------------------------------------
5147

5148 5149
get_exception_utility_code = UtilityCode(
proto = """
5150
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5151 5152
""",
impl = """
5153
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5154
    PyObject *tmp_type, *tmp_value, *tmp_tb;
5155 5156
    PyThreadState *tstate = PyThreadState_GET();
    __Pyx_ErrFetch(type, value, tb);
5157 5158 5159 5160 5161 5162
    PyErr_NormalizeException(type, value, tb);
    if (PyErr_Occurred())
        goto bad;
    Py_INCREF(*type);
    Py_INCREF(*value);
    Py_INCREF(*tb);
5163 5164 5165
    tmp_type = tstate->exc_type;
    tmp_value = tstate->exc_value;
    tmp_tb = tstate->exc_traceback;
5166 5167 5168
    tstate->exc_type = *type;
    tstate->exc_value = *value;
    tstate->exc_traceback = *tb;
5169 5170 5171 5172 5173
    /* 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);
5174
    return 0;
5175 5176 5177 5178 5179
bad:
    Py_XDECREF(*type);
    Py_XDECREF(*value);
    Py_XDECREF(*tb);
    return -1;
5180
}
5181

5182
""")
5183 5184

#------------------------------------------------------------------------------------
5185

5186 5187
reset_exception_utility_code = UtilityCode(
proto = """
5188
static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5189
static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5190 5191
""",
impl = """
5192
static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5193 5194 5195 5196
    PyThreadState *tstate = PyThreadState_GET();
    *type = tstate->exc_type;
    *value = tstate->exc_value;
    *tb = tstate->exc_traceback;
Stefan Behnel's avatar
Stefan Behnel committed
5197 5198 5199
    Py_XINCREF(*type);
    Py_XINCREF(*value);
    Py_XINCREF(*tb);
5200 5201
}

5202
static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214
    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);
}
5215
""")
5216 5217

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