/tools/dspec/output.d

http://github.com/wilkie/djehuty · D · 596 lines · 462 code · 110 blank · 24 comment · 78 complexity · 55c02f08110cf873e6c049de18b09932 MD5 · raw file

  1. module output;
  2. import djehuty;
  3. import io.file;
  4. import io.console;
  5. import ast;
  6. import parser;
  7. class Output {
  8. this(string path) {
  9. if (!readyOutput(path)) {
  10. // Error: cannot write file
  11. Console.putln("Error: Cannot write to ", path);
  12. }
  13. printHeader();
  14. }
  15. ~this() {
  16. }
  17. void work(AST result, string path) {
  18. specName = path.dup;
  19. //Console.putln("Outputting ... ");
  20. AST working = result;
  21. AST node;
  22. moduleName = "";
  23. packageName = "";
  24. while(working !is null) {
  25. node = working.right;
  26. if (node !is null) {
  27. if (node.valueType == AST.ValueType.Name) {
  28. string name;
  29. node.getValue(name);
  30. //Console.putln("Tree: ", name.array);
  31. //writefln(name);
  32. switch(name) {
  33. case "ParseDescribe":
  34. tests = null;
  35. lines = null;
  36. className = null;
  37. printDescribe(node);
  38. break;
  39. case "ParseImport":
  40. printImport(node);
  41. break;
  42. case "ParseModule":
  43. AST work = node;
  44. while (work !is null) {
  45. node = work.right;
  46. if (node !is null) {
  47. if (node.valueType == AST.ValueType.Name) {
  48. }
  49. else {
  50. string content;
  51. node.getValue(content);
  52. moduleName = content.trim();
  53. packageName = moduleName.substring(0, moduleName.findReverse("."));
  54. moduleName = moduleName.substring(packageName.length+1);
  55. }
  56. }
  57. work = work.left;
  58. }
  59. break;
  60. default:
  61. // error
  62. break;
  63. }
  64. }
  65. }
  66. working = working.left;
  67. }
  68. }
  69. bool finalizeOutput() {
  70. if (outfp is null) {
  71. return false;
  72. }
  73. outfp.close();
  74. //fclose(outfp);
  75. return true;
  76. }
  77. protected:
  78. string specName;
  79. File outfp;
  80. //_iobuf* outfp;
  81. string className;
  82. string moduleName;
  83. string packageName;
  84. string[] tests;
  85. ulong[] lines;
  86. string[] classes;
  87. string exception;
  88. bool shouldThrow = false;
  89. bool readyOutput(string path) {
  90. //Console.putln("opening file");
  91. //outfp = fopen(std.string.toStringz(path), "w+");
  92. outfp = new File(path);
  93. if (outfp is null) {
  94. return false;
  95. }
  96. return true;
  97. }
  98. bool printHeader() {
  99. //fwritef(outfp, "%s", header);
  100. //Console.putln("output header");
  101. print("/*\n *\n */\n\n");
  102. print("import spec.specification;\n");
  103. print("import spec.itemspecification;\n");
  104. print("import spec.modulespecification;\n");
  105. print("import spec.packagespecification;\n");
  106. print("\nimport spec.logic;\n");
  107. print("\nimport djehuty;\n");
  108. return true;
  109. }
  110. bool printDone(AST tree, string describing) {
  111. AST working = tree;
  112. AST node;
  113. if (describing !is null) {
  114. print("done before_" ~ describing);
  115. }
  116. else {
  117. print("done before");
  118. }
  119. print("()\n\t{");
  120. while (working !is null) {
  121. node = working.right;
  122. if (node !is null) {
  123. if (node.valueType == AST.ValueType.Name) {
  124. }
  125. else {
  126. string content;
  127. node.getValue(content);
  128. printContent(content, 3);
  129. }
  130. }
  131. working = working.left;
  132. }
  133. print("}");
  134. return true;
  135. }
  136. bool printImport(AST tree) {
  137. AST working = tree;
  138. AST node;
  139. while (working !is null) {
  140. node = working.right;
  141. if (node !is null) {
  142. if (node.valueType == AST.ValueType.Name) {
  143. }
  144. else {
  145. string content;
  146. node.getValue(content);
  147. if (!(content == " testing.support")) {
  148. print("import");
  149. print(content);
  150. print(";\n\n");
  151. }
  152. }
  153. }
  154. working = working.left;
  155. }
  156. return true;
  157. }
  158. bool printIt(AST tree, string describing) {
  159. AST working = tree;
  160. AST node;
  161. while (working !is null) {
  162. node = working.right;
  163. if (node !is null) {
  164. if (node.valueType == AST.ValueType.Name) {
  165. string name;
  166. node.getValue(name);
  167. switch(name) {
  168. case "Identifier":
  169. string val;
  170. node.right.getValue(val);
  171. print("\n\tit ");
  172. if (describing !is null) {
  173. val = describing ~ "!" ~ val;
  174. }
  175. print(val.replace('!','_') ~ "() {\n");
  176. print("\t\tbefore();\n");
  177. print("\t\tbefore");
  178. if (describing !is null) {
  179. print("_" ~ describing);
  180. }
  181. print("();\n");
  182. if (describing is null) {
  183. val = "_" ~ val;
  184. }
  185. tests ~= val;
  186. print("\t\tit _ret = it.does;\n");
  187. print("\t\ttry {\n");
  188. break;
  189. case "LineNumber":
  190. ulong val;
  191. node.right.getValue(val);
  192. //Console.putln("LineNumber ", val);
  193. lines ~= [val];
  194. //Console.putln(lines);
  195. break;
  196. case "ParseDone":
  197. printDone(node,describing);
  198. break;
  199. case "ParseShould":
  200. printShould(node);
  201. break;
  202. case "ParseShouldNot":
  203. printShouldNot(node);
  204. break;
  205. case "ParseShouldThrow":
  206. printShouldThrow(node);
  207. break;
  208. default:
  209. break;
  210. }
  211. }
  212. else {
  213. string content;
  214. node.getValue(content);
  215. printContent(content, 3);
  216. }
  217. }
  218. working = working.left;
  219. }
  220. print("\t\t}\n\t\tcatch(Exception _exception_) {\n");
  221. if (shouldThrow) {
  222. //Console.putln("!!", exception.array);
  223. if (exception == "") {
  224. print("\t\t\t_ret = it.does");
  225. }
  226. else {
  227. print("\t\t\tif (_exception_.msg != ");
  228. print(exception);
  229. print(") { _ret = it.doesnt; }\n\t\t\t_ret = it.does");
  230. }
  231. }
  232. else {
  233. print("\t\t\t_ret = it.doesnt");
  234. }
  235. print(";\n\t\t}\n\t\treturn _ret;\n\t}\n");
  236. return true;
  237. }
  238. bool printShould(AST tree) {
  239. AST working = tree;
  240. AST node;
  241. print("\t\t\tif(!(");
  242. while (working !is null) {
  243. node = working.right;
  244. if (node !is null) {
  245. if (node.valueType == AST.ValueType.Name) {
  246. }
  247. else {
  248. string content;
  249. node.getValue(content);
  250. printContent(content, 0);
  251. }
  252. }
  253. working = working.left;
  254. }
  255. print(")) {\n\t\t\t\t_ret = it.doesnt;\n\t\t\t}\n");
  256. return true;
  257. }
  258. bool printShouldNot(AST tree) {
  259. AST working = tree;
  260. AST node;
  261. print("\t\t\tif(");
  262. while (working !is null) {
  263. node = working.right;
  264. if (node !is null) {
  265. if (node.valueType == AST.ValueType.Name) {
  266. }
  267. else {
  268. string content;
  269. node.getValue(content);
  270. printContent(content, 0);
  271. }
  272. }
  273. working = working.left;
  274. }
  275. print(") {\n\t\t\t\t_ret = it.doesnt;\n\t\t\t}\n");
  276. return true;
  277. }
  278. bool printShouldThrow(AST tree) {
  279. AST working = tree;
  280. AST node;
  281. exception = "";
  282. while (working !is null) {
  283. node = working.right;
  284. if (node !is null) {
  285. if (node.valueType == AST.ValueType.Name) {
  286. }
  287. else {
  288. string content;
  289. node.getValue(content);
  290. exception = content;
  291. }
  292. }
  293. working = working.left;
  294. }
  295. shouldThrow = true;
  296. return true;
  297. }
  298. bool printDescribeSection(AST tree) {
  299. AST working = tree;
  300. AST node;
  301. string describing;
  302. bool hasDone = false;
  303. while (working !is null) {
  304. node = working.right;
  305. if (node !is null) {
  306. if (node.valueType == AST.ValueType.Name) {
  307. string name;
  308. node.getValue(name);
  309. switch(name) {
  310. case "Identifier":
  311. node.right.getValue(describing);
  312. break;
  313. case "ParseDone":
  314. hasDone = true;
  315. printDone(node,describing);
  316. break;
  317. case "ParseIt":
  318. printIt(node,describing);
  319. break;
  320. default:
  321. break;
  322. }
  323. }
  324. else {
  325. string content;
  326. node.getValue(content);
  327. printContent(content, 3);
  328. }
  329. }
  330. working = working.left;
  331. }
  332. if (!hasDone) {
  333. print("\n\tdone before_" ~ describing ~ "() {\n\t}\n");
  334. }
  335. return true;
  336. }
  337. bool printDescribe(AST tree) {
  338. AST working = tree;
  339. AST node;
  340. bool hasDone = false;
  341. string val;
  342. while (working !is null) {
  343. node = working.right;
  344. if (node !is null) {
  345. if (node.valueType == AST.ValueType.Name) {
  346. string name;
  347. node.getValue(name);
  348. switch(name) {
  349. case "Identifier":
  350. node.right.getValue(val);
  351. //Console.putln("ID: ", val.array);
  352. if (val[0] >= 'a' && val[0] <= 'z') {
  353. val[0] = val[0] - 32;
  354. }
  355. //Console.putln("ID: ", val.array, " len ", val.length);
  356. val ~= "Tests";
  357. //Console.putln("ID: ", val.array, " len ", val.length);
  358. print("private struct " ~ val ~ " {\nstatic:\n");
  359. Console.putln("Creating ", val);
  360. className = val;
  361. break;
  362. case "ParseDone":
  363. hasDone = true;
  364. printDone(node,null);
  365. break;
  366. case "ParseIt":
  367. printIt(node,null);
  368. break;
  369. case "ParseDescribeSection":
  370. printDescribeSection(node);
  371. break;
  372. default:
  373. break;
  374. }
  375. }
  376. else {
  377. string content;
  378. node.getValue(content);
  379. if (content.trim() != "") {
  380. print("\n");
  381. printContent(content, 1);
  382. }
  383. }
  384. }
  385. working = working.left;
  386. }
  387. if (!hasDone) {
  388. print("\n\tdone before() {\n\t}\n\n");
  389. }
  390. // do tests
  391. //Console.putln("className: ", className.array, " len " , className.length);
  392. string classNameFixed = className.substring(0,className.length-6);
  393. //Console.putln("className::", classNameFixed.array);
  394. //Console.putln("className::", className[0..className.length-6]);
  395. print("\n}\n\n");
  396. print ("\nstatic this() {\n");
  397. print ("\t// Add to specification\n");
  398. // Split packageName into separate things
  399. string[] packages = packageName.split('.');
  400. print ("\tPackageSpecification ps;\n");
  401. print ("\tPackageSpecification tmpps;\n");
  402. print ("\tps = Specification.traverse(\"" ~ packages[0] ~ "\");\n");
  403. print ("\tif(ps is null) {\n");
  404. print ("\t\tps = new PackageSpecification(\"" ~ packages[0] ~ "\");\n");
  405. print ("\t\tSpecification.add(ps);\n");
  406. print ("\t}\n\n");
  407. foreach(pack; packages[1..$]) {
  408. print ("\ttmpps = ps;\n");
  409. print ("\tps = tmpps.traverse(\"" ~ pack ~ "\");\n");
  410. print ("\tif(ps is null) {\n");
  411. print ("\t\tps = new PackageSpecification(\"" ~ pack ~ "\");\n");
  412. print ("\t\ttmpps.add(ps);\n");
  413. print ("\t}\n\n");
  414. }
  415. print ("\t// Add to this module\n");
  416. print ("\tModuleSpecification ms = ps.retrieve(\"" ~ moduleName ~ "\");\n");
  417. print ("\tif(ms is null) {\n");
  418. print ("\t\tms = new ModuleSpecification(\"" ~ moduleName ~ "\");\n");
  419. print ("\t\tps.add(ms);\n");
  420. print ("\t}\n\n");
  421. print ("\tItemSpecification item;\n\n");
  422. string currentSection = "";
  423. foreach(i, test; tests) {
  424. int pos = test.find("!");
  425. string section = test[0..pos].dup;
  426. Console.putln("cs:", currentSection, " t:", test);
  427. if (currentSection != section) {
  428. currentSection = section;
  429. print ("\titem = new ItemSpecification(\"" ~ section ~ "\");\n");
  430. print ("\tms.add(item);\n");
  431. }
  432. print("\titem.add(\"" ~ test[pos+1..$].replace('_', ' ') ~ "\", &" ~ className ~ "." ~ test.replace('!','_') ~ ");\n");
  433. }
  434. print("}\n\n");
  435. classes ~= classNameFixed;
  436. return true;
  437. }
  438. bool print(string stuff) {
  439. return outfp.write(Unicode.toUtf8(stuff));
  440. //fwritef(outfp, "%s", stuff);
  441. //return true;
  442. }
  443. void printContent(string content, int tabs) {
  444. content = content.trim();
  445. if (content == "") { return; }
  446. int pos = content.find("\n");
  447. while(pos != -1) {
  448. if (tabs > 0) {
  449. switch(tabs) {
  450. case 3:
  451. print("\t");
  452. case 2:
  453. print("\t");
  454. case 1:
  455. print("\t");
  456. default:
  457. break;
  458. }
  459. print(content.substring(0, pos));
  460. print("\n");
  461. }
  462. else {
  463. print(content.substring(0, pos));
  464. }
  465. content = content.substring(pos+1).trim();
  466. pos = content.find("\n");
  467. }
  468. if (tabs > 0) {
  469. switch(tabs) {
  470. case 3:
  471. print("\t");
  472. case 2:
  473. print("\t");
  474. case 1:
  475. print("\t");
  476. default:
  477. break;
  478. }
  479. print(content);
  480. print("\n");
  481. }
  482. else {
  483. print(content);
  484. }
  485. }
  486. }