package TP2.asd; import java.util.ArrayList; import org.pcollections.*; import TP2.asd.Interface.Type; import TP2.asd.Program.Type_intImp; import TP2.llvm.ProgramLLVM.DeclarGlobalLLVMImp; import TP2.llvm.ProgramLLVM.DefineLLVMImp; public class SymTable { private PStack> varMap; private PMap functionsMap; private int[] id ; //id partagé entre toute les symTable, [0] : idVar, [1] : idLabel, [2] : idGlobalVar private ArrayList declarationsGlobal; //aussi partagé entre toute les symTable (.fmt pour les print et scan) public SymTable(){ this.id = new int[3]; this.varMap= ConsPStack.singleton(HashTreePMap.empty()); this.functionsMap = HashTreePMap.empty(); this.declarationsGlobal = new ArrayList<>(); this.id[0] = 1; //idVar this.id[1] = 1; //idLaber this.id[2] = 1; //idGlobalVar } public SymTable(PStack> varMap, PMap functionsMap, int[] id,ArrayList declarationsGlobal){ this.varMap= varMap; this.id = id; this.functionsMap = functionsMap; this.declarationsGlobal = declarationsGlobal; } public static class ValueFunMap{ public DefineLLVMImp define; public Boolean isProto; public ValueFunMap(DefineLLVMImp define, Boolean isProto){ this.define = define; this.isProto = isProto; } } public SymTable newBlock() { return new SymTable(varMap.plus(HashTreePMap.empty()), functionsMap, id,declarationsGlobal); } public SymTable outBlock() { if (varMap.size() > 1) { return new SymTable(varMap.minus(0), functionsMap, id,declarationsGlobal); } else { return this; } } public static class ValueVarMap{ public Type type; public int id; public Boolean isParam; public ValueVarMap(Type type,int id, Boolean isParam){ this.type = type; this.id = id; this.isParam = isParam; } } /*public void update(SymTable symTable2){ this.id = symTable2.getId(); this.idLabel = symTable2.getIdLabel(); this.declarationsGlobal = symTable2.getDeclarationGlobal(); }*/ public ArrayList getDeclarationGlobal(){ return this.declarationsGlobal; } public static class Result{ public SymTable symTable; public String var; public Result(SymTable symTable, String var){ this.symTable = symTable; this.var = var; } } public SymTable addFunction(DefineLLVMImp function, Boolean isProto){ ValueFunMap value = this.functionsMap.get(function.name()); if(value == null || (value!=null && value.isProto && !isProto)){ return new SymTable(this.varMap, this.functionsMap.plus(function.name(),new ValueFunMap(function,isProto)), this.id,this.declarationsGlobal); } else{ if(value.isProto) System.err.println("[VSL compile error] : Le prototype "+function.name()+" existe déjà"); else if(isProto) System.err.println("[VSL compile error] : Le prototype "+function.name()+" doit être déclaré avant son implémentation"); else System.err.println("[VSL compile error] : La fonction "+function.name()+" existe déjà"); return null; } } public ValueFunMap getFunction(String name){ return this.functionsMap.get(name); } public int getId(){ return this.id[0]; } public int getIdLabel(){ return this.id[1]; } public int getNewId(){ int a = this.id[0]; this.id[0]++; return a; } public int getNewIdLabel(){ int a = this.id[1]; this.id[1]++; return a; } public Result addNewTempVar(){ String newVar = "temp"+id[0]; SymTable newSymTab = this.addVarInTab(newVar,new Type_intImp(),false); return new Result(newSymTab,newVar); } public Result addParam(String nomParam){ String newParam = "param_"+nomParam; SymTable newSymTab = this.addVarInTab(nomParam,new Type_intImp(),true); return new Result(newSymTab,newParam); } public String getGlobalDeclName(){; return "fmt"+id[2]; } public void addGlobalDecl(DeclarGlobalLLVMImp decl){ id[2]++; this.declarationsGlobal.add(decl); } public Result addVar(String nomVar) { PMap top = varMap.get(0); if (top.containsKey(nomVar)) { System.err.println("[VSL compile error] :" + "Erreur"); return new Result(this, null); } String realName = nomVar + id[0]; top = top.plus(nomVar, new ValueVarMap(new Type_intImp(), id[0], false)); id[0]++; SymTable newSym = new SymTable(varMap.minus(0).plus(0, top), functionsMap, id,this.declarationsGlobal); return new Result(newSym, realName); } //retourne le nom de la var déjà déclaré avec son id public String getVar(String nomVar){ for(PMap scope : varMap) { if (scope.containsKey(nomVar)) { ValueVarMap value = scope.get(nomVar); String prefix = ""; if(value.isParam){ prefix = "param_"; } return prefix + nomVar + value.id; } } System.err.println("[VSL compile error] :" + nomVar+" n'est pas trovué"); return null; } public Boolean isPresentVar(String nomVar){ for (PMap scope : varMap) { if (scope.containsKey(nomVar)) { return true; } } System.err.println("[VSL compile error] :" + nomVar+" n'est pas trouvé"); return false; } public Type getvar_Type(String s){ for (PMap scope : varMap) { if (scope.containsKey(s)) { return scope.get(s).type; } } return null; } //retourne le type de la var public Type getType(String nomVar){ for (PMap scope : varMap) { if (scope.containsKey(nomVar)) { return scope.get(nomVar).type; } } return null; } public SymTable addVarInTab(String nomVar, Interface.Type type, boolean isParam) { PMap top = varMap.get(0); if (top.containsKey(nomVar)) { System.err.println(nomVar+ " déjà déclaré."); return this; } top = top.plus(nomVar, new ValueVarMap(type, id[0], isParam)); if(!isParam) this.id[0]++; return new SymTable(varMap.minus(0).plus(0, top), functionsMap, id, this.declarationsGlobal); } public String print_all(){ StringBuilder str = new StringBuilder(); str.append("Id = ").append(id[0]).append("\n"); str.append("VARIABLES:\n"); int scopeLevel = varMap.size(); for (PMap scope : varMap) { str.append("Block Level ").append(scopeLevel--).append(":\n"); for (String varName : scope.keySet()) { ValueVarMap value = scope.get(varName); str.append("Name: ").append(varName) .append(", Id: ").append(value.id) .append(", Type: ").append(value.type) .append(", IsParam: ").append(value.isParam) .append("\n"); } } str.append("FUNCTIONS:\n"); for (String funcName : functionsMap.keySet()) { str.append(" Name: ").append(funcName).append("\n"); } return str.toString(); } }