PageRenderTime 394ms CodeModel.GetById 110ms app.highlight 152ms RepoModel.GetById 120ms app.codeStats 0ms

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