[svn] r6199: nemerle/trunk/ncc: external/LibrariesLoader.n
hierarchy/ExtensionMethod.n testsuite/negative/...
malekith
svnadmin at nemerle.org
Wed Apr 26 18:09:11 CEST 2006
Log:
Allow extension methods to be defined on generic types.
Author: malekith
Date: Wed Apr 26 18:09:09 2006
New Revision: 6199
Modified:
nemerle/trunk/ncc/external/LibrariesLoader.n
nemerle/trunk/ncc/hierarchy/ExtensionMethod.n
nemerle/trunk/ncc/testsuite/negative/extension-methods.n
nemerle/trunk/ncc/testsuite/positive/extension-methods-lib.n
nemerle/trunk/ncc/testsuite/positive/extension-methods.n
nemerle/trunk/ncc/typing/TypedTree.n
nemerle/trunk/ncc/typing/Typer2.n
Modified: nemerle/trunk/ncc/external/LibrariesLoader.n
==============================================================================
--- nemerle/trunk/ncc/external/LibrariesLoader.n (original)
+++ nemerle/trunk/ncc/external/LibrariesLoader.n Wed Apr 26 18:09:09 2006
@@ -1284,7 +1284,7 @@
foreach (m is IMethod in GetMembers ())
when (m.IsStatic && m.GetHandle ().IsDefined (t, false))
match (m.GetParameters ().Head.ty.Fix ()) {
- | Class (tc, []) =>
+ | Class (tc, _) =>
tc.AddExtensionMethod (m);
| _ => Util.ice ()
}
Modified: nemerle/trunk/ncc/hierarchy/ExtensionMethod.n
==============================================================================
--- nemerle/trunk/ncc/hierarchy/ExtensionMethod.n (original)
+++ nemerle/trunk/ncc/hierarchy/ExtensionMethod.n Wed Apr 26 18:09:09 2006
@@ -26,13 +26,16 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+using Nemerle.Collections;
using Nemerle.Compiler;
+using Nemerle.Compiler.SolverMacros;
using Nemerle.Compiler.Typedtree;
namespace Nemerle.Compiler
{
class ExtensionMethod : BuiltinMethod
{
+
internal this (parent : TypeInfo,
impl : IMethod)
{
@@ -41,9 +44,42 @@
def h = impl.GetHeader ();
assert (h != null);
assert (h.parms != null);
- assert (h.typarms is []);
- assert (h.tenv == null || h.tenv.IsEmpty);
- header = Fun_header (h.loc, h.name, h.ret_type, h.parms.Tail, [], h.tenv);
+ when (impl.DeclaringType.TyparmsCount != 0)
+ Message.Error ("cannot define extension methods in generic types");
+ match (h.parms) {
+ | first_parm :: rest_of_parms =>
+ match (first_parm.ty.Fix ()) {
+ | MType.Class (tc, tcparms) =>
+ assert (parent.Equals (tc));
+ if (tcparms.Length > h.typarms.Length ||
+ List.Exists2 (tcparms, h.typarms.FirstN (tcparms.Length),
+ fun (x, y) { ! x.Equals (MType.TyVarRef (y)) })) {
+ Message.Error ("type parameters of first parameter of extension "
+ "methods should be prefix of type parameters of the "
+ "method itself");
+ Message.HintOnce ("for example: public static foo[A,B,C,D] "
+ "(this a : Qux[A,B], b : list [C * D]) : int");
+ } else {
+ def our_typarms = h.typarms.ChopFirstN (tcparms.Length);
+ def tosubst = h.typarms.FirstN (tcparms.Length);
+ def forward_sub = Subst ();
+ List.Iter2 (tosubst, parent.Typarms, fun (meth, typ) {
+ forward_sub.Add (meth, MType.TyVarRef (typ));
+ });
+ def parms = rest_of_parms.Map (fun (tp) {
+ def tp = tp.Clone ();
+ tp.ty = forward_sub.Apply (tp.ty.Fix ());
+ tp
+ });
+ // tenv is not important I guess
+ header = Fun_header (h.loc, h.name,
+ forward_sub.Apply (h.ret_type.Fix ()),
+ parms, our_typarms, h.tenv);
+ }
+ | _ => Util.ice ()
+ }
+ | [] => Util.ice ()
+ }
}
public override Attributes : NemerleAttributes {
@@ -56,6 +92,5 @@
{
get { false }
}
-
}
}
Modified: nemerle/trunk/ncc/testsuite/negative/extension-methods.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/negative/extension-methods.n (original)
+++ nemerle/trunk/ncc/testsuite/negative/extension-methods.n Wed Apr 26 18:09:09 2006
@@ -15,3 +15,10 @@
public foo (p : int, this a : A) : void // E: 'this' modifier \(for extension method\) can only be used on the first parameter
Write ($"foo($(a.v),$p)\n")
+class D[X]
+ public static foo (this a : A, p : int) : void // E: cannot define extension methods in generic types
+ ()
+
+class D2
+ public static foo[A,B] (this a : D[B]) : void // E: type parameters.*extension method
+ ()
Modified: nemerle/trunk/ncc/testsuite/positive/extension-methods-lib.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/positive/extension-methods-lib.n (original)
+++ nemerle/trunk/ncc/testsuite/positive/extension-methods-lib.n Wed Apr 26 18:09:09 2006
@@ -17,6 +17,13 @@
public static foo (this a : A, p : int) : void
Write ($"foo($(a.v),$p)\n")
+ public static bar[A,B] (this a : G[A,B]) : void
+ a.Describe ()
+
+ public static bar[A,B,C] (this a : G[A,B], _c : C) : void
+ a.Describe ()
+ System.Console.WriteLine ($"$(typeof(C))")
+
public static Run () : void
def a = A (42)
a.foo ()
@@ -26,3 +33,12 @@
def c = C(77, "aa")
c.foo (3)
B.foo (c, 4)
+
+ def g = G.[int,string]()
+ g.Describe ()
+ g.bar ()
+ g.bar (7.0)
+
+public class G[X, Y]
+ public Describe () : void
+ System.Console.WriteLine ($"$(typeof(X)) $(typeof(Y))")
Modified: nemerle/trunk/ncc/testsuite/positive/extension-methods.n
==============================================================================
--- nemerle/trunk/ncc/testsuite/positive/extension-methods.n (original)
+++ nemerle/trunk/ncc/testsuite/positive/extension-methods.n Wed Apr 26 18:09:09 2006
@@ -8,6 +8,11 @@
a.foo (1)
B.foo (a, 2)
+def g = G.[int,string]()
+g.Describe ()
+g.bar ()
+g.bar (7.0)
+
/*
BEGIN-OUTPUT
foo()
@@ -15,8 +20,16 @@
foo(42,2)
foo(77,3)
foo(77,4)
+System.Int32 System.String
+System.Int32 System.String
+System.Int32 System.String
+System.Double
foo()
foo(42,1)
foo(42,2)
+System.Int32 System.String
+System.Int32 System.String
+System.Int32 System.String
+System.Double
END-OUTPUT
*/
Modified: nemerle/trunk/ncc/typing/TypedTree.n
==============================================================================
--- nemerle/trunk/ncc/typing/TypedTree.n (original)
+++ nemerle/trunk/ncc/typing/TypedTree.n Wed Apr 26 18:09:09 2006
@@ -79,6 +79,11 @@
this.kind = kind;
}
+ public Clone () : Fun_parm
+ {
+ MemberwiseClone () :> Fun_parm
+ }
+
public SystemType : System.Type
{
get {
Modified: nemerle/trunk/ncc/typing/Typer2.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer2.n (original)
+++ nemerle/trunk/ncc/typing/Typer2.n Wed Apr 26 18:09:09 2006
@@ -978,13 +978,18 @@
ivtc.ty = expr.ty;
ivtc
- | TExpr.MethodRef (obj, IMethod where (BuiltinKind = ExtensionMethod (impl)), type_parms, _) as func =>
+ | TExpr.MethodRef (obj, IMethod where (BuiltinKind = ExtensionMethod (impl)) as im, type_parms, _) as func =>
//Message.Debug ($"expand to $impl");
def from = impl.DeclaringType.GetMemType ();
def fnt = {
def (parms, ret) = func.MType.FunReturnTypeAndParms ().Value;
MType.ConstructFunctionType (obj.Type :: parms, ret)
}
+ def type_parms =
+ (match (obj.Type.Fix ().GetInstantiatedSuperType (im.DeclaringType)) {
+ | MType.Class (_, parms) => parms
+ | _ => Util.ice ()
+ }) + type_parms;
def fn = TExpr.StaticRef (fnt, from, impl, type_parms);
Walk (Context.IsCalledValue,
TExpr.Call (expr.Type, fn, Parm (obj) :: parms, false))
More information about the svn
mailing list