/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2010.
*/
package x10rose.visit;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import polyglot.ast.AbstractBlock_c;
import polyglot.ast.Allocation_c;
import polyglot.ast.AmbAssign_c;
import polyglot.ast.AmbExpr_c;
import polyglot.ast.AmbReceiver_c;
import polyglot.ast.AmbTypeNode_c;
import polyglot.ast.ArrayAccessAssign_c;
import polyglot.ast.ArrayAccess_c;
import polyglot.ast.ArrayInit_c;
import polyglot.ast.Assert_c;
import polyglot.ast.Assign_c;
import polyglot.ast.Block_c;
import polyglot.ast.Branch_c;
import polyglot.ast.Case_c;
import polyglot.ast.Catch_c;
import polyglot.ast.ClassLit_c;
import polyglot.ast.Do_c;
import polyglot.ast.Empty_c;
import polyglot.ast.Eval_c;
import polyglot.ast.Expr_c;
import polyglot.ast.FieldAssign_c;
import polyglot.ast.For_c;
import polyglot.ast.Import_c;
import polyglot.ast.IntLit_c;
import polyglot.ast.Labeled_c;
import polyglot.ast.LocalAssign_c;
import polyglot.ast.LocalClassDecl_c;
import polyglot.ast.NewArray_c;
import polyglot.ast.Node;
import polyglot.ast.NodeFactory;
import polyglot.ast.Node_c;
import polyglot.ast.NullLit_c;
import polyglot.ast.PackageNode_c;
import polyglot.ast.Return_c;
import polyglot.ast.SourceFile;
import polyglot.ast.SourceFile_c;
import polyglot.ast.Stmt_c;
import polyglot.ast.SwitchBlock_c;
import polyglot.ast.Switch_c;
import polyglot.ast.Term_c;
import polyglot.ast.Throw_c;
import polyglot.ast.TopLevelDecl;
import polyglot.ast.Try_c;
import polyglot.ast.TypeNode_c;
import polyglot.ast.While_c;
import polyglot.frontend.Compiler;
import polyglot.frontend.Job;
import polyglot.frontend.Source;
import polyglot.frontend.TargetFactory;
import polyglot.main.Options;
import polyglot.types.TypeSystem;
import polyglot.util.CodeWriter;
import polyglot.util.ErrorInfo;
import polyglot.util.ErrorQueue;
import polyglot.util.StringUtil;
import polyglot.visit.Translator;
import x10.ExtensionInfo.X10Scheduler.X10Job;
import x10.ast.AmbDepTypeNode_c;
import x10.ast.AnnotationNode_c;
import x10.ast.AssignPropertyCall_c;
import x10.ast.Async_c;
import x10.ast.AtEach_c;
import x10.ast.AtExpr_c;
import x10.ast.AtHomeExpr_c;
import x10.ast.AtHomeStmt_c;
import x10.ast.AtStmt_c;
import x10.ast.Atomic_c;
import x10.ast.ClosureCall_c;
import x10.ast.Closure_c;
import x10.ast.DepParameterExpr_c;
import x10.ast.Finish_c;
import x10.ast.ForLoop_c;
import x10.ast.HasZeroTest_c;
import x10.ast.Here_c;
import x10.ast.LocalTypeDef_c;
import x10.ast.Next_c;
import x10.ast.ParExpr_c;
import x10.ast.PropertyDecl_c;
import x10.ast.SettableAssign_c;
import x10.ast.StmtExpr_c;
import x10.ast.StmtSeq_c;
import x10.ast.SubtypeTest_c;
import x10.ast.Tuple_c;
import x10.ast.TypeDecl_c;
import x10.ast.When_c;
import x10.ast.X10Binary_c;
import x10.ast.X10BooleanLit_c;
import x10.ast.X10Call_c;
import x10.ast.X10CanonicalTypeNode_c;
import x10.ast.X10Cast_c;
import x10.ast.X10CharLit_c;
import x10.ast.X10ClassBody_c;
import x10.ast.X10ClassDecl_c;
import x10.ast.X10ClockedLoop_c;
import x10.ast.X10Conditional_c;
import x10.ast.X10ConstructorCall_c;
import x10.ast.X10ConstructorDecl_c;
import x10.ast.X10Do_c;
import x10.ast.X10FieldDecl_c;
import x10.ast.X10Field_c;
import x10.ast.X10FloatLit_c;
import x10.ast.X10Formal_c;
import x10.ast.X10If_c;
import x10.ast.X10Instanceof_c;
import x10.ast.X10LocalDecl_c;
import x10.ast.X10Local_c;
import x10.ast.X10Loop_c;
import x10.ast.X10MethodDecl_c;
import x10.ast.X10New_c;
import x10.ast.X10Special_c;
import x10.ast.X10StringLit_c;
import x10.ast.X10Unary_c;
import x10.ast.X10While_c;
import x10.visit.X10DelegatingVisitor;
public class RoseTranslator extends Translator {
public RoseTranslator(Job job, TypeSystem ts, NodeFactory nf, TargetFactory tf) {
super(job, ts, nf, tf);
}
protected boolean translateSource(SourceFile sfn) {
TypeSystem ts = typeSystem();
NodeFactory nf = nodeFactory();
TargetFactory tf = this.tf;
ErrorQueue eq = job.compiler().errorQueue();
Compiler compiler = job.compiler();
Options options = job.extensionInfo().getOptions();
Source src = sfn.source();
String in_file_name = sfn.source().path();
String out_file_name = in_file_name + ".Rose.dot";
// Find the public declarations in the file. We'll use these to
// derive the names of the target files. There will be one
// target file per public declaration. If there are no public
// declarations, we'll use the source file name to derive the
// target file name.
List<TopLevelDecl> exports = exports(sfn);
CodeWriter w = null;
try {
w = tf.outputCodeWriter(new File(out_file_name), 100);
job.compiler().addOutputFile(in_file_name, out_file_name);
w.writeln("digraph \"" + in_file_name + "\" {");
new DV(w, null).visitAppropriate(sfn);
w.writeln("}");
w.newline(0);
return true;
} catch (IOException e) {
eq.enqueue(ErrorInfo.IO_ERROR, "I/O error while translating: " + e.getMessage());
return false;
} finally {
if (w != null) {
try {
w.close();
String[] cmdline = {"dot", "-Tpng", "-O", out_file_name};
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(cmdline, null, options.output_directory);
InputStreamReader err = new InputStreamReader(proc.getErrorStream());
String output = null;
try {
char[] c = new char[72];
int len;
StringBuffer sb = new StringBuffer();
while((len = err.read(c)) > 0) {
sb.append(String.valueOf(c, 0, len));
}
if (sb.length() != 0) {
output = sb.toString();
}
}
finally {
err.close();
}
proc.waitFor();
if (!options.keep_output_files) {
String[] rmCmd = new String[] {"rm", out_file_name};
runtime.exec(rmCmd, null, options.output_directory);
}
if (output != null)
eq.enqueue(proc.exitValue()>0 ? ErrorInfo.POST_COMPILER_ERROR : ErrorInfo.WARNING, output);
if (proc.exitValue() > 0) {
eq.enqueue(ErrorInfo.POST_COMPILER_ERROR, "Non-zero return code: " + proc.exitValue());
return false;
}
} catch(Exception e) {
eq.enqueue(ErrorInfo.POST_COMPILER_ERROR, e.getMessage() != null ? e.getMessage() : e.toString());
return false;
}
} catch (IOException e) {
job.compiler().errorQueue().enqueue(ErrorInfo.IO_ERROR, "I/O error while closing output file: " + e.getMessage());
}
}
}
}
int counter = 0;
String getDotNode(Node n) {
String id;
if (dotNode.containsKey(n)) {
id = dotNode.get(n);
} else {
id = Integer.toString(counter++);
dotNode.put(n, id);
}
return id;
}
Map<Node, String> dotNode = new HashMap<Node, String>();
public class DV extends X10DelegatingVisitor {
Node parent;
CodeWriter w;
DV(CodeWriter w, Node parent) {
this.parent = parent;
this.w = w;
}
void createDotNode(Node n, String name, String... extra) {
w.write(getDotNode(n) + " [");
Map<String, String> extraMap = new HashMap<String, String>();
// defaults
extraMap.put("style", "filled");
extraMap.put("penwidth", "2.0");
extraMap.put("label", n.getClass().toString() + (name != null ? "\\n" + name : ""));
extraMap.put("shape", "box");
extraMap.put("color", "#000000");
extraMap.put("fillcolor", "#FFFFFF");
// override defaults here
for (String s : extra) {
if (!s.contains("=")) {
System.err.println("Unrecognised dot node option: " + s);
continue;
}
String before = s.substring(0, s.indexOf("="));
String after = s.substring(s.indexOf("=") + 1);
extraMap.put(before, after);
}
for (String key : extraMap.keySet()) {
w.writeln(key + "=\"" + extraMap.get(key) + "\", ");
}
w.writeln("];");
if (parent != null)
w.writeln(getDotNode(parent) + " -> " + getDotNode(n));
try {
w.flush();
} catch (IOException e) {
throw new Error(e);
}
}
void visitChild(Node p, Node n) {
if (n == null)
return;
new DV(w, p).visitAppropriate(n);
}
void visitChildren(Node p, List<? extends Node> l) {
if (l == null)
return;
for (Node n : l)
visitChild(p, n);
}
public void visit(Node_c n) {
createDotNode(n, null, "fillcolor=#FF0000", "fontcolor=#ffffff", "shape=Mdiamond");
System.err.println("UNRECOGNISED NODE in DotTranslator: " + n.getClass());
}
public void visit(SourceFile_c n) {
createDotNode(n, n.source().path(), "shape=folder", "fillcolor=#000040", "fontcolor=#ffffff");
visitChildren(n, n.decls());
}
public void visit(Import_c n) {
createDotNode(n, n.kind() + " " + n.name().toString());
}
public void visit(PackageNode_c n) {
createDotNode(n, n.package_().get().toString());
}
public void visit(X10ClassDecl_c n) {
createDotNode(n, n.name().id().toString(), "shape=house", "fillcolor=#004000", "fontcolor=#ffffff");
visitChildren(n, n.typeParameters());
visitChildren(n, n.properties());
visitChild(n, n.classInvariant());
visitChild(n, n.superClass());
visitChildren(n, n.interfaces());
visitChild(n, n.body());
}
public void visit(LocalClassDecl_c n) {
createDotNode(n, null);
visitChild(n, n.decl());
}
public void visit(X10ClassBody_c n) {
createDotNode(n, null, "shape=house");
visitChildren(n, n.members());
}
public void visit(X10MethodDecl_c n) {
createDotNode(n, n.name().id().toString(), "shape=trapezium", "fillcolor=#FFC0A0");
visitChildren(n, n.formals());
visitChild(n, n.guard());
visitChild(n, n.offerType());
visitChildren(n, n.throwsTypes());
visitChild(n, n.body());
}
public void visit(X10Formal_c n) {
createDotNode(n, n.name().id().toString(), "shape=trapezium", "fillcolor=#FFC0A0");
visitChild(n, n.type());
}
public void visit(X10Call_c n) {
createDotNode(n, n.name().id().toString(), "fillcolor=#FFC0A0", "shape=oval");
visitChild(n, n.target());
visitChildren(n, n.typeArguments());
visitChildren(n, n.arguments());
}
public void visit(X10ConstructorDecl_c n) {
createDotNode(n, n.name().id().toString(), "shape=trapezium", "fillcolor=#FFFFA0");
visitChildren(n, n.formals());
visitChild(n, n.guard());
visitChild(n, n.offerType());
visitChildren(n, n.throwsTypes());
visitChild(n, n.body());
}
public void visit(X10ConstructorCall_c n) {
createDotNode(n, null, "fillcolor=#FFFFC0", "shape=oval");
visitChild(n, n.target());
visitChildren(n, n.typeArguments());
visitChildren(n, n.arguments());
}
public void visit(Block_c n) {
createDotNode(n, null, "fillcolor=#000000", "fontcolor=#ffffff");
visitChildren(n, n.statements());
}
public void visit(StmtSeq_c n) {
createDotNode(n, null, "fillcolor=#000000", "fontcolor=#ffffff");
visitChildren(n, n.statements());
}
public void visit(AssignPropertyCall_c n) {
createDotNode(n, null);
visitChildren(n, n.arguments());
}
public void visit(Empty_c n) {
createDotNode(n, null, "fillcolor=#000000", "fontcolor=#ffffff");
}
public void visit(X10CanonicalTypeNode_c n) {
createDotNode(n, n.nameString(), "shape=oval", "fillcolor=#C0FFC0");
}
public void visit(Return_c n) {
createDotNode(n, null, "fillcolor=#000000", "fontcolor=#ffffff");
visitChild(n, n.expr());
}
public void visit(X10Binary_c n) {
createDotNode(n, n.operator().toString(), "shape=oval");
visitChild(n, n.left());
visitChild(n, n.right());
}
public void visit(X10Unary_c n) {
createDotNode(n, n.operator().toString(), "shape=oval");
visitChild(n, n.expr());
}
public void visit(ParExpr_c n) { // parentheses
createDotNode(n, "( )", "shape=oval");
visitChild(n, n.expr());
}
public void visit(X10Special_c n) {
createDotNode(n, n.kind().toString(), "shape=oval", "fillcolor=#C0C0FF");
}
public void visit(Here_c n) {
createDotNode(n, "here", "shape=oval", "fillcolor=#C0C0FF");
}
public void visit(X10Local_c n) {
createDotNode(n, n.name().id().toString(), "shape=oval", "fillcolor=#C0C0C0");
}
public void visit(Eval_c n) {
createDotNode(n, null);
visitChild(n, n.expr());
}
public void visit(For_c n) {
createDotNode(n, null, "shape=parallelogram", "fillcolor=#000000", "fontcolor=#ffffff");
visitChildren(n, n.inits());
visitChild(n, n.cond());
visitChildren(n, n.iters());
visitChild(n, n.body());
}
public void visit(ForLoop_c n) {
createDotNode(n, null, "shape=parallelogram", "fillcolor=#000000", "fontcolor=#ffffff");
visitChild(n, n.formal());
visitChild(n, n.cond());
visitChild(n, n.domain());
visitChild(n, n.body());
}
public void visit(Branch_c n) {
createDotNode(n, n.kind()+(n.labelNode()!=null ? "\\n"+n.labelNode().id().toString() : ""), "fillcolor=#000000", "fontcolor=#ffffff");
}
public void visit(X10Do_c n) {
createDotNode(n, null, "shape=parallelogram", "fillcolor=#000000", "fontcolor=#ffffff");
visitChild(n, n.cond());
visitChild(n, n.body());
}
public void visit(X10While_c n) {
createDotNode(n, null, "shape=parallelogram", "fillcolor=#000000", "fontcolor=#ffffff");
visitChild(n, n.cond());
visitChild(n, n.body());
}
public void visit(Tuple_c n) {
createDotNode(n, null, "shape=oval");
visitChildren(n, n.arguments());
}
public void visit(SettableAssign_c n) {
createDotNode(n, null, "shape=oval");
visitChild(n, n.left());
visitChildren(n, n.index());
visitChild(n, n.right());
}
public void visit(FieldAssign_c n) {
createDotNode(n, n.name().id().toString(), "shape=oval", "fillcolor=#008000", "fontcolor=#ffffff");
visit(n.target());
visit(n.right());
}
public void visit(X10Field_c n) {
createDotNode(n, n.name().id().toString(), "shape=oval", "fillcolor=#008000", "fontcolor=#ffffff");
visit(n.target());
}
public void visit(X10FieldDecl_c n) {
createDotNode(n, n.name().id().toString(), "fillcolor=#008000", "fontcolor=#ffffff");
visitChild(n, n.type());
visitChild(n, n.init());
}
public void visit(X10LocalDecl_c n) {
createDotNode(n, n.name().id().toString());
visitChild(n, n.type());
visitChild(n, n.init());
}
public void visit(PropertyDecl_c n) {
createDotNode(n, n.name().id().toString());
visitChild(n, n.type());
visitChild(n, n.init());
}
public void visit(X10If_c n) {
createDotNode(n, null, "fillcolor=#000000", "fontcolor=#ffffff");
visitChild(n, n.cond());
visitChild(n, n.consequent());
visitChild(n, n.alternative());
}
public void visit(X10Conditional_c n) {
createDotNode(n, "? :", "shape=oval");
visitChild(n, n.cond());
visitChild(n, n.consequent());
visitChild(n, n.alternative());
}
public void visit(Assert_c n) {
createDotNode(n, null, "color=#FF0000");
visitChild(n, n.cond());
visitChild(n, n.errorMessage());
}
public void visit(Throw_c n) {
createDotNode(n, null, "fillcolor=#400000", "fontcolor=#ffffff");
visitChild(n, n.expr());
}
public void visit(Try_c n) {
createDotNode(n, null, "fillcolor=#400000", "fontcolor=#ffffff");
visitChild(n, n.tryBlock());
visitChildren(n, n.catchBlocks());
visitChild(n, n.finallyBlock());
}
public void visit(Catch_c n) {
createDotNode(n, null, "fillcolor=#400000", "fontcolor=#ffffff");
visitChild(n, n.formal());
visitChild(n, n.body());
}
public void visit(Labeled_c n) {
createDotNode(n, n.labelNode().id().toString(), "color=#A0A0A0");
visitChild(n, n.statement());
}
public void visit(X10BooleanLit_c n) {
createDotNode(n, Boolean.toString(n.value()), "shape=invtriangle", "fillcolor=#A0A0FF");
}
public void visit(ClassLit_c n) {
createDotNode(n, null, "shape=invtriangle", "fillcolor=#A0A0FF");
visitChild(n, n.typeNode());
}
public void visit(X10FloatLit_c n) {
createDotNode(n, Double.toString(n.value()), "shape=invtriangle", "fillcolor=#A0A0FF");
}
public void visit(NullLit_c n) {
createDotNode(n, "null", "shape=invtriangle", "fillcolor=#A0A0FF");
}
public void visit(X10CharLit_c n) {
createDotNode(n, "" + n.value(), "shape=invtriangle", "fillcolor=#A0A0FF");
}
public void visit(IntLit_c n) {
createDotNode(n, Long.toString(n.value()), "shape=invtriangle", "fillcolor=#A0A0FF");
}
public void visit(X10StringLit_c n) {
createDotNode(n, StringUtil.escape(n.value()), "shape=invtriangle", "fillcolor=#A0A0FF");
}
public void visit(Finish_c n) {
createDotNode(n, null, "fillcolor=#004040", "fontcolor=#ffffff");
visitChild(n, n.body());
}
public void visit(AtStmt_c n) {
createDotNode(n, null, "fillcolor=#004040", "fontcolor=#ffffff");
visitChild(n, n.place());
visitChild(n, n.body());
}
public void visit(AtHomeStmt_c n) {
createDotNode(n, null, "fillcolor=#004040", "fontcolor=#ffffff");
visitChild(n, n.place());
visitChild(n, n.body());
}
public void visit(AtExpr_c n) {
createDotNode(n, null, "shape=oval", "fillcolor=#004040", "fontcolor=#ffffff");
visitChild(n, n.place());
visitChild(n, n.body());
}
public void visit(AtHomeExpr_c n) {
createDotNode(n, null, "shape=oval", "fillcolor=#004040", "fontcolor=#ffffff");
visitChild(n, n.place());
visitChild(n, n.body());
}
public void visit(AtEach_c n) {
createDotNode(n, null, "fillcolor=#004040", "fontcolor=#ffffff");
visitChild(n, n.formal());
visitChild(n, n.domain());
visitChild(n, n.body());
}
public void visit(Async_c n) {
createDotNode(n, null, "fillcolor=#004040", "fontcolor=#ffffff");
visitChild(n, n.body());
}
public void visit(Atomic_c n) {
createDotNode(n, null, "fillcolor=#004040", "fontcolor=#ffffff");
visitChild(n, n.body());
}
public void visit(When_c n) {
createDotNode(n, null, "fillcolor=#004040", "fontcolor=#ffffff");
visitChild(n, n.expr());
visitChild(n, n.stmt());
}
public void visit(X10New_c n) {
createDotNode(n, null, "shape=oval", "fillcolor=#FFFFC0");
visitChildren(n, n.typeArguments());
visitChildren(n, n.arguments());
visitChild(n, n.objectType());
visitChild(n, n.body());
}
public void visit(Allocation_c n) {
createDotNode(n, null, "shape=oval");
visitChild(n, n.objectType());
}
public void visit(LocalAssign_c n) {
createDotNode(n, null, "shape=oval");
visitChild(n, n.local());
visitChild(n, n.right());
}
public void visit(X10Cast_c n) {
createDotNode(n, null, "shape=oval");
visitChild(n, n.castType());
visitChild(n, n.expr());
}
public void visit(X10Instanceof_c n) {
createDotNode(n, null, "shape=oval");
visitChild(n, n.compareType());
visitChild(n, n.expr());
}
public void visit(SubtypeTest_c n) {
createDotNode(n, null, "shape=oval", "fillcolor=#C0FFC0");
visitChild(n, n.subtype());
visitChild(n, n.supertype());
}
public void visit(DepParameterExpr_c n) {
createDotNode(n, null, "shape=oval");
visitChildren(n, n.formals());
visitChildren(n, n.condition());
}
public void visit(HasZeroTest_c n) {
createDotNode(n, null, "shape=oval", "fillcolor=#C0FFC0");
visitChild(n, n.parameter());
}
public void visit(Closure_c n) {
createDotNode(n, null, "shape=oval", "fillcolor=#FFA0A0");
visitChildren(n, n.formals());
visitChild(n, n.body());
}
public void visit(ClosureCall_c n) {
createDotNode(n, null, "shape=oval", "fillcolor=#FFA0A0");
visitChild(n, n.target());
visitChildren(n, n.arguments());
}
public void visit(StmtExpr_c n) {
createDotNode(n, null, "shape=oval");
visitChildren(n, n.statements());
}
public void visit(AmbReceiver_c n) {
createDotNode(n, n.nameNode().id().toString());
}
public void visit(Switch_c n) {
createDotNode(n, null);
visitChild(n, n.expr());
visitChildren(n, n.elements());
}
public void visit(SwitchBlock_c n) {
createDotNode(n, null);
visitChildren(n, n.statements());
}
public void visit(Case_c n) {
createDotNode(n, null);
visitChild(n, n.expr());
}
public void visit(LocalTypeDef_c n) {
createDotNode(n, null);
visitChild(n, n.typeDef());
}
public void visit(Next_c n) {
createDotNode(n, "here", "shape=oval", "fillcolor=#C0C0FF");
}
public void visit(TypeDecl_c n) {
createDotNode(n, n.name().id().toString(), "fillcolor=#C0FFC0");
visitChild(n, n.type());
}
}
}