1 /** 2 * This module was used to parse template constraints 3 * and instantiate the various constituent, 4 * to find which one is blocking a template to be instantiated. 5 * 6 * I have to code this again, using the D parser. 7 */ 8 module pegged.examples.constraints; 9 10 import std.conv; 11 import std.stdio; 12 import std.traits; 13 14 import pegged.grammar; 15 16 17 18 string constraintToCode(ParseResult p) 19 { 20 string result; 21 switch (p.name) 22 { 23 case "ConstraintExp": 24 result = constraintToCode(p.children[0]); 25 foreach(child; p.children[1..$]) 26 result ~= " || " ~ constraintToCode(child); 27 return result; 28 case "AndExp": 29 result = constraintToCode(p.children[0]); 30 foreach(child; p.children[1..$]) 31 result ~= " && " ~ constraintToCode(child); 32 return result; 33 case "Primary": 34 return constraintToCode(p.children[0]); 35 case "NotExp": 36 return "!" ~ p.matches[0]; 37 case "Parens": 38 return "("~constraintToCode(p.children[0])~")"; 39 case "Ident": 40 return p.matches[0]; 41 case "IsExpr": 42 return p.matches[0]; 43 default: 44 break; 45 } 46 return result; 47 } 48 49 string[] generateAllConstraints(ParseResult p) 50 { 51 string[] result; 52 result ~= constraintToCode(p); 53 foreach(child; p.children) 54 { 55 auto temp = generateAllConstraints(child); 56 if (temp[0] != result[$-1]) 57 result ~= temp; 58 else 59 result ~= temp[1..$]; 60 } 61 return result; 62 } 63 64 string testAllConstraints(string input)() @property 65 { 66 string result = "string[] testResult;\n"; 67 string[] constraints = generateAllConstraints(Constraint(input)); 68 foreach(i, c; constraints) 69 { 70 auto mock = "mock"~to!string(i); 71 result ~= "void "~mock~"(Args args) if (" ~ c ~ ") {};\n"; 72 result ~= "static if (!__traits(compiles, "~mock~"(args)))\n"; 73 result ~= " testResult ~= \""~c~"\";\n"; 74 } 75 return result; 76 } 77 78 string argListAlias(ParseResult p) 79 { 80 string aliases; 81 string associations = "enum assoc = `( ` ~ "; 82 foreach(i,arg; p.children) 83 if (arg.children[0].name != "TupleParameter") 84 { 85 aliases ~= "alias Args["~to!string(i)~"] " ~ arg.matches[0] ~ ";\n"; 86 associations ~= "`" ~ arg.matches[0] ~ ": ` ~ Args["~to!string(i)~"].stringof ~ `, ` ~ "; 87 } 88 else 89 { 90 aliases ~= "alias Args["~to!string(i)~"..$] " ~ arg.matches[0] ~ ";\n"; 91 associations ~= "`" ~ arg.matches[0] ~ ": ` ~ Args["~to!string(i)~"..$].stringof ~ `, `"; 92 } 93 return aliases ~ associations[0..$-6]~" ~ `)`;\n"; 94 } 95 96 string generateAllMockUps(string argList, string[] constraints) 97 { 98 string result; 99 foreach(i,constraint; constraints) 100 { 101 result ~= "struct Mock"~to!string(i)~argList~" if ("~constraint~") {}\n"; 102 } 103 return result; 104 } 105 106 string generateAllTests(string assoc, string[] constraints) 107 { 108 string result; 109 foreach(i,constr; constraints) // to iterate at CT on the right number of mockups 110 { 111 string si = to!string(i); 112 result ~= 113 "static if (__traits(compiles, Mock"~si~"!(Args))) 114 pragma(msg, constraints["~si~"], ` with " ~ assoc ~ ": true`); 115 else 116 pragma(msg, constraints["~si~"], ` with " ~ assoc ~ ": false`);\n"; 117 } 118 return result; 119 } 120 121 auto testInstantiation(alias name, Args...)() @property 122 { 123 enum constraint = getConstraint!name; 124 enum argList0 = "("~ExtractTemplateArgumentList(name.stringof).matches[0] ~")"; 125 enum argList = Type.TemplateParametersList(argList0); 126 enum aliases = argListAlias(argList); 127 mixin(aliases); 128 enum constraints = generateAllConstraints(ConstraintExp.parse(constraint)); 129 enum mockups = generateAllMockUps(argList0, constraints); 130 mixin(mockups); 131 enum test = generateAllTests(assoc, constraints); 132 mixin(test); 133 return argList; 134 }