package synthesijer.ast; import java.util.ArrayList; import java.util.Hashtable; import java.util.LinkedHashMap; import synthesijer.Manager; import synthesijer.SynthesijerUtils; import synthesijer.UnknownModuleException; import synthesijer.ast.expr.Ident; import synthesijer.ast.expr.MethodInvocation; import synthesijer.ast.statement.ExprStatement; import synthesijer.ast.statement.VariableDecl; import synthesijer.ast.type.PrimitiveTypeKind; public class Module implements Scope, SynthesijerAstTree{ // properties private final Scope parent; private final String name; private final Hashtable<String, String> importTable; private final String extending; private final ArrayList<String> implementing; // inner data private LinkedHashMap<String, Method> methodTable = new LinkedHashMap<>(); private LinkedHashMap<String, Variable> variableTable = new LinkedHashMap<>(); private ArrayList<VariableDecl> variableDecls = new ArrayList<>(); private boolean synthesijerHDLFlag = false; private final Method moduleInitMethod; private ArrayList<Scope> scopes = new ArrayList<>(); public Module(String name, Hashtable<String, String> importTable, String extending, ArrayList<String> implementing){ this(null, name, importTable, extending, implementing); } public Module(Scope parent, String name, Hashtable<String, String> importTable, String extending, ArrayList<String> implementing){ this.parent = parent; this.name = name; this.importTable = importTable; this.extending = extending; this.implementing = implementing; scopes.add(this); //this.moduleInitMethod = new Method(this, "synthesijer_class_init_" + name, PrimitiveTypeKind.VOID); //this.moduleInitMethod.setPrivateFlag(true); this.moduleInitMethod = null; } public Hashtable<String, String> getImportTable(){ return importTable; } public ArrayList<String> getImplementingList(){ return implementing; } public void addScope(Scope s){ scopes.add(s); } public Scope[] getChildScope(){ return scopes.toArray(new Scope[]{}); } public String getName(){ return name; } public Scope getParentScope(){ return parent; } public String getExtending(){ return extending; } public Variable search(String name){ Variable var = variableTable.get(name); if(var != null) return var; if(parent != null) return parent.search(name); return null; } public Module getModule(){ return this; } public Method getMethod(){ return moduleInitMethod; } public void addMethod(Method m){ methodTable.put(m.getName(), m); } public Method searchMethod(String name){ return methodTable.get(name); } public void addVariableDecl(VariableDecl v){ variableTable.put(v.getName(), v.getVariable()); variableDecls.add(v); } public VariableDecl[] getVariableDecls(){ return variableDecls.toArray(new VariableDecl[]{}); } public Variable[] getVariables(){ return variableTable.values().toArray(new Variable[]{}); } public Method[] getMethods(){ return methodTable.values().toArray(new Method[]{}); } public void accept(SynthesijerModuleVisitor v){ v.visitModule(this); } @Override public void accept(SynthesijerAstVisitor v) { v.visitModule(this); } public void resolveExtends(){ if(getExtending() == null) return; if(getExtending().equals("HDLModule")){ // skip }else if(getExtending().equals("Thread")){ //TODO experimental addThread(this); }else{ System.out.println("extends: " + getExtending()); Module ext; try{ ext = Manager.INSTANCE.searchModule(getExtending()); }catch(UnknownModuleException e){ SynthesijerUtils.error("cannot find the extending class:" + getExtending()); throw new RuntimeException("cannot find the extending class:" + getExtending()); } ext.resolveExtends(); for(Method m: ext.getMethods()){ if(!methodTable.containsKey(m.getName())){ addMethod(m); } } for(VariableDecl v: ext.getVariableDecls()){ if(!variableTable.containsKey(v.getName())){ addVariableDecl(v); } } } } public boolean isSynthesijerHDL(){ return this.synthesijerHDLFlag; } public void setSynthesijerHDL(boolean flag){ this.synthesijerHDLFlag = flag; } // TODO experimental private void addThread(Module m){ // start Method start = new Method(m, "start", PrimitiveTypeKind.VOID); m.addMethod(start); MethodInvocation tmp = new MethodInvocation(start); Ident run = new Ident(start); run.setIdent("run"); tmp.setMethod(run); start.getBody().addStatement(new ExprStatement(start, tmp)); start.setNoWaitFlag(true); // join Method join = new Method(m, "join", PrimitiveTypeKind.VOID); m.addMethod(join); join.setWaitWithMethod(start); // "join" must wait for "start". Method yield = new Method(m, "yield", PrimitiveTypeKind.VOID); m.addMethod(yield); } }