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

antocuni at codespeak.net antocuni at codespeak.net
Wed Jan 23 15:08:06 CET 2008


Author: antocuni
Date: Wed Jan 23 15:08:05 2008
New Revision: 50916

Modified:
   pypy/dist/pypy/translator/cli/cts.py
   pypy/dist/pypy/translator/cli/dotnet.py
   pypy/dist/pypy/translator/cli/ilgenerator.py
   pypy/dist/pypy/translator/cli/metavm.py
   pypy/dist/pypy/translator/cli/opcodes.py
   pypy/dist/pypy/translator/cli/query.py
   pypy/dist/pypy/translator/cli/src/query.cs
   pypy/dist/pypy/translator/cli/test/test_dotnet.py
   pypy/dist/pypy/translator/cli/test/test_query.py
Log:
- add support for reading static fields of .NET classes

- add support to value types



Modified: pypy/dist/pypy/translator/cli/cts.py
==============================================================================
--- pypy/dist/pypy/translator/cli/cts.py	(original)
+++ pypy/dist/pypy/translator/cli/cts.py	Wed Jan 23 15:08:05 2008
@@ -41,13 +41,14 @@
 
 
 class CliReferenceType(CliType):
+    prefix = 'class '
+    
     def typename(self):
-        return 'class ' + self.classname()
+        return self.prefix + self.classname()
 
     def classname(self):
         raise NotImplementedError
 
-
 class CliClassType(CliReferenceType):
     def __init__(self, assembly, name):
         self.assembly = assembly
@@ -59,6 +60,9 @@
         else:
             return self.name
 
+class CliValueType(CliClassType):
+    prefix = 'valuetype '
+
 
 class CliGenericType(CliReferenceType):
     def __init__(self, assembly, name, numparam):
@@ -229,12 +233,16 @@
         elif isinstance(t, lltype.Ptr) and isinstance(t.TO, lltype.OpaqueType):
             return types.object
         elif isinstance(t, ootype.Instance):
+            if getattr(t, '_is_value_type', False):
+                cls = CliValueType
+            else:
+                cls = CliClassType
             NATIVE_INSTANCE = t._hints.get('NATIVE_INSTANCE', None)
             if NATIVE_INSTANCE:
-                return CliClassType(None, NATIVE_INSTANCE._name)
+                return cls(None, NATIVE_INSTANCE._name)
             else:
                 name = self.db.pending_class(t)
-                return CliClassType(None, name)
+                return cls(None, name)
         elif isinstance(t, ootype.Record):
             name = self.db.pending_record(t)
             return CliClassType(None, name)

Modified: pypy/dist/pypy/translator/cli/dotnet.py
==============================================================================
--- pypy/dist/pypy/translator/cli/dotnet.py	(original)
+++ pypy/dist/pypy/translator/cli/dotnet.py	Wed Jan 23 15:08:05 2008
@@ -21,7 +21,15 @@
     def getattr(self, s_attr):
         assert self.is_constant()
         assert s_attr.is_constant()
-        return SomeCliStaticMethod(self.const, s_attr.const)
+        cliclass = self.const
+        attrname = s_attr.const
+        if attrname in cliclass._static_fields:
+            TYPE = cliclass._static_fields[attrname]
+            return OverloadingResolver.lltype_to_annotation(TYPE)
+        elif attrname in cliclass._static_methods:
+            return SomeCliStaticMethod(cliclass, attrname)
+        else:
+            return s_ImpossibleValue
 
     def simple_call(self, *s_args):
         assert self.is_constant()
@@ -75,7 +83,15 @@
         self.cli_class = cli_class
 
     def rtype_getattr(self, hop):
-        return hop.inputconst(ootype.Void, self.cli_class)
+        attrname = hop.args_v[1].value
+        if attrname in self.cli_class._static_methods:
+            return hop.inputconst(ootype.Void, self.cli_class)
+        else:
+            assert attrname in self.cli_class._static_fields
+            TYPE = self.cli_class._static_fields[attrname]
+            c_class = hop.inputarg(hop.args_r[0], arg=0)
+            c_name = hop.inputconst(ootype.Void, hop.args_v[1].value)
+            return hop.genop("cli_getstaticfield", [c_class, c_name], resulttype=hop.r_result.lowleveltype)
 
     def rtype_simple_call(self, hop):
         # TODO: resolve constructor overloading
@@ -199,16 +215,18 @@
         fullname = '%s%s.%s' % (assembly, namespace, name)
         self._namespace = namespace
         self._classname = name
+        self._is_value_type = False
         ootype.Instance.__init__(self, fullname, superclass, fields, methods, _is_root, _hints)
 
 
 ## RPython interface definition
 
 class CliClass(object):
-    def __init__(self, INSTANCE, static_methods):
+    def __init__(self, INSTANCE, static_methods, static_fields):
         self._name = INSTANCE._name
         self._INSTANCE = INSTANCE
         self._static_methods = {}
+        self._static_fields = {}
         self._add_methods(static_methods)
 
     def __repr__(self):
@@ -222,6 +240,9 @@
         for name, meth in methods.iteritems():
             meth._set_attrs(self, name)
 
+    def _add_static_fields(self, fields):
+        self._static_fields.update(fields)
+
     def _lookup(self, meth_name, ARGS):
         meth = self._static_methods[meth_name]
         return meth._get_desc(ARGS)
@@ -239,7 +260,7 @@
         self._PythonNet_class = obj
 
     def __getattr__(self, attr):
-        if attr in self._static_methods:
+        if attr in self._static_methods or attr in self._static_fields:
             self._load_class()
             return getattr(self._PythonNet_class, attr)
         else:

Modified: pypy/dist/pypy/translator/cli/ilgenerator.py
==============================================================================
--- pypy/dist/pypy/translator/cli/ilgenerator.py	(original)
+++ pypy/dist/pypy/translator/cli/ilgenerator.py	Wed Jan 23 15:08:05 2008
@@ -203,17 +203,21 @@
     def load_self(self):
         self.opcode('ldarg.0')
     
-    def load_arg(self,v):
+    def load_arg(self, v):
         self.opcode('ldarg', repr(v.name))
     
-    def load_local(self,v):
-        self.opcode('ldloc', repr(v.name))
+    def load_local(self, v):
+        TYPE = v.concretetype
+        if getattr(TYPE, '_is_value_type', False):
+            self.opcode('ldloca', repr(v.name))
+        else:
+            self.opcode('ldloc', repr(v.name))
 
     def switch(self, targets):
         cmd = 'switch(%s)' % ', '.join(targets)
         self.opcode(cmd)
 
-    def load_const(self,type_,v):
+    def load_const(self,type_, v):
         if type_ is Void:
             pass
         elif type_ is Bool:

Modified: pypy/dist/pypy/translator/cli/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/cli/metavm.py	(original)
+++ pypy/dist/pypy/translator/cli/metavm.py	Wed Jan 23 15:08:05 2008
@@ -215,6 +215,14 @@
         generator.ilasm.opcode('ldftn instance', desc)
         generator.ilasm.opcode('newobj', 'instance void class [mscorlib]System.EventHandler::.ctor(object, native int)')
 
+class _GetStaticField(MicroInstruction):
+    def render(self, generator, op):
+        cli_class = op.args[0].value
+        fldname = op.args[1].value
+        TYPE = op.result.concretetype
+        cts_type = generator.cts.lltype_to_cts(TYPE)
+        desc = '%s::%s' % (cli_class._name, fldname)
+        generator.ilasm.load_static_field(cts_type, desc)
 
 
 OOTYPE_TO_MNEMONIC = {
@@ -243,4 +251,5 @@
 SetArrayElem = _SetArrayElem()
 TypeOf = _TypeOf()
 EventHandler = _EventHandler()
+GetStaticField = _GetStaticField()
 CastPrimitive = _CastPrimitive()

Modified: pypy/dist/pypy/translator/cli/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/cli/opcodes.py	(original)
+++ pypy/dist/pypy/translator/cli/opcodes.py	Wed Jan 23 15:08:05 2008
@@ -1,7 +1,7 @@
 from pypy.translator.cli.metavm import  Call, CallMethod, \
      IndirectCall, GetField, SetField, DownCast, NewCustomDict,\
      MapException, Box, Unbox, NewArray, GetArrayElem, SetArrayElem,\
-     TypeOf, CastPrimitive, EventHandler
+     TypeOf, CastPrimitive, EventHandler, GetStaticField
 from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult, InstructionList,\
     New, RuntimeNew, CastTo, PushPrimitive, OOString, OOUnicode
 from pypy.translator.cli.cts import WEAKREF
@@ -44,6 +44,7 @@
     'cli_typeof':               [TypeOf],
     'cli_arraylength':          'ldlen',
     'cli_eventhandler':         [EventHandler],
+    'cli_getstaticfield':       [GetStaticField],
     'oois':                     'ceq',
     'oononnull':                [PushAllArgs, 'ldnull', 'ceq']+Not,
     'instanceof':               [CastTo, 'ldnull', 'cgt.un'],

Modified: pypy/dist/pypy/translator/cli/query.py
==============================================================================
--- pypy/dist/pypy/translator/cli/query.py	(original)
+++ pypy/dist/pypy/translator/cli/query.py	Wed Jan 23 15:08:05 2008
@@ -86,8 +86,6 @@
         desc.BaseType = 'System.Object'
         desc.IsArray = True
         desc.ElementType = 'System.Object' # not really true, but we need something
-        desc.StaticMethods = []
-        desc.Methods = []
     elif name.endswith('[]'): # it's an array
         itemname = name[:-2]
         itemdesc = get_class_desc(itemname)
@@ -97,7 +95,6 @@
         desc.BaseType = 'System.Array'
         desc.ElementType = itemdesc.FullName
         desc.IsArray = True
-        desc.StaticMethods = []
         desc.Methods = [
             ('Get', ['ootype.Signed', ], itemdesc.FullName),
             ('Set', ['ootype.Signed', itemdesc.FullName], 'ootype.Void')
@@ -110,6 +107,13 @@
 
 
 class ClassDesc(object):
+
+    # default values
+    StaticFields = []
+    StaticMethods = []
+    Methods = []
+    IsValueType = False
+
     _cliclass = None
 
     def __eq__(self, other):
@@ -131,7 +135,8 @@
         # construct OOTYPE and CliClass
         # no superclass for now, will add it later
         TYPE = NativeInstance('[mscorlib]', namespace, name, None, {}, {})
-        Class = CliClass(TYPE, {})
+        TYPE._is_value_type = self.IsValueType
+        Class = CliClass(TYPE, {}, {})
         self._cliclass = Class
         # we need to check also for System.Array to prevent a circular recursion
         if self.FullName in ('System.Object', 'System.Array'):
@@ -144,11 +149,13 @@
         if self.IsArray:
             TYPE._ELEMENT = get_ootype(self.ElementType)
 
-        # add both static and instance methods
+        # add both static and instance methods, and static fields
         static_meths = self.group_methods(self.StaticMethods, _overloaded_static_meth,
                                           _static_meth, ootype.StaticMethod)
         meths = self.group_methods(self.Methods, ootype.overload, ootype.meth, ootype.Meth)
+        fields = dict([(name, get_ootype(t)) for name, t in self.StaticFields])
         Class._add_methods(static_meths)
+        Class._add_static_fields(fields)
         TYPE._add_methods(meths)
         return Class
 

Modified: pypy/dist/pypy/translator/cli/src/query.cs
==============================================================================
--- pypy/dist/pypy/translator/cli/src/query.cs	(original)
+++ pypy/dist/pypy/translator/cli/src/query.cs	Wed Jan 23 15:08:05 2008
@@ -60,8 +60,10 @@
         outfile.WriteLine("desc.FullName = '{0}'", t.FullName);
         outfile.WriteLine("desc.BaseType = '{0}'", GetBaseType(t));
         outfile.WriteLine("desc.IsArray = {0}", t.IsArray);
+        outfile.WriteLine("desc.IsValueType = {0}", t.IsValueType);
         PrintMethods("desc.StaticMethods", t.GetMethods(BindingFlags.Static|BindingFlags.Public|BindingFlags.DeclaredOnly));
         PrintMethods("desc.Methods", t.GetMethods(BindingFlags.Instance|BindingFlags.Public|BindingFlags.DeclaredOnly));
+        PrintFields("desc.StaticFields", t.GetFields(BindingFlags.Static|BindingFlags.Public|BindingFlags.DeclaredOnly));
     }
 
     private static string GetBaseType(Type t)
@@ -118,6 +120,15 @@
         outfile.WriteLine("  ]");
     }
 
+    private static void PrintFields(string varname, FieldInfo[] fields)
+    {
+        outfile.WriteLine("{0} = [", varname);
+        // FieldName, RESULT
+        foreach(FieldInfo fld in fields)
+            outfile.WriteLine("    ('{0}', '{1}'),", fld.Name, GetOOType(fld.FieldType));
+        outfile.WriteLine("  ]");
+    }
+
     private static bool IgnoreMethod(MethodInfo meth)
     {
         if (!meth.IsPublic)

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	Wed Jan 23 15:08:05 2008
@@ -432,6 +432,14 @@
         res = self.interpret(fn, [False])
         assert res == 42
 
+    def test_static_fields(self):
+        OpCodes = System.Reflection.Emit.OpCodes
+        def fn():
+            op = OpCodes.Add
+            return op.get_Name()
+        res = self.interpret(fn, [])
+        assert self.ll_to_string(res) == 'add'
+
 class TestPythonnet(TestDotnetRtyping):
     # don't interpreter functions but execute them directly through pythonnet
     def interpret(self, f, args, backendopt='ignored'):

Modified: pypy/dist/pypy/translator/cli/test/test_query.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_query.py	(original)
+++ pypy/dist/pypy/translator/cli/test/test_query.py	Wed Jan 23 15:08:05 2008
@@ -23,6 +23,10 @@
     assert System._name == 'System'
     assert hasattr(CLR, 'System')
 
+def test_static_fields():
+    desc = query.get_class_desc('System.Reflection.Emit.OpCodes')
+    assert ('Add', 'System.Reflection.Emit.OpCode') in desc.StaticFields
+
 def test_System_Object():
     Object = CLR.System.Object
     assert Object._name == '[mscorlib]System.Object'



More information about the Pypy-commit mailing list