[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