comparison 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
comparison
equal deleted inserted replaced
281:7f2e3ffa1c33 282:256ab6cb8e85
856 { 856 {
857 return sh.slotCount(signalId); 857 return sh.slotCount(signalId);
858 } 858 }
859 } 859 }
860 860
861 template CheckSlot(Slot, A...)
862 {
863 static assert(ParameterTupleOf!(Slot).length <= A.length, "Slot " ~ ParameterTypeTuple!(Slot).stringof ~
864 " has more prameters than signal " ~ A.stringof);
865 alias CheckSlotImpl!(Slot, 0, A) check;
866 }
867
868 template CheckSlotImpl(Slot, int i, A...)
869 {
870 alias ParameterTupleOf!(Slot) SlotArgs;
871 static if (i < SlotArgs.length)
872 {
873 static assert (is(SlotArgs[i] : A[i]), "Argument " ~ __toString(i) ~
874 ":" ~ A[i].stringof ~ " of signal " ~ A.stringof ~ " is not implicitly convertible to parameter "
875 ~ SlotArgs[i].stringof ~ " of slot " ~ SlotArgs.stringof);
876 alias CheckSlotImpl!(Slot, i + 1, A) next;
877 }
878 }
879
880 public template SignalHandlerOps() 861 public template SignalHandlerOps()
881 { 862 {
882 static assert (is(typeof(this.signalHandler)), 863 static assert (is(typeof(this.signalHandler)),
883 "SignalHandlerOps is already instantiated in " ~ typeof(this).stringof ~ " or one of its base classes"); 864 "SignalHandlerOps is already instantiated in " ~ typeof(this).stringof ~ " or one of its base classes");
884 865
908 final void unblockSignals() 889 final void unblockSignals()
909 { 890 {
910 signalHandler.unblockSignals(); 891 signalHandler.unblockSignals();
911 } 892 }
912 893
913 void connect(string signalName, T, R, B...)(T sender, R function(B) dg, ConnectionFlags flags = ConnectionFlags.None) 894 template connect(string signalName, A...)
914 { 895 {
915 alias findSymbol!(SignalQualifier, T, signalName) sig; 896 static void connect(T, Func)(T sender, Func func, ConnectionFlags flags = ConnectionFlags.None)
916 alias CheckSlot!(typeof(fn), sig[2].at) check; 897 {
917 auto sh = sender.signalHandler(); 898 static if (isFnOrDg!(Func)) // D1 has no constraints
918 auto invoker = Dg(&sh.invokeSlot!(typeof(fn), Fn, sig[2].at)); 899 {
919 sh.connect(sig[1], Fn(fn), invoker, flags); 900 alias findSignal!(T, signalName, Func, A).result sig;
920 } 901 auto sh = sender.signalHandler();
921 902 static if (isFn!(Func))
922 void connect(string signalName, T, R, B...)(T sender, R delegate(B) dg, ConnectionFlags flags = ConnectionFlags.None) 903 alias Fn Callable;
923 { 904 else
924 alias findSymbol!(SignalQualifier, T, signalName) sig; 905 alias Dg Callable;
925 alias CheckSlot!(typeof(dg), sig[2].at) check; 906 auto invoker = Dg(&sh.invokeSlot!(typeof(func), Callable, sig[2..$]));
926 auto sh = sender.signalHandler(); 907 sh.connect(sig[1], Callable(func), invoker, flags);
927 auto invoker = Dg(&sh.invokeSlot!(typeof(dg), Dg, sig[2].at)); 908 }
928 sh.connect(sig[1], Dg(dg), invoker, flags); 909 else
929 } 910 {
930 911 static assert(false, "The slot must be a function or delegate type.");
931 void disconnect(string signalName, T, R, B...)(T sender, R function(B) fn) 912 }
932 { 913 }
933 alias findSymbol!(SignalQualifier, T, signalName) sig; 914 }
934 auto sh = sender.signalHandler(); 915
935 sh.disconnect(sig[1], Fn(fn)); 916 template disconnect(string signalName, A...)
936 } 917 {
937 918 static void connect(T, Func)(T sender, Func func, ConnectionFlags flags = ConnectionFlags.None)
938 void disconnect(string signalName, T, R, B...)(T sender, R delegate(B) dg) 919 {
939 { 920 static if (isFnOrDg!(Func)) // D1 has no constraints
940 alias findSymbol!(SignalQualifier, T, signalName) sig; 921 {
941 auto sh = sender.signalHandler(); 922 alias findSignal!(T, signalName, Func, A).result sig;
942 sh.disconnect(sig[1], Dg(dg)); 923 auto sh = sender.signalHandler();
943 } 924 static if (isFn!(Func))
944 925 alias Fn Callable;
945 debug size_t slotCount(string signalName, T)(T sender) 926 else
946 { 927 alias Dg Callable;
947 alias findSymbol!(SignalQualifier, T, signalName) sig; 928 sh.disconnect(sig[1], Callable(func));
948 auto sh = sender.signalHandler(); 929 }
949 return sh.slotCount(sig[1]); 930 else
950 } 931 {
932 static assert(false, "The slot must be a function or delegate type.");
933 }
934 }
935 }
936 /*
937 template slotCount(string signalName, A...)
938 {
939 debug static void slotCount(T)(T sender)
940 {
941 alias findSignal!(T, signalName, Func, A).result sig;
942 auto sh = sender.signalHandler();
943 return sh.slotCount(sig[1]);
944 }
945 }
946 */
951 } 947 }
952 948
953 /** 949 /**
954 New implementation. 950 New implementation.
955 */ 951 */
956 952
957 public bool startsWith(T)(T[] source, T[] pattern) 953 const string signalPrefix = "__signal";
958 {
959 return source.length >= pattern.length && source[0 .. pattern.length] == pattern[];
960 }
961 954
962 template TupleWrapper(A...) { alias A at; } 955 template TupleWrapper(A...) { alias A at; }
956
957 template isDg(Dg)
958 {
959 enum { isDg = is(Dg == delegate) }
960 }
961
962 template isFn(Fn)
963 {
964 enum { isFn = is(typeof(*Fn.init) == function) }
965 }
966
967 template isFnOrDg(Dg)
968 {
969 enum { isFnOrDg = isFn!(Dg) || isDg!(Dg) }
970 }
963 971
964 string joinArgs(A...)() 972 string joinArgs(A...)()
965 { 973 {
966 string res = ""; 974 string res = "";
967 static if(A.length) 975 static if(A.length)
971 res ~= "," ~ k.stringof; 979 res ~= "," ~ k.stringof;
972 } 980 }
973 return res; 981 return res;
974 } 982 }
975 983
976 struct SignalQualifier 984 template SlotPred(T1, T2)
977 { 985 {
978 const string staticSymbolPrefix = "__signal"; 986 enum { SlotPred = is(T1 : T2) }
979 const string name = "signal"; 987 }
980 988
981 static bool matches(alias source, string sigName)() 989 template CheckSlot(alias Needle, alias Source)
982 { 990 {
983 return startsWith(source.at[0], sigName); 991 static if(Needle.at.length <= Source.at.length)
984 } 992 enum { CheckSlot = CheckArgs!(Needle, Source, SlotPred, 0).value }
985 } 993 else
986 994 enum { CheckSlot = false }
987 template staticSymbolName(Qualifier, int id) 995 }
988 { 996
989 const string staticSymbolName = Qualifier.staticSymbolPrefix ~ ToString!(id); 997 template SignalPred(T1, T2)
998 {
999 enum { SignalPred = is(T1 == T2) }
1000 }
1001
1002 template CheckSignal(alias Needle, alias Source)
1003 {
1004 static if(Needle.at.length == Source.at.length)
1005 enum { CheckSignal = CheckArgs!(Needle, Source, SignalPred, 0).value }
1006 else
1007 enum { CheckSignal = false }
1008 }
1009
1010 template CheckArgs(alias Needle, alias Source, alias pred, int i)
1011 {
1012 static if (i < Needle.at.length)
1013 {
1014 static if (pred!(Needle.at[i], Source.at[i]))
1015 enum { value = CheckArgs!(Needle, Source, pred, i + 1).value }
1016 else
1017 enum { value = false }
1018 }
1019 else
1020 {
1021 enum { value = true }
1022 }
1023 }
1024
1025 template SigByNamePred(string name, SlotArgs...)
1026 {
1027 template SigByNamePred(source...)
1028 {
1029 static if (source[0] == name) // only instantiate CheckSlot if names match
1030 enum { SigByNamePred = CheckSlot!(TupleWrapper!(SlotArgs), TupleWrapper!(source[2 .. $])) }
1031 else
1032 enum { SigByNamePred = false }
1033 }
1034 }
1035
1036 template SigBySignPred(string name, SigArgs...)
1037 {
1038 template SigBySignPred(source...)
1039 {
1040 static if (source[0] == name) // only instantiate CheckSignal if names match
1041 enum { SigBySignPred = CheckSignal!(TupleWrapper!(SigArgs), TupleWrapper!(source[2 .. $])) }
1042 else
1043 enum { SigBySignPred = false }
1044 }
1045 }
1046
1047 template staticSymbolName(string prefix, int id)
1048 {
1049 const string staticSymbolName = prefix ~ ToString!(id);
990 } 1050 }
991 1051
992 template signatureString(string name, A...) 1052 template signatureString(string name, A...)
993 { 1053 {
994 const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")"; 1054 const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")";
995 } 1055 }
996 1056
997 template findSymbolImpl(Qualifier, C, int id, string key) 1057 template findSymbolImpl(string prefix, C, int id, alias pred)
998 { 1058 {
999 static if ( is(typeof(mixin("C." ~ staticSymbolName!(Qualifier, id)))) ) 1059 static if ( is(typeof(mixin("C." ~ staticSymbolName!(prefix, id)))) )
1000 { 1060 {
1001 mixin ("alias C." ~ staticSymbolName!(Qualifier, id) ~ " current;"); 1061 mixin ("alias C." ~ staticSymbolName!(prefix, id) ~ " current;");
1002 static if ( Qualifier.matches!(TupleWrapper!(current), key)() ) { 1062 static if (pred!(current))
1003 alias current result; 1063 alias current result;
1004 }
1005 else 1064 else
1006 alias findSymbolImpl!(Qualifier, C, id + 1, key).result result; 1065 alias findSymbolImpl!(prefix, C, id + 1, pred).result result;
1007 } 1066 }
1008 else 1067 else
1009 { 1068 {
1010 static assert(0, Qualifier.name ~ " " ~ key ~ " not found."); 1069 alias void result;
1011 } 1070 }
1012 } 1071 }
1013 1072
1014 template findSymbol(Qualifier, C, string key) 1073 template findSymbol(string prefix, C, alias pred)
1015 { 1074 {
1016 alias findSymbolImpl!(Qualifier, C, 0, key).result findSymbol; 1075 alias findSymbolImpl!(prefix, C, 0, pred).result findSymbol;
1076 }
1077
1078 template findSignal(C, string name, Receiver, SigArgs...)
1079 {
1080 alias TupleWrapper!(ParameterTupleOf!(Receiver)) SlotArgsWr;
1081 static if (SigArgs.length > 0)
1082 {
1083 alias findSymbol!(signalPrefix, C, SigBySignPred!(name, SigArgs)) result;
1084 static if (is(result == void))
1085 static assert(0, "Signal " ~ name ~ "(" ~ joinArgs!(SigArgs)() ~ ") was not found.");
1086 else
1087 static if (!CheckSlot!(SlotArgsWr, TupleWrapper!(result[2 .. $])))
1088 static assert(0, "Signature of slot is incompatible with signal " ~ name ~ ".");
1089 }
1090 else
1091 {
1092 alias findSymbol!(signalPrefix, C, SigByNamePred!(name, SlotArgsWr.at)) result;
1093 static if (is(result == void))
1094 static assert(0, "Signal " ~ name ~ " was not found.");
1095 }
1017 } 1096 }
1018 1097
1019 1098
1020 /** 1099 /**
1021 Examples: 1100 Examples:
1054 mixin SignalImpl!(0, name, A); 1133 mixin SignalImpl!(0, name, A);
1055 } 1134 }
1056 1135
1057 template SignalImpl(int index, string name, A...) 1136 template SignalImpl(int index, string name, A...)
1058 { 1137 {
1059 static if (is(typeof(mixin(typeof(this).stringof ~ ".__sig" ~ ToString!(index))))) 1138 static if (is(typeof(mixin(typeof(this).stringof ~ ".__signal" ~ ToString!(index)))))
1060 mixin SignalImpl!(index + 1, name, A); 1139 mixin SignalImpl!(index + 1, name, A);
1061 else 1140 else
1062 { 1141 {
1063 // mixed-in once 1142 // mixed-in once
1064 static if (!is(typeof(this.signalHandler))) 1143 static if (!is(typeof(this.signalHandler)))
1065 { 1144 {
1066 mixin SignalHandlerOps; 1145 mixin SignalHandlerOps;
1067 } 1146 }
1068 mixin("private static const int __sig" ~ ToString!(index) ~ " = " ~ ToString!(index) ~ ";"); 1147 mixin("public alias Tuple!(\"" ~ name ~ "\", index, A) __signal" ~ ToString!(index) ~ ";");
1069 // mixin("public alias Tuple!(\"" ~ signatureString!(name, A) ~ "\", index, TupleWrapper!(A)) __signal" ~ ToString!(index) ~ ";");
1070 mixin("SignalOps!(" ~ ToString!(index) ~ ", A) " ~ name ~ "(){ return SignalOps!(" 1148 mixin("SignalOps!(" ~ ToString!(index) ~ ", A) " ~ name ~ "(){ return SignalOps!("
1071 ~ ToString!(index) ~ ", A)(signalHandler); }"); 1149 ~ ToString!(index) ~ ", A)(signalHandler); }");
1072 } 1150 }
1073 } 1151 }
1074 1152