[pypy-svn] r25641 - in pypy/dist/pypy/translator/cli: . src test

antocuni at codespeak.net antocuni at codespeak.net
Mon Apr 10 01:14:25 CEST 2006


Author: antocuni
Date: Mon Apr 10 01:14:05 2006
New Revision: 25641

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/ilgenerator.py
   pypy/dist/pypy/translator/cli/opcodes.py
   pypy/dist/pypy/translator/cli/rte.py
   pypy/dist/pypy/translator/cli/src/pypy.cs
   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:
Added support for classes as first class objects.

The 'runtimenew' operation is executed by calling an external function
defined in src/pypy.cs; that file is automatically compiled into
pypy.dll when changed thanks to rte.py.

Some minor bugs concerning the 'meta' fields has been corrected.



Modified: pypy/dist/pypy/translator/cli/class_.py
==============================================================================
--- pypy/dist/pypy/translator/cli/class_.py	(original)
+++ pypy/dist/pypy/translator/cli/class_.py	Mon Apr 10 01:14:05 2006
@@ -44,7 +44,9 @@
 
         ilasm.begin_class(self.name, self.get_base_class())
         for f_name, (f_type, f_default) in self.classdef._fields.iteritems():
-            ilasm.field(f_name, self.cts.lltype_to_cts(f_type))
+            cts_type = self.cts.lltype_to_cts(f_type)
+            if cts_type != 'void':
+                ilasm.field(f_name, cts_type)
 
         # TODO: should the .ctor set the default values?
         self._ctor()

Modified: pypy/dist/pypy/translator/cli/cts.py
==============================================================================
--- pypy/dist/pypy/translator/cli/cts.py	(original)
+++ pypy/dist/pypy/translator/cli/cts.py	Mon Apr 10 01:14:05 2006
@@ -6,7 +6,7 @@
 
 from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float
 from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong
-from pypy.rpython.ootypesystem.ootype import Instance, Class
+from pypy.rpython.ootypesystem.ootype import Instance, Class, StaticMethod
 from pypy.translator.cli.option import getoption
 
 from pypy.tool.ansi_print import ansi_log
@@ -23,7 +23,7 @@
     UnsignedLongLong: 'unsigned int64',
     Bool: 'bool',
     Float: 'float64',
-    Class: 'class [mscorlib]System.Type', # TODO: check this
+    Class: 'class [mscorlib]System.Type',
     }
 
 _pyexception_to_cts = {
@@ -51,6 +51,8 @@
             name = t._name
             self.db.pending_class(t)
             return 'class %s' % name
+        elif isinstance(t, StaticMethod):
+            return 'void' # TODO: is it correct to ignore StaticMethod?
 
         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	Mon Apr 10 01:14:05 2006
@@ -45,8 +45,12 @@
 
     def record_const(self, value):
         const = AbstractConst.make(self, value)
-        name = const.get_name(len(self.consts))
-        self.consts[const] = name
+        try:
+            name = self.consts[const]
+        except KeyError:
+            name = const.get_name(len(self.consts))
+            self.consts[const] = name
+
         return '%s.%s::%s' % (CONST_NAMESPACE, CONST_CLASS, name)
 
     def gen_constants(self, ilasm):
@@ -96,21 +100,33 @@
         self.cts = CTS(db)
         self.obj = obj
 
+    def __hash__(self):
+        return hash(self.obj)
+
+    def __eq__(self, other):
+        return self.obj == other.obj
+
     def get_name(self, n):
         name = self.obj._TYPE._name.replace('.', '_')
         return '%s_%d' % (name, n)
 
     def get_type(self):
         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)
         while classdef is not None:
-            for name, (type_, value) in classdef._fields.iteritems():
+            for name, (type_, default) in classdef._fields.iteritems():
                 if isinstance(type_, ootype.StaticMethod):
                     continue
                 elif type_ is ootype.Class:
-                    continue
+                    value = getattr(self.obj, name)
+                    self.cts.lltype_to_cts(value._INSTANCE) # force scheduling class generation
+                    classname = value._INSTANCE._name
+                    ilasm.opcode('dup')
+                    ilasm.opcode('ldtoken', classname)
+                    ilasm.call('class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)')
+                    ilasm.opcode('stfld class [mscorlib]System.Type %s::%s' % (classdef._name, name))
             classdef = classdef._superclass
+

Modified: pypy/dist/pypy/translator/cli/ilgenerator.py
==============================================================================
--- pypy/dist/pypy/translator/cli/ilgenerator.py	(original)
+++ pypy/dist/pypy/translator/cli/ilgenerator.py	Mon Apr 10 01:14:05 2006
@@ -37,6 +37,7 @@
         self.out = outfile
         self.code = CodeGenerator(self.out)
         self.code.writeline('.assembly extern mscorlib {}')
+        self.code.writeline('.assembly extern pypy {}')
         self.code.writeline('.assembly %s {}' % name)
 
     def close(self):

Modified: pypy/dist/pypy/translator/cli/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/cli/opcodes.py	(original)
+++ pypy/dist/pypy/translator/cli/opcodes.py	Mon Apr 10 01:14:05 2006
@@ -11,10 +11,12 @@
 def _abs(type_):
     return [PushAllArgs, 'call %s class [mscorlib]System.Math::Abs(%s)' % (type_, type_)]
 
+_runtimenew = 'object [pypy]pypy.runtime.Utils::RuntimeNew([mscorlib]System.Type)'
 
 opcodes = {
     # __________ object oriented operations __________
     'new':                      [New],
+    'runtimenew':               [PushAllArgs, 'call ' + _runtimenew],
     'oosetfield':               [SetField],
     'oogetfield':               [GetField],
     'oosend':                   [CallMethod],

Modified: pypy/dist/pypy/translator/cli/rte.py
==============================================================================
--- pypy/dist/pypy/translator/cli/rte.py	(original)
+++ pypy/dist/pypy/translator/cli/rte.py	Mon Apr 10 01:14:05 2006
@@ -6,6 +6,7 @@
 import os
 import os.path
 import subprocess
+import py
 
 SRC = 'pypy.cs'
 DLL = 'pypy.dll'
@@ -33,10 +34,18 @@
     return dll
     
 def compile(source):
-    compiler = subprocess.Popen(['mcs', '/t:library', source],
+    mcs = _get_compiler()
+    compiler = subprocess.Popen([mcs, '/t:library', source],
                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     stdout, stderr = compiler.communicate()
     retval = compiler.wait()
 
     assert retval == 0, 'Failed to compile %s: the compiler said:\n %s' % (DLL, stderr)
 
+def _get_compiler():
+    try:
+        py.path.local.sysfind('mcs') # TODO: support windows
+        return 'mcs'
+    except py.error.ENOENT:
+        py.test.skip("%s is not on your path." % helper)
+

Modified: pypy/dist/pypy/translator/cli/src/pypy.cs
==============================================================================
--- pypy/dist/pypy/translator/cli/src/pypy.cs	(original)
+++ pypy/dist/pypy/translator/cli/src/pypy.cs	Mon Apr 10 01:14:05 2006
@@ -1,8 +1,12 @@
 using System;
 
-namespace PyPy
+namespace pypy.runtime
 {
-    public class Foo
+    public class Utils
     {
+        public static object RuntimeNew(Type t)
+        {
+            return t.GetConstructor(new Type[0]).Invoke(new object[0]);
+        }
     }
 }

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	Mon Apr 10 01:14:05 2006
@@ -39,8 +39,7 @@
 
 def bar(x, y):
     b = Derived(x)
-    return b.compute()
-#    return foo(Base, x) + foo(Derived, y)
+    return foo(Base, x) + foo(Derived, y)
 
 f = compile_function(bar, [int, int])
 

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	Mon Apr 10 01:14:05 2006
@@ -1,6 +1,7 @@
 import os
 import subprocess
 import platform
+import shutil
 
 import py
 from pypy.tool.udir import udir
@@ -11,6 +12,7 @@
 from pypy.translator.cli.node import Node
 from pypy.translator.cli.cts import CTS
 from pypy.translator.cli.database import LowLevelDatabase
+from pypy.translator.cli.rte import get_pypy_dll
 
 FLOAT_PRECISION = 8
 
@@ -103,11 +105,11 @@
            t.viewcg()
 
         if getoption('wd'):
-            tmpdir = py.path.local('.')
+            self.tmpdir = py.path.local('.')
         else:
-            tmpdir = udir
+            self.tmpdir = udir
 
-        return GenCli(tmpdir, t, TestEntryPoint(self.graph))
+        return GenCli(self.tmpdir, t, TestEntryPoint(self.graph))
 
     def __check_helper(self, helper):
         try:
@@ -127,6 +129,9 @@
         if getoption('source'):
             return None
 
+        pypy_dll = get_pypy_dll() # get or recompile pypy.dll
+        shutil.copy(pypy_dll, self.tmpdir.strpath)
+
         self.__check_helper("ilasm")
         ilasm = subprocess.Popen(["ilasm", tmpfile], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         stdout, stderr = ilasm.communicate()

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	Mon Apr 10 01:14:05 2006
@@ -36,11 +36,19 @@
     INCREMENT = 2
 
     def __init__(self, x, y):
-        MyClass.__init__(self, x, y)
+        MyClass.__init__(self, x+12, y+34)
 
     def compute(self):
         return self.x - self.y
 
+# helper functions
+def call_method(obj):
+    return obj.compute()
+
+def init_and_compute(cls, x, y):
+    return cls(x, y).compute()
+
+# test functions
 def oo_compute(x, y):
     obj = MyClass(x, y)
     return obj.compute()
@@ -53,13 +61,10 @@
     obj = MyDerivedClass(x, y)
     return obj.compute_and_multiply(2)
 
-def helper(obj):
-    return obj.compute()
-
 def oo_liskov(x, y):
     base = MyClass(x, y)
     derived = MyDerivedClass(x, y)
-    return helper(base) + helper(derived)
+    return call_method(base) + call_method(derived)
 
 def oo_static_method(x, y):
     base = MyClass(x, y)
@@ -72,6 +77,9 @@
     derived = MyDerivedClass(x, y)
     return base.class_attribute() + derived.class_attribute()
 
+def oo_runtimenew(x, y):
+    return init_and_compute(MyClass, x, y) + init_and_compute(MyDerivedClass, x, y)
+
 ##def oo_class_meth(x, y):
 ##    return MyClass.class_meth(x, y) + MyDerivedClass.class_meth(x, y)
 



More information about the Pypy-commit mailing list