@@ -8,7 +8,8 @@ alias wasmImport(string mod, string name) = AliasSeq!(
88
99enum wasmExport (string name) = llvmAttr(" wasm-export-name" , name);
1010
11- struct witExport { string mod; string name; }
11+ struct witInterface { string name; }
12+ struct witExport { string name; }
1213
1314// / Thin CABI compliant wrapper over `T[]`
1415struct WitList (T) {
@@ -443,28 +444,112 @@ T[] mallocSlice(T)(size_t count) @nogc nothrow {
443444// from std.meta
444445alias AliasSeq (T... ) = T;
445446
447+ template witInterfaceOf (alias Symbol) {
448+ alias udas = AliasSeq! ();
449+ static foreach (uda; __traits (getAttributes , Symbol)) {
450+ static if (! is (uda) && is (typeof (uda) == witInterface)) {
451+ udas = AliasSeq! (udas, uda);
452+ }
453+ }
446454
447- template findWitExportFunc (string mod, string name, Sig, bool implicitSelf, Impl... ) {
448- static foreach (Func; Impl) {
449- static foreach (uda; __traits (getAttributes, Func)) {
450- static if (! is (uda) && is (typeof (uda) == witExport) && uda == witExport(mod, name)) {
451- static assert (
452- ! is (Func) &&
453- (is (typeof (Func) == function )),
454- " The implementation of '" , mod, " #" , name, " ' " ,
455- " `" , __traits(fullyQualifiedName, findWitExportFunc), " ` " ,
456- " must be a function or method."
457- );
458-
459- static assert (
460- ! is (typeof (findWitExportFunc) == void ) || __traits(isSame, findWitExportFunc, Func),
461- " There must be only one implementation of '" , mod, " #" , name, " '. " ,
462- " Found at least `" , __traits(fullyQualifiedName, findWitExportFunc),
463- " ` and `" , __traits(fullyQualifiedName, Func), " `."
464- );
465- alias findWitExportFunc = Func;
455+ static assert (
456+ udas.length <= 1 ,
457+ " There must be at most one `@witInterface` attached. Found multiple on `" ,
458+ __traits(fullyQualifiedName, Symbol), " `." ,
459+ );
460+
461+ static if (udas.length) {
462+ enum string witInterfaceOf = udas[0 ].name;
463+ } else {
464+ enum string witInterfaceOf = " " ;
465+ }
466+ }
467+
468+ alias toKebabCase = (string s) { // lambda to satisfy `betterC` (use of GC)
469+ if (s.length == 0 ) return " " ;
470+
471+ char [] buf;
472+ foreach (i, c; s) {
473+ if (i > 0 && c >= ' A' && c <= ' Z' ) {
474+ char prev = s[i - 1 ];
475+ char next = ((i + 1 ) < s.length) ? s[i + 1 ] : ' \0 ' ;
476+ if (
477+ (prev >= ' a' && prev <= ' z' ) ||
478+ (
479+ next != ' \0 ' &&
480+ prev >= ' A' && prev <= ' Z' &&
481+ ! (next >= ' A' && next <= ' Z' )
482+ )
483+ ) {
484+ buf ~= ' -' ;
466485 }
467486 }
487+ buf ~= (c >= ' A' && c <= ' Z' ) ? (c + 32 ) : c;
488+ }
489+ return cast (string )buf;
490+ };
491+
492+ template witNameOf (alias Symbol) {
493+ alias udas = AliasSeq! ();
494+ static foreach (uda; __traits (getAttributes , Symbol)) {
495+ static if ((! is (uda) && is (typeof (uda) == witExport)) || is (uda == witExport)) {
496+ udas = AliasSeq! (udas, uda);
497+ }
498+ }
499+
500+ static assert (
501+ udas.length <= 1 ,
502+ " There must be at most one `@witExport` attached. Found multiple on `" ,
503+ __traits(fullyQualifiedName, Symbol), " `." ,
504+ );
505+
506+ static if (udas.length) {
507+ static if (is (udas[0 ])) {
508+ enum string witNameOf = toKebabCase(__traits(identifier, Symbol));
509+ } else {
510+ static assert (
511+ udas[0 ].name.length,
512+ " Specifying an empty name for `@witExport(...)` is not allowed. Found empty on `" ,
513+ __traits(fullyQualifiedName, Symbol), " `. Omit the parenthesis and parameter" ,
514+ " (i.e. use as `@witExport`) or specify non-empty name." ,
515+ );
516+ enum string witNameOf = udas[0 ].name;
517+ }
518+ } else {
519+ enum string witNameOf = " " ;
520+ }
521+ }
522+
523+ template witNameInResourceOf (T, alias Func) {
524+ enum resName = witNameOf! T;
525+ enum name = witNameOf! Func;
526+
527+ static if (name == " [constructor]" ) {
528+ enum witNameInResourceOf = " [constructor]" ~ resName;
529+ } else {
530+ enum witNameInResourceOf = (__traits(isStaticFunction, Func) ? " [static]" : " [method]" ) ~ resName ~ " ." ~ name;
531+ }
532+ }
533+
534+ template findWitExportFunc (string mod, string name, Sig, Impl... ) {
535+ static foreach (Func; Impl) {
536+ static if (witNameOf! Func == name && witInterfaceOf! Func == mod) {
537+ static assert (
538+ ! is (Func) &&
539+ (is (typeof (Func) == function )),
540+ " The implementation of '" , mod, " #" , name, " ' " ,
541+ " `" , __traits(fullyQualifiedName, findWitExportFunc), " ` " ,
542+ " must be a function or method."
543+ );
544+
545+ static assert (
546+ ! is (typeof (findWitExportFunc) == void ) || __traits(isSame, findWitExportFunc, Func),
547+ " There must be only one implementation of '" , mod, " #" , name, " '. " ,
548+ " Found at least `" , __traits(fullyQualifiedName, findWitExportFunc),
549+ " ` and `" , __traits(fullyQualifiedName, Func), " `."
550+ );
551+ alias findWitExportFunc = Func;
552+ }
468553 }
469554
470555 static assert (
@@ -473,7 +558,14 @@ template findWitExportFunc(string mod, string name, Sig, bool implicitSelf, Impl
473558 );
474559
475560 static assert (
476- is (typeof (&findWitExportFunc) : Sig) && __traits(isStaticFunction, findWitExportFunc) != implicitSelf,
561+ __traits (isStaticFunction , findWitExportFunc),
562+ " The implementation of '" , mod, " #" , name, " ' " ,
563+ " `" , __traits(fullyQualifiedName, findWitExportFunc), " ` " ,
564+ " must be static." ,
565+ );
566+
567+ static assert (
568+ is (typeof (&findWitExportFunc) : Sig),
477569 " The implementation of '" , mod, " #" , name, " ' " ,
478570 " `" , __traits(fullyQualifiedName, findWitExportFunc), " ` " ,
479571 " must conform to the necessary signature. " ,
@@ -482,25 +574,70 @@ template findWitExportFunc(string mod, string name, Sig, bool implicitSelf, Impl
482574 );
483575}
484576
577+ template findWitExportMethod (T, string name, Sig, bool isStatic) {
578+ alias Impl = witExportsIn! T;
579+
580+ enum mod = witInterfaceOf! T;
581+
582+ static foreach (Func; Impl) {
583+ static if (witNameInResourceOf! (T, Func) == name) {
584+ static assert (
585+ ! is (Func) &&
586+ (is (typeof (Func) == function )),
587+ " The implementation of '" , mod, " #" , name, " ' " ,
588+ " `" , __traits(fullyQualifiedName, findWitExportMethod), " ` " ,
589+ " must be a function or method."
590+ );
591+
592+ static assert (
593+ ! is (typeof (findWitExportMethod) == void ) || __traits(isSame, findWitExportMethod, Func),
594+ " There must be only one implementation of '" , mod, " #" , name, " '. " ,
595+ " Found at least `" , __traits(fullyQualifiedName, findWitExportMethod),
596+ " ` and `" , __traits(fullyQualifiedName, Func), " `."
597+ );
598+ alias findWitExportMethod = Func;
599+ }
600+ }
601+
602+ static assert (
603+ ! is (typeof (findWitExportMethod) == void ),
604+ " Could not find implementation for '" , mod, " #" , name, " '"
605+ );
606+
607+ static assert (
608+ __traits (isStaticFunction , findWitExportMethod) == isStatic,
609+ " The implementation of '" , mod, " #" , name, " ' " ,
610+ " `" , __traits(fullyQualifiedName, findWitExportMethod), " ` " ,
611+ " must " ~ (isSttic ? " be static" : " have implicit `this`" ) ~ " ." ,
612+ );
613+
614+ static assert (
615+ is (typeof (&findWitExportMethod) : Sig),
616+ " The implementation of '" , mod, " #" , name, " ' " ,
617+ " `" , __traits(fullyQualifiedName, findWitExportMethod), " ` " ,
618+ " must conform to the necessary signature. " ,
619+ " Found `" , typeof (&findWitExportMethod), " `" ,
620+ " , but expected `" , Sig, " `"
621+ );
622+ }
623+
485624template findWitExportResource (string mod, string name, Impl... ) {
486625 static foreach (Resource; Impl) {
487- static foreach (uda; __traits (getAttributes, Resource)) {
488- static if (! is (uda) && is (typeof (uda) == witExport) && uda == witExport(mod, name)) {
489- static assert (
490- is (Resource == struct ),
491- " The implementation of '" , mod, " #" , name, " ' " ,
492- " `" , __traits(fullyQualifiedName, findWitExportResource), " ` " ,
493- " must be a struct."
494- );
495-
496- static assert (
497- ! is (typeof (findWitExportResource) == void ) || __traits(isSame, findWitExportResource, Resource),
498- " There must be only one implementation of '" , mod, " #" , name, " '. " ,
499- " Found at least `" , __traits(fullyQualifiedName, findWitExportResource),
500- " ` and `" , __traits(fullyQualifiedName, Resource), " `."
501- );
502- alias findWitExportResource = Resource;
503- }
626+ static if (witNameOf! Resource == name && witInterfaceOf! Resource == mod) {
627+ static assert (
628+ is (Resource == struct ),
629+ " The implementation of '" , mod, " #" , name, " ' " ,
630+ " `" , __traits(fullyQualifiedName, findWitExportResource), " ` " ,
631+ " must be a struct."
632+ );
633+
634+ static assert (
635+ ! is (typeof (findWitExportResource) == void ) || __traits(isSame, findWitExportResource, Resource),
636+ " There must be only one implementation of '" , mod, " #" , name, " '. " ,
637+ " Found at least `" , __traits(fullyQualifiedName, findWitExportResource),
638+ " ` and `" , __traits(fullyQualifiedName, Resource), " `."
639+ );
640+ alias findWitExportResource = Resource;
504641 }
505642 }
506643
@@ -510,16 +647,21 @@ template findWitExportResource(string mod, string name, Impl...) {
510647 );
511648}
512649
513-
514- template witExportsIn (T) {
650+ public template witExportsIn (T) {
515651 alias witExportsIn = AliasSeq! ();
516652
517- static foreach (M; __traits (allMembers, T)) {
518- static foreach (Export; __traits (getOverloads, T, M)) {
519- static foreach (uda; __traits (getAttributes, Export)) {
520- static if (! is (uda) && is (typeof (uda) == witExport)) {
521- witExportsIn = AliasSeq! (witExportsIn, Export);
522- }
653+ static foreach (member; __traits (allMembers, T)) {
654+ witExportsIn = AliasSeq! (witExportsIn, findWitExports! (__traits(getOverloads, T, member)));
655+ }
656+ }
657+
658+ public template findWitExports (Exports... ) {
659+ alias findWitExports = AliasSeq! ();
660+
661+ static foreach (elem; Exports) {
662+ static foreach (uda; __traits (getAttributes, elem)) {
663+ static if ((! is (uda) && is (typeof (uda) == witExport)) || is (uda == witExport)) {
664+ findWitExports = AliasSeq! (findWitExports, elem);
523665 }
524666 }
525667 }
0 commit comments