// This generates functions with all specified test types as first argument + // variables for each specified test type. // Then it calls all functions with every type to see which ones are accepted by // the compiler, to automatically stay up-to-date. import std; import fs = std.file; string[] testTypes = [ "bool", "byte", "ubyte", "short", "ushort", "int", "uint", "long", "ulong", "char", "wchar", "dchar", "float", "double", "real", "BasicStruct", "AliasThisInt", ]; // index here must map onto varTypePermutations index string[][] funcTypePermutations = [ // TODO: check for const/inout/immutable/shared in UFCS checks [ "%s", // "const(%s)", "ref %s", // "ref const(%s)" ], [ "%s*", // "const(%s)*", // "const(%s*)", "ref %s*", // "ref const(%s)*", // "ref const(%s*)" ], [ "%s[]", // "const(%s)[]", // "const(%s[])", "ref %s[]", // "ref const(%s)[]", // "ref const(%s[])" ] ]; string[][] varTypePermutations = [ [ "%s", // "const(%s)" ], [ "%s*", // "const(%s)*", // "const(%s*)" ], [ "%s[]", // "const(%s)[]", // "const(%s[])" ] ]; string preamble = ` struct BasicStruct { int member1; string member2; } struct AliasThisInt { int member1; string member2; alias member1 this; } `; int main(string[] args) { string functionsCode; string varsCode; string callCode; string[] allFunctions; string[string] funcLookup; string[string] varLookup; foreach (ti, type; testTypes) { foreach (pi, perms; funcTypePermutations) { foreach (i, perm; perms) { string resolved = format(perm, type); string id = getID(ti, pi, i); allFunctions ~= ("func_" ~ id); functionsCode ~= "void func_" ~ id ~ "(" ~ resolved ~ " arg) {}\n"; functionsCode ~= resolved ~ " make_" ~ id ~ "() { static " ~ resolved .chompPrefix("ref ") ~ " x; return x; }\n"; funcLookup["func_" ~ id] = resolved; } } foreach (pi, perms; varTypePermutations) { foreach (i, perm; perms) { string resolved = format(perm, type); string id = getID(ti, pi, i); varsCode ~= resolved ~ " var_" ~ id ~ " = make_" ~ id ~ "();\n"; varLookup["var_" ~ id] = resolved; foreach (cti, subType; testTypes) foreach (ci, subPerms; funcTypePermutations) foreach (fi, subPerm; subPerms) { callCode ~= "var_" ~ id ~ ".func_" ~ getID(cti, ci, fi) ~ "();\n"; } } } } allFunctions.sort!"a 1_000, "compiler didn't error as expected, need to adjust tests!"); writeln("Total incompatible type combinations: ", numErrors); string[][string] wrongDCDCompletions; foreach (varName; varLookup.byKey) { string input = code[0 .. $ - 2] ~ "\n" ~ varName ~ ".func_"; string[] dcdClient = ["../../../bin/dcd-client"]; if (args[1].length) dcdClient ~= args[1]; auto proc = pipeProcess(dcdClient ~ ["-c" ~ to!string(input.length)]); proc.stdin.rawWrite(input); proc.stdin.rawWrite("\n}\n"); proc.stdin.close(); string[] dcdResult; size_t i = 0; foreach (line; proc.stdout.byLineCopy) { if (i++ == 0) { enforce(line == "identifiers"); continue; } auto parts = line.split("\t"); if (parts[1] != "F") continue; dcdResult ~= parts[0]; } enforce(i > 0, "every variable must auto-complete something! Missing completion for var " ~ varName ~ " of type " ~ varLookup[varName] ~ generateEmptyResponseReproductionCode( varLookup[varName])); enforce(dcdResult.length > 0, "Wrongly no UFCS completion for var " ~ varName ~ " of type " ~ varLookup[varName] ~ generateEmptyResponseReproductionCode( varLookup[varName])); dcdResult.sort!"a '+' ~ ln) .chain(missingFunctions.map!(ln => '-' ~ ln)) .array; // writeln(varLookup[varName], " -> ", dcdResult); if (diff.length) wrongDCDCompletions[varName] = diff; } foreach (varName, wrongTypes; wrongDCDCompletions) { writeln("Incorrect results for ", varLookup[varName], ":"); wrongTypes.sort!"a