Big merge of -devel
authorDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Tue, 19 May 2009 16:05:29 +0000 (18:05 +0200)
committerDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Tue, 19 May 2009 16:05:29 +0000 (18:05 +0200)
14 files changed:
1  2 
Cython/Compiler/Builtin.py
Cython/Compiler/Code.py
Cython/Compiler/ExprNodes.py
Cython/Compiler/Main.py
Cython/Compiler/ModuleNode.py
Cython/Compiler/Naming.py
Cython/Compiler/Nodes.py
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/Parsing.py
Cython/Compiler/PyrexTypes.py
Cython/Compiler/Symtab.py
tests/errors/nogil.pyx
tests/run/bufaccess.pyx
tests/run/cdef_setitem_T284.pyx

Simple merge
index 195548396df598bd65d674f1e1e91b2df4421e38,48fbbd01156736d85d0f8e4b62596525e0205102..3f10cd8b773ac0e189bc3d9b52b49666c07af57a
@@@ -6,9 -5,9 +6,10 @@@ import r
  import codecs
  import Naming
  import Options
 -from Cython.Utils import open_new_file, open_source_file
 +import StringEncoding
 +from Cython import Utils
  from PyrexTypes import py_object_type, typecast
+ import PyrexTypes
  from TypeSlots import method_coexist
  from Scanning import SourceDescriptor
  from Cython.StringIOTree import StringIOTree
@@@ -302,10 -211,9 +301,12 @@@ class GlobalState(object)
      #                                  check if constants are already added).
      #                                  In time, hopefully the literals etc. will be
      #                                  supplied directly instead.
 +    #
 +    # const_cname_counter int          global counter for constant identifiers
 +    #
  
+     # parts            {string:CCodeWriter}
      
      # interned_strings
      # consts
  
      directives = {}
  
-     def __init__(self, rootwriter, emit_linenums=False):
+     code_layout = [
+         'h_code',
+         'utility_code_proto',
+         'type_declarations',
+         'module_declarations',
+         'typeinfo',
+         'before_global_var',
+         'global_var',
++        'decls',
+         'all_the_rest',
+         'utility_code_def'
+     ]
+     
+     def __init__(self, writer, emit_linenums=False):
          self.filename_table = {}
          self.filename_list = []
          self.input_file_contents = {}
-         self.used_utility_code = set()
+         self.utility_codes = set()
          self.declared_cnames = {}
 -        self.pystring_table_needed = False
          self.in_utility_code_generation = False
          self.emit_linenums = emit_linenums
+         self.parts = {}
  
-     def initwriters(self, rootwriter):
-         self.utilprotowriter = rootwriter.new_writer()
-         self.utildefwriter = rootwriter.new_writer()
-         self.decls_writer = rootwriter.new_writer()
 +        self.const_cname_counter = 1
 +        self.string_const_index = {}
 +        self.int_const_index = {}
 +        self.py_constants = []
 +
 -        self.decls_writer = rootwriter.new_writer()
+         assert writer.globalstate is None
+         writer.globalstate = self
+         self.rootwriter = writer
+     def initialize_main_c_code(self):
+         rootwriter = self.rootwriter
+         for part in self.code_layout:
+             self.parts[part] = rootwriter.insertion_point()
          self.pystring_table = rootwriter.new_writer()
          self.init_cached_builtins_writer = rootwriter.new_writer()
          self.initwriter = rootwriter.new_writer()
          self.cleanupwriter.putln("")
          self.cleanupwriter.putln("static void __Pyx_CleanupGlobals(void) {")
  
 -        self.pystring_table.putln("")
 -        self.pystring_table.putln("static __Pyx_StringTabEntry %s[] = {" %
 -                Naming.stringtab_cname)
 -
 -
+         #
+         # utility_code_def
+         #
+         code = self.parts['utility_code_def']
+         if self.emit_linenums:
+             code.write('\n#line 1 "cython_utility"\n')
+         code.putln("")
+         code.putln("/* Runtime support code */")
+         code.putln("")
+         code.putln("static void %s(void) {" % Naming.fileinit_cname)
+         code.putln("%s = %s;" % 
+             (Naming.filetable_cname, Naming.filenames_cname))
+         code.putln("}")
+     def finalize_main_c_code(self):
+         self.close_global_decls()
+         #
+         # utility_code_def
+         #
+         code = self.parts['utility_code_def']
+         code.put(PyrexTypes.type_conversion_functions)
+         code.putln("")
+     def __getitem__(self, key):
+         return self.parts[key]
      #
      # Global constants, interned objects, etc.
      #
          code.insert(self.cleanupwriter)
  
      def put_pyobject_decl(self, entry):
-         self.decls_writer.putln("static PyObject *%s;" % entry.cname)
+         self['global_var'].putln("static PyObject *%s;" % entry.cname)
  
-             self.decls_writer.putln(
 +    # constant handling at code generation time
 +
 +    def get_int_const(self, str_value, longness=False):
 +        longness = bool(longness or Utils.long_literal(str_value))
 +        try:
 +            c = self.int_const_index[(str_value, longness)]
 +        except KeyError:
 +            c = self.new_int_const(str_value, longness)
 +        return c
 +
 +    def get_py_const(self, type):
 +        # create a new Python object constant
 +        return self.new_py_const(type)
 +
 +    def get_string_const(self, text):
 +        # return a C string constant, creating a new one if necessary
 +        if text.is_unicode:
 +            byte_string = text.utf8encode()
 +        else:
 +            byte_string = text.byteencode()
 +        try:
 +            c = self.string_const_index[byte_string]
 +        except KeyError:
 +            c = self.new_string_const(text, byte_string)
 +        return c
 +
 +    def get_py_string_const(self, text, identifier=None):
 +        # return a Python string constant, creating a new one if necessary
 +        c_string = self.get_string_const(text)
 +        py_string = c_string.get_py_string_const(text.encoding, identifier)
 +        return py_string
 +
 +    def new_string_const(self, text, byte_string):
 +        cname = self.new_string_const_cname(text)
 +        c = StringConst(cname, text, byte_string)
 +        self.string_const_index[byte_string] = c
 +        return c
 +
 +    def new_int_const(self, value, longness):
 +        cname = self.new_int_const_cname(value, longness)
 +        c = IntConst(cname, value, longness)
 +        self.int_const_index[(value, longness)] = c
 +        return c
 +
 +    def new_py_const(self, type):
 +        cname = self.new_const_cname()
 +        c = PyObjectConst(cname, type)
 +        self.py_constants.append(c)
 +        return c
 +
 +    def new_string_const_cname(self, value, intern=None):
 +        # Create a new globally-unique nice name for a C string constant.
 +        if len(value) < 20 and nice_identifier(value):
 +            return "%s%s" % (Naming.const_prefix, value)
 +        else:
 +            return self.new_const_cname()
 +
 +    def new_int_const_cname(self, value, longness):
 +        if longness:
 +            value += 'L'
 +        cname = "%s%s" % (Naming.interned_num_prefix, value)
 +        cname = cname.replace('-', 'neg_').replace('.','_')
 +        return cname
 +
 +    def new_const_cname(self, prefix=''):
 +        n = self.const_cname_counter
 +        self.const_cname_counter += 1
 +        return "%s%s%d" % (Naming.const_prefix, prefix, n)
 +
 +    def add_cached_builtin_decl(self, entry):
 +        if Options.cache_builtins:
 +            if self.should_declare(entry.cname, entry):
 +                interned_cname = self.get_py_string_const(entry.name, True).cname
 +                self.put_pyobject_decl(entry)
 +                self.init_cached_builtins_writer.putln('%s = __Pyx_GetName(%s, %s); if (!%s) %s' % (
 +                    entry.cname,
 +                    Naming.builtins_cname,
 +                    interned_cname,
 +                    entry.cname,
 +                    self.init_cached_builtins_writer.error_goto(entry.pos)))
 +
 +    def generate_const_declarations(self):
 +        self.generate_string_constants()
 +        self.generate_int_constants()
 +        self.generate_object_constant_decls()
 +
 +    def generate_object_constant_decls(self):
 +        consts = [ (len(c.cname), c.cname, c)
 +                   for c in self.py_constants ]
 +        consts.sort()
++        decls_writer = self.parts['decls']
 +        for _, cname, c in consts:
-             self.decls_writer.putln('static char %s[] = "%s";' % (
++            decls_writer.putln(
 +                "static %s;" % c.type.declaration_code(cname))
 +
 +    def generate_string_constants(self):
 +        c_consts = [ (len(c.cname), c.cname, c)
 +                     for c in self.string_const_index.itervalues() ]
 +        c_consts.sort()
 +        py_strings = []
++
++        decls_writer = self.parts['decls']
 +        for _, cname, c in c_consts:
-                 self.decls_writer.putln(
++            decls_writer.putln('static char %s[] = "%s";' % (
 +                cname, c.escaped_value))
 +            if c.py_strings is not None:
 +                for py_string in c.py_strings.itervalues():
 +                    py_strings.append((c.cname, len(py_string.cname), py_string))
 +
 +        if py_strings:
 +            import Nodes
 +            self.use_utility_code(Nodes.init_string_tab_utility_code)
 +
 +            py_strings.sort()
 +            self.pystring_table.putln("")
 +            self.pystring_table.putln("static __Pyx_StringTabEntry %s[] = {" %
 +                                      Naming.stringtab_cname)
 +            for c_cname, _, py_string in py_strings:
-             self.decls_writer.putln("static PyObject *%s;" % cname)
++                decls_writer.putln(
 +                    "static PyObject *%s;" % py_string.cname)
 +                self.pystring_table.putln(
 +                    "{&%s, %s, sizeof(%s), %d, %d, %d}," % (
 +                    py_string.cname,
 +                    c_cname,
 +                    c_cname,
 +                    py_string.unicode,
 +                    py_string.intern,
 +                    py_string.identifier
 +                    ))
 +            self.pystring_table.putln("{0, 0, 0, 0, 0, 0}")
 +            self.pystring_table.putln("};")
 +
 +            self.initwriter.putln(
 +                "if (__Pyx_InitStrings(%s) < 0) %s;" % (
 +                    Naming.stringtab_cname,
 +                    self.initwriter.error_goto(self.module_pos)))
 +
 +    def generate_int_constants(self):
 +        consts = [ (len(c.value), c.value, c.is_long, c)
 +                   for c in self.int_const_index.itervalues() ]
 +        consts.sort()
++        decls_writer = self.parts['decls']
 +        for _, value, longness, c in consts:
 +            cname = c.cname
++            decls_writer.putln("static PyObject *%s;" % cname)
 +            if longness:
 +                function = '%s = PyLong_FromString((char *)"%s", 0, 0); %s;'
 +            else:
 +                function = "%s = PyInt_FromLong(%s); %s;"
 +            self.initwriter.putln(function % (
 +                cname,
 +                value,
 +                self.initwriter.error_goto_if_null(cname, self.module_pos)))
 +
      # The functions below are there in a transition phase only
      # and will be deprecated. They are called from Nodes.BlockNode.
      # The copy&paste duplication is intentional in order to be able
@@@ -687,11 -511,10 +699,13 @@@ class CCodeWriter(object)
      #                                  generation (labels and temps state etc.)
      # globalstate      GlobalState     contains state global for a C file (input file info,
      #                                  utility code, declared constants etc.)
 -    # emit_linenums    boolean         whether or not to write #line pragmas 
 +    # emit_linenums    boolean         whether or not to write #line pragmas
 +    #
 +    # pyclass_stack    list            used during recursive code generation to pass information
 +    #                                  about the current class one is in
  
+     globalstate = None
+     
      def __init__(self, create_from=None, buffer=None, copy_formatting=False, emit_linenums=None):
          if buffer is None: buffer = StringIOTree()
          self.buffer = buffer
      def exit_cfunc_scope(self):
          self.funcstate = None
  
-     def putln(self, code = ""):
 +    # constant handling
 +
 +    def get_py_num(self, str_value, longness):
 +        return self.globalstate.get_int_const(str_value, longness).cname
 +
 +    def get_string_const(self, text):
 +        return self.globalstate.get_string_const(text).cname
 +
 +    def get_py_string_const(self, text, identifier=None):
 +        return self.globalstate.get_py_string_const(text, identifier).cname
 +
 +    def get_argument_default_const(self, type):
 +        return self.globalstate.get_py_const(type).cname
 +
 +    def intern(self, text):
 +        return self.get_py_string_const(text)
 +
 +    def intern_identifier(self, text):
 +        return self.get_py_string_const(text, True)
 +
 +    # code generation
 +
+     def putln(self, code = "", safe=False):
          if self.marker and self.bol:
              self.emit_marker()
          if self.emit_linenums and self.last_marker_line != 0:
index c456f262c189e3256faabab1cac0ab3ba92772ca,cb59255e10fdfc4e6ab5124ec7e44adb438d2797..04de084822411f383a721df5bad18387264b92fe
@@@ -878,8 -1041,19 +885,18 @@@ class ImagNode(AtomicExprNode)
          return complex(0.0, self.value)
      
      def analyse_types(self, env):
-         self.type = py_object_type
-         self.is_temp = 1
+         self.type.create_declaration_utility_code(env)
+     def coerce_to(self, dst_type, env):
+         # Arrange for a Python version of the number to be pre-allocated
+         # when coercing to a Python type.
+         if dst_type.is_pyobject:
+             self.is_temp = 1
+             self.type = PyrexTypes.py_object_type
 -            self.gil_check(env)
+         # We still need to perform normal coerce_to processing on the
+         # result, because we might be coercing to an extension type,
+         # in which case a type test node will be needed.
 -        return AtomicNewTempExprNode.coerce_to(self, dst_type, env)
++        return AtomicExprNode.coerce_to(self, dst_type, env)
  
      gil_message = "Constructing complex number"
  
@@@ -5128,13 -5177,14 +5219,13 @@@ class CoerceToPyTypeNode(CoercionNode)
      def __init__(self, arg, env):
          CoercionNode.__init__(self, arg)
          self.type = py_object_type
 -        self.gil_check(env)
          self.is_temp = 1
-         if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
+         if not arg.type.create_to_py_utility_code(env):
              error(arg.pos,
                  "Cannot convert '%s' to Python object" % arg.type)
 -        
 +
      gil_message = "Converting to Python object"
 -    
 +
      def coerce_to_boolean(self, env):
          return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
      
index a07ec2e4720f56e49d7d74cd4e6dc2de2e3b8dab,7b8b7efd4a96ff8baf08588aca22504b836005a7..cc7999e2bf59cd604aa5464a9c666762c31c9d73
@@@ -124,7 -123,8 +124,8 @@@ class Context(object)
              IntroduceBufferAuxiliaryVars(self),
              _check_c_declarations,
              AnalyseExpressionsTransform(self),
 -            FlattenBuiltinTypeCreation(),
 +            OptimizeBuiltinCalls(),
+             ConstantFolding(),
              IterationTransform(),
              SwitchTransform(),
              FinalOptimizePhase(self),
index 93829b8f64c5e934d171b0f9c36a0271b07ac8d5,32be4c715e26ea1f2c0345ffdc7960d0f949cf10..7822b941d9f4043556f7f6d7fa70ba52421b40d1
@@@ -237,23 -244,35 +239,31 @@@ class ModuleNode(Nodes.Node, Nodes.Bloc
      
      def generate_c_code(self, env, options, result):
          modules = self.referenced_modules
          if Options.annotate or options.annotate:
-             code = Annotate.AnnotationCCodeWriter()
+             emit_linenums = False
+             rootwriter = Annotate.AnnotationCCodeWriter()
          else:
-             code = Code.CCodeWriter(emit_linenums=options.emit_linenums)
-         h_code = code.insertion_point()
+             emit_linenums = options.emit_linenums
+             rootwriter = Code.CCodeWriter(emit_linenums=emit_linenums)
+         globalstate = Code.GlobalState(rootwriter, emit_linenums)
+         globalstate.initialize_main_c_code()
+         h_code = globalstate['h_code']
+         
          self.generate_module_preamble(env, modules, h_code)
  
-         code.globalstate.module_pos = self.pos
-         code.globalstate.directives = self.directives
+         globalstate.module_pos = self.pos
+         globalstate.directives = self.directives
  
-         code.globalstate.use_utility_code(refcount_utility_code)
+         globalstate.use_utility_code(refcount_utility_code)
  
+         code = globalstate['before_global_var']
          code.putln('#define __Pyx_MODULE_NAME "%s"' % self.full_module_name)
+         code.putln("int %s%s = %s;" % (Naming.module_is_main, self.full_module_name.replace('.', '__'), int(Options.embed)))
          code.putln("")
          code.putln("/* Implementation of %s */" % env.qualified_name)
 -        self.generate_const_definitions(env, code)
 -        self.generate_interned_num_decls(env, code)
 -        self.generate_interned_string_decls(env, code)
 -        self.generate_py_string_decls(env, code)
  
-         code.globalstate.insert_global_var_declarations_into(code)
+         code = globalstate['all_the_rest']
  
          self.generate_cached_builtins_decls(env, code)
          self.body.generate_function_definitions(env, code)
                  env.module_cname,
                  Naming.builtins_cname,
                  code.error_goto(self.pos)))
-         if Options.embed:
-             __main__name = code.globalstate.get_py_string_const(
-                 EncodedString("__main__"), identifier=True)
-             code.putln(
-                 'if (__Pyx_SetAttrString(%s, "__name__", %s) < 0) %s;' % (
-                     env.module_cname,
-                     __main__name.cname,
-                     code.error_goto(self.pos)))
++
++
++        __main__name = code.globalstate.get_py_string_const(
++            EncodedString("__main__"), identifier=True)
+         code.putln("if (%s%s) {" % (Naming.module_is_main, self.full_module_name.replace('.', '__')))
+         code.putln(
+             'if (__Pyx_SetAttrString(%s, "__name__", %s) < 0) %s;' % (
+                 env.module_cname,
 -                self.__main__cname,
++                __main__name.cname,
+                 code.error_goto(self.pos)))
+         code.putln("}")
          if Options.pre_import is not None:
              code.putln(
                  '%s = PyImport_AddModule(__Pyx_NAMESTR("%s"));' % (
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index e3a5b6d3d57f85bd6c1b1405dac293124852d0e6,570aeb1425f226e3ed8d8b5b85371064b27be23f..841e5487b01b3ca04fb3787398488e1446d64028
@@@ -82,14 -82,14 +82,14 @@@ _ERRORS = u""
  6: 6: Assignment of Python object not allowed without gil
  4: 5: Function declared nogil has Python locals or temporaries
  11: 5: Function with Python return type cannot be declared nogil
 -15: 5: Calling gil-requiring function without gil
 -24: 9: Calling gil-requiring function without gil
 +15: 5: Calling gil-requiring function not allowed without gil
 +24: 9: Calling gil-requiring function not allowed without gil
  26:12: Assignment of Python object not allowed without gil
- 28: 8: Constructing complex number not allowed without gil
+ 28:16: Constructing complex number not allowed without gil
  29:12: Accessing Python global or builtin not allowed without gil
  30: 8: Backquote expression not allowed without gil
 -31:15: Python import not allowed without gil
  31:15: Assignment of Python object not allowed without gil
 +31:15: Python import not allowed without gil
  32:13: Python import not allowed without gil
  32:25: Constructing Python list not allowed without gil
  33:17: Iterating over Python object not allowed without gil
Simple merge
index 2f042ae2c1ff39ea9cecbf04a3855f70e6968c1d,2d1971fab96db32820c5fb7c5123a469f2291091..4438e4daa095631954397af250e6a034025d4a85
@@@ -1,18 -1,15 +1,26 @@@
  __doc__ = u'''
  >>> no_cdef()
  >>> with_cdef()
++<<<<<<< local
 +
 +>>> test_list(range(11), -2, None)
++=======
+ >>> test_list(list(range(11)), -2, None)
++>>>>>>> other
  [0, 1, 2, 3, 4, 5, 6, 7, 8, None, 10]
++<<<<<<< local
 +
 +>>> test_list(range(11), "invalid index", None)
++=======
+ >>> test_list(list(range(11)), "invalid index", None) #doctest: +ELLIPSIS
++>>>>>>> other
  Traceback (most recent call last):
  ...
- TypeError: list indices must be integers, not str
+ TypeError: list indices must be integers...
  '''
 +
  def no_cdef():
-     lst = range(11)
+     lst = list(range(11))
      ob = 10L
      lst[ob] = -10
      dd = {}