diff qt/d1/qt/Signal.d @ 282:256ab6cb8e85

Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
author eldar
date Fri, 16 Oct 2009 02:43:59 +0000
parents 519befd5a5d1
children 1f6923c8cba0
line wrap: on
line diff
--- a/qt/d1/qt/Signal.d	Sun Oct 11 05:23:41 2009 +0000
+++ b/qt/d1/qt/Signal.d	Fri Oct 16 02:43:59 2009 +0000
@@ -858,25 +858,6 @@
     }
 }
 
-template CheckSlot(Slot, A...)
-{
-    static assert(ParameterTupleOf!(Slot).length <= A.length, "Slot " ~ ParameterTypeTuple!(Slot).stringof ~
-        " has more prameters than signal " ~ A.stringof);
-    alias CheckSlotImpl!(Slot, 0, A) check;
-}
-
-template CheckSlotImpl(Slot, int i, A...)
-{
-    alias ParameterTupleOf!(Slot) SlotArgs;
-    static if (i < SlotArgs.length)
-    {
-        static assert (is(SlotArgs[i] : A[i]), "Argument " ~ __toString(i) ~
-            ":" ~ A[i].stringof ~ " of signal " ~ A.stringof ~ " is not implicitly convertible to parameter "
-            ~ SlotArgs[i].stringof ~ " of slot " ~ SlotArgs.stringof);
-        alias CheckSlotImpl!(Slot, i + 1, A) next;
-    }
-}
-
 public template SignalHandlerOps()
 {
     static assert (is(typeof(this.signalHandler)),
@@ -910,56 +891,83 @@
         signalHandler.unblockSignals();
     }
     
-    void connect(string signalName, T, R, B...)(T sender, R function(B) dg, ConnectionFlags flags = ConnectionFlags.None)
+    template connect(string signalName, A...)
     {
-        alias findSymbol!(SignalQualifier, T, signalName) sig;
-        alias CheckSlot!(typeof(fn), sig[2].at) check;
-        auto sh = sender.signalHandler();
-        auto invoker = Dg(&sh.invokeSlot!(typeof(fn), Fn, sig[2].at));
-        sh.connect(sig[1], Fn(fn), invoker, flags);
-    }
-
-    void connect(string signalName, T, R, B...)(T sender, R delegate(B) dg, ConnectionFlags flags = ConnectionFlags.None)
-    {
-        alias findSymbol!(SignalQualifier, T, signalName) sig;
-        alias CheckSlot!(typeof(dg), sig[2].at) check;
-        auto sh = sender.signalHandler();
-        auto invoker = Dg(&sh.invokeSlot!(typeof(dg), Dg, sig[2].at));
-        sh.connect(sig[1], Dg(dg), invoker, flags);
+        static void connect(T, Func)(T sender, Func func, ConnectionFlags flags = ConnectionFlags.None)
+        {
+            static if (isFnOrDg!(Func)) // D1 has no constraints
+        {
+            alias findSignal!(T, signalName, Func, A).result sig;
+            auto sh = sender.signalHandler();
+            static if (isFn!(Func))
+                alias Fn Callable;
+            else
+                alias Dg Callable;
+            auto invoker = Dg(&sh.invokeSlot!(typeof(func), Callable, sig[2..$]));
+            sh.connect(sig[1], Callable(func), invoker, flags);
+        }
+        else
+        {
+            static assert(false, "The slot must be a function or delegate type.");
+        }
+        }
     }
 
-    void disconnect(string signalName, T, R, B...)(T sender, R function(B) fn)
-    {
-        alias findSymbol!(SignalQualifier, T, signalName) sig;
-        auto sh = sender.signalHandler();
-        sh.disconnect(sig[1], Fn(fn));
-    }
-
-    void disconnect(string signalName, T, R, B...)(T sender, R delegate(B) dg)
+    template disconnect(string signalName, A...)
     {
-        alias findSymbol!(SignalQualifier, T, signalName) sig;
-        auto sh = sender.signalHandler();
-        sh.disconnect(sig[1], Dg(dg));
+        static void connect(T, Func)(T sender, Func func, ConnectionFlags flags = ConnectionFlags.None)
+        {
+            static if (isFnOrDg!(Func)) // D1 has no constraints
+        {
+            alias findSignal!(T, signalName, Func, A).result sig;
+            auto sh = sender.signalHandler();
+            static if (isFn!(Func))
+                alias Fn Callable;
+            else
+                alias Dg Callable;
+            sh.disconnect(sig[1], Callable(func));
+        }
+        else
+        {
+            static assert(false, "The slot must be a function or delegate type.");
+        }
+        }
     }
-
-    debug size_t slotCount(string signalName, T)(T sender)
+/*
+    template slotCount(string signalName, A...)
     {
-        alias findSymbol!(SignalQualifier, T, signalName) sig;
-        auto sh = sender.signalHandler();
-        return sh.slotCount(sig[1]);
+        debug static void slotCount(T)(T sender)
+        {
+            alias findSignal!(T, signalName, Func, A).result sig;
+            auto sh = sender.signalHandler();
+            return sh.slotCount(sig[1]);
+        }
     }
+    */
 }
 
 /**
     New implementation.
 */
 
-public bool startsWith(T)(T[] source, T[] pattern)
+const string signalPrefix = "__signal";
+
+template TupleWrapper(A...) { alias A at; }
+
+template isDg(Dg)
 {
-    return source.length >= pattern.length && source[0 .. pattern.length] == pattern[];
+    enum { isDg = is(Dg == delegate) }
 }
 
-template TupleWrapper(A...) { alias A at; }
+template isFn(Fn)
+{
+    enum { isFn = is(typeof(*Fn.init) == function) }
+}
+
+template isFnOrDg(Dg)
+{
+    enum { isFnOrDg = isFn!(Dg) || isDg!(Dg) }
+}
 
 string joinArgs(A...)()
 {
@@ -973,20 +981,72 @@
     return res;
 }
 
-struct SignalQualifier
+template SlotPred(T1, T2)
+{
+    enum { SlotPred = is(T1 : T2) }
+}
+
+template CheckSlot(alias Needle, alias Source)
+{
+    static if(Needle.at.length <= Source.at.length)
+        enum { CheckSlot = CheckArgs!(Needle, Source, SlotPred, 0).value }
+    else
+        enum { CheckSlot = false }
+}
+
+template SignalPred(T1, T2)
 {
-    const string staticSymbolPrefix = "__signal";
-    const string name = "signal";
-    
-    static bool matches(alias source, string sigName)()
+    enum { SignalPred = is(T1 == T2) }
+}
+
+template CheckSignal(alias Needle, alias Source)
+{
+    static if(Needle.at.length == Source.at.length)
+        enum { CheckSignal = CheckArgs!(Needle, Source, SignalPred, 0).value }
+    else
+        enum { CheckSignal = false }
+}
+
+template CheckArgs(alias Needle, alias Source, alias pred, int i)
+{
+    static if (i < Needle.at.length)
     {
-        return startsWith(source.at[0], sigName);
+        static if (pred!(Needle.at[i], Source.at[i]))
+            enum { value = CheckArgs!(Needle, Source, pred, i + 1).value }
+        else
+            enum { value = false }
+    }
+    else
+    {
+        enum { value = true }
     }
 }
 
-template staticSymbolName(Qualifier, int id)
+template SigByNamePred(string name, SlotArgs...)
+{
+    template SigByNamePred(source...)
+    {
+        static if (source[0] == name) // only instantiate CheckSlot if names match
+            enum { SigByNamePred = CheckSlot!(TupleWrapper!(SlotArgs), TupleWrapper!(source[2 .. $])) }
+        else
+            enum { SigByNamePred = false }
+    }
+}
+
+template SigBySignPred(string name, SigArgs...)
 {
-    const string staticSymbolName = Qualifier.staticSymbolPrefix ~ ToString!(id);
+    template SigBySignPred(source...)
+    {
+        static if (source[0] == name) // only instantiate CheckSignal if names match
+            enum { SigBySignPred = CheckSignal!(TupleWrapper!(SigArgs), TupleWrapper!(source[2 .. $])) }
+        else
+            enum { SigBySignPred = false }
+    }
+}
+
+template staticSymbolName(string prefix, int id)
+{
+    const string staticSymbolName = prefix ~ ToString!(id);
 }
 
 template signatureString(string name, A...)
@@ -994,26 +1054,45 @@
     const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")";
 }
 
-template findSymbolImpl(Qualifier, C, int id, string key)
+template findSymbolImpl(string prefix, C, int id, alias pred)
 {
-    static if ( is(typeof(mixin("C." ~ staticSymbolName!(Qualifier, id)))) )
+    static if ( is(typeof(mixin("C." ~ staticSymbolName!(prefix, id)))) )
     {
-        mixin ("alias C." ~ staticSymbolName!(Qualifier, id) ~ " current;");
-        static if ( Qualifier.matches!(TupleWrapper!(current), key)() ) {
+        mixin ("alias C." ~ staticSymbolName!(prefix, id) ~ " current;");
+        static if (pred!(current))
             alias current result;
-        }
         else
-            alias findSymbolImpl!(Qualifier, C, id + 1, key).result result;
+            alias findSymbolImpl!(prefix, C, id + 1, pred).result result;
     }
     else
     {
-        static assert(0, Qualifier.name ~ " " ~ key ~ " not found.");
+        alias void result;
     }
 }
 
-template findSymbol(Qualifier, C, string key)
+template findSymbol(string prefix, C, alias pred)
+{
+    alias findSymbolImpl!(prefix, C, 0, pred).result findSymbol;
+}
+
+template findSignal(C, string name, Receiver, SigArgs...)
 {
-    alias findSymbolImpl!(Qualifier, C, 0, key).result findSymbol;
+    alias TupleWrapper!(ParameterTupleOf!(Receiver)) SlotArgsWr;
+    static if (SigArgs.length > 0)
+    {
+        alias findSymbol!(signalPrefix, C, SigBySignPred!(name, SigArgs)) result;
+        static if (is(result == void))
+            static assert(0, "Signal " ~ name ~ "(" ~ joinArgs!(SigArgs)() ~ ") was not found.");
+        else
+            static if (!CheckSlot!(SlotArgsWr, TupleWrapper!(result[2 .. $])))
+                static assert(0, "Signature of slot is incompatible with signal " ~ name ~ ".");
+    }
+    else
+    {
+        alias findSymbol!(signalPrefix, C, SigByNamePred!(name, SlotArgsWr.at)) result;
+        static if (is(result == void))
+            static assert(0, "Signal " ~ name ~ " was not found.");
+    }
 }
 
 
@@ -1056,7 +1135,7 @@
 
 template SignalImpl(int index, string name, A...)
 {
-    static if (is(typeof(mixin(typeof(this).stringof ~ ".__sig" ~ ToString!(index)))))
+    static if (is(typeof(mixin(typeof(this).stringof ~ ".__signal" ~ ToString!(index)))))
         mixin SignalImpl!(index + 1, name, A);
     else
     {
@@ -1065,8 +1144,7 @@
         {
             mixin SignalHandlerOps;
         }
-        mixin("private static const int __sig" ~ ToString!(index) ~ " = " ~ ToString!(index) ~ ";");
-//        mixin("public alias Tuple!(\"" ~ signatureString!(name, A) ~ "\", index, TupleWrapper!(A)) __signal" ~ ToString!(index) ~ ";");
+        mixin("public alias Tuple!(\"" ~ name ~ "\", index, A) __signal" ~ ToString!(index) ~ ";");
         mixin("SignalOps!(" ~ ToString!(index) ~ ", A) " ~ name ~ "(){ return SignalOps!("
             ~ ToString!(index) ~ ", A)(signalHandler); }");
     }