Added pre-import option, which assumes all undeclared names come from the given module.
authorRobert Bradshaw <robertwb@math.washington.edu>
Wed, 11 Jul 2007 05:02:54 +0000 (22:02 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Wed, 11 Jul 2007 05:02:54 +0000 (22:02 -0700)
Emulates behavior of

from <module> import *

Cython/Compiler/CmdLine.py
Cython/Compiler/Code.py
Cython/Compiler/ModuleNode.py
Cython/Compiler/Naming.py
Cython/Compiler/Options.py
Cython/Compiler/Symtab.py

index 51b148f30cdd6aa045866042e0cf7c770cb7e551..c47932030a520c0619d4c46a2a93c1d6254f3881 100644 (file)
@@ -18,6 +18,9 @@ Options:
   -o, --output-file <filename>   Specify name of generated C file
   -p, --embed-positions          If specified, the positions in Pyrex files of each
                                  function definition is embedded in its docstring.
+  -z, --pre-import <module>      If specified, assume undeclared names in this 
+                                 module. Emulates the behavior of putting 
+                                 "from <module> import *" at the top of the file. 
 """  
 #The following experimental options are supported only on MacOSX:
 #  -C, --compile    Compile generated .c file to .o file
@@ -70,6 +73,8 @@ def parse_command_line(args):
                 options.output_file = pop_arg()
             elif option in ("-p", "--embed-positions"):
                 Options.embed_pos_in_docstring = 1
+            elif option in ("-z", "--pre-import"):
+                Options.pre_import = pop_arg()
             else:
                 bad_usage()
         else:
index dec44344636c9455a16cff3f2037ffb6d310ff44..5ba0f7a67ff3d29b2c7ae49d1521ad995698982f 100644 (file)
@@ -311,7 +311,7 @@ class CCodeWriter:
             lbl)
             
     def error_goto_if(self, cond, pos):
-        if Options.gcc_branch_hints or 0: # TODO this path is almost _never_ taken, yet this macro makes is slower!
+        if Options.gcc_branch_hints:
             return "if (unlikely(%s)) %s" % (cond, self.error_goto(pos))
         else:
             return "if (%s) %s" % (cond, self.error_goto(pos))
index 649420024f45114089f2a375b3838beb14aa0e50..4424be3562a35a31ca7d283f157b7121333bc1e6 100644 (file)
@@ -163,6 +163,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln('')
         code.putln('static PyObject *%s;' % env.module_cname)
         code.putln('static PyObject *%s;' % Naming.builtins_cname)
+        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 char *%s;' % Naming.filename_cname)
         code.putln('static char **%s;' % Naming.filetable_cname)
@@ -1122,6 +1124,15 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 env.module_cname,
                 Naming.builtins_cname,
                 code.error_goto(self.pos)))
+        if Options.pre_import is not None:
+            code.putln(
+                '%s = PyImport_AddModule("%s");' % (
+                    Naming.preimport_cname, 
+                    Options.pre_import))
+            code.putln(
+                "if (!%s) %s;" % (
+                    Naming.preimport_cname,
+                    code.error_goto(self.pos)));
     
     def generate_intern_code(self, env, code):
         if env.intern_map:
index abd5a30b9b2f131b18e3e631956d24938507c60f..faa191662c34616479ee9de88cc8cd1b3b1e8e94 100644 (file)
@@ -35,6 +35,7 @@ args_cname       = pyrex_prefix + "args"
 kwdlist_cname    = pyrex_prefix + "argnames"
 obj_base_cname   = pyrex_prefix + "base"
 builtins_cname   = pyrex_prefix + "b"
+preimport_cname  = pyrex_prefix + "i"
 moddict_cname    = pyrex_prefix + "d"
 dummy_cname      = pyrex_prefix + "dummy"
 filename_cname   = pyrex_prefix + "filename"
index 0456cf7723b9ad72eddb637da197f28d82b472dc..d89d304eb2cb328a350bfc56472227ffa96c7b49 100644 (file)
@@ -7,3 +7,5 @@ cache_builtins = 1  #  Perform lookups on builtin names only once
 
 embed_pos_in_docstring = 0
 gcc_branch_hints = 1
+
+pre_import = None
index ac394348de73b5d93db4887554ec505b63679dc1..22122abf23c4324ffdec1742d040117b7976b3c7 100644 (file)
@@ -448,12 +448,27 @@ class Scope:
                 return 1
         return 0
 
+class PreImportScope(Scope):
+    def __init__(self):
+        Scope.__init__(self, Options.pre_import, None, None)
+        
+    def declare_builtin(self, name, pos):
+        entry = self.declare(name, name, py_object_type, pos)
+        entry.is_variable = True
+        entry.is_pyglobal = True
+        entry.namespace_cname = Naming.preimport_cname
+        return entry
+
 
 class BuiltinScope(Scope):
     #  The builtin namespace.
     
     def __init__(self):
-        Scope.__init__(self, "__builtin__", None, None)
+        if Options.pre_import is None:
+            Scope.__init__(self, "__builtin__", None, None)
+        else:
+            Scope.__init__(self, "__builtin__", PreImportScope(), None)
+        
         for name, definition in self.builtin_functions.iteritems():
             if len(definition) < 4: definition.append(None) # exception_value
             if len(definition) < 5: definition.append(False) # exception_check
@@ -468,7 +483,10 @@ class BuiltinScope(Scope):
         
     def declare_builtin(self, name, pos):
         if not hasattr(__builtin__, name):
-            error(pos, "undeclared name not builtin: %s"%name)
+            if self.outer_scope is not None:
+                return self.outer_scope.declare_builtin(name, pos)
+            else:
+                error(pos, "undeclared name not builtin: %s"%name)
         entry = self.declare(name, name, py_object_type, pos)
         if Options.cache_builtins:
             entry.is_builtin = 1