Modify name conversion to be (hopefully) a bit more efficient.

Use a dictionary instead of a list to map objects to their offsets in
a const/name tuple of a code object.

XXX The conversion is perhaps incomplete, in that we shouldn't have to
do the list2dict to start.
diff --git a/Lib/compiler/pyassem.py b/Lib/compiler/pyassem.py
index 3063b5b..0cdc6ea 100644
--- a/Lib/compiler/pyassem.py
+++ b/Lib/compiler/pyassem.py
@@ -15,6 +15,17 @@
     l.sort(sorter)
     return l
 
+def list2dict(l):
+    d = {}
+    for i in range(len(l)):
+        d[l[i]] = i
+    return d
+
+def dict2list(d):
+    l = [(v, k) for k, v in d.items()]
+    l.sort()
+    return [k for v, k in l]
+
 class FlowGraph:
     def __init__(self):
         self.current = self.entry = Block()
@@ -326,13 +337,14 @@
 class PyFlowGraph(FlowGraph):
     super_init = FlowGraph.__init__
 
-    def __init__(self, name, filename, args=(), optimized=0):
+    def __init__(self, name, filename, args=(), optimized=0, klass=None):
         self.super_init()
         self.name = name
         self.filename = filename
         self.docstring = None
         self.args = args # XXX
         self.argcount = getArgCount(args)
+        self.klass = klass
         if optimized:
             self.flags = CO_OPTIMIZED | CO_NEWLOCALS 
         else:
@@ -445,14 +457,25 @@
         assert self.stage == FLAT
         self.consts.insert(0, self.docstring)
         self.sort_cellvars()
+
+        self.c_varnames = list2dict(self.varnames)
+        self.c_names = list2dict(self.names)
+        self.c_consts = list2dict(self.consts)
+        self.c_closure = list2dict(self.closure)
+
         for i in range(len(self.insts)):
             t = self.insts[i]
             if len(t) == 2:
-                opname = t[0]
-                oparg = t[1]
+                opname, oparg = t
                 conv = self._converters.get(opname, None)
                 if conv:
                     self.insts[i] = opname, conv(self, oparg)
+
+        self.varnames = dict2list(self.c_varnames)
+        self.names = dict2list(self.c_names)
+        self.consts = dict2list(self.c_consts)
+        self.closure = dict2list(self.c_closure)
+
         self.stage = CONV
 
     def sort_cellvars(self):
@@ -468,12 +491,23 @@
         self.cellvars = self.cellvars + cells.keys()
         self.closure = self.cellvars + self.freevars
 
-    def _lookupName(self, name, list):
+    def _lookupName(self, name, dict):
+        i = dict.get(name, None)
+        if i is None:
+            i = dict[name] = len(dict)
+        return i
+
+    def XXX_lookupName(self, name, list):
         """Return index of name in list, appending if necessary"""
+        # XXX It should be possible to replace this with some
+        # dictionary operations, but not sure how
         t = type(name)
         for i in range(len(list)):
-            # must do a comparison on type first to prevent UnicodeErrors 
-            if t == type(list[i]) and list[i] == name:
+            # must do a comparison on type first to prevent UnicodeErrors
+            # not clear that a dictionary would work, because we could
+            # get UnicodeErrors on lookups 
+            elt = list[i]
+            if isinstance(elt, t) and elt == name:
                 return i
         end = len(list)
         list.append(name)
@@ -483,20 +517,21 @@
     def _convert_LOAD_CONST(self, arg):
         if hasattr(arg, 'getCode'):
             arg = arg.getCode()
-        return self._lookupName(arg, self.consts)
+        return self._lookupName(arg, self.c_consts)
 
     def _convert_LOAD_FAST(self, arg):
-        self._lookupName(arg, self.names)
-        return self._lookupName(arg, self.varnames)
+        self._lookupName(arg, self.c_names)
+        return self._lookupName(arg, self.c_varnames)
     _convert_STORE_FAST = _convert_LOAD_FAST
     _convert_DELETE_FAST = _convert_LOAD_FAST
 
     def _convert_LOAD_NAME(self, arg):
-        return self._lookupName(arg, self.names)
+        return self._lookupName(arg, self.c_names)
 
     def _convert_NAME(self, arg):
-        self._lookupName(arg, self.varnames)
-        return self._lookupName(arg, self.names)
+        if self.klass is None:
+            self._lookupName(arg, self.c_varnames)
+        return self._lookupName(arg, self.c_names)
     _convert_STORE_NAME = _convert_NAME
     _convert_DELETE_NAME = _convert_NAME
     _convert_IMPORT_NAME = _convert_NAME
@@ -509,15 +544,15 @@
     _convert_DELETE_GLOBAL = _convert_NAME
 
     def _convert_DEREF(self, arg):
-        self._lookupName(arg, self.names)
-        self._lookupName(arg, self.varnames)
-        return self._lookupName(arg, self.closure)
+        self._lookupName(arg, self.c_names)
+        self._lookupName(arg, self.c_varnames)
+        return self._lookupName(arg, self.c_closure)
     _convert_LOAD_DEREF = _convert_DEREF
     _convert_STORE_DEREF = _convert_DEREF
 
     def _convert_LOAD_CLOSURE(self, arg):
-        self._lookupName(arg, self.varnames)
-        return self._lookupName(arg, self.closure)
+        self._lookupName(arg, self.c_varnames)
+        return self._lookupName(arg, self.c_closure)
 
     _cmp = list(dis.cmp_op)
     def _convert_COMPARE_OP(self, arg):