[pypy-svn] r25621 - in pypy/dist/pypy/translator/cli: . test
antocuni at codespeak.net
antocuni at codespeak.net
Sun Apr 9 14:18:34 CEST 2006
Author: antocuni
Date: Sun Apr 9 14:18:17 2006
New Revision: 25621
Added:
pypy/dist/pypy/translator/cli/test/autopath.py (contents, props changed)
Modified:
pypy/dist/pypy/translator/cli/class_.py
pypy/dist/pypy/translator/cli/cts.py
pypy/dist/pypy/translator/cli/database.py
pypy/dist/pypy/translator/cli/function.py
pypy/dist/pypy/translator/cli/gencli.py
pypy/dist/pypy/translator/cli/metavm.py
pypy/dist/pypy/translator/cli/test/compile.py
pypy/dist/pypy/translator/cli/test/runtest.py
pypy/dist/pypy/translator/cli/test/test_oo.py
Log:
The algorithm for rendering pending nodes has been refactored. Now
every node (such as Function or Class) can enqueue new nodes that it
depends on, instead of having static dependencies as it was before.
Modified: pypy/dist/pypy/translator/cli/class_.py
==============================================================================
--- pypy/dist/pypy/translator/cli/class_.py (original)
+++ pypy/dist/pypy/translator/cli/class_.py Sun Apr 9 14:18:17 2006
@@ -1,5 +1,4 @@
from pypy.translator.cli.node import Node
-from pypy.translator.cli.function import Function
from pypy.translator.cli.cts import CTS
class Class(Node):
@@ -9,6 +8,15 @@
self.classdef = classdef
self.namespace, self.name = self.cts.split_class_name(classdef._name)
+ if not self.is_root(classdef):
+ self.db.pending_class(classdef._superclass)
+
+ def __hash__(self):
+ return hash(self.classdef)
+
+ def __eq__(self, other):
+ return self.classdef == other.classdef
+
def is_root(classdef):
return classdef._superclass is None
is_root = staticmethod(is_root)
@@ -26,7 +34,10 @@
def render(self, ilasm):
if self.is_root(self.classdef):
return
-
+
+ if self.db.class_name(self.classdef) is not None:
+ return # already rendered
+
self.ilasm = ilasm
if self.namespace:
ilasm.begin_namespace(self.namespace)
@@ -38,9 +49,10 @@
# TODO: should the .ctor set the default values?
self._ctor()
+ # lazy import to avoid circular dependencies
+ import pypy.translator.cli.function as function
for m_name, m_meth in self.classdef._methods.iteritems():
- # TODO: handle class methods and attributes
- f = Function(self.db, m_meth.graph, m_name, is_method = True)
+ f = function.Function(self.db, m_meth.graph, m_name, is_method = True)
f.render(ilasm)
ilasm.end_class()
@@ -48,10 +60,12 @@
if self.namespace:
ilasm.end_namespace()
+ self.db.record_class(self.classdef, self.name)
+
+
def _ctor(self):
self.ilasm.begin_function('.ctor', [], 'void', False, 'specialname', 'rtspecialname', 'instance')
self.ilasm.opcode('ldarg.0')
self.ilasm.call('instance void %s::.ctor()' % self.get_base_class())
self.ilasm.opcode('ret')
self.ilasm.end_function()
-
Modified: pypy/dist/pypy/translator/cli/cts.py
==============================================================================
--- pypy/dist/pypy/translator/cli/cts.py (original)
+++ pypy/dist/pypy/translator/cli/cts.py Sun Apr 9 14:18:17 2006
@@ -49,7 +49,7 @@
def lltype_to_cts(self, t):
if isinstance(t, Instance):
name = t._name
- self.db.classes.add(t)
+ self.db.pending_class(t)
return 'class %s' % name
return _get_from_dict(_lltype_to_cts, t, 'Unknown type %s' % t)
Modified: pypy/dist/pypy/translator/cli/database.py
==============================================================================
--- pypy/dist/pypy/translator/cli/database.py (original)
+++ pypy/dist/pypy/translator/cli/database.py Sun Apr 9 14:18:17 2006
@@ -1,3 +1,6 @@
+from pypy.translator.cli.cts import CTS
+from pypy.translator.cli.function import Function
+from pypy.translator.cli.class_ import Class
from pypy.rpython.ootypesystem import ootype
try:
@@ -10,20 +13,38 @@
class LowLevelDatabase(object):
def __init__(self):
- self.classes = set()
- self.pending_graphs = []
+ self._pending_nodes = set()
+ self._rendered_nodes = set()
+ self.classes = {} # classdef --> class_name
self.functions = {} # graph --> function_name
self.methods = {} # graph --> method_name
self.consts = {} # value --> const_name
+ def pending_function(self, graph):
+ self.pending_node(Function(self, graph))
+
+ def pending_class(self, classdef):
+ self.pending_node(Class(self, classdef))
+
+ def pending_node(self, node):
+ if node in self._pending_nodes or node in self._rendered_nodes:
+ return
+ self._pending_nodes.add(node)
+
def record_function(self, graph, name):
self.functions[graph] = name
+ def record_class(self, classdef, name):
+ self.classes[classdef] = name
+
def function_name(self, graph):
return self.functions.get(graph, None)
+ def class_name(self, classdef):
+ return self.classes.get(classdef, None)
+
def record_const(self, value):
- const = AbstractConst.make(value)
+ const = AbstractConst.make(self, value)
name = const.get_name(len(self.consts))
self.consts[const] = name
return '%s.%s::%s' % (CONST_NAMESPACE, CONST_CLASS, name)
@@ -52,11 +73,11 @@
class AbstractConst(object):
- def make(const):
+ def make(db, const):
if isinstance(const, ootype._view):
const = const._inst
if isinstance(const, ootype._instance):
- return InstanceConst(const)
+ return InstanceConst(db, const)
else:
assert False, 'Unknown constant: %s' % const
make = staticmethod(make)
@@ -71,7 +92,8 @@
pass
class InstanceConst(AbstractConst):
- def __init__(self, obj):
+ def __init__(self, db, obj):
+ self.cts = CTS(db)
self.obj = obj
def get_name(self, n):
@@ -79,9 +101,16 @@
return '%s_%d' % (name, n)
def get_type(self):
- return 'class %s' % self.obj._TYPE._name
+ return self.cts.lltype_to_cts(self.obj._TYPE)
+ #return 'class %s' % self.obj._TYPE._name
def init(self, ilasm):
classdef = self.obj._TYPE
ilasm.new('instance void class %s::.ctor()' % classdef._name)
- # TODO: initialize fields
+ while classdef is not None:
+ for name, (type_, value) in classdef._fields.iteritems():
+ if isinstance(type_, ootype.StaticMethod):
+ continue
+ elif type_ is ootype.Class:
+ continue
+ classdef = classdef._superclass
Modified: pypy/dist/pypy/translator/cli/function.py
==============================================================================
--- pypy/dist/pypy/translator/cli/function.py (original)
+++ pypy/dist/pypy/translator/cli/function.py Sun Apr 9 14:18:17 2006
@@ -12,6 +12,7 @@
from pypy.translator.cli.opcodes import opcodes
from pypy.translator.cli.metavm import InstructionList, Generator
from pypy.translator.cli.node import Node
+from pypy.translator.cli.class_ import Class
from pypy.tool.ansi_print import ansi_log
import py
@@ -33,6 +34,12 @@
def get_name(self):
return self.name
+ def __hash__(self):
+ return hash(self.graph)
+
+ def __eq__(self, other):
+ return self.graph == other.graph
+
def _is_return_block(self, block):
return (not block.exits) and len(block.inputargs) == 1
@@ -40,6 +47,9 @@
return (not block.exits) and len(block.inputargs) == 2
def render(self, ilasm):
+ if self.db.function_name(self.graph) is not None and not self.is_method:
+ return # already rendered
+
self.ilasm = ilasm
graph = self.graph
returntype, returnvar = self.cts.llvar_to_cts(graph.getreturnvar())
@@ -67,7 +77,7 @@
self.ilasm.begin_try()
for op in block.operations:
- self._search_for_classes(op)
+ #self._search_for_classes(op)
self._render_op(op)
if self._is_raise_block(block):
@@ -200,14 +210,13 @@
if isinstance(arg, flowmodel.Variable):
lltype = arg.concretetype
elif isinstance(arg, flowmodel.Constant):
-
lltype = arg.value
if isinstance(lltype, ootype._view) and isinstance(lltype._inst, ootype._instance):
lltype = lltype._inst._TYPE
if isinstance(lltype, ootype.Instance):
- self.db.classes.add(lltype)
+ self.db.pending_class(lltype)
def _render_op(self, op):
instr_list = opcodes.get(op.opname, None)
@@ -248,7 +257,7 @@
self.ilasm.opcode(instr, *args)
def call(self, graph, func_name):
- self.db.pending_graphs.append(graph)
+ self.db.pending_function(graph)
self.ilasm.call(func_name)
def new(self, obj):
Modified: pypy/dist/pypy/translator/cli/gencli.py
==============================================================================
--- pypy/dist/pypy/translator/cli/gencli.py (original)
+++ pypy/dist/pypy/translator/cli/gencli.py Sun Apr 9 14:18:17 2006
@@ -47,41 +47,22 @@
# methods are rendered twice, once within the class and once
# as an external function. Fix this.
self.gen_entrypoint()
- self.find_superclasses()
- self.gen_classes()
- self.gen_functions()
+ self.gen_pendings()
self.db.gen_constants(self.ilasm)
+ self.gen_pendings()
out.close()
return self.tmpfile.strpath
def gen_entrypoint(self):
if self.entrypoint:
- self.db.pending_graphs += self.entrypoint.render(self.ilasm)
+ self.entrypoint.db = self.db
+ self.db.pending_node(self.entrypoint)
else:
- self.db.pending_graphs.append(self.translator.graphs[0])
+ self.db.pending_function(self.translator.graphs[0])
- self.gen_functions()
+ def gen_pendings(self):
+ while self.db._pending_nodes:
+ node = self.db._pending_nodes.pop()
+ node.render(self.ilasm)
- def gen_functions(self):
- while self.db.pending_graphs:
- graph = self.db.pending_graphs.pop()
- if self.db.function_name(graph) is None:
- f = Function(self.db, graph)
- f.render(self.ilasm)
- def find_superclasses(self):
- classes = set()
- pendings = self.db.classes
-
- while pendings:
- classdef = pendings.pop()
- if classdef not in classes and classdef is not None:
- classes.add(classdef)
- pendings.add(classdef._superclass)
-
- self.db.classes = classes
-
- def gen_classes(self):
- for classdef in self.db.classes:
- c = Class(self.db, classdef)
- c.render(self.ilasm)
Modified: pypy/dist/pypy/translator/cli/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/cli/metavm.py (original)
+++ pypy/dist/pypy/translator/cli/metavm.py Sun Apr 9 14:18:17 2006
@@ -84,8 +84,8 @@
class _SetField(MicroInstruction):
def render(self, generator, op):
this, field, value = op.args
- if field.value == 'meta':
- return # TODO
+## if field.value == 'meta':
+## return # TODO
generator.load(this)
generator.load(value)
Added: pypy/dist/pypy/translator/cli/test/autopath.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/cli/test/autopath.py Sun Apr 9 14:18:17 2006
@@ -0,0 +1,112 @@
+"""
+self cloning, automatic path configuration
+
+copy this into any subdirectory of pypy from which scripts need
+to be run, typically all of the test subdirs.
+The idea is that any such script simply issues
+
+ import autopath
+
+and this will make sure that the parent directory containing "pypy"
+is in sys.path.
+
+If you modify the master "autopath.py" version (in pypy/tool/autopath.py)
+you can directly run it which will copy itself on all autopath.py files
+it finds under the pypy root directory.
+
+This module always provides these attributes:
+
+ pypydir pypy root directory path
+ this_dir directory where this autopath.py resides
+
+"""
+
+
+def __dirinfo(part):
+ """ return (partdir, this_dir) and insert parent of partdir
+ into sys.path. If the parent directories don't have the part
+ an EnvironmentError is raised."""
+
+ import sys, os
+ try:
+ head = this_dir = os.path.realpath(os.path.dirname(__file__))
+ except NameError:
+ head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0]))
+
+ while head:
+ partdir = head
+ head, tail = os.path.split(head)
+ if tail == part:
+ break
+ else:
+ raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir)
+
+ pypy_root = os.path.join(head, '')
+ try:
+ sys.path.remove(head)
+ except ValueError:
+ pass
+ sys.path.insert(0, head)
+
+ munged = {}
+ for name, mod in sys.modules.items():
+ fn = getattr(mod, '__file__', None)
+ if '.' in name or not isinstance(fn, str):
+ continue
+ newname = os.path.splitext(os.path.basename(fn))[0]
+ if not newname.startswith(part + '.'):
+ continue
+ path = os.path.join(os.path.dirname(os.path.realpath(fn)), '')
+ if path.startswith(pypy_root) and newname != part:
+ modpaths = os.path.normpath(path[len(pypy_root):]).split(os.sep)
+ if newname != '__init__':
+ modpaths.append(newname)
+ modpath = '.'.join(modpaths)
+ if modpath not in sys.modules:
+ munged[modpath] = mod
+
+ for name, mod in munged.iteritems():
+ if name not in sys.modules:
+ sys.modules[name] = mod
+ if '.' in name:
+ prename = name[:name.rfind('.')]
+ postname = name[len(prename)+1:]
+ if prename not in sys.modules:
+ __import__(prename)
+ if not hasattr(sys.modules[prename], postname):
+ setattr(sys.modules[prename], postname, mod)
+
+ return partdir, this_dir
+
+def __clone():
+ """ clone master version of autopath.py into all subdirs """
+ from os.path import join, walk
+ if not this_dir.endswith(join('pypy','tool')):
+ raise EnvironmentError("can only clone master version "
+ "'%s'" % join(pypydir, 'tool',_myname))
+
+
+ def sync_walker(arg, dirname, fnames):
+ if _myname in fnames:
+ fn = join(dirname, _myname)
+ f = open(fn, 'rwb+')
+ try:
+ if f.read() == arg:
+ print "checkok", fn
+ else:
+ print "syncing", fn
+ f = open(fn, 'w')
+ f.write(arg)
+ finally:
+ f.close()
+ s = open(join(pypydir, 'tool', _myname), 'rb').read()
+ walk(pypydir, sync_walker, s)
+
+_myname = 'autopath.py'
+
+# set guaranteed attributes
+
+pypydir, this_dir = __dirinfo('pypy')
+
+if __name__ == '__main__':
+ __clone()
Modified: pypy/dist/pypy/translator/cli/test/compile.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/compile.py (original)
+++ pypy/dist/pypy/translator/cli/test/compile.py Sun Apr 9 14:18:17 2006
@@ -28,25 +28,24 @@
self.x = x
def compute(self):
- return self.x + 1
+ return self.x
class Derived(Base):
def __init__(self, x):
- Base.__init__(self, x)
+ Base.__init__(self, x+42)
-def foo(cls, arg):
- obj = cls(arg)
- return obj.compute()
+def foo(cls, x):
+ return cls(x).compute()
def bar(x, y):
- obj = Base(x)
- return obj.compute()
+ b = Derived(x)
+ return b.compute()
# return foo(Base, x) + foo(Derived, y)
f = compile_function(bar, [int, int])
-##try:
-## pass
-##except py.test.Item.Skipped:
-## print 'Test skipped'
+try:
+ check(bar, f, 42, 13)
+except py.test.Item.Skipped:
+ print 'Test skipped'
Modified: pypy/dist/pypy/translator/cli/test/runtest.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/runtest.py (original)
+++ pypy/dist/pypy/translator/cli/test/runtest.py Sun Apr 9 14:18:17 2006
@@ -7,6 +7,7 @@
from pypy.translator.translator import TranslationContext
from pypy.translator.cli.option import getoption
from pypy.translator.cli.gencli import GenCli
+from pypy.translator.cli.function import Function
from pypy.translator.cli.node import Node
from pypy.translator.cli.cts import CTS
from pypy.translator.cli.database import LowLevelDatabase
@@ -33,6 +34,7 @@
def __init__(self, graph_to_call):
self.graph = graph_to_call
+ self.db = None
def get_name(self):
return 'main'
@@ -56,7 +58,7 @@
ilasm.call('void class [mscorlib]System.Console::WriteLine(%s)' % ret_type)
ilasm.opcode('ret')
ilasm.end_function()
- return [self.graph]
+ self.db.pending_function(self.graph)
def __convert_method(self, arg_type):
_conv = {
@@ -126,8 +128,10 @@
return None
self.__check_helper("ilasm")
- retval = subprocess.call(["ilasm", tmpfile], stdout=subprocess.PIPE)
- assert retval == 0, 'ilasm failed to assemble %s (%s)' % (self.graph.name, tmpfile)
+ ilasm = subprocess.Popen(["ilasm", tmpfile], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout, stderr = ilasm.communicate()
+ retval = ilasm.wait()
+ assert retval == 0, 'ilasm failed to assemble %s (%s):\n%s' % (self.graph.name, tmpfile, stdout)
return tmpfile.replace('.il', '.exe')
def __call__(self, *args):
Modified: pypy/dist/pypy/translator/cli/test/test_oo.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_oo.py (original)
+++ pypy/dist/pypy/translator/cli/test/test_oo.py Sun Apr 9 14:18:17 2006
@@ -9,6 +9,8 @@
class MyClass:
+ INCREMENT = 1
+
def __init__(self, x, y):
self.x = x
self.y = y
@@ -23,7 +25,16 @@
return x*y
static_meth = staticmethod(static_meth)
+## def class_meth(cls, x, y):
+## return x*y + cls.INCREMENT
+## class_meth = classmethod(class_meth)
+
+ def class_attribute(self):
+ return self.x + self.INCREMENT
+
class MyDerivedClass(MyClass):
+ INCREMENT = 2
+
def __init__(self, x, y):
MyClass.__init__(self, x, y)
@@ -56,3 +67,15 @@
return base.static_meth(x,y) + derived.static_meth(x, y)\
+ MyClass.static_meth(x, y) + MyDerivedClass.static_meth(x, y)
+def oo_class_attribute(x, y):
+ base = MyClass(x, y)
+ derived = MyDerivedClass(x, y)
+ return base.class_attribute() + derived.class_attribute()
+
+##def oo_class_meth(x, y):
+## return MyClass.class_meth(x, y) + MyDerivedClass.class_meth(x, y)
+
+if __name__ == '__main__':
+ from pypy.translator.cli import conftest
+ conftest.option.wd = True
+ check(oo_liskov, [int, int], (42, 13))
More information about the Pypy-commit
mailing list