Nodes.py :  » Development » Pyrex » Pyrex-0.9.9 » Pyrex » Compiler » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » Pyrex 
Pyrex » Pyrex 0.9.9 » Pyrex » Compiler » Nodes.py
#
#   Pyrex - Parse tree nodes
#

import string, sys

import Code
from Errors import error,one_time_warning,InternalError
import Naming
import PyrexTypes
from PyrexTypes import py_object_type,c_int_type,error_type,\
    CTypedefType, CFuncType
from Symtab import ModuleScope,LocalScope,\
    StructOrUnionScope, PyClassScope, CClassScope
from Pyrex.Utils import open_new_file,replace_suffix
import Options

from DebugFlags import debug_disposal_code

class Node:
    #  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
    
    def __init__(self, pos, **kw):
        self.pos = pos
        self.__dict__.update(kw)
    
    gil_message = "Operation"
    
    def gil_check(self, env):
        if env.nogil:
            self.gil_error()
    
    def gil_error(self, message = None):
        error(self.pos, "%s not allowed without gil" % (message or self.gil_message))
    
    #
    #  There are 3 phases of parse tree processing, applied in order to
    #  all the statements in a given scope-block:
    #
    #  (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).
    #
    #    (2)  analyse_expressions
    #         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.
    #
    #   (3) generate_code
    #         Emit C code for all declarations, statements and expressions.
    #         Recursively applies the 3 processing phases to the bodies of
    #         functions.
    #
    
    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__)


class BlockNode:
    #  Mixin class for nodes representing a declaration block.
    pass

#  def generate_const_definitions(self, env, code):
#    if env.const_entries:
#      code.putln("")
#      for entry in env.const_entries:
#        if not entry.is_interned:
#          code.put_var_declaration(entry, static = 1)
    
#  def generate_interned_name_decls(self, env, code):
#    #  Flush accumulated interned names from the global scope
#    #  and generate declarations for them.
#    genv = env.global_scope()
#    intern_map = genv.intern_map
#    names = genv.interned_names
#    if names:
#      code.putln("")
#      for name in names:
#        code.putln(
#          "static PyObject *%s;" % intern_map[name])
#      del names[:]
    
#  def generate_py_string_decls(self, env, code):
#    entries = env.pystring_entries
#    if entries:
#      code.putln("")
#      for entry in entries:
#        code.putln(
#          "static PyObject *%s;" % entry.pystring_cname)


class StatListNode(Node):
    # stats     a list of StatNode
    
    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)
    
    def generate_function_definitions(self, env, code):
        #print "StatListNode.generate_function_definitions" ###
        for stat in self.stats:
            stat.generate_function_definitions(env, code)
            
    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)
    

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.
    #
    
    def generate_function_definitions(self, env, code):
        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
    
    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
        

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


class CNameDeclaratorNode(CDeclaratorNode):
    #  name   string           The Pyrex name being declared
    #  cname  string or None   C name, if specified
    
    def analyse(self, base_type, env):
        return self, base_type


class CPtrDeclaratorNode(CDeclaratorNode):
    # base     CDeclaratorNode
    
    def analyse(self, base_type, env):
        if base_type.is_pyobject:
            error(self.pos,
                "Pointer base type cannot be a Python object")
        ptr_type = PyrexTypes.c_ptr_type(base_type)
        return self.base.analyse(ptr_type, env)
        

class CArrayDeclaratorNode(CDeclaratorNode):
    # base        CDeclaratorNode
    # dimension   ExprNode
    
    def analyse(self, base_type, env):
        if self.dimension:
            self.dimension.analyse_const_expression(env)
            if not self.dimension.type.is_int:
                error(self.dimension.pos, "Array dimension not integer")
            size = self.dimension.result()
        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")
        if base_type.is_cfunction:
            error(self.pos,
                "Array element cannot be a function")
        array_type = PyrexTypes.c_array_type(base_type, size)
        return self.base.analyse(array_type, env)


class CFuncDeclaratorNode(CDeclaratorNode):
    # base             CDeclaratorNode
    # args             [CArgDeclNode]
    # has_varargs      boolean
    # exception_value  ConstNode
    # exception_check  boolean    True if PyErr_Occurred check needed
    # nogil            boolean    Can be called without gil
    # with_gil         boolean    Acquire gil around function body

    def analyse(self, return_type, env):
        func_type_args = []
        for arg_node in self.args:
            name_declarator, type = arg_node.analyse(env)
            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:
                error(arg_node.pos, "Function argument cannot be void")
            func_type_args.append(
                PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
            if arg_node.default:
                error(arg_node.pos, "C function argument cannot have default value")
        exc_val = None
        exc_check = 0
        if return_type.is_pyobject \
            and (self.exception_value or self.exception_check):
                error(self.pos,
                    "Exception clause not allowed for function returning Python object")
        else:
            if self.exception_value:
                self.exception_value.analyse_const_expression(env)
                exc_val = self.exception_value.result()
                if not return_type.assignable_from(self.exception_value.type):
                    error(self.exception_value.pos,
                        "Exception value incompatible with function return type")
            exc_check = self.exception_check
        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")
        func_type = PyrexTypes.CFuncType(
            return_type, func_type_args, self.has_varargs, 
            exception_value = exc_val, exception_check = exc_check,
            calling_convention = self.base.calling_convention,
            nogil = self.nogil, with_gil = self.with_gil)
        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'
    # allow_none     tristate           True == 'or None', False == 'not None', None = unspecified
    # default        ExprNode or None
    # default_entry  Symtab.Entry       Entry for the variable holding the default value
    # is_self_arg    boolean            Is the "self" arg of an extension type method
    # is_kw_only     boolean            Is a keyword-only argument

    is_self_arg = 0
    
    def analyse(self, env):
        #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
        base_type = self.base_type.analyse(env)
        return self.declarator.analyse(base_type, env)


class CBaseTypeNode(Node):
    # Abstract base class for C base type nodes.
    #
    # Processing during analyse_declarations phase:
    #
    #   analyse
    #     Returns the type.
    
    pass


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

    def analyse(self, env):
        # Return type descriptor.
        #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
        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:
                #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
                type = env.parent_type
            else:
                type = py_object_type
        else:
            scope = env.find_imported_module(self.module_path, self.pos)
            if scope:
                entry = scope.find(self.name, self.pos)
                if entry and entry.is_type:
                    type = entry.type
                else:
                    error(self.pos, "'%s' is not a type identifier" % self.name)
        if type:
            return type
        else:
            return PyrexTypes.error_type


class CComplexBaseTypeNode(CBaseTypeNode):
    # base_type   CBaseTypeNode
    # declarator  CDeclaratorNode
    
    def analyse(self, env):
        base = self.base_type.analyse(env)
        _, 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]
    #  in_pxd        boolean
    #  api           boolean
    
    def analyse_declarations(self, env, dest_scope = None):
        if not dest_scope:
            dest_scope = env
        base_type = self.base_type.analyse(env)
        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
            if type.is_cfunction:
                entry = dest_scope.declare_cfunction(name, type, declarator.pos,
                    cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
                    api = self.api)
            else:
                if self.in_pxd and self.visibility <> 'extern':
                    error(self.pos, 
                        "Only 'extern' C variable declaration allowed in .pxd file")          
                dest_scope.declare_var(name, type, declarator.pos,
                    cname = cname, visibility = self.visibility, is_cdef = 1)
    
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        pass


class CStructOrUnionDefNode(StatNode):
    #  name          string
    #  cname         string or None
    #  module_path   [string]
    #  kind          "struct" or "union"
    #  typedef_flag  boolean
    #  cplus_flag    boolean
    #  visibility    "public" or "private"
    #  in_pxd        boolean
    #  attributes    [CVarDefNode] or None
    #  entry         Entry
    #  bases         [([name, ...], name), ...]
    
    def analyse_declarations(self, env):
        scope = None
        base_scopes = []
        for base in self.bases:
            base_entry = env.find_qualified_name(base, self.pos)
            if base_entry:
                if base_entry.is_type and base_entry.type.is_struct_or_union \
                    and base_entry.type.scope.is_cplus:
                        base_scopes.append(base_entry.type.scope)
                else:
                    error(self.pos, "Base type '%s' is not a C++ struct" %
                        ".".join(base[0] + [base[1]]))
        if self.attributes is not None:
            scope = StructOrUnionScope(base_scopes = base_scopes, is_cplus = self.cplus_flag)
        if self.module_path:
            home_scope = env.find_imported_module(self.module_path, self.pos)
            if not home_scope:
                return
        else:
            home_scope = env
        def declare():
            self.entry = home_scope.declare_struct_or_union(
                self.name, self.kind, scope, self.typedef_flag, self.pos,
                self.cname, visibility = self.visibility)
            if self.attributes is not None:
                if self.in_pxd and not env.in_cinclude:
                    self.entry.defined_in_pxd = 1
        if not self.typedef_flag:
            declare()
        if self.attributes is not None:
            for attr in self.attributes:
                attr.analyse_declarations(env, scope)
        if self.typedef_flag:
            declare()

    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
    #  visibility     "public" or "private"
    #  in_pxd         boolean
    #  entry          Entry
    
    def analyse_declarations(self, env):
        self.entry = env.declare_enum(self.name, self.pos,
            cname = self.cname, typedef_flag = self.typedef_flag,
            visibility = self.visibility)
        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)

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


class CEnumDefItemNode(StatNode):
    #  name     string
    #  cname    string or None
    #  value    ExprNode or None
    
    def analyse_declarations(self, env, enum_entry):
        value_node = self.value
        if value_node:
            value_node.analyse_const_expression(env)
            type = value_node.type
            if type.is_int or type.is_enum:
                value = value_node.result()
            else:
                error(self.pos,
                    "Type '%s' is not a valid enum value" % type)
                value = "<error>"
        else:
            value = self.name
        entry = env.declare_const(self.name, enum_entry.type, 
            value, self.pos, cname = self.cname)
        enum_entry.enum_values.append(entry)


class CTypeDefNode(StatNode):
    #  base_type    CBaseTypeNode
    #  declarator   CDeclaratorNode
    #  visibility   "public" or "private"
    #  in_pxd       boolean
    
    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
        entry = env.declare_typedef(name, type, self.pos,
            cname = cname, visibility = self.visibility)
        if self.in_pxd and not env.in_cinclude:
            entry.defined_in_pxd = 1
    
    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
    
    def analyse_expressions(self, env):
        pass
    
    def need_gil_acquisition(self, lenv):
        return 0
                
    def generate_function_definitions(self, env, code):
        # Generate C code for header and body of function
        genv = env.global_scope()
        lenv = LocalScope(name = self.entry.name, outer_scope = genv)
        lenv.return_type = self.return_type
        type = self.entry.type
        if type.is_cfunction:
            lenv.nogil = type.nogil and not type.with_gil
        code.init_labels()
        self.declare_arguments(lenv)
        self.body.analyse_declarations(lenv)
        self.body.analyse_expressions(lenv)
        # Code for nested function definitions would go here
        # if we supported them, which we probably won't.
        # ----- Function header
        code.putln("")
        self.generate_function_header(code,
            with_pymethdef = env.is_py_class_scope)
        # ----- Local variable declarations
        self.generate_argument_declarations(lenv, code)
        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))
        code.put_var_declarations(lenv.temp_entries)
        self.generate_keyword_list(code)
        # ----- Extern library function declarations
        lenv.generate_library_function_declarations(code)
        # ----- GIL acquisition
        acquire_gil = self.need_gil_acquisition(lenv)
        if acquire_gil:
            lenv.global_scope().gil_used = 1
            code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
        # ----- Fetch arguments
        self.generate_argument_parsing_code(code)
        self.generate_argument_increfs(lenv, code)
        # ----- Initialise local variables
        for entry in lenv.var_entries:
            if entry.type.is_pyobject and entry.init_to_none and entry.used:
                code.put_init_var_to_py_none(entry)
        # ----- Check and convert arguments
        self.generate_argument_conversion_code(code)
        self.generate_argument_type_tests(code)
        # ----- 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))
        #code.putln("goto %s;" % code.return_label)
        # ----- Error cleanup
        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)
            default_retval = self.return_type.default_value
            err_val = self.error_value()
            exc_check = self.caller_will_check_exceptions()
            if err_val or exc_check:
                code.putln(
                    '__Pyx_AddTraceback("%s");' % 
                        self.entry.qualified_name)
                val = err_val or default_retval
                if val:
                    code.putln(
                        "%s = %s;" % (
                            Naming.retval_cname, 
                            val))
            else:
                code.use_utility_code(unraisable_exception_utility_code)
                code.putln(
                    '__Pyx_WriteUnraisable("%s");' % 
                        self.entry.qualified_name)
                #if not self.return_type.is_void:
                if default_retval:
                    code.putln(
                        "%s = %s;" % (
                            Naming.retval_cname,
                            default_retval))
                            #self.return_type.default_value))
        # ----- Return cleanup
        code.put_label(code.return_label)
        code.put_var_decrefs(lenv.var_entries, used_only = 1)
        #code.put_var_decrefs(lenv.arg_entries)
        self.generate_argument_decrefs(lenv, code)
        self.put_stararg_decrefs(code)
        if acquire_gil:
            code.putln("PyGILState_Release(_save);")
        if not self.return_type.is_void:
            code.putln("return %s;" % Naming.retval_cname)
        code.putln("}")
    
    def put_stararg_decrefs(self, code):
        pass

    def declare_argument(self, env, arg, readonly = 0):
        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,
            readonly = readonly)
    
    def generate_argument_increfs(self, env, code):
        # Turn writable borrowed argument refs into owned refs.
        # This is necessary, because if the argument is assigned to,
        # it will be decrefed.
        for entry in env.arg_entries:
            if not entry.is_readonly:
                code.put_var_incref(entry)
    
    def generate_argument_decrefs(self, env, code):
        for entry in env.arg_entries:
            if not entry.is_readonly:
                code.put_var_decref(entry)

    def generate_execution_code(self, code):
        pass


class CFuncDefNode(FuncDefNode):
    #  C function definition.
    #
    #  visibility    'private' or 'public' or 'extern'
    #  base_type     CBaseTypeNode
    #  declarator    CDeclaratorNode
    #  body          StatListNode
    #  api           boolean
    #
    #  with_gil      boolean    Acquire GIL around body
    #  type          CFuncType
    
    def unqualified_name(self):
        return self.entry.name
        
    def analyse_declarations(self, env):
        base_type = self.base_type.analyse(env)
        name_declarator, type = self.declarator.analyse(base_type, env)
        if not type.is_cfunction:
            error(self.pos, 
                "Suite attached to non-function declaration")
        # 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
        name = name_declarator.name
        cname = name_declarator.cname
        self.entry = env.declare_cfunction(
            name, type, self.pos, 
            cname = cname, visibility = self.visibility,
            defining = self.body is not None,
            api = self.api)
        self.return_type = type.return_type
    
    def declare_arguments(self, env):
        type = self.type
        without_gil = type.nogil and not type.with_gil
        for arg in type.args:
            if not arg.name:
                error(arg.pos, "Missing argument name")
            self.declare_argument(env, arg,
                readonly = without_gil and arg.type.is_pyobject)
            
    def need_gil_acquisition(self, lenv):
        type = self.type
        with_gil = type.with_gil
        if type.nogil and not with_gil:
#      for arg in type.args:
#        if arg.type.is_pyobject:
#          error(self.pos,
#            "Function with Python argument cannot be declared nogil")
            if type.return_type.is_pyobject:
                error(self.pos,
                    "Function with Python return type cannot be declared nogil")
            for entry in lenv.var_entries + lenv.temp_entries:
                #print "CFuncDefNode.need_gil_acquisition:", entry.name, entry.cname, "readonly =", entry.is_readonly ###
                if entry.type.is_pyobject and not entry.is_readonly:
                    error(self.pos, "Function declared nogil has Python locals or temporaries")
        return with_gil

    def generate_function_header(self, code, with_pymethdef):
        arg_decls = []
        type = self.type
        visibility = self.entry.visibility
        for arg in type.args:
            arg_decls.append(arg.declaration_code())
        if type.has_varargs:
            arg_decls.append("...")
        if not arg_decls:
            arg_decls = ["void"]
        entity = type.function_header_code(self.entry.func_cname,
            string.join(arg_decls, ","))
        if visibility == 'public':
            dll_linkage = "DL_EXPORT"
        else:
            dll_linkage = None
        header = self.return_type.declaration_code(entity,
            dll_linkage = dll_linkage)
        if visibility <> 'private':
            storage_class = "%s " % Naming.extern_c_macro
        else:
            storage_class = "static "
        code.putln("%s%s {" % (
            storage_class,
            header))

    def generate_argument_declarations(self, env, code):
        # Arguments already declared in function header
        pass
    
    def generate_keyword_list(self, code):
        pass
        
    def generate_argument_parsing_code(self, code):
        pass
    
    def generate_argument_conversion_code(self, code):
        pass
    
    def generate_argument_type_tests(self, code):
        pass
    
    def error_value(self):
        if self.return_type.is_pyobject:
            return "0"
        else:
            #return None
            return self.entry.type.exception_value
            
    def caller_will_check_exceptions(self):
        return self.entry.type.exception_check


class PyArgDeclNode(Node):
    # Argument which must be a Python object (used
    # for * and ** arguments).
    #
    # name   string
    # entry  Symtab.Entry
    
    pass
    

class DefNode(FuncDefNode):
    # A Python function definition.
    #
    # name          string                 the Python name of the function
    # args          [CArgDeclNode]         formal arguments
    # star_arg      PyArgDeclNode or None  * argument
    # starstar_arg  PyArgDeclNode or None  ** argument
    # doc           string or None
    # body          StatListNode
    #
    #  The following subnode is constructed internally
    #  when the def statement is inside a Python class definition.
    #
    #  assmt   AssignmentNode   Function construction/assignment
    
    assmt = None
    num_kwonly_args = 0
    reqd_kw_flags_cname = "0"
    has_star_or_kwonly_args = 0
    
    def __init__(self, pos, **kwds):
        FuncDefNode.__init__(self, pos, **kwds)
        n = 0
        for arg in self.args:
            if arg.kw_only:
                n += 1
        self.num_kwonly_args = n
        if self.star_arg or self.starstar_arg or n > 0:
            self.has_star_or_kwonly_args = 1
    
    def analyse_declarations(self, env):
        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
            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.allow_none is not None and not arg.type.is_extension_type:
                error(self.pos,
                    "Only extension type arguments can have 'or None' or 'not None'")
        self.declare_pyfunction(env)
        self.analyse_signature(env)
        self.return_type = self.entry.signature.return_type()
#    if self.has_star_or_kwonly_args:
#      env.use_utility_code(get_starargs_utility_code)
    
    def analyse_signature(self, env):
        any_type_tests_needed = 0
        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:
                if arg.is_generic and arg.type.is_extension_type:
                    arg.needs_type_test = 1
                    any_type_tests_needed = 1
#    if any_type_tests_needed:
#      env.use_utility_code(arg_type_test_utility_code)
    
    def bad_signature(self):
        sig = self.entry.signature
        expected_str = "%d" % sig.num_fixed_args()
        if sig.has_generic_args:
            expected_str = expected_str + " or more"
        name = self.name
        if name.startswith("__") and name.endswith("__"):
            desc = "Special method"
        else:
            desc = "Method"
        error(self.pos,
            "%s %s has wrong number of arguments "
            "(%d declared, %s expected)" % (
                desc, self.name, len(self.args), expected_str))
    
    def declare_pyfunction(self, env):
        #print "DefNode.declare_pyfunction:", self.name, "in", env ###
        name = self.name
        entry = env.declare_pyfunction(self.name, self.pos)
        self.entry = entry
        prefix = env.scope_prefix
        entry.func_cname = \
            Naming.func_prefix + prefix + name
        entry.pymethdef_cname = \
            Naming.pymethdef_prefix + prefix + name
        if not entry.is_special:
            entry.doc = self.doc
            entry.doc_cname = \
                Naming.funcdoc_prefix + prefix + name
        
    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)
                if arg.type.is_pyobject:
                    arg.entry.init = "0"
                arg.entry.init_to_none = 0
            else:
                arg.entry = self.declare_argument(env, arg)
            arg.entry.used = 1
            arg.entry.is_self_arg = arg.is_self_arg
            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:
            entry = env.declare_var(arg.name, 
                PyrexTypes.py_object_type, arg.pos)
            entry.used = 1
            entry.init = "0"
            entry.init_to_none = 0
            entry.xdecref_cleanup = 1
            arg.entry = entry
            
    def analyse_expressions(self, env):
        self.analyse_default_values(env)
        if env.is_py_class_scope:
            self.synthesize_assignment_node(env)
    
    def analyse_default_values(self, env):
        for arg in self.args:
            if arg.default:
                if arg.is_generic:
                    arg.default.analyse_types(env)
                    arg.default = arg.default.coerce_to(arg.type, env)
                    arg.default.allocate_temps(env)
                    arg.default_entry = env.add_default_value(arg.type)
                    arg.default_entry.used = 1
                else:
                    error(arg.pos,
                        "This argument cannot have a default value")
                    arg.default = None
    
    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)
            
    def generate_function_header(self, code, with_pymethdef):
        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))
        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)
        if self.entry.doc:
            code.putln(
                'static char %s[] = "%s";' % (
                    self.entry.doc_cname,
                    self.entry.doc))
        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:
                code.put_var_declaration(arg.entry)
    
    def generate_keyword_list(self, code):
        if self.entry.signature.has_generic_args:
            reqd_kw_flags = []
            has_reqd_kwds = False
            code.put(
                "static char *%s[] = {" %
                    Naming.kwdlist_cname)
            for arg in self.args:
                if arg.is_generic:
                    code.put(
                        '"%s",' % 
                            arg.name)
                    if arg.kw_only and not arg.default:
                        has_reqd_kwds = 1
                        flag = "1"
                    else:
                        flag = "0"
                    reqd_kw_flags.append(flag)
            code.putln(
                "0};")
            if has_reqd_kwds:
                flags_name = Naming.reqd_kwds_cname
                self.reqd_kw_flags_cname = flags_name
                code.putln(
                    "static char %s[] = {%s};" % (
                        flags_name,
                        ",".join(reqd_kw_flags)))
    
    def generate_argument_parsing_code(self, code):
        # Generate PyArg_ParseTuple call for generic
        # arguments, if any.
        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
        if not self.entry.signature.has_generic_args:
            if has_star_or_kw_args:
                error(self.pos, "This method cannot have * or keyword arguments")
        else:
            arg_addrs = []
            arg_formats = []
            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,
                                arg.default_entry.cname))
                        if not default_seen:
                            arg_formats.append("|")
                        default_seen = 1
                    elif default_seen and not arg.kw_only:
                        error(arg.pos, "Non-default argument following default argument")
                    arg_addrs.append("&" + arg_entry.cname)
                    format = arg_entry.type.parsetuple_format
                    if format:
                        arg_formats.append(format)
                    else:
                        error(arg.pos, 
                            "Cannot convert Python object argument to type '%s'" 
                                % arg.type)
            error_return_code = "return %s;" % self.error_value()
            argformat = '"%s"' % string.join(arg_formats, "")
            if has_star_or_kw_args:
                self.generate_stararg_getting_code(code)
            pt_arglist = [Naming.args_cname, Naming.kwds_cname, argformat,
                    Naming.kwdlist_cname] + arg_addrs
            pt_argstring = string.join(pt_arglist, ", ")
            code.put(
                'if (!PyArg_ParseTupleAndKeywords(%s)) ' %
                    pt_argstring)
            if has_star_or_kw_args:
                code.putln("{")
                code.put_xdecref(Naming.args_cname, py_object_type)
                code.put_xdecref(Naming.kwds_cname, py_object_type)
                self.generate_arg_xdecref(self.star_arg, code)
                self.generate_arg_xdecref(self.starstar_arg, code)
                code.putln(error_return_code)
                code.putln("}")
            else:
                code.putln(error_return_code)
        
    def put_stararg_decrefs(self, code):
        if self.has_star_or_kwonly_args:
            code.put_xdecref(Naming.args_cname, py_object_type)
            code.put_xdecref(Naming.kwds_cname, py_object_type)
    
    def generate_arg_xdecref(self, arg, code):
        if arg:
            code.put_var_xdecref(arg.entry)
    
    def arg_address(self, arg):
        if arg:
            return "&%s" % arg.entry.cname
        else:
            return 0

    def generate_stararg_getting_code(self, code):
        num_kwonly = self.num_kwonly_args
        nargs = len(self.args) - num_kwonly - self.entry.signature.num_fixed_args()
        star_arg_addr = self.arg_address(self.star_arg)
        starstar_arg_addr = self.arg_address(self.starstar_arg)
        code.use_utility_code(get_starargs_utility_code)
        code.putln(
            "if (__Pyx_GetStarArgs(&%s, &%s, %s, %s, %s, %s, %s) < 0) return %s;" % (
                Naming.args_cname,
                Naming.kwds_cname,
                Naming.kwdlist_cname,
                nargs,
                star_arg_addr,
                starstar_arg_addr,
                self.reqd_kw_flags_cname,
                self.error_value()))
    
    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:
            self.generate_arg_conversion_from_pyobject(arg, code)
        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,
                    "Cannot convert argument from '%s' to '%s'" %
                        (old_type, new_type))
    
    def generate_arg_conversion_from_pyobject(self, arg, code):
        new_type = arg.type
        func = new_type.from_py_function
        if func:
            code.putln("%s = %s(%s); if (PyErr_Occurred()) %s" % (
                arg.entry.cname,
                func,
                arg.hdr_cname,
                code.error_goto(arg.pos)))
        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:
            code.putln("%s = %s(%s); if (!%s) %s" % (
                arg.entry.cname,
                func,
                arg.hdr_cname,
                arg.entry.cname,
                code.error_goto(arg.pos)))
        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.use_utility_code(arg_type_test_utility_code)
            code.putln(
                'if (!__Pyx_ArgTypeTest(%s, %s, %d, "%s")) %s' % (
                    arg_code, 
                    typeptr_cname,
                    #not arg.not_none,
                    arg.allow_none <> False,
                    arg.name,
                    code.error_goto(arg.pos)))
            if arg.allow_none is None:
                one_time_warning(arg.pos, 'or_none',
                    "'not None' will become the default in a future version of Pyrex. "
                    "Use 'or None' to allow passing None.")
        else:
            error(arg.pos, "Cannot test type of extern C class "
                "without type object name specification")
    
    def generate_execution_code(self, code):
        # Evaluate and store argument default values
        for arg in self.args:
            default = arg.default
            if default:
                default.generate_evaluation_code(code)
                default.make_owned_reference(code)
                code.putln(
                    "%s = %s;" % (
                        arg.default_entry.cname,
                        default.result_as(arg.default_entry.type)))
                default.generate_post_assignment_code(code)
#        if default.is_temp and default.type.is_pyobject:
#          code.putln(
#            "%s = 0;" %
#              default.result())
        # For Python class methods, create and store function object
        if self.assmt:
            self.assmt.generate_execution_code(code)
    
    def error_value(self):
        return self.entry.signature.error_value
    
    def caller_will_check_exceptions(self):
        return 1
            

class PyClassDefNode(StatNode, BlockNode):
    #  A Python class definition.
    #
    #  name     string          Name of the class
    #  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
    
    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 = [])
        if self.doc:
            doc_node = ExprNodes.StringNode(pos, value = self.doc)
        else:
            doc_node = None
        self.classobj = ExprNodes.ClassNode(pos,
            name = ExprNodes.StringNode(pos, value = name), 
            bases = bases, dict = self.dict, doc = doc_node)
        self.target = ExprNodes.NameNode(pos, name = name)
    
    def analyse_declarations(self, env):
        self.target.analyse_target_declaration(env)
    
    def analyse_expressions(self, env):
        self.dict.analyse_expressions(env)
        self.classobj.analyse_expressions(env)
        genv = env.global_scope()
        cenv = PyClassScope(name = self.name, outer_scope = genv)
        cenv.class_dict_cname = self.dict.result()
        cenv.class_obj_cname = self.classobj.result()
        self.scope = cenv
        self.body.analyse_declarations(cenv)
        self.body.analyse_expressions(cenv)
        self.target.analyse_target_expression(env, self.classobj)
        self.dict.release_temp(env)
        #self.classobj.release_temp(env)
        #self.target.release_target_temp(env)
    
    def generate_function_definitions(self, env, code):
        #self.generate_py_string_decls(self.scope, code)
        self.body.generate_function_definitions(
            self.scope, code)
    
    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)


class CClassDefNode(StatNode):
    #  An extension type definition.
    #
    #  visibility         'private' or 'public' or 'extern'
    #  typedef_flag       boolean
    #  api                boolean
    #  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
    #  options            CClassOptions:
    #    objstruct_name     string or None    Specified C name of object struct
    #    typeobj_name       string or None    Specified C name of type object
    #    no_gc              boolean           Suppress GC support
    #  in_pxd             boolean           Is in a .pxd file
    #  doc                string or None
    #  body               StatNode or None
    #  entry              Symtab.Entry
    #  base_type          PyExtensionType or None
    
    entry = None
    
    def analyse_declarations(self, env):
        #print "CClassDefNode.analyse_declarations:", self.class_name
        #print "...visibility =", self.visibility
        #print "...module_name =", self.module_name
        if env.in_cinclude and not self.options.objstruct_cname:
            error(self.pos, "Object struct name specification required for "
                "C class defined in 'extern from' block")
        self.base_type = None
        has_body = self.body is not None
        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 has_body and base_class_entry.visibility <> 'extern' and not base_class_entry.type.is_defined():
                        error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
                    else:
                        self.base_type = base_class_entry.type
        if self.module_name and self.visibility <> 'extern':
            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(
            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,
            visibility = self.visibility,
            typedef_flag = self.typedef_flag,
            api = self.api,
            options = self.options)
        if home_scope is not env and self.visibility == 'extern':
            env.add_imported_entry(self.class_name, self.entry, pos)
        scope = self.entry.type.scope
        if self.doc:
            scope.doc = self.doc
        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:
            self.body.analyse_expressions(env)
    
    def generate_function_definitions(self, env, code):
        if self.entry and self.body:
#      self.body.generate_function_definitions(
#        self.entry.type.scope, code)
            self.body.generate_function_definitions(env, code)
    
    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)


class PropertyNode(StatNode):
    #  Definition of a property in an extension type.
    #
    #  name   string
    #  doc    string or None    Doc string
    #  body   StatListNode
    
    def analyse_declarations(self, env):
        #print "PropertyNode.analyse_declarations:", env ###
        entry = env.declare_property(self.name, self.doc, self.pos)
        if entry:
            #if self.doc:
            #  doc_entry = env.get_string_const(self.doc)
            #  entry.doc_cname = doc_entry.cname
            self.body.analyse_declarations(entry.scope)
        
    def analyse_expressions(self, env):
        self.body.analyse_expressions(env)
    
    def generate_function_definitions(self, env, code):
        self.body.generate_function_definitions(env, code)

    def generate_execution_code(self, code):
        pass


class GlobalNode(StatNode):
    # Global variable declaration.
    #
    # names    [string]
    
    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
    
    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)
        if not self.expr.is_temp and self.expr.result():
            code.putln("%s;" % self.expr.result())
        self.expr.generate_disposal_code(code)


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

    def generate_execution_code(self, code):
        self.generate_rhs_evaluation_code(code)
        self.generate_assignment_code(code)


class SingleAssignmentNode(AssignmentNode):
    #  The simplest case:
    #
    #    a = b
    #
    #  lhs      ExprNode      Left hand side
    #  rhs      ExprNode      Right hand side

    def analyse_declarations(self, env):
        self.lhs.analyse_target_declaration(env)
    
    def analyse_types(self, env, use_temp = 0):
        self.rhs.analyse_types(env)
        self.lhs.analyse_target_types(env)
        self.lhs.gil_assignment_check(env)
        self.rhs = self.rhs.coerce_to(self.lhs.type, env)
        if use_temp:
            self.rhs = self.rhs.coerce_to_temp(env)
    
    def allocate_rhs_temps(self, env):
        self.rhs.allocate_temps(env)

    def allocate_lhs_temps(self, env):
        self.lhs.allocate_target_temps(env, self.rhs)

    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)


class AugmentedAssignmentNode(SingleAssignmentNode):
    #  An in-place operation:
    #
    #    a op= b
    #
    #  lhs       ExprNode      Left hand side
    #  operator  string
    #  rhs       ExprNode      Right hand side

    def analyse_types(self, env):
        op = self.operator
        self.rhs.analyse_types(env)
        self.lhs.analyse_inplace_types(env)
        type = self.lhs.type
        if type.is_pyobject:
            type = py_object_type
        else:
            if type.is_ptr and (op == '+=' or op == '-='):
                type = c_int_type
            elif op == "**=":
                error(self.pos, "**= operator not supported for non-Python types")
                return
        self.rhs = self.rhs.coerce_to(type, env)

    def allocate_lhs_temps(self, env):
        self.lhs.allocate_inplace_target_temps(env, self.rhs)

    def generate_assignment_code(self, code):
        self.lhs.generate_inplace_assignment_code(self.operator, self.rhs, code)


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
    
    def analyse_declarations(self, env):
        for lhs in self.lhs_list:
            lhs.analyse_target_declaration(env)
    
    def analyse_types(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)
        from ExprNodes import CloneNode
        self.coerced_rhs_list = []
        for lhs in self.lhs_list:
            lhs.analyse_target_types(env)
            lhs.gil_assignment_check(env)
            rhs = CloneNode(self.rhs)
            rhs = rhs.coerce_to(lhs.type, env)
            self.coerced_rhs_list.append(rhs)

    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):
            rhs.allocate_temps(env)
            lhs.allocate_target_temps(env, rhs)
            #lhs.release_target_temp(env)
            #rhs.release_temp(env)
        self.rhs.release_temp(env)
    
    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)

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
    
    def analyse_declarations(self, env):
        for stat in self.stats:
            stat.analyse_declarations(env)
    
    def analyse_expressions(self, env):
        for stat in self.stats:
            stat.analyse_types(env, use_temp = 1)
            stat.allocate_rhs_temps(env)
        for stat in self.stats:
            stat.allocate_lhs_temps(env)
    
    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)


class PrintStatNode(StatNode):
    #  print statement
    #
    #  args              [ExprNode]
    #  ends_with_comma   boolean
    
    def analyse_expressions(self, env):
        for i in range(len(self.args)):
            arg = self.args[i]
            arg.analyse_types(env)
            arg = arg.coerce_to_pyobject(env)
            arg.allocate_temps(env)
            arg.release_temp(env)
            self.args[i] = arg
#    env.use_utility_code(printing_utility_code)
        self.gil_check(env)

    gil_message = "Python print statement"
    
    def generate_execution_code(self, code):
        for arg in self.args:
            arg.generate_evaluation_code(code)
            code.use_utility_code(printing_utility_code)
            code.putln(
                "if (__Pyx_PrintItem(%s) < 0) %s" % (
                    arg.py_result(),
                    code.error_goto(self.pos)))
            arg.generate_disposal_code(code)
        if not self.ends_with_comma:
            code.use_utility_code(printing_utility_code)
            code.putln(
                "if (__Pyx_PrintNewline() < 0) %s" %
                    code.error_goto(self.pos))


class DelStatNode(StatNode):
    #  del statement
    #
    #  args     [ExprNode]
    
    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:
            arg.analyse_target_expression(env, None)
            type = arg.type
            if not (type.is_pyobject
                or (type.is_ptr and type.base_type.is_struct_or_union
                    and type.base_type.scope.is_cplus)):
                error(arg.pos, "'del' can only be applied to Python object or pointer to C++ type")
            if type.is_pyobject:
                self.gil_check(env)
    
    gil_message = "Deleting Python object"
    
    def generate_execution_code(self, code):
        for arg in self.args:
            if arg.type.is_pyobject:
                arg.generate_deletion_code(code)
            else:
                arg.generate_evaluation_code(code)
                code.putln("delete %s;" % arg.result())
                arg.generate_disposal_code(code)


class PassStatNode(StatNode):
    #  pass statement
    
    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        pass


class BreakStatNode(StatNode):

    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:
            #code.putln(
            #  "goto %s;" %
            #    code.break_label)
            code.put_goto(code.break_label)


class ContinueStatNode(StatNode):

    def analyse_expressions(self, env):
        pass
    
    def generate_execution_code(self, code):
        if code.in_try_finally:
            error(self.pos, "continue statement inside try of try...finally")
        elif not code.continue_label:
            error(self.pos, "continue statement not inside loop")
        else:
            #code.putln(
            #  "goto %s;" %
            #    code.continue_label)
            code.put_goto(code.continue_label)


class ReturnStatNode(StatNode):
    #  return statement
    #
    #  value         ExprNode or None
    #  return_type   PyrexType
    #  temps_in_use  [Entry]            Temps in use at time of return
    
    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")
        if return_type.is_pyobject:
            self.gil_check(env)
    
    gil_message = "Returning Python object"
    
    def generate_execution_code(self, code):
        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))
        for entry in self.temps_in_use:
            code.put_var_decref_clear(entry)
        #code.putln(
        #  "goto %s;" %
        #    code.return_label)
        code.put_goto(code.return_label)


class RaiseStatNode(StatNode):
    #  raise statement
    #
    #  exc_type    ExprNode or None
    #  exc_value   ExprNode or None
    #  exc_tb      ExprNode or None
    
    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)
        self.gil_check(env)
    
    gil_message = "Raising exception"
    
    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"
        code.use_utility_code(raise_utility_code)
        code.putln(
            "__Pyx_Raise(%s, %s, %s);" % (
                type_code,
                value_code,
                tb_code))
        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))


class ReraiseStatNode(StatNode):

    def analyse_expressions(self, env):
        env.reraise_used = 1
        self.gil_check(env)
    
    gil_message = "Raising exception"

    def generate_execution_code(self, code):
        vars = code.exc_vars
        if vars:
            tvars = tuple(vars)
            code.putln("PyErr_Restore(%s, %s, %s);" % tvars)
            code.putln("%s = %s = %s = 0;" % tvars)
            code.putln(code.error_goto(self.pos))
        else:
            error(self.pos, "Reraise not inside except clause")
        

class AssertStatNode(StatNode):
    #  assert statement
    #
    #  cond    ExprNode
    #  value   ExprNode or None
    
    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)
        self.gil_check(env)
    
    gil_message = "Raising exception"
    
    def generate_execution_code(self, code):
        code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
        self.cond.generate_evaluation_code(code)
        code.putln(
            "if (!%s) {" %
                self.cond.result())
        if self.value:
            self.value.generate_evaluation_code(code)
        if self.value:
            code.putln(
                "PyErr_SetObject(PyExc_AssertionError, %s);" %
                    self.value.py_result())
        else:
            code.putln(
                "PyErr_SetNone(PyExc_AssertionError);")
        code.putln(
                code.error_goto(self.pos))
        code.putln(
            "}")
        self.cond.generate_disposal_code(code)
        # Disposal code for value not needed because exception always raised
        #if self.value:
        #  self.value.generate_disposal_code(code)
        code.putln("#endif")

class IfStatNode(StatNode):
    #  if statement
    #
    #  if_clauses   [IfClauseNode]
    #  else_clause  StatNode or None
    
    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):
        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)


class IfClauseNode(Node):
    #  if or elif clause in an if statement
    #
    #  condition   ExprNode
    #  body        StatNode
    
    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) {" %
                self.condition.result())
        self.body.generate_execution_code(code)
        #code.putln(
        #  "goto %s;" %
        #    end_label)
        code.put_goto(end_label)
        code.putln("}")
        
    
class WhileStatNode(StatNode):
    #  while statement
    #
    #  condition    ExprNode
    #  body         StatNode
    #  else_clause  StatNode
    
    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;" %
                self.condition.result())
        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)


class ForInStatNode(StatNode):
    #  for statement
    #
    #  target        ExprNode
    #  iterator      IteratorNode
    #  body          StatNode
    #  else_clause   StatNode
    #  item          NextNode       used internally
    
    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)
    
    def analyse_expressions(self, env):
        import ExprNodes
        self.iterator.analyse_expressions(env)
        self.target.analyse_target_types(env)
        self.item = ExprNodes.NextNode(self.iterator, env)
        self.item = self.item.coerce_to(self.target.type, env)
        self.item.allocate_temps(env)
        self.target.allocate_target_temps(env, self.item)
        #self.item.release_temp(env)
        #self.target.release_target_temp(env)
        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)
        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.iterator.generate_disposal_code(code)


class IntegerForStatNode(StatNode):
    #  for expr rel name rel expr
    #
    #  bound1        ExprNode
    #  relation1     string
    #  target        NameNode
    #  relation2     string
    #  bound2        ExprNode
    #  body          StatNode
    #  else_clause   StatNode or None
    #
    #  Used internally:
    #
    #  is_py_target       bool
    #  loopvar_name       string
    #  py_loopvar_node    PyTempNode or None
    
    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)

    def analyse_expressions(self, env):
        import ExprNodes
        self.target.analyse_target_types(env)
        self.bound1.analyse_types(env)
        self.bound2.analyse_types(env)
        self.bound1 = self.bound1.coerce_to_integer(env)
        self.bound2 = self.bound2.coerce_to_integer(env)
        if not (self.bound2.is_name or self.bound2.is_literal):
            self.bound2 = self.bound2.coerce_to_temp(env)
        target_type = self.target.type
        if not (target_type.is_pyobject or target_type.is_int):
            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)
        if target_type.is_int:
            self.is_py_target = 0
            self.loopvar_name = self.target.entry.cname
            self.py_loopvar_node = None
        else:
            self.is_py_target = 1
            c_loopvar_node = ExprNodes.TempNode(self.pos, 
                PyrexTypes.c_long_type, env)
            c_loopvar_node.allocate_temps(env)
            self.loopvar_name = c_loopvar_node.result()
            self.py_loopvar_node = \
                ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
        self.bound1.allocate_temps(env)
        self.bound2.allocate_temps(env)
        if self.is_py_target:
            self.py_loopvar_node.allocate_temps(env)
            self.target.allocate_target_temps(env, self.py_loopvar_node)
            #self.target.release_target_temp(env)
            #self.py_loopvar_node.release_temp(env)
        self.body.analyse_expressions(env)
        if self.is_py_target:
            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)
            
    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]
        code.putln(
            "for (%s = %s%s; %s %s %s; %s%s) {" % (
                self.loopvar_name,
                self.bound1.result(), offset,
                self.loopvar_name, self.relation2, self.bound2.result(),
                incop, self.loopvar_name))
        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)
    
    relation_table = {
        # {relop : (initial offset, increment op)}
        '<=': ("",   "++"),
        '<' : ("+1", "++"),
        '>=': ("",   "--"),
        '>' : ("-1", "--")
    }


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
    
    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)
        self.gil_check(env)
    
    def analyse_expressions(self, env):
        self.body.analyse_expressions(env)
        self.cleanup_list = env.free_temp_entries[:]
        for except_clause in self.except_clauses:
            except_clause.analyse_expressions(env)
        if self.else_clause:
            self.else_clause.analyse_expressions(env)
        self.gil_check(env)
    
    gil_message = "Try-except statement"
    
    def generate_execution_code(self, code):
        old_error_label = code.new_error_label()
        our_error_label = code.error_label
        end_label = code.new_label()
        code.putln(
            "/*try:*/ {")
        self.body.generate_execution_code(code)
        code.putln(
            "}")
        code.error_label = old_error_label
        if self.else_clause:
            code.putln(
                "/*else:*/ {")
            self.else_clause.generate_execution_code(code)
            code.putln(
                "}")
        code.put_goto(end_label)
        code.put_label(our_error_label)
        code.put_var_xdecrefs_clear(self.cleanup_list)
        default_clause_seen = 0
        for except_clause in self.except_clauses:
            if not except_clause.pattern:
                default_clause_seen = 1
            else:
                if default_clause_seen:
                    error(except_clause.pos, "Default except clause not last")
            except_clause.generate_handling_code(code, end_label)
        if not default_clause_seen:
            code.put_goto(code.error_label)
        code.put_label(end_label)


class ExceptClauseNode(Node):
    #  Part of try ... except statement.
    #
    #  pattern        ExprNode
    #  exc_target     ExprNode or None
    #  tb_target      ExprNode or None
    #  body           StatNode
    #  match_flag     string             result of exception match
    #  exc_value      ExcValueNode       used internally
    #  tb_value       ExcValueNode       used internally
    #  function_name  string             qualified name of enclosing function
    #  exc_vars       (string * 3)       local exception variables
    #  reraise_used   boolean            body contains reraise statement
    
    def analyse_declarations(self, env):
        if self.exc_target:
            self.exc_target.analyse_target_declaration(env)
        if self.tb_target:
            self.tb_target.analyse_target_declaration(env)
        self.body.analyse_declarations(env)
    
    def analyse_expressions(self, env):
        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)
        self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
        self.exc_value = self.analyse_target(env, self.exc_target, 1)
        self.tb_value = self.analyse_target(env, self.tb_target, 2)
        old_reraise_used = env.reraise_used
        env.reraise_used = False
        self.body.analyse_expressions(env)
        self.reraise_used = env.reraise_used
        env.reraise_used = old_reraise_used
        for var in self.exc_vars:
            env.release_temp(var)
    
    def analyse_target(self, env, target, var_no):
        if target:
            import ExprNodes
            value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[var_no])
            value.allocate_temps(env)
            target.analyse_target_expression(env, value)
            return value

    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:
            code.putln(
                "/*except:*/ {")
        any_bindings = self.exc_target or self.tb_target
        exc_vars_used = any_bindings or self.reraise_used
        if exc_vars_used:
            if any_bindings:
                code.putln(
                    '%s; __Pyx_AddTraceback("%s");' % (
                        code.error_setup(self.pos),
                        self.function_name))
            exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
            code.putln("PyErr_Fetch(%s);" % exc_args)
            if any_bindings:
                code.use_utility_code(normalize_exception_utility_code)
                code.putln("if (__Pyx_NormalizeException(%s) < 0) %s" % (exc_args,
                    code.error_goto(self.pos)))
            if self.exc_target:
                self.exc_value.generate_evaluation_code(code)
                self.exc_target.generate_assignment_code(self.exc_value, code)
            if self.tb_target:
                self.tb_value.generate_evaluation_code(code)
                self.tb_target.generate_assignment_code(self.tb_value, code)
        old_exc_vars = code.exc_vars
        code.exc_vars = self.exc_vars
        self.body.generate_execution_code(code)
        code.exc_vars = old_exc_vars
        if exc_vars_used:
            for var in self.exc_vars:
                code.putln("Py_XDECREF(%s); %s = 0;" % (var, var))
        code.put_goto(end_label)
        code.putln(
            "}")


class TryFinallyStatNode(StatNode):
    #  try ... finally statement
    #
    #  body             StatNode
    #  finally_clause   StatNode
    #
    #  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.
    
    preserve_exception = 1
    
    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.
    
    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)
        self.gil_check(env)
    
    gil_message = "Try-finally statement"
    
    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:
            was_in_try_finally = code.in_try_finally
            code.in_try_finally = 1
        self.body.generate_execution_code(code)
        if self.disallow_continue_in_try_finally:
            code.in_try_finally = was_in_try_finally
        code.putln(
            "}")
        code.putln(
            "/*finally:*/ {")
        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)
            code.use_label(catch_label)
            code.putln(
                    "__pyx_why = 0; goto %s;" % catch_label)
            for i in cases_used:
                new_label = new_labels[i]
                #if new_label and new_label <> "<try>":
                if new_label == new_error_label and self.preserve_exception:
                    self.put_error_catcher(code, 
                        new_error_label, i+1, catch_label)
                else:
                    code.putln(
                        "%s: __pyx_why = %s; goto %s;" % (
                            new_label,
                            i+1,
                            catch_label))
            code.put_label(catch_label)
        code.set_all_labels(old_labels)
        if error_label_used:
            code.new_error_label()
            finally_error_label = code.error_label
        self.finally_clause.generate_execution_code(code)
        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(
                "switch (__pyx_why) {")
            for i in cases_used:
                old_label = old_labels[i]
                if old_label == old_error_label and self.preserve_exception:
                    self.put_error_uncatcher(code, i+1, old_error_label)
                else:
                    code.use_label(old_label)
                    code.putln(
                        "case %s: goto %s;" % (
                            i+1,
                            old_label))
            code.putln(
                "}")    
        code.putln(
            "}")

    def put_error_catcher(self, code, error_label, i, catch_label):
        code.putln(
            "%s: {" %
                error_label)
        code.putln(
                "__pyx_why = %s;" %
                    i)
        code.put_var_xdecrefs_clear(self.cleanup_list)
        code.putln(
                "PyErr_Fetch(&%s, &%s, &%s);" %
                    Naming.exc_vars)
        code.putln(
                "%s = %s;" % (
                    Naming.exc_lineno_name, Naming.lineno_cname))
        #code.putln(
        #    "goto %s;" %
        #      catch_label)
        code.put_goto(catch_label)
        code.putln(
            "}")
            
    def put_error_uncatcher(self, code, i, error_label):
        code.putln(
            "case %s: {" %
                i)
        code.putln(
                "PyErr_Restore(%s, %s, %s);" %
                    Naming.exc_vars)
        code.putln(
                "%s = %s;" % (
                    Naming.lineno_cname, Naming.exc_lineno_name))
        for var in Naming.exc_vars:
            code.putln(
                "%s = 0;" %
                    var)
        code.put_goto(error_label)
        code.putln(
            "}")


class GILStatNode(TryFinallyStatNode):
    #  'with gil' or 'with nogil' statement
    #
    #   state   string   'gil' or 'nogil'
        
    preserve_exception = 0

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

    def analyse_expressions(self, env):
        env.global_scope().gil_used = 1
        was_nogil = env.nogil
        env.nogil = 1
        TryFinallyStatNode.analyse_expressions(self, env)
        env.nogil = was_nogil
    
    def gil_check(self, env):
        pass

    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'

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


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
    
    def analyse_declarations(self, env):
        module_scope = env.find_module(self.module_name, self.pos)
        if "." in self.module_name:
            names = self.module_name.split(".")
            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)
                if not self.as_name:
                    env.add_imported_module(submodule_scope)
                module_scope = submodule_scope
            if self.as_name:
                env.declare_module(self.as_name, module_scope, self.pos)
                env.add_imported_module(module_scope)
            else:
                env.declare_module(top_name, top_module_scope, self.pos)
                env.add_imported_module(top_module_scope)
        else:
            name = self.as_name or self.module_name
            env.declare_module(name, module_scope, self.pos)
            env.add_imported_module(module_scope)

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

class FromCImportStatNode(StatNode):
    #  from ... cimport statement
    #
    #  module_name     string                  Qualified name of module
    #  imported_names  Parsing.ImportedName    Names to be imported
    
    def analyse_declarations(self, env):
        module_scope = env.find_module(self.module_name, self.pos)
        env.add_imported_module(module_scope)
        for imp in self.imported_names:
            kind = imp.kind
            #entry = module_scope.find(imp.name, imp.pos)
            entry = module_scope.lookup(imp.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(imp.name,
                        kind = kind, scope = None, typedef_flag = 0, pos = imp.pos)
                elif kind == 'class':
                    entry = module_scope.declare_c_class(imp.name, pos = imp.pos,
                        module_name = self.module_name)
                else:
                    error(imp.pos, "Name '%s' not declared in module '%s'"
                        % (imp.name, self.module_name)) 
            if entry:
                local_name = imp.as_name or imp.name
                env.add_imported_entry(local_name, entry, imp.pos)
    
    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

    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
    
    def analyse_declarations(self, env):
        for _, target in self.items:
            target.analyse_target_declaration(env)
    
    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:
            #self.interned_items.append((env.intern(name), target))
            target.analyse_target_expression(env, None)
        self.module.release_temp(env)
        self.item.release_temp(env)
    
    def generate_execution_code(self, code):
        self.module.generate_evaluation_code(code)
        #for cname, target in self.interned_items:
        for name, target in self.items:
            cname = code.intern(name)
            code.putln(
                '%s = PyObject_GetAttr(%s, %s); if (!%s) %s' % (
                    self.item.result(), 
                    self.module.py_result(),
                    cname,
                    self.item.result(),
                    code.error_goto(self.pos)))
            target.generate_assignment_code(self.item, code)
        self.module.generate_disposal_code(code)

#------------------------------------------------------------------------------------
#
#  Runtime support code
#
#------------------------------------------------------------------------------------

#utility_function_predeclarations = \
#"""
#typedef struct {PyObject **p; char *s;} __Pyx_InternTabEntry; /*proto*/
#typedef struct {PyObject **p; char *s; long n;} __Pyx_StringTabEntry; /*proto*/
#"""

utility_function_predeclarations = \
"""
typedef struct {PyObject **p; int i; char *s; long n;} __Pyx_StringTabEntry; /*proto*/
"""

#get_name_predeclaration = \
#"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"

#get_name_interned_predeclaration = \
#"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"

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

printing_utility_code = [
"""
static int __Pyx_PrintItem(PyObject *); /*proto*/
static int __Pyx_PrintNewline(void); /*proto*/
""",r"""
static PyObject *__Pyx_GetStdout(void) {
    PyObject *f = PySys_GetObject("stdout");
    if (!f) {
        PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
    }
    return f;
}

static int __Pyx_PrintItem(PyObject *v) {
    PyObject *f;
    
    if (!(f = __Pyx_GetStdout()))
        return -1;
    if (PyFile_SoftSpace(f, 1)) {
        if (PyFile_WriteString(" ", f) < 0)
            return -1;
    }
    if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
        return -1;
    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);
    }
    return 0;
}

static int __Pyx_PrintNewline(void) {
    PyObject *f;
    
    if (!(f = __Pyx_GetStdout()))
        return -1;
    if (PyFile_WriteString("\n", f) < 0)
        return -1;
    PyFile_SoftSpace(f, 0);
    return 0;
}
"""]

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

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

raise_utility_code = [
"""
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
""","""
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
    if (value == Py_None)
        value = NULL;
    if (tb == Py_None)
        tb = NULL;
    Py_XINCREF(type);
    Py_XINCREF(value);
    Py_XINCREF(tb);
    if (tb && !PyTraceBack_Check(tb)) {
        PyErr_SetString(PyExc_TypeError,
            "raise: arg 3 must be a traceback or None");
        goto raise_error;
    }
    #if PY_VERSION_HEX < 0x02050000
    if (!PyClass_Check(type))
    #else
    if (!PyType_Check(type))
    #endif
    {
        /* Raising an instance.  The value should be a dummy. */
        if (value) {
            PyErr_SetString(PyExc_TypeError,
                "instance exception may not have a separate value");
            goto raise_error;
        }
        /* Normalize to raise <class>, <instance> */
        value = type;
        #if PY_VERSION_HEX < 0x02050000
            if (PyInstance_Check(type)) {
                type = (PyObject*) ((PyInstanceObject*)type)->in_class;
                Py_INCREF(type);
            }
            else {
                PyErr_SetString(PyExc_TypeError,
                    "raise: exception must be an old-style class or instance");
                goto raise_error;
            }
        #else
            type = (PyObject*) type->ob_type;
            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
    }
    PyErr_Restore(type, value, tb);
    return;
raise_error:
    Py_XDECREF(value);
    Py_XDECREF(type);
    Py_XDECREF(tb);
    return;
}
"""]

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

#reraise_utility_code = [
#"""
#static void __Pyx_ReRaise(void); /*proto*/
#""","""
#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);
#  PyErr_Restore(type, value, tb);
#}
#"""]

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

arg_type_test_utility_code = [
"""
static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name); /*proto*/
""","""
static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name) {
    if (!type) {
        PyErr_Format(PyExc_SystemError, "Missing type object");
        return 0;
    }
    if ((none_allowed && obj == Py_None) || PyObject_TypeCheck(obj, type))
        return 1;
    PyErr_Format(PyExc_TypeError,
        "Argument '%s' has incorrect type (expected %s, got %s)",
        name, type->tp_name, obj->ob_type->tp_name);
    return 0;
}
"""]

#------------------------------------------------------------------------------------
#
#  __Pyx_GetStarArgs splits the args tuple and kwds dict into two parts
#  each, one part suitable for passing to PyArg_ParseTupleAndKeywords,
#  and the other containing any extra arguments. On success, replaces
#  the borrowed references *args and *kwds with references to a new
#  tuple and dict, and passes back new references in *args2 and *kwds2.
#  Does not touch any of its arguments on failure.
#
#  Any of *kwds, args2 and kwds2 may be 0 (but not args or kwds). If
#  *kwds == 0, it is not changed. If kwds2 == 0 and *kwds != 0, a new
#  reference to the same dictionary is passed back in *kwds.
#
#  If rqd_kwds is not 0, it is an array of booleans corresponding to the
#  names in kwd_list, indicating required keyword arguments. If any of
#  these are not present in kwds, an exception is raised.
#

get_starargs_utility_code = [
"""
static int __Pyx_GetStarArgs(PyObject **args, PyObject **kwds, char *kwd_list[], \
    Py_ssize_t nargs, PyObject **args2, PyObject **kwds2, char rqd_kwds[]); /*proto*/
""","""
static int __Pyx_GetStarArgs(
    PyObject **args, 
    PyObject **kwds,
    char *kwd_list[], 
    Py_ssize_t nargs,
    PyObject **args2, 
    PyObject **kwds2,
    char rqd_kwds[])
{
    PyObject *x = 0, *args1 = 0, *kwds1 = 0;
    int i;
    char **p;
    
    if (args2)
        *args2 = 0;
    if (kwds2)
        *kwds2 = 0;
    
    if (args2) {
        args1 = PyTuple_GetSlice(*args, 0, nargs);
        if (!args1)
            goto bad;
        *args2 = PyTuple_GetSlice(*args, nargs, PyTuple_GET_SIZE(*args));
        if (!*args2)
            goto bad;
    }
    else if (PyTuple_GET_SIZE(*args) > nargs) {
        int m = nargs;
        int n = PyTuple_GET_SIZE(*args);
        PyErr_Format(PyExc_TypeError,
            "function takes at most %d positional arguments (%d given)",
                m, n);
        goto bad;
    }
    else {
        args1 = *args;
        Py_INCREF(args1);
    }
    
    if (rqd_kwds && !*kwds)
            for (i = 0, p = kwd_list; *p; i++, p++)
                if (rqd_kwds[i])
                    goto missing_kwarg;
    
    if (kwds2) {
        if (*kwds) {
            kwds1 = PyDict_New();
            if (!kwds1)
                goto bad;
            *kwds2 = PyDict_Copy(*kwds);
            if (!*kwds2)
                goto bad;
            for (i = 0, p = kwd_list; *p; i++, p++) {
                x = PyDict_GetItemString(*kwds, *p);
                if (x) {
                    if (PyDict_SetItemString(kwds1, *p, x) < 0)
                        goto bad;
                    if (PyDict_DelItemString(*kwds2, *p) < 0)
                        goto bad;
                }
                else if (rqd_kwds && rqd_kwds[i])
                    goto missing_kwarg;
            }
        }
        else {
            *kwds2 = PyDict_New();
            if (!*kwds2)
                goto bad;
        }
    }
    else {
        kwds1 = *kwds;
        Py_XINCREF(kwds1);
        if (rqd_kwds && *kwds)
            for (i = 0, p = kwd_list; *p; i++, p++)
                if (rqd_kwds[i] && !PyDict_GetItemString(*kwds, *p))
                        goto missing_kwarg;
    }
    
    *args = args1;
    *kwds = kwds1;
    return 0;
missing_kwarg:
    PyErr_Format(PyExc_TypeError,
        "required keyword argument '%s' is missing", *p);
bad:
    Py_XDECREF(args1);
    Py_XDECREF(kwds1);
    if (args2) {
        Py_XDECREF(*args2);
    }
    if (kwds2) {
        Py_XDECREF(*kwds2);
    }
    return -1;
}
"""]

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

unraisable_exception_utility_code = [
"""
static void __Pyx_WriteUnraisable(char *name); /*proto*/
""","""
static void __Pyx_WriteUnraisable(char *name) {
    PyObject *old_exc, *old_val, *old_tb;
    PyObject *ctx;
    PyGILState_STATE state = PyGILState_Ensure();
    PyErr_Fetch(&old_exc, &old_val, &old_tb);
    ctx = PyString_FromString(name);
    PyErr_Restore(old_exc, old_val, old_tb);
    if (!ctx)
        ctx = Py_None;
    PyErr_WriteUnraisable(ctx);
    PyGILState_Release(state);
}
"""]

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

traceback_utility_code = [
"""
static void __Pyx_AddTraceback(char *funcname); /*proto*/
""","""
#include "compile.h"
#include "frameobject.h"
#include "traceback.h"

static void __Pyx_AddTraceback(char *funcname) {
    PyObject *py_srcfile = 0;
    PyObject *py_funcname = 0;
    PyObject *py_globals = 0;
    PyObject *empty_tuple = 0;
    PyObject *empty_string = 0;
    PyCodeObject *py_code = 0;
    PyFrameObject *py_frame = 0;
    
    py_srcfile = PyString_FromString(%(FILENAME)s);
    if (!py_srcfile) goto bad;
    py_funcname = PyString_FromString(funcname);
    if (!py_funcname) goto bad;
    py_globals = PyModule_GetDict(%(GLOBALS)s);
    if (!py_globals) goto bad;
    empty_tuple = PyTuple_New(0);
    if (!empty_tuple) goto bad;
    empty_string = PyString_FromString("");
    if (!empty_string) goto bad;
    py_code = PyCode_New(
        0,            /*int argcount,*/
        0,            /*int nlocals,*/
        0,            /*int stacksize,*/
        0,            /*int flags,*/
        empty_string, /*PyObject *code,*/
        empty_tuple,  /*PyObject *consts,*/
        empty_tuple,  /*PyObject *names,*/
        empty_tuple,  /*PyObject *varnames,*/
        empty_tuple,  /*PyObject *freevars,*/
        empty_tuple,  /*PyObject *cellvars,*/
        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(
        PyThreadState_Get(), /*PyThreadState *tstate,*/
        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_tuple);
    Py_XDECREF(empty_string);
    Py_XDECREF(py_code);
    Py_XDECREF(py_frame);
}
""" % {
    'FILENAME': Naming.filename_cname,
    'LINENO':  Naming.lineno_cname,
    'GLOBALS': Naming.module_cname
}]

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

set_vtable_utility_code = [
"""
static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
""","""
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;
}
"""]

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

get_vtable_utility_code = [
"""
static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
""",r"""
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;
}
"""]

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

#init_intern_tab_utility_code = [
#"""
#static int __Pyx_InternStrings(__Pyx_InternTabEntry *t); /*proto*/
#""","""
#static int __Pyx_InternStrings(__Pyx_InternTabEntry *t) {
#  while (t->p) {
#    *t->p = PyString_InternFromString(t->s);
#    if (!*t->p)
#      return -1;
#    ++t;
#  }
#  return 0;
#}
#"""]

#init_intern_tab_utility_code = [
#"""
#static int __Pyx_InternStrings(PyObject **t[]); /*proto*/
#""","""
#static int __Pyx_InternStrings(PyObject **t[]) {
#  while (*t) {
#    PyString_InternInPlace(*t);
#    if (!**t)
#      return -1;
#    ++t;
#  }
#  return 0;
#}
#"""]

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

init_string_tab_utility_code = [
"""
static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
""","""
static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
    while (t->p) {
        *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
        if (!*t->p)
            return -1;
        if (t->i)
            PyString_InternInPlace(t->p);
        ++t;
    }
    return 0;
}
"""]

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

#get_exception_utility_code = [
#"""
#static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
#""","""
#static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
#  PyThreadState *tstate = PyThreadState_Get();
#  PyObject *old_type, *old_value, *old_tb;
#  PyErr_Fetch(type, value, tb);
#  PyErr_NormalizeException(type, value, tb);
#  if (PyErr_Occurred())
#    goto bad;
#  if (!*tb) {
#    printf("no traceback\n");
#    *tb = Py_None;
#    Py_INCREF(*tb);
#  }
##if 1
#  Py_INCREF(*type);
#  Py_INCREF(*value);
#  Py_INCREF(*tb);
#  old_type = tstate->exc_type;
#  old_value = tstate->exc_value;
#  old_tb = tstate->exc_traceback;
#  tstate->exc_type = *type;
#  tstate->exc_value = *value;
#  tstate->exc_traceback = *tb;
#  Py_XDECREF(old_type);
#  Py_XDECREF(old_value);
#  Py_XDECREF(old_tb);
##endif
#  return 0;
#bad:
#  Py_XDECREF(*type);
#  Py_XDECREF(*value);
#  Py_XDECREF(*tb);
#  return -1;
#}
#"""]

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

#get_exception_utility_code = [
#"""
#static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
#""","""
#static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
#  PyErr_Fetch(type, value, tb);
#  PyErr_NormalizeException(type, value, tb);
#  if (PyErr_Occurred())
#    goto bad;
#  if (!*tb) {
#    *tb = Py_None;
#    Py_INCREF(*tb);
#  }
#  return 0;
#bad:
#  Py_XDECREF(*type);
#  Py_XDECREF(*value);
#  Py_XDECREF(*tb);
#  return -1;
#}
#"""]

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

normalize_exception_utility_code = [
"""
static int __Pyx_NormalizeException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
""","""
static int __Pyx_NormalizeException(PyObject **type, PyObject **value, PyObject **tb) {
    PyErr_NormalizeException(type, value, tb);
    if (PyErr_Occurred())
        goto bad;
    if (!*tb) {
        *tb = Py_None;
        Py_INCREF(*tb);
    }
    return 0;
bad:
    Py_XDECREF(*type);
    Py_XDECREF(*value);
    Py_XDECREF(*tb);
    return -1;
}
"""]

#------------------------------------------------------------------------------------
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.