package synthesijer.jcfrontend;
import java.util.List;
import openjdk.com.sun.tools.javac.tree.JCTree;
import openjdk.com.sun.tools.javac.tree.JCTree.JCAnnotation;
import openjdk.com.sun.tools.javac.tree.JCTree.JCAssign;
import openjdk.com.sun.tools.javac.tree.JCTree.JCClassDecl;
import openjdk.com.sun.tools.javac.tree.JCTree.JCExpression;
import openjdk.com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import openjdk.com.sun.tools.javac.tree.JCTree.JCStatement;
import openjdk.com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import openjdk.com.sun.tools.javac.tree.JCTree.Visitor;
import synthesijer.SynthesijerUtils;
import synthesijer.ast.Method;
import synthesijer.ast.Module;
import synthesijer.ast.Scope;
import synthesijer.ast.Type;
import synthesijer.ast.statement.VariableDecl;
import synthesijer.ast.type.MySelfType;
/**
* A visitor to generate an instance of Module from a given instance of JCClassDecl.
*
* @author miyo
*
*/
public class JCTopVisitor extends Visitor{
private final Module module;
public JCTopVisitor(Module m){
this.module = m;
}
public Scope getScope(){
return module;
}
public void visitClassDef(JCClassDecl that){
for (JCTree def : that.defs) {
if(def == null){
;
}else if(def instanceof JCMethodDecl){
def.accept(this);
}else if(def instanceof JCVariableDecl){
def.accept(new JCStmtVisitor(module));
}else{
System.err.printf("Unknown class: %s (%s)", def, def.getClass());
}
}
}
public void visitMethodDef(JCMethodDecl decl){
String name = decl.getName().toString();
Type type;
if(JCFrontendUtils.isConstructor(decl)){
type = new MySelfType();
}else{
type = TypeBuilder.genType(decl.getReturnType());
}
Method m = new Method(module, name, type);
m.setArgs(parseArgs(decl.getParameters(), m));
if(JCFrontendUtils.isAnnotatedBy(decl.mods.annotations, "unsynthesizable")){
return;
}
m.setUnsynthesizableFlag(JCFrontendUtils.isAnnotatedBy(decl.mods.annotations, "unsynthesizable"));
/*
m.setAutoFlag(JCFrontendUtils.isAnnotatedBy(decl.mods.annotations, "auto") & module.isSynthesijerHDL());
if(JCFrontendUtils.isAnnotatedBy(decl.mods.annotations, "auto") & (!module.isSynthesijerHDL())){
SynthesijerUtils.warn("@auto for " + module.getName() + "::" + name + " is skipped, because @synthesijerhdl is not set.");
}
*/
m.setAutoFlag(JCFrontendUtils.isAnnotatedBy(decl.mods.annotations, "auto"));
m.setSynchronizedFlag(JCFrontendUtils.isSynchronized(decl.mods));
m.setPrivateFlag(JCFrontendUtils.isPrivate(decl.mods));
m.setRawFlag(JCFrontendUtils.isAnnotatedBy(decl.mods.annotations, "raw"));
m.setCombinationFlag(JCFrontendUtils.isAnnotatedBy(decl.mods.annotations, "combination"));
m.setParallelFlag(JCFrontendUtils.isAnnotatedBy(decl.mods.annotations, "parallel"));
m.setNoWaitFlag(JCFrontendUtils.isAnnotatedBy(decl.mods.annotations, "no_wait"));
m.setConstructorFlag(JCFrontendUtils.isConstructor(decl));
if(JCFrontendUtils.isAnnotatedBy(decl.mods.annotations, "CallStack")){
m.setCallStackFlag(true);
JCAnnotation a = JCFrontendUtils.getAnnotation(decl.mods.annotations, "CallStack");
for(JCExpression expr: a.args){
if(expr instanceof JCAssign){
JCAssign assign = (JCAssign)expr;
m.setCallStackSize(Integer.parseInt(assign.rhs.toString()));
}else{
SynthesijerUtils.warn("unexpected argument for @CallStack: " + expr);
SynthesijerUtils.warn("Use \"value=immidiate\" or \"immidiate\"");
}
}
}else{
m.setCallStackFlag(false);
}
if(decl.body != null){
for(JCStatement stmt: decl.body.getStatements()){
JCStmtVisitor visitor = new JCStmtVisitor(m);
stmt.accept(visitor);
m.getBody().addStatement(visitor.getStatement());
}
}
module.addMethod(m);
}
/**
* parse arguments of method declaration.
* @param args
* @param scope
* @return
*/
private VariableDecl[] parseArgs(List<JCVariableDecl> args, Scope scope){
if(args == null || args.size() == 0) return new VariableDecl[0];
VariableDecl[] v = new VariableDecl[args.size()];
for(int i = 0; i < v.length; i++){
JCStmtVisitor visitor = new JCStmtVisitor(scope);
args.get(i).accept(visitor); // Since args.get(i) is an instance of JCVariableDecl,
// this visitor should visit visitVarDef
v[i] = (VariableDecl)(visitor.getStatement()); // this type cast should occur no errors.
v[i].setMethodParam(true);
}
return v;
}
public void visitTree(JCTree t){
SynthesijerUtils.error("[JCTopVisitor] The following is unexpected in this context.");
SynthesijerUtils.dump(t);
}
}