[pypy-svn] r13900 - in pypy/dist/pypy: rpython rpython/test tool

tismer at codespeak.net tismer at codespeak.net
Sat Jun 25 20:23:16 CEST 2005


Author: tismer
Date: Sat Jun 25 20:23:14 2005
New Revision: 13900

Modified:
   pypy/dist/pypy/rpython/rdict.py
   pypy/dist/pypy/rpython/test/test_rdict.py
   pypy/dist/pypy/tool/asterisk.py
Log:
(arre, chris)
refactored stringlist.keys()/values()/items()
to use just a single implementation and specialization.
Have a look, it is crazy!

Modified: pypy/dist/pypy/rpython/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/rdict.py	(original)
+++ pypy/dist/pypy/rpython/rdict.py	Sat Jun 25 20:23:14 2005
@@ -106,23 +106,21 @@
         v_dic1, v_dic2 = hop.inputargs(self, self)
         return hop.gendirectcall(ll_update, v_dic1, v_dic2)
 
-    def rtype_method_keys(self, hop):
+    def _rtype_method_kvi(self, hop, spec):
         v_dic, = hop.inputargs(self)
         r_list = hop.r_result
+        v_func = hop.inputconst(lltype.Void, spec)
         c1 = hop.inputconst(lltype.Void, r_list.lowleveltype)
-        return hop.gendirectcall(ll_keys, v_dic, c1)
+        return hop.gendirectcall(ll_kvi, v_dic, c1, v_func)
+
+    def rtype_method_keys(self, hop):
+        return self._rtype_method_kvi(hop, dum_keys)
 
     def rtype_method_values(self, hop):
-        v_dic, = hop.inputargs(self)
-        r_list = hop.r_result
-        c1 = hop.inputconst(lltype.Void, r_list.lowleveltype)
-        return hop.gendirectcall(ll_values, v_dic, c1)
+        return self._rtype_method_kvi(hop, dum_values)
 
     def rtype_method_items(self, hop):
-        v_dic, = hop.inputargs(self)
-        r_list = hop.r_result
-        c1 = hop.inputconst(lltype.Void, r_list.lowleveltype)
-        return hop.gendirectcall(ll_items, v_dic, c1)
+        return self._rtype_method_kvi(hop, dum_items)
 
 class __extend__(pairtype(StrDictRepr, rmodel.StringRepr)): 
 
@@ -359,50 +357,31 @@
             ll_strdict_setitem(v_dic1, entry.key, entry.value)
         i += 1
 
-def ll_keys(v_dic, LISTPTR):
-    res = rlist.ll_newlist(LISTPTR, v_dic.num_items)
-    dlen = len(v_dic.entries)
-    entries = v_dic.entries
-    i = 0
-    p = 0
-    while i < dlen:
-        key = entries[i].key
-        if key and key != deleted_entry_marker:
-                res.items[p] = key
-                p += 1
-        i += 1
-    return res
-
-def ll_values(v_dic, LISTPTR):
-    res = rlist.ll_newlist(LISTPTR, v_dic.num_items)
-    dlen = len(v_dic.entries)
-    entries = v_dic.entries
-    i = 0
-    p = 0
-    while i < dlen:
-        key = entries[i].key
-        value = entries[i].value
-        if key and key != deleted_entry_marker:
-                res.items[p] = value
-                p += 1
-        i += 1
-    return res
+def dum_keys(): pass
+def dum_values(): pass
+def dum_items():pass
 
-def ll_items(v_dic, LISTPTR):
+def ll_kvi(v_dic, LISTPTR, v_func):
     res = rlist.ll_newlist(LISTPTR, v_dic.num_items)
     dlen = len(v_dic.entries)
     entries = v_dic.entries
+    items = res.items
     i = 0
     p = 0
     while i < dlen:
-        key = entries[i].key
-        value = entries[i].value
+        entry = entries[i]
+        key = entry.key
         if key and key != deleted_entry_marker:
+            if v_func is dum_items:
                 r = lltype.malloc(LISTPTR.TO.items.TO.OF.TO)
                 r.item0 = key
-                r.item1 = value
-                res.items[p] = r
-                p += 1
+                r.item1 = entry.value
+                items[p] = r
+            elif v_func is dum_keys:
+                items[p] = key
+            elif v_func is dum_values:
+                items[p] = entry.value
+            p += 1
         i += 1
     return res
 

Modified: pypy/dist/pypy/rpython/test/test_rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rdict.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rdict.py	Sat Jun 25 20:23:14 2005
@@ -215,7 +215,7 @@
         dic = {' 4':1000, ' 8':200}
         keys = dic.keys()
         return ord(keys[0][1]) + ord(keys[1][1]) - 2*ord('0') + len(keys)
-    res = interpret(func, ())
+    res = interpret(func, ())#, view=True)
     assert res == 14
 
 def test_dict_values():

Modified: pypy/dist/pypy/tool/asterisk.py
==============================================================================
--- pypy/dist/pypy/tool/asterisk.py	(original)
+++ pypy/dist/pypy/tool/asterisk.py	Sat Jun 25 20:23:14 2005
@@ -23,16 +23,26 @@
     finally:
         sys.stdout = hold
 
-def offset2lineno(c, stopat):
-    tab = c.co_lnotab
-    line = c.co_firstlineno
-    addr = 0
-    for i in range(0, len(tab), 2):
-        addr = addr + ord(tab[i])
-        if addr > stopat:
-            break
-        line = line + ord(tab[i+1])
-    return line
+def opsequence(code):
+    for line in disasm(code).split('\n'):
+        pieces = line.split('(', 1)
+        if len(pieces) == 1:
+            start, arg = pieces[0], None
+        else:
+            start, arg = pieces
+        words = start.split()
+        while words and (words[0].isdigit() or words[0] == '>>'):
+            word = words.pop(0)
+            if word.isdigit():
+                ofs = int(word)
+        if not words:
+            continue
+        op = words[0]
+        if arg:
+            arg = arg[:-1] # )
+        if op.startswith('JUMP'):
+            arg = int(words[1])
+        yield ofs, op, arg
 
 def globalsof(code, globrefs=None, stars=None, globals=None):
     names = code.co_names
@@ -41,30 +51,23 @@
     if stars is None: stars = [] # do stars in order
     if globals is None: globals = {}
     in_seq = False
-    for line in disasm(code).split('\n'):
-        words = line.split()
-        ofs = -1
-        while words and words[0].isdigit():
-            ofs = int(words.pop(0))
-        if not words:
-            continue
-        op = words[0]
+    for ofs, op, arg in opsequence(code):
         if op == 'LOAD_GLOBAL':
-            name = words[-1][1:-1] # omit ()
+            name = arg
             refs = globrefs.setdefault(name, {})
             offsets = refs.setdefault(code, [])
             offsets.append(ofs)
         elif op == 'IMPORT_NAME':
             in_seq = True
-            imp_module = words[-1][1:-1]
+            imp_module = arg
             imp_what = None
         elif op == 'IMPORT_FROM':
             in_seq = True
-            imp_what = words[-1][1:-1]
+            imp_what = arg
         elif op == 'STORE_NAME':
             # we are not interested in local imports, which
             # would generate a STORE_FAST
-            name = words[-1][1:-1]
+            name = arg
             if in_seq:
                 globals[name] = imp_what, imp_module
                 in_seq = False
@@ -77,29 +80,44 @@
             in_seq = False
     return globrefs, stars, globals
 
-def allglobalsof(code):
-    globrefs = {}
-    stars = []
-    globals = {}
-    seen = {}
-    if type(code) is str:
-        fname = code
-        code = compile(file(fname).read(), fname, 'exec')
-    todo = [code]
-    while todo:
-        code = todo.pop(0)
-        globalsof(code, globrefs, stars, globals)
-        seen[code] = True
-        for const in code.co_consts:
-            if type(const) is type(code) and const not in seen:
-                todo.append(const)
-    return globrefs, stars, globals
+def offsetmap(c):
+    # create a mapping from offsets to line numbers.
+    # we count lines from zero, here.
+    tab = c.co_lnotab
+    line = c.co_firstlineno - 1
+    addr = 0
+    res = { addr: line }
+    for i in range(0, len(tab), 2):
+        addr = addr + ord(tab[i])
+        line = line + ord(tab[i+1])
+        res[addr] = line
+    return res
+
 
 class Analyser:
     def __init__(self, fname):
         self.fname = fname
-        self.globrefs, self.stars, self.globals = allglobalsof(fname)
+        self.source = file(fname).read()
         self.starimports = []
+        self.codeobjects = {}
+        self.globrefs, self.stars, self.globals = self.analyse()
+
+    def analyse(self):
+        globrefs = {}
+        stars = []
+        globals = {}
+        seen = {}
+        code = compile(self.source, self.fname, 'exec')
+        todo = [code]
+        while todo:
+            code = todo.pop(0)
+            self.codeobjects[code] = offsetmap(code)
+            globalsof(code, globrefs, stars, globals)
+            seen[code] = True
+            for const in code.co_consts:
+                if type(const) is type(code) and const not in seen:
+                    todo.append(const)
+        return globrefs, stars, globals
 
     def get_unknown_globals(self):
         from __builtin__ import __dict__ as bltin
@@ -111,7 +129,7 @@
         dic = {}
         exec "from %s import *" % modname in dic
         return dic
-    
+
     def resolve_star_imports(self):
         implicit = {}
         which = {}
@@ -129,4 +147,26 @@
         for star, ofs in self.stars:
             imps.append( (ofs, star, which[star]) )
         self.starimports = imps
+
+    def find_statements(self):
+        # go through all code objects and collect
+        # line numbers. This gives us all statements.
+        lineset = {}
+        for co, ofs2line in self.codeobjects.items():
+            for ofs, line in ofs2line.items():
+                lineset[line] = True
+        linenos = lineset.keys()
+        if 0 not in linenos:
+            linenos.append(0)
+        linenos.sort()
+        self.linenos = linenos
+        # now create statement chunks
+        srclines = self.source.split('\n')
+        stmts = []
+        start = 0
+        for lno in linenos[1:] + [sys.maxint]:
+            stmt = '\n'.join(srclines[start:lno])
+            stmts.append(stmt)
+            start = lno
+        self.statements = stmts
         
\ No newline at end of file



More information about the Pypy-commit mailing list