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 }