/src/org/ooc/backend/json/JSONGenerator.java

http://github.com/nddrylliog/ooc · Java · 487 lines · 436 code · 38 blank · 13 comment · 75 complexity · fdf1a44ecddef0acf04e5d87c6c9c576 MD5 · raw file

  1. package org.ooc.backend.json;
  2. import java.io.File;
  3. import java.io.FileWriter;
  4. import java.io.IOException;
  5. import org.json.JSONArray;
  6. import org.json.JSONException;
  7. import org.json.JSONObject;
  8. import org.ooc.backend.Generator;
  9. import org.ooc.frontend.BuildParams;
  10. import org.ooc.frontend.Visitor;
  11. import org.ooc.frontend.model.Add;
  12. import org.ooc.frontend.model.AddressOf;
  13. import org.ooc.frontend.model.Argument;
  14. import org.ooc.frontend.model.ArrayAccess;
  15. import org.ooc.frontend.model.ArrayLiteral;
  16. import org.ooc.frontend.model.Assignment;
  17. import org.ooc.frontend.model.BinaryCombination;
  18. import org.ooc.frontend.model.BinaryNegation;
  19. import org.ooc.frontend.model.Block;
  20. import org.ooc.frontend.model.BoolLiteral;
  21. import org.ooc.frontend.model.BuiltinType;
  22. import org.ooc.frontend.model.Case;
  23. import org.ooc.frontend.model.Cast;
  24. import org.ooc.frontend.model.CharLiteral;
  25. import org.ooc.frontend.model.ClassDecl;
  26. import org.ooc.frontend.model.CommaSequence;
  27. import org.ooc.frontend.model.Compare;
  28. import org.ooc.frontend.model.CoverDecl;
  29. import org.ooc.frontend.model.Dereference;
  30. import org.ooc.frontend.model.Div;
  31. import org.ooc.frontend.model.Else;
  32. import org.ooc.frontend.model.FloatLiteral;
  33. import org.ooc.frontend.model.FlowControl;
  34. import org.ooc.frontend.model.For;
  35. import org.ooc.frontend.model.Foreach;
  36. import org.ooc.frontend.model.FuncType;
  37. import org.ooc.frontend.model.FunctionCall;
  38. import org.ooc.frontend.model.FunctionDecl;
  39. import org.ooc.frontend.model.If;
  40. import org.ooc.frontend.model.Import;
  41. import org.ooc.frontend.model.Include;
  42. import org.ooc.frontend.model.IntLiteral;
  43. import org.ooc.frontend.model.InterfaceDecl;
  44. import org.ooc.frontend.model.Line;
  45. import org.ooc.frontend.model.Match;
  46. import org.ooc.frontend.model.MemberAccess;
  47. import org.ooc.frontend.model.MemberArgument;
  48. import org.ooc.frontend.model.MemberAssignArgument;
  49. import org.ooc.frontend.model.MemberCall;
  50. import org.ooc.frontend.model.Mod;
  51. import org.ooc.frontend.model.Module;
  52. import org.ooc.frontend.model.Mul;
  53. import org.ooc.frontend.model.Node;
  54. import org.ooc.frontend.model.NodeList;
  55. import org.ooc.frontend.model.Not;
  56. import org.ooc.frontend.model.NullLiteral;
  57. import org.ooc.frontend.model.OpDecl;
  58. import org.ooc.frontend.model.Parenthesis;
  59. import org.ooc.frontend.model.RangeLiteral;
  60. import org.ooc.frontend.model.RegularArgument;
  61. import org.ooc.frontend.model.Return;
  62. import org.ooc.frontend.model.StringLiteral;
  63. import org.ooc.frontend.model.Sub;
  64. import org.ooc.frontend.model.Ternary;
  65. import org.ooc.frontend.model.Type;
  66. import org.ooc.frontend.model.TypeDecl;
  67. import org.ooc.frontend.model.TypeParam;
  68. import org.ooc.frontend.model.Use;
  69. import org.ooc.frontend.model.ValuedReturn;
  70. import org.ooc.frontend.model.VarArg;
  71. import org.ooc.frontend.model.VariableAccess;
  72. import org.ooc.frontend.model.VariableDecl;
  73. import org.ooc.frontend.model.VersionBlock;
  74. import org.ooc.frontend.model.While;
  75. import org.ooc.frontend.parser.TypeArgument;
  76. import org.ooc.middle.structs.MultiMap;
  77. import org.ooc.middle.structs.NodeMap;
  78. public class JSONGenerator extends Generator implements Visitor {
  79. public File out;
  80. public JSONArray root;
  81. public JSONGenerator(File outPath, Module module) {
  82. super(outPath, module);
  83. String basePath = module.getOutPath();
  84. this.root = new JSONArray();
  85. this.out = new File(outPath, basePath + ".json");
  86. this.out.getParentFile().mkdirs();
  87. }
  88. @Override
  89. public void generate(BuildParams params) throws IOException {
  90. module.accept(this);
  91. FileWriter writer = new FileWriter(this.out);
  92. try {
  93. root.write(writer);
  94. } catch(JSONException e) {
  95. throw new IOException("Failed.");
  96. }
  97. writer.close();
  98. }
  99. public void visit(Module module) throws IOException {
  100. /* the "!module" entity */
  101. try {
  102. JSONObject obj = new JSONObject();
  103. obj.put("type", "module");
  104. obj.put("tag", "!module");
  105. obj.put("path", module.getFullName().replace('.', '/')); // we want the ooc name.
  106. JSONArray imports = new JSONArray();
  107. for(Import import_: module.getAllImports()) { // TODO: respect namespaced imports
  108. imports.put(import_.getPath());
  109. }
  110. obj.put("imports", imports);
  111. addObject(obj);
  112. } catch (JSONException e) {
  113. throw new IOException("Failed.");
  114. }
  115. /* functions */
  116. NodeList<FunctionDecl> functions = new NodeList<FunctionDecl>();
  117. module.getFunctions(functions);
  118. functions.accept(this);
  119. /* classes */
  120. for(TypeDecl type: module.getTypes().values()) {
  121. if(type instanceof ClassDecl || type instanceof CoverDecl)
  122. type.accept(this);
  123. }
  124. /* variables */
  125. NodeList<VariableDecl> variables = new NodeList<VariableDecl>();
  126. module.getVariables(variables);
  127. variables.accept(this);
  128. }
  129. public void visit(Add add) throws IOException {}
  130. public void visit(Mul mul) throws IOException {}
  131. public void visit(Sub sub) throws IOException {}
  132. public void visit(Div div) throws IOException {}
  133. public void visit(Not not) throws IOException {}
  134. public void visit(BinaryNegation binaryNegation) throws IOException {}
  135. public void visit(Mod mod) throws IOException {}
  136. public void visit(Compare compare) throws IOException {}
  137. public void visit(FunctionCall functionCall) throws IOException {}
  138. public void visit(MemberCall memberCall) throws IOException {}
  139. public void visit(Parenthesis parenthesis) throws IOException {}
  140. public void visit(Assignment assignment) throws IOException {}
  141. public void visit(ValuedReturn return1) throws IOException {}
  142. public void visit(Return return1) throws IOException {}
  143. public void visit(NullLiteral nullLiteral) throws IOException {}
  144. public void visit(IntLiteral numberLiteral) throws IOException {}
  145. public void visit(FloatLiteral floatLiteral) throws IOException {}
  146. public void visit(StringLiteral stringLiteral) throws IOException {}
  147. public void visit(RangeLiteral rangeLiteral) throws IOException {}
  148. public void visit(BoolLiteral boolLiteral) throws IOException {}
  149. public void visit(CharLiteral charLiteral) throws IOException {}
  150. public void visit(ArrayLiteral arrayLiteral) throws IOException {}
  151. public void visit(Line line) throws IOException {}
  152. public void visit(Include include) throws IOException {}
  153. public void visit(Import import1) throws IOException {}
  154. public void visit(Use use) throws IOException {}
  155. public void visit(If if1) throws IOException {}
  156. public void visit(Else else1) throws IOException {}
  157. public void visit(While while1) throws IOException {}
  158. public void visit(For for1) throws IOException {}
  159. public void visit(Foreach foreach) throws IOException {}
  160. public void visit(FlowControl break1) throws IOException {}
  161. public void visit(VariableAccess variableAccess) throws IOException {}
  162. public void visit(MemberAccess memberAccess) throws IOException {}
  163. public void visit(ArrayAccess arrayAccess) throws IOException {}
  164. public void visit(VariableDecl variableDecl) throws IOException {
  165. try {
  166. addObject(buildVariableDecl(variableDecl, null));
  167. } catch (JSONException e) {
  168. throw new IOException("fail!");
  169. }
  170. }
  171. String resolveType(Type type) {
  172. if(type instanceof FuncType) {
  173. return "Func";
  174. }
  175. String tag = type.getName();
  176. int pointerLevel = type.getPointerLevel();
  177. while(pointerLevel-- > 0)
  178. tag = "pointer(" + tag + ")";
  179. int referenceLevel = type.getReferenceLevel();
  180. while(referenceLevel-- > 0)
  181. tag = "reference(" + tag + ")";
  182. return tag;
  183. }
  184. public void visit(FunctionDecl functionDecl) throws IOException {
  185. try {
  186. addObject(buildFunctionDecl(functionDecl));
  187. } catch(JSONException e) {
  188. throw new IOException("Fail.");
  189. }
  190. }
  191. void addObject(JSONObject obj) throws JSONException {
  192. JSONArray entry = new JSONArray();
  193. entry.put(obj.getString("tag"));
  194. entry.put(obj);
  195. root.put(entry);
  196. }
  197. JSONObject buildFunctionDecl(FunctionDecl node) throws JSONException {
  198. JSONObject obj = new JSONObject();
  199. String name = node.getName();
  200. if(node.getSuffix().length() > 0)
  201. name = name + "~" + node.getSuffix();
  202. obj.put("name", name);
  203. if(node.isMember()) {
  204. obj.put("tag", "memberFunction(" + node.getTypeDecl().getName() + ", " + name + ")");
  205. obj.put("type", "memberFunction");
  206. } else {
  207. obj.put("tag", name);
  208. obj.put("type", "function");
  209. }
  210. if(node.getComment() != null) {
  211. obj.put("doc", node.getComment().getContent());
  212. } else {
  213. obj.put("doc", JSONObject.NULL);
  214. }
  215. if(node.isExtern()) {
  216. if(!node.isExternWithName()) {
  217. obj.put("extern", true);
  218. } else {
  219. obj.put("extern", node.getExternName());
  220. }
  221. } else {
  222. obj.put("extern", false);
  223. }
  224. if(node.isUnmangled()) {
  225. if(!node.isUnmangledWithName()) {
  226. obj.put("unmangled", true);
  227. } else {
  228. obj.put("unmangled", node.getUnmangledName());
  229. }
  230. } else {
  231. obj.put("unmangled", false);
  232. }
  233. obj.put("fullName", node.getFullName());
  234. JSONArray modifiers = new JSONArray();
  235. if(node.isStatic())
  236. modifiers.put("static");
  237. if(node.isFinal())
  238. modifiers.put("final");
  239. if(node.isAbstract())
  240. modifiers.put("abstract");
  241. obj.put("modifiers", modifiers);
  242. /* `genericTypes` */
  243. JSONArray genericTypes = new JSONArray();
  244. for(TypeParam typeParam: node.getTypeParams().values()) {
  245. genericTypes.put(typeParam.getName());
  246. }
  247. obj.put("genericTypes", genericTypes);
  248. /* `arguments` */
  249. JSONArray arguments = new JSONArray();
  250. Boolean first = Boolean.TRUE;
  251. for(Argument arg: node.getArguments()) {
  252. if(first.booleanValue() && node.hasThis()) {
  253. /* ignore the `this` argument */
  254. first = Boolean.FALSE;
  255. continue;
  256. } else if(first.booleanValue()) {
  257. first = Boolean.FALSE;
  258. }
  259. JSONArray argObj = new JSONArray();
  260. argObj.put(arg.getName());
  261. argObj.put(resolveType(arg.getType()));
  262. if(arg.getType().isConst()) {
  263. JSONArray mods = new JSONArray();
  264. mods.put("const");
  265. argObj.put(mods);
  266. } else {
  267. argObj.put(JSONObject.NULL);
  268. }
  269. arguments.put(argObj);
  270. }
  271. obj.put("arguments", arguments);
  272. /* `returnType` */
  273. if(node.getReturnType() != Type.getVoid()) {
  274. obj.put("returnType", resolveType(node.getReturnType()));
  275. } else {
  276. obj.put("returnType", JSONObject.NULL);
  277. }
  278. return obj;
  279. }
  280. JSONObject buildVariableDecl(VariableDecl decl, ClassDecl cls) throws JSONException {
  281. JSONObject obj = new JSONObject();
  282. obj.put("name", decl.getName());
  283. if(cls != null) {
  284. obj.put("tag", "field(" + cls.getName() + ", " + decl.getName() + ")");
  285. obj.put("type", "field");
  286. } else {
  287. obj.put("tag", decl.getName());
  288. obj.put("type", "globalVariable");
  289. }
  290. JSONArray modifiers = new JSONArray();
  291. if(decl.isStatic())
  292. modifiers.put("static");
  293. /* if(node.isConst())
  294. modifiers.put("const");*/
  295. obj.put("modifiers", modifiers);
  296. if(decl.isExtern()) {
  297. if(!decl.isExternWithName()) {
  298. obj.put("extern", true);
  299. } else {
  300. obj.put("extern", decl.getExternName());
  301. }
  302. } else {
  303. obj.put("extern", false);
  304. }
  305. if(decl.isGlobal()) {
  306. if(decl.isUnmangled()) {
  307. if(!decl.isUnmangledWithName()) {
  308. obj.put("unmangled", true);
  309. } else {
  310. obj.put("unmangled", decl.getUnmangledName());
  311. }
  312. } else {
  313. obj.put("unmangled", false);
  314. }
  315. obj.put("fullName", decl.getFullName());
  316. }
  317. obj.put("varType", resolveType(decl.getType()));
  318. if(decl.getExpression() != null) /* TODO: make this work for `:=` */
  319. obj.put("value", decl.getExpression().toString());
  320. else
  321. obj.put("value", JSONObject.NULL);
  322. return obj;
  323. }
  324. public void visit(ClassDecl node) throws IOException {
  325. try {
  326. JSONObject obj = new JSONObject();
  327. obj.put("name", node.getName());
  328. obj.put("type", "class");
  329. obj.put("tag", node.getName());
  330. obj.put("abstract", node.isAbstract());
  331. if(node.getSuperRef() != null)
  332. obj.put("extends", node.getSuperRef().getName());
  333. else
  334. obj.put("extends", JSONObject.NULL);
  335. if(node.getComment() != null) {
  336. obj.put("doc", node.getComment().getContent());
  337. } else {
  338. obj.put("doc", JSONObject.NULL);
  339. }
  340. /* `genericTypes` */
  341. JSONArray genericTypes = new JSONArray();
  342. for(TypeParam typeParam: node.getTypeParams().values()) {
  343. genericTypes.put(typeParam.getName());
  344. }
  345. obj.put("genericTypes", genericTypes);
  346. if(node.isUnmangled()) {
  347. if(!node.isUnmangledWithName()) {
  348. obj.put("unmangled", true);
  349. } else {
  350. obj.put("unmangled", node.getUnmangledName());
  351. }
  352. } else {
  353. obj.put("unmangled", false);
  354. }
  355. obj.put("fullName", node.getUnderName());
  356. /* `members` */
  357. JSONArray members = new JSONArray();
  358. for(FunctionDecl function: node.getFunctions()) {
  359. if(!function.getName().startsWith("__")) {/* exclude "private" functions */
  360. JSONArray member = new JSONArray();
  361. member.put(function.getName());
  362. member.put(buildFunctionDecl(function));
  363. members.put(member);
  364. }
  365. }
  366. for(VariableDecl decl: node.getVariables()) {
  367. JSONArray member = new JSONArray();
  368. member.put(decl.getName());
  369. member.put(buildVariableDecl(decl, node));
  370. members.put(member);
  371. }
  372. obj.put("members", members);
  373. addObject(obj);
  374. } catch(JSONException e) {
  375. throw new IOException("Fail.");
  376. }
  377. }
  378. public void visit(CoverDecl node) throws IOException {
  379. try {
  380. JSONObject obj = new JSONObject();
  381. obj.put("name", node.getName());
  382. obj.put("type", "cover");
  383. obj.put("tag", node.getName());
  384. if(node.getSuperRef() != null)
  385. obj.put("extends", node.getSuperRef().getName());
  386. else
  387. obj.put("extends", JSONObject.NULL);
  388. if(node.getFromType() != null)
  389. obj.put("from", node.getFromType().toString());
  390. else
  391. obj.put("from", JSONObject.NULL);
  392. if(node.getComment() != null) {
  393. obj.put("doc", node.getComment().getContent());
  394. } else {
  395. obj.put("doc", JSONObject.NULL);
  396. }
  397. if(node.isUnmangled()) {
  398. if(!node.isUnmangledWithName()) {
  399. obj.put("unmangled", true);
  400. } else {
  401. obj.put("unmangled", node.getUnmangledName());
  402. }
  403. } else {
  404. obj.put("unmangled", false);
  405. }
  406. obj.put("fullName", node.getUnderName());
  407. /* `members` */
  408. JSONArray members = new JSONArray();
  409. for(FunctionDecl function: node.getFunctions())
  410. if(!function.getName().equals("class")) {
  411. JSONArray member = new JSONArray();
  412. member.put(function.getName());
  413. member.put(buildFunctionDecl(function));
  414. members.put(member);
  415. }
  416. obj.put("addon", node.isAddon());
  417. obj.put("members", members);
  418. addObject(obj);
  419. } catch(JSONException e) {
  420. throw new IOException("Fail.");
  421. }
  422. }
  423. public void visit(InterfaceDecl interfaceDecl) throws IOException {}
  424. public void visit(TypeArgument typeArgument) throws IOException {}
  425. public void visit(RegularArgument regularArgument) throws IOException {}
  426. public void visit(MemberArgument memberArgument) throws IOException {}
  427. public void visit(MemberAssignArgument memberArgument) throws IOException {}
  428. public void visit(Type type) throws IOException {}
  429. public void visit(BuiltinType builtinType) throws IOException {}
  430. public void visit(VarArg varArg) throws IOException {}
  431. public void visit(NodeList<? extends Node> list) throws IOException {
  432. for(Node node: list) {
  433. node.accept(this);
  434. }
  435. }
  436. public void visit(NodeMap<?, ? extends Node> list) throws IOException {}
  437. public void visit(MultiMap<?, ?> list) throws IOException {}
  438. public void visit(Block block) throws IOException {}
  439. public void visit(VersionBlock versionBlock) throws IOException {}
  440. public void visit(Cast cast) throws IOException {}
  441. public void visit(AddressOf addressOf) throws IOException {}
  442. public void visit(Dereference dereference) throws IOException {}
  443. public void visit(OpDecl opDecl) throws IOException {}
  444. public void visit(BinaryCombination binaryCombination) throws IOException {}
  445. public void visit(Ternary ternary) throws IOException {}
  446. public void visit(Match match) throws IOException {}
  447. public void visit(Case case1) throws IOException {}
  448. public void visit(CommaSequence seq) throws IOException {}
  449. }