@@ -301,21 +301,25 @@ mixin(registerMethods);
301301
302302auto registerMethods (string moduleName = __MODULE__ )
303303{
304- return format ( " static import openmethods;"
305- ~ " mixin(openmethods._registerMethods!(%s)); "
306- ~ " mixin openmethods._registerSpecs !(%s); \n " ,
307- moduleName, moduleName);
304+ return ` static import openmethods;
305+ import std.traits : FunctionAttribute;
306+ mixin( openmethods._registerMethods !(%s));
307+ mixin openmethods._registerSpecs!(%s); ` .format( moduleName, moduleName);
308308}
309309
310310mixin template declareMethod(string index, ReturnType, string name, ParameterType... )
311311{
312- mixin (openmethods._declareMethod! (index, ReturnType, name, ParameterType));
312+ mixin (openmethods.Method! (index, ReturnType, name,
313+ FunctionAttribute.none, ParameterType)
314+ .code);
313315}
314316
315317mixin template declareMethod(ReturnType, string name, ParameterType... )
316318{
317- mixin openmethods.declareMethod! (openmethods.MptrInDeallocator, ReturnType, name,
318- ParameterType);
319+ import std.traits ;
320+ mixin (openmethods.Method! (openmethods.MptrInDeallocator, ReturnType, name,
321+ FunctionAttribute.none, ParameterType)
322+ .code);
319323}
320324
321325mixin template defineMethod(alias Dispatcher, alias Fun)
@@ -468,9 +472,9 @@ setMethodErrorHandler(void function(MethodError error) handler)
468472enum IsVirtual (T) = false ;
469473enum IsVirtual (T : virtual! U, U) = true ;
470474
471- private alias VirtualType (T : virtual! U, U) = U;
475+ alias VirtualType (T : virtual! U, U) = U;
472476
473- private template VirtualArity (QP ... )
477+ template VirtualArity (QP ... )
474478{
475479 static if (QP .length == 0 ) {
476480 enum VirtualArity = 0 ;
@@ -550,14 +554,22 @@ template castArgs(T...)
550554immutable MptrInDeallocator = " deallocator" ;
551555immutable MptrViaHash = " hash" ;
552556
553- struct Method (string Mptr, R, string id, T... )
557+ struct Method (string Mptr, R, string id, FunctionAttribute functionAttributes_, T... )
554558{
555559 alias QualParams = T;
556560 alias Params = CallParams! T;
557- alias R function (Params) Spec;
558561 alias ReturnType = R;
559562 alias Word = Runtime .Word;
560563 enum name = id;
564+ alias functionAttributes = functionAttributes_;
565+ alias This = Method! (Mptr, R, id, functionAttributes, T);
566+
567+
568+ static if (functionAttributes & FunctionAttribute.ref_) {
569+ alias ref R function (Params) Spec;
570+ } else {
571+ alias R function (Params) Spec;
572+ }
561573
562574 static __gshared Runtime .MethodInfo info;
563575
@@ -679,32 +691,81 @@ struct Method(string Mptr, R, string id, T...)
679691 }
680692 }
681693
682- static auto dispatcher (CallParams! T args)
683- {
684- debug (traceCalls) {
685- stderr.write(info.name);
686- }
694+ enum code = discriminatorCode ~ dispatcherCode;
687695
688- alias Word = Runtime .Word;
689- assert (info.slotStride);
696+ enum discriminatorCode = ` openmethods.%s %s(openmethods.MethodTag, %s);
697+ ` .format(This.stringof,
698+ name,
699+ Params.stringof[1 .. $- 1 ]
700+ );
690701
691- static if (VirtualArity! QualParams == 1 ) {
692- auto mptr = Indexer! (QualParams).unary(args);
693- debug (traceCalls) {
694- stderr.writef(" %s %s" , mptr, info.slotStride[0 ].i);
695- }
696- auto pf = cast (Spec) mptr[info.slotStride[0 ].i].p;
697- } else {
698- auto pf =
699- cast (Spec) Indexer! (QualParams).move(info.slotStride, args).p;
702+ enum refAttribute = functionAttributes & FunctionAttribute.ref_ ? " ref " : " " ;
703+
704+ enum string nonRefAttributes= ` %s%s%s%s%s%s`
705+ .format(
706+ functionAttributes & FunctionAttribute.pure_ ? " pure" : " " ,
707+ functionAttributes & FunctionAttribute.nothrow_ ? " nothrow" : " " ,
708+ functionAttributes & FunctionAttribute.trusted ? " @trusted" : " " ,
709+ functionAttributes & FunctionAttribute.safe ? " @safe" : " " ,
710+ functionAttributes & FunctionAttribute.nogc ? " @nogc" : " " ,
711+ functionAttributes & FunctionAttribute.system ? " @system" : " " );
712+
713+ static string dispatcherCode () {
714+ string params;
715+ string args;
716+ string sep = " " ;
717+
718+ foreach (i, p; Params) {
719+ args ~= ` %sarg%d` .format(sep, i);
720+ params ~= ` %s%s arg%d` .format(sep, p.stringof, i);
721+ sep = " , " ;
700722 }
701723
724+ return `
725+ %s%s %s(%s)%s%s%s%s%s%s
726+ {
727+ import std.traits, openmethods;
728+
729+ debug(traceCalls) {
730+ import std.stdio;
731+ stderr.write(info.name);
732+ }
733+
734+ alias Word = Runtime.Word;
735+ alias Method = openmethods.%s;
736+ assert(Method.info.slotStride);
737+
738+ static if (openmethods.VirtualArity!(Method.QualParams) == 1) {
739+ auto mptr = Method.Indexer!(Method.QualParams).unary(%s);
702740 debug(traceCalls) {
703- writefln( " pf = % s" , pf );
741+ stderr.writef("%%s %% s", mptr, Method.info.slotStride[0].i );
704742 }
743+ auto pf = cast(Method.Spec) mptr[Method.info.slotStride[0].i].p;
744+ } else {
745+ auto pf =
746+ cast(Method.Spec) Method.Indexer!(Method.QualParams).move(Method.info.slotStride, %s).p;
747+ }
748+
749+ debug(traceCalls) {
750+ import std.stdio;
751+ writefln(" pf = %%s", pf);
752+ }
705753
706- assert (pf);
707- return pf (args);
754+ assert(pf);
755+ return pf(%s);
756+ }
757+ ` .format(functionAttributes & FunctionAttribute.ref_ ? " ref " : " " ,
758+ ReturnType.stringof,
759+ name,
760+ params,
761+ functionAttributes & FunctionAttribute.pure_ ? " pure" : " " ,
762+ functionAttributes & FunctionAttribute.nothrow_ ? " nothrow" : " " ,
763+ functionAttributes & FunctionAttribute.trusted ? " @trusted" : " " ,
764+ functionAttributes & FunctionAttribute.safe ? " @safe" : " " ,
765+ functionAttributes & FunctionAttribute.nogc ? " @nogc" : " " ,
766+ functionAttributes & FunctionAttribute.system ? " @system" : " " ,
767+ This.stringof,
768+ args, args, args);
708769 }
709770
710771 shared static this () {
@@ -879,16 +940,16 @@ struct Runtime
879940
880941 Metrics update ()
881942 {
943+ // Create a Method object for each method. Create a Class object for all
944+ // the classes or interfaces that occur as virtual parameters in a method,
945+ // or were registered explicitly with 'registerClasses'.
946+
882947 seed();
883948
884- foreach (ci; additionalClasses) {
885- if (ci ! in classMap) {
886- auto c = classMap[ci] = new Class(ci);
887- debug (explain) {
888- writefln(" %s" , c.name);
889- }
890- }
891- }
949+ // Create a Class object for all the classes or interfaces that derive from
950+ // a class or interface that occur as virtual parameters in a method,
951+ // or were registered explicitly with 'registerClasses'. Also record in
952+ // each Class object all the method parameters that target it.
892953
893954 debug (explain) {
894955 writefln(" Scooping..." );
@@ -900,11 +961,32 @@ struct Runtime
900961 }
901962 }
902963
964+ // Fill the 'directBases' and 'directDerived' arrays in the Class objects.
965+
903966 initClasses();
967+
968+ // Copy the Class objects to the 'classes' array, ensuring that derived
969+ // classes and interface come after their base class and interfaces, but as
970+ // close to them as possible.
904971 layer();
972+
973+ // Fill the 'conforming' arrays, i.e. for each class record all the classes
974+ // and interfaces that are type compatible with it. Note that every class
975+ // is in its own 'conforming' array.
976+
905977 calculateInheritanceRelationships();
978+
979+ // Check if there are classes that define the 'delete' operator.
980+
906981 checkDeallocatorConflicts();
982+
983+ // For each method, reserve one slot per virtual parameter in the target
984+ // Class.
985+
907986 allocateSlots();
987+
988+ // Build dispatch tables and install the global vectors.
989+
908990 buildTables();
909991
910992 if (methodsUsingHash) {
@@ -958,6 +1040,15 @@ struct Runtime
9581040 debug (explain) {
9591041 writeln();
9601042 }
1043+
1044+ foreach (ci; additionalClasses) {
1045+ if (ci ! in classMap) {
1046+ auto c = classMap[ci] = new Class(ci);
1047+ debug (explain) {
1048+ writefln(" %s" , c.name);
1049+ }
1050+ }
1051+ }
9611052 }
9621053
9631054 bool scoop (ClassInfo ci)
@@ -1607,6 +1698,7 @@ struct Runtime
16071698 }
16081699 }
16091700 }
1701+
16101702 foreach (spec; m.specs) {
16111703 auto nextSpec = findNext(spec, m.specs);
16121704 * spec.info.nextPtr = nextSpec ? nextSpec.info.pf : null ;
@@ -1680,7 +1772,9 @@ version (GNU) {
16801772string _registerMethods (alias MODULE )()
16811773{
16821774 import std.array ;
1775+
16831776 string [] code;
1777+
16841778 foreach (m; __traits (allMembers , MODULE )) {
16851779 static if (is (typeof (__traits(getOverloads, MODULE , m)))) {
16861780 foreach (o; __traits (getOverloads , MODULE , m)) {
@@ -1694,13 +1788,19 @@ string _registerMethods(alias MODULE)()
16941788 }
16951789
16961790 auto meth =
1697- format(` openmethods.Method!("%s", %s, "%s", %s)` ,
1791+ format(` openmethods.Method!("%s", %s, "%s", %s, %s )` ,
16981792 index,
16991793 ReturnType! o.stringof,
17001794 m,
1795+ functionAttributes! o,
17011796 Parameters! o.stringof[1 .. $- 1 ]);
1702- code ~= format(` alias %s = %s.dispatcher;` , m, meth);
1703- code ~= format(` alias %s = %s.discriminator;` , m, meth);
1797+ // code ~= format(`alias %s = %s.dispatcher;`, m, meth);
1798+ // alias Method = openmethods.Method!(index, ReturnType, m, functionAttributes!o, Parameters!o);
1799+ alias Method = openmethods.Method! (index, ReturnType! o, m, functionAttributes! o, Parameters! o);
1800+ // code ~= `mixin(%s.code);`.format(meth);
1801+ code ~= Method.dispatcherCode;
1802+ code ~= Method.discriminatorCode;
1803+ // code ~= format(`alias %s = %s.discriminator;`, m, meth);
17041804 }
17051805 }
17061806 }
@@ -1716,14 +1816,20 @@ mixin template _registerSpecs(alias MODULE)
17161816 {
17171817 static struct Register {
17181818
1719- static wrapper = function Meth.ReturnType(Meth.Params args) {
1720- return Fun (openmethods.castArgs! (Meth.QualParams).To! (Parameters! Fun).arglist(args).expand);
1721- };
1819+ static if (Meth.functionAttributes & FunctionAttribute.ref_) {
1820+ static ref Meth.ReturnType wrapper (Meth.Params args) {
1821+ return Fun (openmethods.castArgs! (Meth.QualParams).To! (Parameters! Fun).arglist(args).expand);
1822+ }
1823+ } else {
1824+ static Meth.ReturnType wrapper (Meth.Params args) {
1825+ return Fun (openmethods.castArgs! (Meth.QualParams).To! (Parameters! Fun).arglist(args).expand);
1826+ }
1827+ }
17221828
17231829 static __gshared Runtime .SpecInfo si;
17241830
17251831 shared static this () {
1726- si.pf = cast (void * ) wrapper;
1832+ si.pf = cast (void * ) & wrapper;
17271833
17281834 debug (explain) {
17291835 import std.stdio ;
@@ -1798,17 +1904,3 @@ mixin template _registerSpecs(alias MODULE)
17981904 }
17991905 }
18001906}
1801-
1802- string _declareMethod (string index, ReturnType, string name, ParameterType... )()
1803- {
1804- import std.format ;
1805-
1806- enum meth =
1807- format(` openmethods.Method!("%s", %s, "%s", %s)` ,
1808- index,
1809- ReturnType.stringof,
1810- name,
1811- ParameterType.stringof[1 .. $- 1 ]);
1812- return format (` alias %s = %s.dispatcher;` , name, meth)
1813- ~ format(` alias %s = %s.discriminator;` , name, meth);
1814- }
0 commit comments