[svn] r7035: nemerle/trunk/ncc: generation/ILEmitter.n testsuite/positive/function-from-tuple.n

malekith svnadmin at nemerle.org
Sat Dec 2 21:29:37 CET 2006


Log:
Use Reflection-independant method of checking if function-tuple conversion is needed. Make it work in additional few cases. Resolves #799.

Author: malekith
Date: Sat Dec  2 21:29:36 2006
New Revision: 7035

Modified:
   nemerle/trunk/ncc/generation/ILEmitter.n
   nemerle/trunk/ncc/testsuite/positive/function-from-tuple.n

Modified: nemerle/trunk/ncc/generation/ILEmitter.n
==============================================================================
--- nemerle/trunk/ncc/generation/ILEmitter.n	(original)
+++ nemerle/trunk/ncc/generation/ILEmitter.n	Sat Dec  2 21:29:36 2006
@@ -459,27 +459,51 @@
       t.MakeByRefType ()
     }
 
-    private emit_tuple_function_conversion (real_type : MType, system_type : System.Type) : void
+    private emit_tuple_function_conversion (after : MType, member_from : MType, member : IMember) : void
     {
-      match (real_type) {
+      def interesting_part (t) {
+        if (member is IMethod)
+          match (t.Fix ()) {
+            | MType.Fun (_, t) => t
+            | _ => Util.ice ()
+          }
+        else t
+      }
+
+      def is_single_arg_function (t) {
+        match (interesting_part (t).Fix ()) {
+          | Fun (from, _) => ! (from.Fix () is MType.Tuple)
+          | _ => false
+        }
+      }
+
+      match (after) {
         | Fun (from, to) =>
           match (from.Fix ()) {
             | Tuple (parms) =>
-              def st = system_type.GetGenericTypeDefinition ();
-              def ft1 = InternalType.GetFunctionType (1);
+
+              // I think there is one more case
+              // class A[T] { x : T; }
+              // B[T] : A[T->void]
+              // C[T] : B[T*T]
+              // but this is really perverse
+
+              when (is_single_arg_function (member.GetMemType ()) ||
+                    is_single_arg_function (member_from.TypeOfMember (member))) {
+
               def ftn = InternalType.GetFunctionType (parms.Length);
               def info =
-                if (st.Equals (ft1.TyCon.SystemType)) {
-                  def mt = MType.Class (ftn.FromTupleTyCon, parms + [to]);
-                  GetConstructorInfo (mt.SystemType, ftn.FromTupleCtor)
-                } else if (st.Equals (ft1.VoidTyCon.SystemType)) {
+                  if (to.Fix () is MType.Void) {
                   def mt = MType.Class (ftn.FromTupleVoidTyCon, parms);
                   GetConstructorInfo (mt.SystemType, ftn.FromTupleVoidCtor)
-                } else null;
-              when (info != null) {
+                  } else {
+                    def mt = MType.Class (ftn.FromTupleTyCon, parms + [to]);
+                    GetConstructorInfo (mt.SystemType, ftn.FromTupleCtor)
+                  }
                 // Message.Warning ($ "using f1->fN conversion");
                 _ilg.Emit (OpCodes.Newobj, info)
               }
+
             | _ => {}
           }
         | _ => {}
@@ -860,7 +884,7 @@
           else
             _ilg.Emit (OpCodes.Ldfld, field_inf);
 
-          emit_tuple_function_conversion (expr.MType, field_inf.FieldType);
+          emit_tuple_function_conversion (expr.MType, base_object.MType, field);
 
         /* load the value of a static field */
         | StaticRef (t, f is IField, _) =>
@@ -878,7 +902,7 @@
           else
             _ilg.Emit (OpCodes.Ldsfld, field_info);
 
-          emit_tuple_function_conversion (expr.MType, field_info.FieldType);
+          emit_tuple_function_conversion (expr.MType, t, f);
 
         /* load an array element */
         | ArrayIndexer (array_obj, [index]) =>
@@ -1045,7 +1069,7 @@
           }
           emit_parms (method_params);
           Mark (expr.loc);
-          emit_method_call (expr, true, method_inf)
+          emit_method_call (expr, true, method_inf, method, th.MType)
 
 
         /* emit a call to an instance method */
@@ -1064,11 +1088,11 @@
               _ilg.Emit (OpCodes.Tailcall);
             }
             _ilg.Emit (OpCodes.Constrained, base_object.SystemType);
-            emit_method_call (expr, false, method_inf); // constrained always need callvirt
+            emit_method_call (expr, false, method_inf, method, base_object.MType); // constrained always need callvirt
             when (is_tail)
               _ilg.Emit (OpCodes.Ret);
           } else
-            emit_method_call (expr, is_value_type || notvirt, method_inf)
+            emit_method_call (expr, is_value_type || notvirt, method_inf, method, base_object.MType)
 
 
         /* emit a call to a static method */
@@ -1080,7 +1104,7 @@
 
           emit_parms (method_parms);
           Mark (expr.loc);          
-          emit_method_call (expr, true, method_info)
+          emit_method_call (expr, true, method_info, mi, _t)
 
 
         /* emit an operator */
@@ -1799,7 +1823,9 @@
      */
     private emit_method_call (expr : TExpr,
                               base_is_value_type_or_static : bool,
-                              method : MethodInfo) : void
+                              method : MethodInfo,
+                              imethod : IMethod = null,
+                              from : MType = null) : void
     {
       // Message.Debug ($"emc: $(method.Name)");
       when (expr.GenerateTail)
@@ -1810,7 +1836,9 @@
       else
         _ilg.Emit (OpCodes.Callvirt, method);
 
-      emit_tuple_function_conversion (expr.MType, method.ReturnType);
+      
+      when (imethod != null)
+        emit_tuple_function_conversion (expr.MType, from, imethod);
 
       when (expr.GenerateTail)
         _ilg.Emit (OpCodes.Ret);

Modified: nemerle/trunk/ncc/testsuite/positive/function-from-tuple.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/positive/function-from-tuple.n	(original)
+++ nemerle/trunk/ncc/testsuite/positive/function-from-tuple.n	Sat Dec  2 21:29:36 2006
@@ -1,3 +1,23 @@
+// more perverse examples
+abstract class C1[T] {
+  public abstract getT () : T
+}
+class C2[X] : C1[X -> void] {
+  public override getT () : X -> void
+  {
+    x => System.Console.WriteLine (x)
+  }
+}
+
+class D1[T] {
+  public getT () : T -> void
+  {
+    x => System.Console.WriteLine (x)
+  }
+}
+class D2[X] : D1[X * X] { }
+// end of perverse examples
+
 class A[T] {
     public CreateFunction() : T->void {
         fun (a) { System.Console.WriteLine (a) }
@@ -37,9 +57,14 @@
 
       System.Console.WriteLine(ack(3,12));
 
+C2().getT()(4,2);
+D2().getT()(4,2);
+
 /*
 BEGIN-OUTPUT
 (1, 2)
 32765
+(4, 2)
+(4, 2)
 END-OUTPUT
 */



More information about the svn mailing list