📄 translate.java
字号:
if (Vargs.size()!=0) { el=new Tree.ExpList(((Exp)Vargs.elementAt(0)).unEx(), null); Tree.ExpList temp1=null, temp2=null; Tree.Exp temp=null; temp1 = el; for (int i=1;i<Vargs.size();i++) { temp=((Exp)Vargs.elementAt(i)).unEx(); temp2=new Tree.ExpList(temp,null); temp1.tail=temp2; temp1=temp1.tail; } } // controlla se e' una funzione di libreria o esterna... // e in base a questo cambia la lista degli argomenti (args) // aggiungendo lo static_link o meno. // lista degli argomenti Tree.ExpList args; // salva la label della funzione Temp.Label labf=levf.frame.name; Hashtable h=frame.funz_ext; // se la funzione non e' di libreria (non esiste gia') if ((h.get(labf.toString())) == null) { Tree.TEMP static_link = new Tree.TEMP(frame.FP()); // calcola lo static link Tree.Exp sl=trovaFrame(levf,curr,static_link); // aggiunge in testa alla lista dei parametri lo static link args = new Tree.ExpList(sl,el); } // altrimenti (se e' una funzione di libreria ... ) else { args = el; } // codice finale: bisogna distinguere se si restituisce un VOID oppure no if (isVoid) return new Nx( new Tree.EXP( new Tree.CALL(new Tree.NAME(levf.frame.name), args))); else return new Ex(new Tree.CALL(new Tree.NAME(levf.frame.name), args)); } // ----- recordExp ----- public Exp recordExp(Vector fields) { // crea il registro per il puntatore al record Temp.Temp r = new Temp.Temp(); Tree.TEMP recordp = new Tree.TEMP(r); // chiama la funzione esterna "allocRecord(size)" che restituisce // il puntatore all'area di memoria allocata (size*wordsize byte) Tree.MOVE extCall= new Tree.MOVE( recordp, frame.externalCall( "allocRecord", new Tree.ExpList( new Tree.CONST(fields.size()*frame.wordSize()), null))); // codice per l'inizializzazione dei campi del record Tree.Stm single_init; Tree.Stm total_init=null; if (fields.size()!=0) { // passo base total_init = new Tree.MOVE(new Tree.MEM(recordp), ((Exp)fields.elementAt(0)).unEx()); // iterazione for (int i=1;i<fields.size();i++) { single_init = new Tree.MOVE( new Tree.MEM( new Tree.BINOP( Tree.BINOP.PLUS, recordp, new Tree.CONST(i*frame.wordSize()))), ((Exp)fields.elementAt(i)).unEx()); total_init = new Tree.SEQ(total_init,single_init); } // for } // if // controlla se non ha campi, in tal caso restituisce CONST(-1) // (non si puo' usare 0 perche' altrimenti si confonde con nilExp) if(fields.isEmpty()) return new Ex(new Tree.CONST(-1)); // completa l'albero (costruisce un ESEQ...) return new Ex(new Tree.ESEQ(new Tree.SEQ(extCall, total_init), recordp)); } // ----- arrayExp ----- public Exp arrayExp(Exp size, Exp init) { // crea il registro per il puntatore all'array Temp.Temp r = new Temp.Temp(); Tree.TEMP arrayp = new Tree.TEMP(r); // calcola lo spazio da allocare ((size + 1) * wordSize) Tree.Exp quantita = intOp( Tree.BINOP.MUL, intOp( Tree.BINOP.PLUS, size, intExp(1)), intExp(frame.wordSize())).unEx(); // chiamata a funzione esterna "initArray(size,init)" che // restituisce il puntatore all'area ampia size*wordsize Tree.Exp routineExt = frame.externalCall( "initArray", new Tree.ExpList( quantita, new Tree.ExpList(size.unEx(), null))); // Codice intermedio totale // initArray alloca la memoria e restituisce il puntatore // al primo campo del vettore. Quindi si riempie il primo campo // con il valore "size". // Infine viene restituito il registro contente il puntatore all'array. return new Ex( new Tree.ESEQ( new Tree.SEQ( new Tree.MOVE(arrayp, routineExt), new Tree.MOVE( new Tree.MEM(arrayp), size.unEx())), arrayp)); } // ----- seqExp ----- /* viene semplicemente costruita una sequenza di "pezzi" di albero gia' passati come parametri (attraverso il Vector pezzi). restituisce un Nx o un Ex a seconda del tipo dell'ultima exp (che fornisce il valore a tutta la sequenza). */ public Exp seqExp(Vector pezzi, boolean isVoid) { Tree.Stm albero_totale = null; // se la sequenza e' vuota... // crea un pezzo di albero fittizio in cui creiamo una nuova etichetta // e ci saltiamo ... if (pezzi.isEmpty()) { Temp.Label lab = new Temp.Label(); return new Nx(new Tree.SEQ(new Tree.JUMP(lab),new Tree.LABEL(lab))); } // controlla prima se la sequenza e' composta da una sola exp // in tal caso restituisce direttamente l'exp totale... if (pezzi.size() == 1 ) { if (isVoid) { return new Nx(((Exp)pezzi.elementAt(0)).unNx()); } else { return new Ex(((Exp)pezzi.elementAt(0)).unEx()); } } // costruisce l'albero fino all'ultimo elemento... for (int i=0;i<pezzi.size() -1;i++) { if (i==0) albero_totale = (((Exp)pezzi.elementAt(0)).unNx()); else albero_totale = new Tree.SEQ(albero_totale,((Exp)pezzi.elementAt(i)).unNx()); } // appende l'ultimo elemento (che da' il valore alla sequenza) in base a isVoid... if (isVoid) { return new Nx(new Tree.SEQ(albero_totale,((Exp)pezzi.lastElement()).unNx())); } else { return new Ex(new Tree.ESEQ(albero_totale,((Exp)pezzi.lastElement()).unEx())); } } // ----- letExp ----- /* Questo metodo crea un ESEQ dove gli stm sono la seq di dichiarazioni (parametro decs) e l'exp e' il corpo della let (parametro body) */ public Exp letExp(Vector decs, Exp body) { // inizializza decs_tree con un "salto a vuoto" per evitare // di mettere null su ESEQ alla fine nel caso in cui il vettore sia vuoto... // cioe' se non ci sono dichiarazioni (...che uso assurdo della let!) Temp.Label lab = new Temp.Label(); Tree.Stm decs_tree = new Tree.SEQ(new Tree.JUMP(lab),new Tree.LABEL(lab)); // crea la SEQ di dichiarazioni... for(int i=0;i<decs.size();i++) { if (i==0) decs_tree = ((Exp)decs.elementAt(0)).unNx(); else { decs_tree=new Tree.SEQ(decs_tree,((Exp)decs.elementAt(i)).unNx()); } } // attacca la sequenza e il body... return new Ex(new Tree.ESEQ(decs_tree,body.unEx())); } // ----- transProg ----- /* il main viene gestito come una funzione il procFrag del main viene inserito nella lista principale dei frags */ public Exp transProg(Exp prg, Level level,boolean isVoid) { if (isVoid) { prg = new Nx( new Tree.SEQ( new Tree.LABEL(level.frame.name), prg.unNx())); } else { if (debflag==1) System.out.println("\n> Registro di restituisce del frame Main, Main.RV(): " + level.frame.RV()); prg = new Nx( new Tree.SEQ( new Tree.LABEL(level.frame.name), new Tree.MOVE( new Tree.TEMP(level.frame.RV()), prg.unEx()))); } // inserisce il ProcFrag nella lista principale frags insFrag(new ProcFrag(prg.unNx(),level.frame)); return prg; } /********************************* * DICHIARAZIONI * *********************************/ // ----- varDec ----- public Exp varDec(Access acc, Level level, Exp init) { return assignExp(simpleVar(acc,level),init); } // ----- functionDec ----- /* Di questo metodo esistono due versioni, una crea un pezzo di albero fittizio (per completare l'albero del Codice Intermedio) l'altra crea il prologo e l'epilogo (tramite il metodo procEntryExit1) e inserisce nella lista dei frags un ProcFrag contenente il codice intermedio del corpo con epilogo e prologo. */ public Exp functionDec() { return new Nx(new Tree.EXP(new Tree.CONST(0))); } public void functionDec(Level level, Exp body, boolean isProc) { procEntryExit1(level,body,isProc); } // ----- typeDec ----- public Exp typeDec() { return new Nx(new Tree.EXP(new Tree.CONST(0))); } // ********************************* // * SUPPORTO * // ********************************* // ----- getResult ----- // restituisce la lista di Data/Proc Frag. public Frag getResult() { return frags; } // ----- procEntryExit1 ---- public void procEntryExit1(Level level,Exp body,boolean isProc) { Tree.Stm body_con_prologo_ed_epilogo; Tree.Stm stmbody; if (isProc) { stmbody = new Tree.SEQ( new Tree.LABEL(level.frame.name), body.unNx()); } else { stmbody = new Tree.SEQ( new Tree.LABEL(level.frame.name), new Tree.MOVE( new Tree.TEMP(frame.RV()), body.unEx())); } // lancia procEntryExit di frame body_con_prologo_ed_epilogo = level.frame.procEntryExit1(stmbody); // inserisce il ProcFrag nella lista principale frags insFrag(new ProcFrag(body_con_prologo_ed_epilogo,level.frame)); } // ----- insFrag ---- // inserisce un frag in "frags" public void insFrag(Frag f) { if (frags==null) frags = f; else if (frags.next==null) frags.next = f; else frags.next.insertFrag(f); } // ----- trovaFrame ----- /* questo metodo trova l'inizio dello stack frame in cui la variabile e' allocata, usando i livelli, partendo dal frame corrente (frame.FP()), e risalendo mano mano un livello per volta. curr.frame.formals.head rappresenta lo static link. NOTA: questo metodo viene utilizzato sia da simpleVar che da callExp. */ public Tree.Exp trovaFrame(Level home, Level curr, Tree.Exp fp) { if (home==curr) return fp; else return trovaFrame(home, curr.parent, curr.frame.formals.head.exp(fp)); } // ----- nullInstr ----- // inserisce codice fittizio nel caso si abbia un "null" in Semant. public Exp nullInstr() { Temp.Label l = new Temp.Label(); return new Nx( new Tree.SEQ( new Tree.JUMP(l), new Tree.LABEL(l))); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -