[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