/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package common; import API.CodeProcessor; import ast.AbstractSyntaxTree; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map; import templates.TemplateDescription; /** * TipoS de SentençaS: – atribuicao : x := y op z ou x := y ou x:= op y – Salto: * goto L – deSvio_condicional: if x relop y goto L – chamda_procedimento: param * x and call p,n – retorno: return y – arrayS: x := y[i] ou x[i]:=y * * @author Eugenio */ public class Code { public static int uniq = 0; public static HashMap reverseName; protected Boolean limparCodigo = true; protected HashMap leaders = new HashMap<>(); protected Integer gline; protected Integer PositionIncrement = 1; protected LinkedList currentBlock = new LinkedList<>(); protected RegistroBase ctx = new Instruction(); protected String name; public AbstractSyntaxTree ast; public Boolean HasCall = false; public Block current; public Code Parent; public DataLayout Data; public HashMap> labels = new HashMap<>(); public HashMap labelsReferenceCount = new HashMap<>(); public Integer PosicaoLabel = 0; public LinkedHashMap stmts = new LinkedHashMap<>(); // public HashMap vars; // protected HashMap templates = new HashMap<>(); // protected HashMap _templates = new HashMap<>(); // protected String commentPrefix = "//"; // protected TPLInterface TPLManager; // private ArrayList processing = new ArrayList<>(); public Code(String id, AbstractSyntaxTree tree) { name = id; ast = tree; Data = new DataLayout(id, null); } public boolean HasCall() { return HasCall; } public Code(String id) { name = id; // currentBlock = new LinkedList<>(); // stmts = new HashMap<>(); Data = new DataLayout(id, null); } public DataLayout GlobalData() { return Data; } public void SetData(DataLayout Data) { this.Data = Data; } public void listBlocks() { System.out.println("Blocks:" + stmts.keySet()); } public void setOtimizacao(boolean lc) { limparCodigo = lc; } public boolean OpenBlock(String id) throws Exception { // if (!bloco.hasChildrens()) { // return false; // } // System.out.println("RegisterBlock:" + id); currentBlock.push(id); current = new Block(id, this); stmts.put(id, current); CodeProcessor.Trigger(this, this.Name(), "OpenBlock"); // incEndereco = 0; // ocorrences = new LinkedHashMap<>(); // ocorrencesPerBlocks.put(id, ocorrences); // dataFrame = new DataLayout(id); // dataFrames.put(id, dataFrame); // current = new ArrayList<>(); // stmts.put(id, current); // pointerCorrente = new Instruction(); // pointers.put(id, pointerCorrente); // pointerCorrente.Set("initAddress", "" + posicaoLabel); // pointerCorrente.Set("bloco", id); // registerVar("sp", 1, dataFrame.TYPE_STACK); // storeReturnAddress = false; // registerVar("ra", 1, dataFrame.TYPE_STACK); // AfterOpen(); return true; } public void CloseBlock() throws Exception { // AfterClose(); CodeProcessor.Trigger(this, this.Name(), "CloseBlock"); Block().Close(); currentBlock.pop(); Use(currentBlock.peek()); // if (!storeReturnAddress) { // dataFrame.delete("ra"); // } // genRepresentation(); // pointerCorrente.Set("endAddress", "" + (posicaoLabel - 1)); // pointerCorrente = null; // current = null; // ocorrences = null; // dataFrame = null; // } public void Use(String id) { // System.out.println("Use '" + id + "'"); if (id == null || id.equals("")) { return; } current = stmts.get(id); // dataFrame = dataFrames.Get(id); // pointerCorrente = pointers.Get(id); } public Block Block() { return current; } public String getCodeStream() throws Exception { // Parametro para formatacao dos enderecos ctx.Set("G.addressLen", (PosicaoLabel + "").length() + ""); // Definicao dos enderecos dos labels for (Map.Entry> x : labels.entrySet()) { ctx.Set("G." + x.getKey(), x.getValue().get(0)); ctx.Set("G.label." + x.getKey(), x.getValue().get(1)); } StringBuilder s = new StringBuilder(); for (Map.Entry entry : stmts.entrySet()) { s.append(getCodeStream(entry.getKey())); } return s.toString(); } public String getCodeStream(String bloco) throws Exception { StringBuilder s = new StringBuilder(); String f; for (Instruction instruction : stmts.get(bloco).Instructions()) { f = FormatInstruction(instruction); if (!f.equals("")) { s.append(f).append("\n"); } } return s.toString(); } protected String FormatInstruction(Instruction inst) throws Exception { String format = inst.Get("format"); String result = ""; if (!format.equals("norender")) { result = templates.Template .FormatRender(format) // Copia todos os atributos do ctx para a instrução .Render(inst.copy("", ctx)); } return result; } public Code Template(TemplateDescription template) throws Exception { templates.Template.Register(template); return this; } public void RemoveLabelReference(String label) { if (!labelsReferenceCount.containsKey(label)) { return; } int count = labelsReferenceCount.get(label); if (count > 0) { labelsReferenceCount.put(label, count - 1); } } public void AddLabelReference(String label) { int count = 0; if (labelsReferenceCount.containsKey(label)) { count = labelsReferenceCount.get(label); } labelsReferenceCount.put(label, count + 1); } public Instruction Add(Instruction nr) throws Exception { boolean add = true; // Se for um acesso ao label registra. a informação é utilizada para remover labels não referenciadas; switch (nr.Get("type")) { case "jump": case "branch": AddLabelReference(nr.Get("label")); } Instruction ur = Last(); // int posicaoLocal = LocalPosition(); if (ur != null) { String label = ur.Get("label"); switch (ur.Get("format")) { case "label": //// nr.Set("line", "" + (posicaoLabel--)); //// nr.Set("value", label + " " + nr.getText()); //// nr.Set("label", label); //// corrente.remove(ur); //// RegisterLabelAddress(label); break; case "jump": /** * Salto para a proxima linha quando o label da nova linha é * igual ao label do salto anterior. Remove o anterior e não * adiciona o novo */ if (nr.Get("format").equals("label") && label.equals(nr.Get("label"))) { current.Remove(ur); add = false; } break; } } if (add) { switch (nr.Get("type")) { case "call": current.HasCall = true; break; case "label": // nr.Set("label.address", RegisterLabelAddress(nr.Get("label"))); break; } current.Add(nr); } return nr; } public Instruction Last() { if (current == null) { return null; } int size = current.Instructions().size(); if (size == 0) { return null; } return current.Instructions().get(size - 1); } public String getCurrentBlockName() { return Block().getName(); } public void PrintData() { System.out.println("DATA LAYOUT ..................."); System.out.println(Data); for (Map.Entry entry : stmts.entrySet()) { System.out.println(entry.getValue().Data()); } } public void Print() throws Exception { System.out.println("INSTRUNCTIONS FRAME ..................."); System.out.println(getCodeStream()); } public String Format() throws Exception { return null; } protected int LocalPosition() throws Exception { return 0; //todo verificar metodo todo // return posicaoLabel - pointerCorrente.getInt("initAddress"); } public String RegisterLabelAddress(String label) { // todo verificar metodo todo // if (!labels.containsKey(label)) { // System.out.println("Registerlabel:" + label.replaceAll("\\+_i\\d+", "+" + Block().CurrentAddress)); // System.out.println("label:" + label); String translated = label.replaceAll("\\+_i\\d+", "+" + Block().CurrentAddress); ArrayList p = new ArrayList<>(); p.add(Position() + ""); p.add(translated); // System.out.println("Register label:" + label + "|" + Block().CurrentAddress); labels.put(label, p); // } return translated; } public static String reverseLabel(String var) { return reverseName.get(var.replaceAll("(\\..*|\\[.*)", "")); } public HashMap getBlocks() { return this.stmts; } // // public Code Formats(HashMap templates) { // this.templates = templates; // return this; // } public String Name() { return this.name; } public String genLabel() { return getCurrentBlockName() + "+" + Block().CurrentAddress; } public void UpdatePositions() throws Exception { // Reseta a posicao inicial; PosicaoLabel = 0; for (Map.Entry x : stmts.entrySet()) { x.getValue().Update(); } } public int Position() { return PosicaoLabel; } public int PositionInc() { int cur = PosicaoLabel; PosicaoLabel += PositionIncrement; return cur; } } // public HashMap getVarOcorrences(String block) throws Exception { //// if (!ocorrencesPerBlocks.containsKey(block)) { //// throw new Exception("Bloco '" + block + "' não definido!"); //// } //// ocorrences = ocorrencesPerBlocks.Get(block); //// //// ArrayList vars = new ArrayList<>(); //// //// for (Map.Entry entry : ocorrences.entrySet()) { //// vars.Add(entry.getValue()); //// } //// Collections.sort(vars); // // HashMap varsOrd = new LinkedHashMap<>(); // //// for (Ocorrence entry : vars) { //// varsOrd.put(entry.var, entry); //// } // return varsOrd; // } // // public static void addVarOcorrence(String var, int access) throws Exception { // Ocorrence o; // //todo verificar metodo todo //// var = Utils.clearName(var); //// //// if (!ocorrences.containsKey(var)) { //// o = new Ocorrence(var); //// ocorrences.put(var, o); //// } else { //// o = ocorrences.Get(var); //// } ////// } else if (line.equals("+1")) { //// o.Add(posicaoLabel, access); // } // public Code CommentPrefix(String cp) { // this.commentPrefix = cp; // return this; // } // public void printOcorrences() { //// System.out.println("VARIABLES OCORRENCES ..................."); //// for (Map.Entry> entry : ocorrenciasGerais.entrySet()) { // //todo //// for (Map.Entry> o : ocorrencesPerBlocks.entrySet()) { //// System.out.println("Block: " + o.getKey()); //// for (Map.Entry x : o.getValue().entrySet()) { //// System.out.println(x); //// } //// } //// } // } // boolean has(String R_RA) { // throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. // }