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

antocuni at codespeak.net antocuni at codespeak.net
Thu Oct 19 00:21:44 CEST 2006


Author: antocuni
Date: Thu Oct 19 00:21:43 2006
New Revision: 33434

Modified:
   pypy/dist/pypy/translator/cli/database.py
   pypy/dist/pypy/translator/cli/dotnet.py
   pypy/dist/pypy/translator/cli/metavm.py
   pypy/dist/pypy/translator/cli/support.py
   pypy/dist/pypy/translator/cli/test/runtest.py
   pypy/dist/pypy/translator/cli/test/test_builtin.py
   pypy/dist/pypy/translator/cli/test/test_dotnet.py
   pypy/dist/pypy/translator/cli/test/test_runtest.py
   pypy/dist/pypy/translator/driver.py
Log:
Second attempt to ".NET-types". The implementation is quite simple
because it reuses most of the logic from ootype.



Modified: pypy/dist/pypy/translator/cli/database.py
==============================================================================
--- pypy/dist/pypy/translator/cli/database.py	(original)
+++ pypy/dist/pypy/translator/cli/database.py	Thu Oct 19 00:21:43 2006
@@ -14,6 +14,7 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.lltypesystem import llmemory
 from pypy.translator.cli.opcodes import opcodes
+from pypy.translator.cli import dotnet
 from pypy.rpython.objectmodel import CDefinedIntSymbolic
 
 try:
@@ -102,16 +103,21 @@
             return self.classes[INSTANCE]
         except KeyError:
             pass
-        namespace, name = self._default_class_name(INSTANCE)
-        name = self.get_unique_class_name(namespace, name)
-        if namespace is None:
-            full_name = name
+        
+        if isinstance(INSTANCE, dotnet.NativeInstance):
+            self.classes[INSTANCE] = INSTANCE._name
+            return INSTANCE._name
         else:
-            full_name = '%s.%s' % (namespace, name)
-        self.classes[INSTANCE] = full_name
-        cls = Class(self, INSTANCE, namespace, name)
-        self.pending_node(cls)
-        return full_name
+            namespace, name = self._default_class_name(INSTANCE)
+            name = self.get_unique_class_name(namespace, name)
+            if namespace is None:
+                full_name = name
+            else:
+                full_name = '%s.%s' % (namespace, name)
+            self.classes[INSTANCE] = full_name
+            cls = Class(self, INSTANCE, namespace, name)
+            self.pending_node(cls)
+            return full_name
 
     def pending_record(self, RECORD):
         try:

Modified: pypy/dist/pypy/translator/cli/dotnet.py
==============================================================================
--- pypy/dist/pypy/translator/cli/dotnet.py	(original)
+++ pypy/dist/pypy/translator/cli/dotnet.py	Thu Oct 19 00:21:43 2006
@@ -3,32 +3,42 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.rmodel import Repr
 
+## Annotation model
+
 class SomeCliClass(annmodel.SomeObject):
     def getattr(self, s_attr):
         assert self.is_constant()
         assert s_attr.is_constant()
         return SomeCliStaticMethod(self.const, s_attr.const)
 
+    def simple_call(self, *s_args):
+        assert self.is_constant()
+        return annmodel.SomeOOInstance(self.const._INSTANCE)
+
     def rtyper_makerepr(self, rtyper):
         return CliClassRepr(self.const)
 
     def rtyper_makekey(self):
         return self.__class__, self.const
 
+
 class SomeCliStaticMethod(annmodel.SomeObject):
     def __init__(self, cli_class, meth_name):
         self.cli_class = cli_class
         self.meth_name = meth_name
 
-    def simple_call(self, *args_s):
-        return self.cli_class.annotate_method(self.meth_name, args_s)
-
     def rtyper_makerepr(self, rtyper):
         return CliStaticMethodRepr(self.cli_class, self.meth_name)
 
     def rtyper_makekey(self):
         return self.__class__, self.cli_class, self.meth_name
 
+    def simple_call(self, *args_s):
+        return self.cli_class._ann_static_method(self.meth_name, args_s)
+
+
+
+## Rtyper model
 
 class CliClassRepr(Repr):
     lowleveltype = ootype.Void
@@ -39,14 +49,12 @@
     def rtype_getattr(self, hop):
         return hop.inputconst(ootype.Void, self.cli_class)
 
-class StaticMethodDesc(object):
-    def __init__(self, class_name, method_name, argtypes, resulttype):
-        # TODO: maybe use ootype.StaticMeth for describing signature?
-        self.class_name = class_name
-        self.method_name = method_name
-        self.argtypes = argtypes
-        self.resulttype = resulttype
-
+    def rtype_simple_call(self, hop):
+        # TODO: resolve constructor overloading
+        INSTANCE = hop.args_r[0].cli_class._INSTANCE
+        cINST = hop.inputconst(ootype.Void, INSTANCE)
+        vlist = hop.inputargs(*hop.args_r)[1:] # discard the first argument
+        return hop.genop("new", [cINST]+vlist, resulttype=hop.r_result.lowleveltype)
 
 class CliStaticMethodRepr(Repr):
     lowleveltype = ootype.Void
@@ -57,7 +65,7 @@
 
     def _build_desc(self, args_v, resulttype):
         argtypes = [v.concretetype for v in args_v]
-        return StaticMethodDesc(self.cli_class.name, self.meth_name, argtypes, resulttype)
+        return StaticMethodDesc(self.cli_class._INSTANCE._name, self.meth_name, argtypes, resulttype)
 
     def rtype_simple_call(self, hop):
         vlist = []
@@ -69,26 +77,39 @@
         return hop.genop("direct_call", [v_desc] + vlist, resulttype=resulttype)
 
 
+
+## RPython interface definition
+
+class StaticMethodDesc(object):
+    def __init__(self, class_name, method_name, argtypes, resulttype):
+        # TODO: maybe use ootype.StaticMeth for describing signature?
+        self.class_name = class_name
+        self.method_name = method_name
+        self.argtypes = argtypes
+        self.resulttype = resulttype
+
+
 class CliClass(object):
-    def __init__(self, name, methods):
-        self.name = name
-        self.methods = methods
+    def __init__(self, INSTANCE, static_methods):
+        self._INSTANCE = INSTANCE
+        self._static_methods = static_methods
 
-    def annotate_method(self, meth_name, args_s):
-        argtypes, rettype = self._lookup(meth_name, args_s)
-        return annmodel.lltype_to_annotation(rettype)
+    def __repr__(self):
+        return '<%s>' % (self,)
+
+    def __str__(self):
+        return '%s(%s)' % (self.__class__.__name__, self._INSTANCE._name)
 
     def _lookup(self, meth_name, args_s):
         # TODO: handle conversion
-        overloads = self.methods[meth_name]
-        argtypes = tuple([_annotation_to_lltype(arg_s) for arg_s in args_s])
+        overloads = self._static_methods[meth_name]
+        argtypes = tuple([annmodel.annotation_to_lltype(arg_s) for arg_s in args_s])
         return argtypes, overloads[argtypes]
 
-def _annotation_to_lltype(arg_s):
-    if isinstance(arg_s, annmodel.SomeString):
-        return ootype.String
-    else:
-        return annmodel.annotation_to_lltype(arg_s)
+    def _ann_static_method(self, meth_name, args_s):
+        argtypes, rettype = self._lookup(meth_name, args_s)
+        return annmodel.lltype_to_annotation(rettype)
+
 
 class Entry(ExtRegistryEntry):
     _type_ = CliClass
@@ -96,11 +117,27 @@
     def compute_annotation(self):
         return SomeCliClass()
 
-Console = CliClass('System.Console',
-                   {'WriteLine': {(ootype.String,): ootype.Void,
-                                  (ootype.Signed,): ootype.Void,
-                                  (ootype.String, ootype.Signed): ootype.Void }
-                    })
-Math = CliClass('System.Math',
-                {'Abs': {(ootype.Signed,): ootype.Signed}
-                 })
+
+## OOType model
+
+class NativeInstance(ootype.Instance):
+    def __init__(self, assembly, namespace, name, superclass,
+                 fields={}, methods={}, _is_root=False, _hints = {}):
+        fullname = '%s%s.%s' % (assembly, namespace, name)
+        ootype.Instance.__init__(self, fullname, superclass, fields, methods, _is_root, _hints)
+
+STRING_BUILDER = NativeInstance('[mscorlib]', 'System.Text', 'StringBuilder', ootype.ROOT, {}, {})
+STRING_BUILDER._add_methods({'Append': ootype.meth(ootype.Meth([ootype.String], STRING_BUILDER))})
+StringBuilder = CliClass(STRING_BUILDER, {})
+
+CONSOLE = NativeInstance('[mscorlib]', 'System', 'Console', ootype.ROOT, {}, {})
+Console = CliClass(CONSOLE, {'WriteLine': {(ootype.String,): ootype.Void,
+                                          (ootype.Signed,): ootype.Void}})
+MATH = NativeInstance('[mscorlib]', 'System', 'Math', ootype.ROOT, {}, {})
+Math = CliClass(MATH, {'Abs': {(ootype.Signed,): ootype.Signed,
+                               (ootype.Float,): ootype.Float}})
+
+ARRAY_LIST = NativeInstance('[mscorlib]', 'System.Collections', 'ArrayList', ootype.ROOT, {},
+                            {'Add': ootype.meth(ootype.Meth([ootype.ROOT], ootype.Signed)),
+                             'get_Count': ootype.meth(ootype.Meth([], ootype.Signed))})
+ArrayList = CliClass(ARRAY_LIST, {})

Modified: pypy/dist/pypy/translator/cli/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/cli/metavm.py	(original)
+++ pypy/dist/pypy/translator/cli/metavm.py	Thu Oct 19 00:21:43 2006
@@ -28,7 +28,7 @@
         ret_type = cts.lltype_to_cts(funcdesc.resulttype)
         arg_types = [cts.lltype_to_cts(arg) for arg in funcdesc.argtypes if arg is not ootype.Void]
         arg_list = ', '.join(arg_types)
-        signature = '%s [mscorlib]%s::%s(%s)' % (ret_type, funcdesc.class_name, funcdesc.method_name, arg_list)
+        signature = '%s %s::%s(%s)' % (ret_type, funcdesc.class_name, funcdesc.method_name, arg_list)
         generator.call_signature(signature)
 
     def _render_function(self, generator, graph, args):

Modified: pypy/dist/pypy/translator/cli/support.py
==============================================================================
--- pypy/dist/pypy/translator/cli/support.py	(original)
+++ pypy/dist/pypy/translator/cli/support.py	Thu Oct 19 00:21:43 2006
@@ -1,3 +1,5 @@
+from pypy.rpython.ootypesystem import ootype
+
 # some code has been stolen from genc
 def string_literal(s):
     def char_repr(c):
@@ -58,7 +60,7 @@
     O_BINARY = 0x8000
     )
 
-def patch_os(defs=None):
+def _patch_os(defs=None):
     """
     Modify the value of some attributes of the os module to be sure
     they are the same on every platform pypy is compiled on. Returns a
@@ -77,3 +79,24 @@
             pass
         setattr(os, name, value)
     return olddefs
+
+def _patch_ROOT():
+    """
+    In gencli ootype.ROOT corresponds to System.Object: make the
+    annotator aware of its native methods such as ToString().
+    """
+    oldmeths = ootype.ROOT._methods.copy()
+    ootype.ROOT._add_methods({'ToString': ootype.meth(ootype.Meth([], ootype.String))})
+    return oldmeths
+
+def _unpatch_ROOT(oldmeths):
+    ootype.ROOT._methods = oldmeths
+
+def patch():
+    olddefs = _patch_os()
+    oldmeths = _patch_ROOT()
+    return olddefs, oldmeths
+
+def unpatch(olddefs, oldmeths):
+    _patch_os(olddefs)
+    _unpatch_ROOT(oldmeths)

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	Thu Oct 19 00:21:43 2006
@@ -18,7 +18,7 @@
 from pypy.translator.cli.database import LowLevelDatabase
 from pypy.translator.cli.sdk import SDK
 from pypy.translator.cli.entrypoint import BaseEntryPoint
-from pypy.translator.cli.support import patch_os
+from pypy.translator.cli.support import patch, unpatch
 
 FLOAT_PRECISION = 8
 
@@ -113,11 +113,11 @@
 
 
 def compile_function(func, annotation=[], graph=None):
-    olddefs = patch_os() # patch the values of some attributes of the os module
+    olddefs = patch()
     gen = _build_gen(func, annotation, graph)
     gen.generate_source()
     exe_name = gen.build_exe()
-    patch_os(olddefs) # restore original values
+    unpatch(*olddefs) # restore original values
     return CliFunctionWrapper(exe_name)
 
 def _build_gen(func, annotation, graph=None):
@@ -136,6 +136,9 @@
         ann = t.buildannotator()
         ann.build_types(func, annotation)
 
+    if getoption('view'):
+       t.view()
+
     t.buildrtyper(type_system="ootype").specialize()
     main_graph = t.graphs[0]
 

Modified: pypy/dist/pypy/translator/cli/test/test_builtin.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_builtin.py	(original)
+++ pypy/dist/pypy/translator/cli/test/test_builtin.py	Thu Oct 19 00:21:43 2006
@@ -17,14 +17,6 @@
     test_os_path_exists = skip_os
     test_os_isdir = skip_os
 
-    def test_patch_os(self):
-        from pypy.translator.cli.support import patch_os, NT_OS
-        original_O_CREAT = os.O_CREAT
-        olddefs = patch_os()
-        assert os.O_CREAT == NT_OS['O_CREAT']
-        patch_os(olddefs)
-        assert os.O_CREAT == original_O_CREAT
-
     def test_os_flags(self):
         from pypy.translator.cli.support import NT_OS
         def fn():

Modified: pypy/dist/pypy/translator/cli/test/test_dotnet.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_dotnet.py	(original)
+++ pypy/dist/pypy/translator/cli/test/test_dotnet.py	Thu Oct 19 00:21:43 2006
@@ -1,9 +1,61 @@
+from pypy.annotation.annrpython import RPythonAnnotator
+from pypy.annotation import model as annmodel
 from pypy.translator.cli.test.runtest import CliTest
-from pypy.translator.cli.dotnet import Math
+from pypy.translator.cli.dotnet import SomeCliClass, SomeCliStaticMethod,\
+     NativeInstance, Math, ArrayList, StringBuilder
 
 class TestDotnet(CliTest):
 
-    def test_abs(self):
+    def test_class_ann(self):
+        def fn():
+            return Math
+        a = RPythonAnnotator()
+        s = a.build_types(fn, [])
+        assert isinstance(s, SomeCliClass)
+        assert s.const is Math
+
+    def test_staticmeth_ann(self):
+        def fn():
+            return Math.Abs
+        a = RPythonAnnotator()
+        s = a.build_types(fn, [])
+        assert isinstance(s, SomeCliStaticMethod)
+        assert s.cli_class is Math
+        assert s.meth_name == 'Abs'
+
+    def test_new_instance_ann(self):
+        def fn():
+            return ArrayList()
+        a = RPythonAnnotator()
+        s = a.build_types(fn, [])
+        assert isinstance(s, annmodel.SomeOOInstance)
+        assert isinstance(s.ootype, NativeInstance)
+        assert s.ootype._name == '[mscorlib]System.Collections.ArrayList'
+
+    def test_static_method_call(self):
         def fn(x):
             return Math.Abs(x)
         assert self.interpret(fn, [-42]) == 42
+
+    def test_static_method_overload(self):
+        def fn(x, y):
+            return Math.Abs(x), Math.Abs(y)
+        res = self.interpret(fn, [-42, -42.5])
+        assert res.item0 == 42
+        assert res.item1 == 42.5
+
+    def test_method_call(self):
+        def fn():
+            x = ArrayList()
+            x.Add("foo")
+            x.Add("bar")
+            return x.get_Count()
+        assert self.interpret(fn, []) == 2
+
+    def test_tostring(self):
+        def fn():
+            x = StringBuilder()
+            x.Append("foo").Append("bar")
+            return x.ToString()
+        res = self.ll_to_string(self.interpret(fn, []))
+        assert res == 'foobar'

Modified: pypy/dist/pypy/translator/cli/test/test_runtest.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_runtest.py	(original)
+++ pypy/dist/pypy/translator/cli/test/test_runtest.py	Thu Oct 19 00:21:43 2006
@@ -7,6 +7,23 @@
 
 class TestRunTest(CliTest):
 
+    def test_patch_os(self):
+        import os
+        from pypy.translator.cli.support import patch, unpatch, NT_OS
+        original_O_CREAT = os.O_CREAT
+        olddefs = patch()
+        assert os.O_CREAT == NT_OS['O_CREAT']
+        unpatch(*olddefs)
+        assert os.O_CREAT == original_O_CREAT
+
+    def test_patch_ROOT(self):
+        from pypy.translator.cli.support import patch, unpatch
+        from pypy.rpython.ootypesystem import ootype
+        olddefs = patch()
+        assert 'ToString' in ootype.ROOT._methods
+        unpatch(*olddefs)
+        assert 'ToString' not in ootype.ROOT._methods
+
     def test_int(self):
         assert self.interpret(ident, [42]) == 42
     

Modified: pypy/dist/pypy/translator/driver.py
==============================================================================
--- pypy/dist/pypy/translator/driver.py	(original)
+++ pypy/dist/pypy/translator/driver.py	Thu Oct 19 00:21:43 2006
@@ -508,12 +508,12 @@
                              'Generating CLI source')
 
     def task_compile_cli(self):
-        from pypy.translator.cli.support import patch_os
+        from pypy.translator.cli.support import unpatch
         from pypy.translator.cli.test.runtest import CliFunctionWrapper
         filename = self.gen.build_exe()
         self.c_entryp = CliFunctionWrapper(filename)
         # restore original os values
-        patch_os(self.old_os_defs)
+        unpatch(*self.old_cli_defs)
         
         self.log.info("Compiled %s" % filename)
     task_compile_cli = taskdef(task_compile_cli, ['source_cli'],
@@ -550,8 +550,8 @@
         # have the same value on every platform.
         backend, ts = driver.get_backend_and_type_system()
         if backend == 'cli':
-            from pypy.translator.cli.support import patch_os
-            driver.old_os_defs = patch_os()
+            from pypy.translator.cli.support import patch
+            driver.old_cli_defs = patch()
         
         target = targetspec_dic['target']
         spec = target(driver, args)


More information about the pypy-svn mailing list