Permalink
Browse files

Generate a callgraph for bin/opy_ too.

Tweak the output to be more concise.  Make note of an issue with bound
methods like sys.stdout.write.

Make a few more things new-style classes.
  • Loading branch information...
Andy Chu
Andy Chu committed Mar 16, 2018
1 parent ccaf91d commit 920d8c565a8c3fd2b37b1c68c499011ba5a26736
Showing with 58 additions and 17 deletions.
  1. +6 −1 bin/opy_.py
  2. +26 −7 opy/callgraph.py
  3. +1 −1 opy/compiler2/pycodegen.py
  4. +5 −5 opy/opy_main.py
  5. +20 −3 scripts/count.sh
View
@@ -80,4 +80,9 @@ def main(argv):
if __name__ == '__main__':
main(sys.argv)
# NOTE: This could end up as opy.InferTypes(), opy.GenerateCode(), etc.
if os.getenv('CALLGRAPH') == '1':
from opy import callgraph
callgraph.Walk(main, sys.modules)
else:
main(sys.argv)
View
@@ -12,7 +12,6 @@
import __builtin__ # For looking up names
import types
#import exceptions
from core import util
log = util.log
@@ -138,9 +137,9 @@ def _Walk(obj, cls, ref, syms):
# OBJ <built-in method get of dict object at 0x7fcd28c53280>
# OBJ <built-in method get of dict object at 0x7fcd28c53398>
if obj.__name__ in ('get', 'Parse'):
#log('OBJ %s', obj)
pass
#if obj.__name__ in ('write', 'get', 'Parse'):
# log('OBJ %s %d', obj, id(obj))
# pass
if module_name is None:
syms.Add(obj, None, ref, None, None, None)
@@ -207,6 +206,19 @@ def _Walk(obj, cls, ref, syms):
#log('%s %s', op, var)
val = _GetAttr(last_val, var)
ref.append(var)
# Crawl the methods below. Otherwise we get duplicate bound/unbound
# methods, which have unique addresses.
# Examples: WAIT_SPEC.Parse, sys.stdout.write
# BUG: os.fork and sys.stdout.write are the same?
# I thought os.fork is types.BuiltinFunctionType, and
# sys.stdout.write is types.BuiltinMethodType, but why not?
if isinstance(val, (types.MethodType, types.BuiltinMethodType)):
val = None
ref = []
else:
val = None
ref = []
@@ -246,7 +258,8 @@ def _Walk(obj, cls, ref, syms):
def PrintSig(fmt, func):
#return
if os.getenv('CALLGRAPH_SIG') != '1':
return
try:
argspec = inspect.getargspec(func)
except TypeError:
@@ -395,7 +408,10 @@ def Report(self, f=sys.stdout):
print('%s' % path)
for func, ref, _ in src.functions:
print(' %s [%s]' % (func.__name__, '.'.join(ref)))
#third = func
third = ''
#print(' %s [%s] %s' % (func.__name__, '.'.join(ref), third))
print(' %s' % func.__name__)
PrintSig(' %s', func)
classes = [(c.Name(), c) for c in src.classes]
@@ -414,7 +430,10 @@ def Report(self, f=sys.stdout):
print('%s' % mod_name)
for func, ref, _ in src.functions:
print(' %s [%s]' % (func.__name__, '.'.join(ref)))
#third = func
third = ''
#print(' %s [%s] %s' % (func.__name__, '.'.join(ref), third))
print(' %s' % func.__name__)
classes = [(c.Name(), c) for c in src.classes]
classes.sort()
@@ -71,7 +71,7 @@ def compile(source, filename, mode, flags=None, dont_inherit=None, transformer=N
gen.compile(transformer=transformer)
return gen.code
class AbstractCompileMode:
class AbstractCompileMode(object):
mode = None # defined by subclass
View
@@ -78,7 +78,7 @@ def WriteGrammar(grammar_path, pickle_path):
# Emulate the interface that Transformer expects from parsermodule.c.
class Pgen2PythonParser:
class Pgen2PythonParser(object):
def __init__(self, driver, start_symbol):
self.driver = driver
self.start_symbol = start_symbol
@@ -105,7 +105,7 @@ def CountTupleTree(tu):
raise AssertionError(tu)
class TupleTreePrinter:
class TupleTreePrinter(object):
def __init__(self, names):
self._names = names
@@ -217,7 +217,7 @@ def py2st(gr, raw_node):
tree = st.totuple()
n = transformer.CountTupleTree(tree)
n = CountTupleTree(tree)
log('COUNT %d', n)
printer = TupleTreePrinter(HostStdlibNames())
printer.Print(tree)
@@ -329,13 +329,13 @@ def py2st(gr, raw_node):
with open(py_path) as f:
contents = f.read()
co = pycodegen.compile(contents, py_path, 'exec', transformer=tr)
execfile.run_code_object(co, opy_argv)
#execfile.run_code_object(co, opy_argv)
elif py_path.endswith('.pyc') or py_path.endswith('.opyc'):
with open(py_path) as f:
f.seek(8) # past header. TODO: validate it!
co = marshal.load(f)
execfile.run_code_object(co, opy_argv)
#execfile.run_code_object(co, opy_argv)
else:
raise args.UsageError('Invalid path %r' % py_path)
View
@@ -200,12 +200,29 @@ top-level() {
| egrep -v ':import|from|class|def' # note: colon is from grep output
}
py-symbols() {
CALLGRAPH=1 bin/oil.py
_python-symbols() {
local main=$1
local name=$2
local out=_tmp/${name}-python-symbols.txt
CALLGRAPH=1 $main | tee $out
wc -l $out
echo
echo "Wrote $out"
}
oil-python-symbols() {
_python-symbols bin/oil.py oil
}
opy-python-symbols() {
_python-symbols bin/opy_.py opy
}
old-style-classes() {
py-symbols | grep -v '<'
oil-python-symbols | grep -v '<'
}
"$@"

0 comments on commit 920d8c5

Please sign in to comment.