Circular cdef's
authorGary Furnish <gfurnish@gfurnish.net>
Sun, 23 Mar 2008 16:02:06 +0000 (10:02 -0600)
committerGary Furnish <gfurnish@gfurnish.net>
Sun, 23 Mar 2008 16:02:06 +0000 (10:02 -0600)
Cython/Compiler/Code.py
Cython/Compiler/Main.py
Cython/Compiler/ModuleNode.py
Cython/Compiler/Naming.py
Cython/Compiler/Nodes.py

index f22a136f52fe6cffc2ca0444eb936c645981124f..ad4c22c16e8e8ab8a2784ea736411ad276867f37 100644 (file)
@@ -329,12 +329,14 @@ class CCodeWriter:
     def error_goto(self, pos):
         lbl = self.error_label
         self.use_label(lbl)
-        return "{%s = %s[%s]; %s = %s; goto %s;}" % (
+        return "{%s = %s[%s]; %s = %s; %s = %s; goto %s;}" % (
             Naming.filename_cname,
             Naming.filetable_cname,
             self.lookup_filename(pos[0]),
             Naming.lineno_cname,
             pos[1],
+            Naming.clineno_cname,
+            Naming.line_c_macro,
             lbl)
             
     def error_goto_if(self, cond, pos):
index ca8dc88d7387a6549a44a6cf803c37da111b0215..819cabc1cd465caa2f6f4cdd8f91804f7e8ade7b 100644 (file)
@@ -310,6 +310,7 @@ def compile(source, options = None, c_compile = 0, c_link = 0,
 #------------------------------------------------------------------------
 
 def main(command_line = 0):
+
     args = sys.argv[1:]
     any_failures = 0
     if command_line:
index 0922aef0038d275e5d77e6db15bcfa338177677f..29e2343b459f51ba8585d7334ab6b2473a133c01 100644 (file)
@@ -19,6 +19,29 @@ from Errors import error
 from PyrexTypes import py_object_type
 from Cython.Utils import open_new_file, replace_suffix
 
+
+def recurse_vtab_check_inheritance(entry,b, dict):
+    base = entry
+    while base is not None:
+        if base.type.base_type is None or base.type.base_type.vtabstruct_cname is None:
+            return False
+        if base.type.base_type.vtabstruct_cname == b.type.vtabstruct_cname:
+            return True
+        base = dict[base.type.base_type.vtabstruct_cname]
+    return False
+    
+def recurse_vtabslot_check_inheritance(entry,b, dict):
+    base = entry
+    while base is not None:
+        if base.type.base_type is None:
+            return False
+        if base.type.base_type.objstruct_cname == b.type.objstruct_cname:
+            return True
+        base = dict[base.type.base_type.objstruct_cname]
+    return False
+    
+
+
 class ModuleNode(Nodes.Node, Nodes.BlockNode):
     #  doc       string or None
     #  body      StatListNode
@@ -226,14 +249,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         self.generate_method_table(env, code)
         self.generate_filename_init_prototype(code)
         self.generate_module_init_func(modules[:-1], env, code)
+        self.generate_module_init2_func(modules[:-1], env, code)
         code.mark_pos(None)
         self.generate_module_cleanup_func(env, code)
         self.generate_filename_table(code)
         self.generate_utility_functions(env, code)
 
-        for module in modules:
-            self.generate_declarations_for_module(module, code.h,
-                definition = module is env)
+        self.generate_declarations_for_module(env, modules, code.h)
 
         f = open_new_file(result.c_file)
         f.write(code.h.f.getvalue())
@@ -245,6 +267,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             self.annotate(code)
             code.save_annotation(result.c_file[:-1] + "pyx") # change?
     
+    
+    
+    
     def find_referenced_modules(self, env, module_list, modules_seen):
         if env not in modules_seen:
             modules_seen[env] = 1
@@ -294,6 +319,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         if Options.pre_import is not None:
             code.putln('static PyObject *%s;' % Naming.preimport_cname)
         code.putln('static int %s;' % Naming.lineno_cname)
+        code.putln('static int %s;' % Naming.clineno_cname)
+        code.putln('static char * %s= %s;' % (Naming.cfilenm_cname, Naming.file_c_macro))
         code.putln('static char *%s;' % Naming.filename_cname)
         code.putln('static char **%s;' % Naming.filetable_cname)
         if env.doc:
@@ -331,16 +358,100 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             code.putln("0")
         code.putln("};")
     
-    def generate_declarations_for_module(self, env, code, definition):
+    def generate_vtab_dict(self, module_list):
+        vtab_dict = {}
+        for module in module_list:
+            for entry in module.c_class_entries:
+                if not entry.in_cinclude:
+                    type = entry.type
+                    scope = type.scope
+                    if type.vtabstruct_cname:
+                        vtab_dict[type.vtabstruct_cname]=entry
+        return vtab_dict
+    def generate_vtab_list(self, vtab_dict):
+        vtab_list = list()
+        for entry in vtab_dict.itervalues():
+            vtab_list.append(entry)
+        for i in range(0,len(vtab_list)):
+            for j in range(0,len(vtab_list)):
+                if(recurse_vtab_check_inheritance(vtab_list[j],vtab_list[i], vtab_dict)==1):
+                    if i > j:
+                        vtab_list.insert(j,vtab_list[i])
+                        if i > j:
+                            vtab_list.pop(i+1)
+                        else:
+                            vtab_list.pop(i)
+        #for entry in vtab_list:
+            #print entry.type.vtabstruct_cname
+        return vtab_list
+        
+    def generate_vtabslot_dict(self, module_list, env):
+        vtab_dict={}
+        type_entries=[]
+        for module in module_list:
+            definition = module is env
+            if definition:
+                type_entries.extend( env.type_entries)
+            else:
+                for entry in module.type_entries:
+                    if entry.defined_in_pxd:
+                        type_entries.append(entry)
+        for entry in type_entries:
+            type = entry.type
+            if type.is_extension_type:
+                if not entry.in_cinclude:
+                    type = entry.type
+                    scope = type.scope
+                    vtab_dict[type.objstruct_cname]=entry
+        return vtab_dict
+    def generate_vtabslot_list(self, vtab_dict):
+        vtab_list = list()
+        for entry in vtab_dict.itervalues():
+            vtab_list.append(entry)
+        for i in range(0,len(vtab_list)):
+            for j in range(0,len(vtab_list)):
+                if(recurse_vtabslot_check_inheritance(vtab_list[j],vtab_list[i], vtab_dict)==1):
+                    if i > j:
+                        vtab_list.insert(j,vtab_list[i])
+                        if i > j:
+                            vtab_list.pop(i+1)
+                        else:
+                            vtab_list.pop(i)
+        #for entry in vtab_list:
+            #print entry.type.vtabstruct_cname
+        return vtab_list
+        
+        
+    def generate_type_definitions(self, env, modules, vtab_list, vtabslot_list, code):
+        for module in modules:
+            definition = module is env
+            if definition:
+                type_entries = module.type_entries
+            else:
+                type_entries = []
+                for entry in module.type_entries:
+                    if entry.defined_in_pxd:
+                        type_entries.append(entry)
+            self.generate_type_header_code(type_entries, code)
+        for entry in vtabslot_list:
+            self.generate_obj_struct_definition(entry.type, code)
+        for entry in vtab_list:
+            self.generate_typeobject_predeclaration(entry, code)
+            self.generate_exttype_vtable_struct(entry, code)
+            self.generate_exttype_vtabptr_declaration(entry, code)
+    
+    def generate_declarations_for_module(self, env, modules, code):
         code.putln("")
-        code.putln("/* Declarations from %s */" % env.qualified_name)
-        self.generate_type_predeclarations(env, code)
-        self.generate_type_definitions(env, code, definition)
-        self.generate_global_declarations(env, code, definition)
-        self.generate_cfunction_predeclarations(env, code, definition)
-
-    def generate_type_predeclarations(self, env, code):
-        pass
+        code.putln("/* Declarations */")
+        vtab_dict = self.generate_vtab_dict(modules)
+        vtab_list = self.generate_vtab_list(vtab_dict)
+        vtabslot_dict = self.generate_vtabslot_dict(modules,env)
+        vtabslot_list = self.generate_vtabslot_list(vtabslot_dict)
+        self.generate_type_definitions(env, modules, vtab_list, vtabslot_list, code)
+        for module in modules:
+            definition = module is env
+            self.generate_global_declarations(module, code, definition)
+            self.generate_cfunction_predeclarations(module, code, definition)
     
     def generate_type_header_code(self, type_entries, code):
         # Generate definitions of structs/unions/enums/typedefs/objstructs.
@@ -356,23 +467,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     self.generate_struct_union_definition(entry, code)
                 elif type.is_enum:
                     self.generate_enum_definition(entry, code)
-                elif type.is_extension_type:
-                    self.generate_obj_struct_definition(type, code)
-    
-    def generate_type_definitions(self, env, code, definition):
-        if definition:
-            type_entries = env.type_entries
-        else:
-            type_entries = []
-            for entry in env.type_entries:
-                if entry.defined_in_pxd:
-                    type_entries.append(entry)
-        self.generate_type_header_code(type_entries, code)
-        for entry in env.c_class_entries:
-            if not entry.in_cinclude:
-                self.generate_typeobject_predeclaration(entry, code)
-                self.generate_exttype_vtable_struct(entry, code)
-                self.generate_exttype_vtabptr_declaration(entry, code)
     
     def generate_gcc33_hack(self, env, code):
         # Workaround for spurious warning generation in gcc 3.3
@@ -1281,10 +1375,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("static void %s(void); /*proto*/" % Naming.fileinit_cname)
 
     def generate_module_init_func(self, imported_modules, env, code):
+        code.putln("")
+        code.putln("PyMODINIT_FUNC init2%s(void);" % env.module_name)
         code.putln("")
         header = "PyMODINIT_FUNC init%s(void)" % env.module_name
         code.putln("%s; /*proto*/" % header)
         code.putln("%s {" % header)
+        code.putln("PyObject* __pyx_internal1;")
+        code.putln("PyObject* __pyx_internal2;")
         code.put_var_declarations(env.temp_entries)
 
         code.putln("/*--- Libary function declarations ---*/")
@@ -1313,30 +1411,47 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("/*--- Function export code ---*/")
         self.generate_c_function_export_code(env, code)
 
-        code.putln("/*--- Function import code ---*/")
-        for module in imported_modules:
-            self.generate_c_function_import_code_for_module(module, env, code)
-
+        env.use_utility_code(function_export_utility_code)
+        code.putln('if (__Pyx_ExportFunction("init2%s", (void*)init2%s, "int (void)") < 0) %s' % (env.module_name, env.module_name, code.error_goto((env.qualified_name,0,0) ) ) )
         code.putln("/*--- Type init code ---*/")
         self.generate_type_init_code(env, code)
-
         code.putln("/*--- Type import code ---*/")
         for module in imported_modules:
             self.generate_type_import_code_for_module(module, env, code)
+        code.putln("/*--- Function import code ---*/")
+        for module in imported_modules:
+            self.generate_c_function_import_code_for_module(module, env, code)
+        env.use_utility_code(function_import_utility_code)
+        code.putln('init2%s();' % env.module_name)
+        if Options.generate_cleanup_code:
+            code.putln("if (__Pyx_RegisterCleanup()) %s;" % code.error_goto(self.pos))
+        code.putln("return;")
+        code.put_label(code.error_label)
+        code.put_var_xdecrefs(env.temp_entries)
+        code.putln('__Pyx_AddTraceback("%s",%s,%s);' % (env.qualified_name,Naming.cfilenm_cname,Naming.clineno_cname))
+        env.use_utility_code(Nodes.traceback_utility_code)
+        code.putln('}')
 
+    def generate_module_init2_func(self, imported_modules, env, code):
+        code.putln("")
+        header = "PyMODINIT_FUNC init2%s(void)" % env.module_name
+        code.putln("%s; /*proto*/" % header)
+        code.putln("%s {" % header)
+        code.putln("static int __Pyx_unique = 0;")
+        code.putln("if (__Pyx_unique==1) return;")
+        code.putln("__Pyx_unique = 1;")
+        code.put_var_declarations(env.temp_entries)
         code.putln("/*--- Execution code ---*/")
         code.mark_pos(None)
         self.body.generate_execution_code(code)
-        
         if Options.generate_cleanup_code:
             code.putln("if (__Pyx_RegisterCleanup()) %s;" % code.error_goto(self.pos))
-        
         code.putln("return;")
         code.put_label(code.error_label)
         code.put_var_xdecrefs(env.temp_entries)
-        code.putln('__Pyx_AddTraceback("%s");' % (env.qualified_name))
+        code.putln('__Pyx_AddTraceback("%s",%s,%s);' % (env.qualified_name,Naming.cfilenm_cname,Naming.clineno_cname))
         env.use_utility_code(Nodes.traceback_utility_code)
-        code.putln('}')
+        code.putln('}')        
             
     def generate_module_cleanup_func(self, env, code):
         if not Options.generate_cleanup_code:
@@ -1521,7 +1636,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 self.generate_exttype_vtable_init_code(entry, code)
                 self.generate_type_ready_code(env, entry, code)
                 self.generate_typeptr_assignment_code(entry, code)
-    
+        
     def generate_base_type_import_code(self, env, entry, code):
         base_type = entry.type.base_type
         if base_type and base_type.module_name != env.qualified_name:
@@ -1656,6 +1771,49 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
 #
 #------------------------------------------------------------------------------------
 
+
+call_module_function_code = [
+"""
+static PyObject *__Pyx_CallModuleFunction(char* module, char *name); /*proto*/
+""","""
+static PyObject *__Pyx_CallModuleFunction(char* module, char *name)
+{
+    PyObject* py_name = 0;
+    PyObject* py_module_name = 0;
+    PyObject* py_module = 0;
+    PyObject* py_dict = 0;
+    PyObject* py_func = 0;
+    PyObject* py_tuple = PyTuple_New(0);
+    PyObject* ret = 0;
+    py_dict = PyImport_GetModuleDict();
+    if(py_dict == 0)
+        goto bad;
+    if(py_tuple == 0)
+        goto bad;
+    py_name = PyString_FromString(name);
+    if(py_name == 0)
+        goto bad;
+    py_module_name = PyString_FromString(module);
+    if(py_module_name == 0)
+        goto bad;
+    py_module = PyObject_GetItem(py_dict, py_module);
+    if(py_module == 0)
+        goto bad;
+    if ( (py_func = PyObject_GetAttr(py_module, py_name) ) == 0)
+        goto bad;
+    if ( (ret = PyObject_Call(py_func, py_tuple,NULL) ) == 0)
+        goto bad;
+    return ret;
+bad:
+    Py_XDECREF(py_name);
+    Py_XDECREF(py_module_name);
+    Py_XDECREF(py_module);
+    Py_XDECREF(py_dict);    
+    Py_XDECREF(py_func);
+    return 0;
+}
+"""]
+
 import_module_utility_code = [
 """
 static PyObject *__Pyx_ImportModule(char *name); /*proto*/
@@ -1692,7 +1850,12 @@ static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name,
 {
     PyObject *py_module = 0;
     PyObject *result = 0;
+    PyObject *py_name = 0;
     
+    py_name = PyString_FromString(module_name);
+    if (!py_name)
+        goto bad;
+        
     py_module = __Pyx_ImportModule(module_name);
     if (!py_module)
         goto bad;
@@ -1713,6 +1876,7 @@ static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name,
     }
     return (PyTypeObject *)result;
 bad:
+    Py_XDECREF(py_name);
     Py_XDECREF(result);
     return 0;
 }
@@ -1725,7 +1889,7 @@ function_export_utility_code = [
 """
 static int __Pyx_ExportFunction(char *n, void *f, char *s); /*proto*/
 """,r"""
-static int __Pyx_ExportFunction(char *n, void *f, char *s) {
+static int __Pyx_ExportFunction(char *name, void *f, char *sig) {
     PyObject *d = 0;
     PyObject *p = 0;
     d = PyObject_GetAttrString(%(MODULE)s, "%(API)s");
@@ -1738,10 +1902,10 @@ static int __Pyx_ExportFunction(char *n, void *f, char *s) {
         if (PyModule_AddObject(%(MODULE)s, "%(API)s", d) < 0)
             goto bad;
     }
-    p = PyCObject_FromVoidPtrAndDesc(f, s, 0);
+    p = PyCObject_FromVoidPtrAndDesc(f, sig, 0);
     if (!p)
         goto bad;
-    if (PyDict_SetItemString(d, n, p) < 0)
+    if (PyDict_SetItemString(d, name, p) < 0)
         goto bad;
     Py_DECREF(d);
     return 0;
index b0a8215c2e736798a69814cceedfe9a4d1cfd416..2c294213df94faeee32793a3758168bc1af8cc9b 100644 (file)
@@ -48,6 +48,8 @@ fileinit_cname   = pyrex_prefix + "init_filenames"
 intern_tab_cname = pyrex_prefix + "intern_tab"
 kwds_cname       = pyrex_prefix + "kwds"
 lineno_cname     = pyrex_prefix + "lineno"
+clineno_cname    = pyrex_prefix + "clineno"
+cfilenm_cname    = pyrex_prefix + "cfilenm"
 module_cname     = pyrex_prefix + "m"
 moddoc_cname     = pyrex_prefix + "mdoc"
 methtable_cname  = pyrex_prefix + "methods"
@@ -64,6 +66,9 @@ cleanup_cname    = pyrex_prefix + "module_cleanup"
 optional_args_cname = pyrex_prefix + "optional_args"
 no_opt_args      = pyrex_prefix + "no_opt_args"
 
+line_c_macro = "__LINE__"
+
+file_c_macro = "__FILE__"
 
 extern_c_macro  = pyrex_prefix.upper() + "EXTERN_C"
 
index e8624d15e47686be2e965157bfe345b74aa4608e..fb1b9845654c1fe08b26709994ba0183d0c7975d 100644 (file)
@@ -885,8 +885,8 @@ class FuncDefNode(StatNode, BlockNode):
             exc_check = self.caller_will_check_exceptions()
             if err_val is not None or exc_check:
                 code.putln(
-                    '__Pyx_AddTraceback("%s");' % 
-                        self.entry.qualified_name)
+                    '__Pyx_AddTraceback("%s",%s,%s);' % 
+                        (self.entry.qualified_name,Naming.cfilenm_cname,Naming.clineno_cname))
                 if err_val is not None:
                     code.putln(
                         "%s = %s;" % (
@@ -3277,7 +3277,7 @@ class ExceptClauseNode(Node):
             code.putln(
                 "/*except:*/ {")
         code.putln(
-            '__Pyx_AddTraceback("%s");' % (self.function_name))
+            '__Pyx_AddTraceback("%s",%s,%s);' % (self.function_name, Naming.cfilenm_cname,Naming.clineno_cname))
         # We always have to fetch the exception value even if
         # there is no target, because this also normalises the 
         # exception and stores it in the thread state.
@@ -4095,13 +4095,13 @@ static void __Pyx_WriteUnraisable(char *name) {
 
 traceback_utility_code = [
 """
-static void __Pyx_AddTraceback(char *funcname); /*proto*/
+static void __Pyx_AddTraceback(char *funcname, char* cfilename, unsigned int cfileline); /*proto*/
 ""","""
 #include "compile.h"
 #include "frameobject.h"
 #include "traceback.h"
 
-static void __Pyx_AddTraceback(char *funcname) {
+static void __Pyx_AddTraceback(char *funcname, char* cfilename, unsigned int cfileline) {
     PyObject *py_srcfile = 0;
     PyObject *py_funcname = 0;
     PyObject *py_globals = 0;
@@ -4111,7 +4111,7 @@ static void __Pyx_AddTraceback(char *funcname) {
     
     py_srcfile = PyString_FromString(%(FILENAME)s);
     if (!py_srcfile) goto bad;
-    py_funcname = PyString_FromString(funcname);
+    py_funcname = PyString_FromFormat( "%%s, %%s, %%u", funcname, cfilename, cfileline);
     if (!py_funcname) goto bad;
     py_globals = PyModule_GetDict(%(GLOBALS)s);
     if (!py_globals) goto bad;