[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