1 /** 2 This module provides the template metaprogramming variant of compile-time 3 reflection, allowing client code to do type-level computations on the 4 contents of a D module. 5 */ 6 module mirror.meta; 7 8 9 /** 10 Compile-time information on a D module. 11 */ 12 template Module(string moduleName) { 13 import std.meta: Filter, staticMap, Alias, AliasSeq; 14 15 mixin(`import `, moduleName, `;`); 16 private alias mod = Alias!(mixin(moduleName)); 17 18 private alias memberNames = __traits(allMembers, mod); 19 20 private template member(string name) { 21 import std.meta: Alias, AliasSeq; 22 23 enum identifier = name; 24 25 static if(__traits(compiles, Alias!(__traits(getMember, mod, name)))) 26 alias symbol = Alias!(__traits(getMember, mod, name)); 27 else 28 alias symbol = AliasSeq!(); 29 } 30 private alias members = staticMap!(member, memberNames); 31 32 private template notPrivate(alias member) { 33 // If a module contains an alias to a basic type, e.g. `alias L = long;`, 34 // then __traits(getProtection, member) fails to compile 35 static if(__traits(compiles, __traits(getProtection, member.symbol))) 36 enum notPrivate = __traits(getProtection, member.symbol) != "private"; 37 else 38 enum notPrivate = false; 39 } 40 41 private alias publicMembers = Filter!(notPrivate, members); 42 43 44 // User-defined types 45 private template isMemberType(alias member) { 46 import std.traits: isType; 47 enum isMemberType = isType!(member.symbol); 48 } 49 private alias symbolOf(alias member) = member.symbol; 50 alias Aggregates = staticMap!(symbolOf, Filter!(isMemberType, publicMembers)); 51 52 53 // Global variables 54 private enum isVariable(alias member) = is(typeof(member.symbol)); 55 private enum toVariable(alias member) = Variable!(typeof(member.symbol))(__traits(identifier, member.symbol)); 56 alias Variables = staticMap!(toVariable, Filter!(isVariable, publicMembers)); 57 58 59 // Function definitions 60 private template isMemberSomeFunction(alias member) { 61 import std.traits: isSomeFunction; 62 enum isMemberSomeFunction = isSomeFunction!(member.symbol); 63 } 64 private alias functionMembers = Filter!(isMemberSomeFunction, publicMembers); 65 private enum toFunction(alias member) = Function!(mod, member.symbol, member.identifier)(); 66 alias Functions = staticMap!(toFunction, functionMembers); 67 } 68 69 70 /** 71 A global variable. 72 */ 73 struct Variable(T) { 74 alias Type = T; 75 string name; 76 } 77 78 79 /** 80 A function. 81 */ 82 struct Function(alias M, alias F, string I = __traits(identifier, F)) { 83 84 alias module_ = M; 85 alias symbol = F; 86 enum identifier = I; 87 alias overloads = __traits(getOverloads, module_, identifier); 88 89 string protection = __traits(getProtection, symbol); 90 string linkage = __traits(getLinkage, symbol); 91 92 string toString() @safe pure nothrow { 93 import std.conv: text; 94 import std.traits: fullyQualifiedName; 95 return text(`Function(`, fullyQualifiedName!symbol, ", ", protection, ", ", linkage, ")"); 96 } 97 } 98 99 100 /// Usable as a predicate to std.meta.Filter 101 enum isEnum(T) = is(T == enum); 102 103 /// Usable as a predicate to std.meta.Filter 104 enum isStruct(T) = is(T == struct); 105 106 /// Usable as a predicate to std.meta.Filter 107 enum isInterface(T) = is(T == interface); 108 109 /// Usable as a predicate to std.meta.Filter 110 enum isClass(T) = is(T == class); 111 112 /** 113 If a type is a class or an interface. 114 Usable as a predicate to std.meta.Filter 115 */ 116 enum isOOP(T) = is(T == class) || is(T == interface);