⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 translate.java

📁 编译原理大作业---tiger编译器 包括semant,translate,mipsframe,regalloc等所有phase 懂的人自会知道
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package Translate;import java.util.Hashtable;import java.util.Vector;public class Translate {   ErrorMsg.ErrorMsg errorMsg;   Frame.Frame frame;   // Serve per evitare di creare tramite new Label(s) tante etichette s   // tutte con lo stesso significato: sarebbero dei duplicati potenzialmente   // in grado di confondere altre parti del compilatore (Appel [2nd Ed.] p.153)   public static Hashtable string_to_label = new Hashtable();   // Lista di tutte le stringhe (DataFrag) e le funzioni con relativo   // corpo in codice intermedio e frame (ProcFrag) incontrate   private static Frag frags;   int debflag; // per il debug   public Translate(ErrorMsg.ErrorMsg err, Frame.Frame fr,int db) {      errorMsg = err;      frame = fr;      debflag = db;   }   /*******************************    *          VARIABILI          *    *******************************/   // ----- simpleVar -----   public Exp simpleVar(Access access, Level level) {      // Puntatore allo stack frame corrente      Tree.TEMP static_link = new Tree.TEMP(frame.FP());      return new Ex( access.acc.exp(trovaFrame(access.home, level, static_link)) );   }   // ----- subscriptVar -----   /*      Poiche' l'array viene inizializzato inserendo al primo      elemento la dimensione dell'array (utile per controllare      l'index out of bounds) e di seguito gli altri elementi,      a questo livello occorre controllare che l'indice i dato nella      subscriptVar a[i] non superi la dimensione dell'array e non      sia < 0.      Quindi la parte di codice intermedio sara' un'istruzione di      controlla per verificare quanto appena detto, seguita dai      rami ramoOK e ramoErr.   */   public Exp subscriptVar(Exp v,Exp index) {      // pseudo-registro per l'indice      Temp.Temp r = new Temp.Temp();      // istruzioni per caricare index nel registro      Tree.MOVE caricaregIndex = new Tree.MOVE(new Tree.TEMP(r),index.unEx());      // per poterlo utilizzare anche con RelCx...      Exp regIndex = new Ex(new Tree.TEMP(r));      // costruzione dei due rami per il controlla dell'indice...      // caso senza errore "index out ot bounds"      Tree.Exp ramoOK = new Tree.MEM(                           new Tree.BINOP(                              Tree.BINOP.PLUS,                              v.unEx(),                              new Tree.BINOP(                                 Tree.BINOP.MUL,                                 new Tree.BINOP(                                    Tree.BINOP.PLUS,                                    regIndex.unEx(),                                    new Tree.CONST(1)),                                 new Tree.CONST(frame.wordSize()))));      // caso con errore "index out of bounds"      Tree.SEQ ramoErr =  new Tree.SEQ(                             new Ex(                                frame.externalCall("print",                                new Tree.ExpList(                                   stringExp("Runtime error: indice dell'array fuori dai limiti").unEx(),                                   null))                             ).unNx(),                             new Ex(frame.externalCall("exit", new Tree.ExpList(intExp(-1).unEx(), null))).unNx()                          );     // condizione della If     Exp cond = intOp(                   Tree.BINOP.OR,                   new RelCx(regIndex, intExp(0), Tree.CJUMP.LT),                   new RelCx(regIndex, new Ex(new Tree.MEM(v.unEx())), Tree.CJUMP.GT)                );     // codice finale per subscriptVar     return new Ex(new Tree.ESEQ(caricaregIndex, ifExp(cond, new Nx(ramoErr), new Ex(ramoOK)).unEx()));   }   // ----- fieldVar -----   /*     Bisogna individuare l'errore runtime     di riferimento ad un campo di una variabile record con valore nil.     nil corrisponde a CONST(0) basta quindi controllare     che v non punti a nil e quindi a 0.   */   public Exp fieldVar(Exp v, int fieldpos) {      // caso ok      Tree.Exp ramoOK = new Tree.MEM(                           new Tree.BINOP(                              Tree.BINOP.PLUS,                              v.unEx(),                              new Tree.BINOP(                                 Tree.BINOP.MUL,                                 new Tree.CONST(fieldpos),                                 new Tree.CONST(frame.wordSize()))));      // caso con errore      Tree.SEQ ramoErr =  new Tree.SEQ(                             new Ex(                                frame.externalCall(                                   "print",                                   new Tree.ExpList(                                      stringExp("Runtime error: riferemento ad un campo di una var. record con valore nil").unEx(),                                      null))                             ).unNx(),                             new Ex(frame.externalCall("exit", new Tree.ExpList(intExp(-1).unEx(), null))).unNx());      // condizione della If      // ( v == nil ) ?      Exp cond = new RelCx(v, nilExp(), Tree.CJUMP.EQ);      // codice finale per fieldVar      return new Ex(ifExp(cond, new Nx(ramoErr), new Ex(ramoOK)).unEx());   }   /********************************    *          ESPRESSIONI         *    ********************************/   // ----- intOp -----   public Exp intOp(int op, Exp sx, Exp dx) {      // distingue il caso della divisione dagli altri casi (per poter gestire la div per 0)      if(op != Tree.BINOP.DIV ) { return new Ex(new Tree.BINOP(op, sx.unEx(), dx.unEx())); }      // se e' una divisione controlla che non sia una divisione per 0      // restituendo errore se div per 0 o il risultato altrimenti.      else {         // prepara lo stm per la div per 0         Tree.Stm div0 = new Tree.SEQ(                            new Ex(                               frame.externalCall(                                  "print",                                   new Tree.ExpList( stringExp("Runtime error: divisione per 0").unEx(), null))                            ).unNx(),                            new Ex(frame.externalCall("exit", new Tree.ExpList( intExp(-1).unEx(), null))).unNx());         // prepara lo stm per il calcolo (non div 0)         Tree.Exp nondiv0 = new Tree.BINOP(op, sx.unEx(), dx.unEx());         // restituisce la IF con il controlla e i due "cammini" possibili         return new IfThenElseExp(new RelCx(dx, intExp(0), Tree.CJUMP.EQ), new Nx(div0), new Ex(nondiv0));      }   }   // ---- compOp ----   /*    converteamo l'Absyn.OpExp nella rispettiva costante di CJUMP                    TABELLA DI CONVERSIONE    Tree.CJUMP    0    1    2    3    4    5    operatore    EQ   NE   LT   GT   LE   GE    Absyn.OpExp   4    5    6    8    7    9   */   public Exp compOp(int op, Exp sx, Exp dx, boolean str) {      int opCJUMP=-1;      switch(op) {         case 4: case 5: case 6: case 9: opCJUMP=op-4; break;         case 8: opCJUMP=op-5; break;         case 7: opCJUMP=op-3; break;         default: errorMsg.error(-1,"Conversione degli interi di comparazione non riuscita.");      }      // se sono stringhe...      if (str) {         return new RelCx(                   new Ex(                      frame.externalCall(                         "stringEqual",                         new Tree.ExpList(sx.unEx(), new Tree.ExpList(dx.unEx(), null)))),                   intExp(1),                   Tree.CJUMP.EQ);      }      // ...altrimenti      else return new RelCx(sx,dx,opCJUMP);   }   // ----- intExp -----   public Exp intExp(int x) { return new Ex(new Tree.CONST(x)); }   // ----- stringExp -----   public Exp stringExp(String s) {      Temp.Label label;      // se e' gia' stata definita prende l'etichetta dalla Hashtable      if(string_to_label.containsKey(s)) { label = (Temp.Label)string_to_label.get(s); }      // altrimenti crea una nuova etichetta e la inserisce nella Hashtable      // in corrispondenza della stringa s      else {        label= new Temp.Label();        string_to_label.put(s,label);        // RICORDARSI DI INVOCARE FRAME.STRING!        insFrag(new DataFrag( frame.string(label,s)));      }      // restituisce cmq un Ex con un NAME      return new Ex(new Tree.NAME(label));   }   // ----- assignExp -----   public Exp assignExp(Exp e1, Exp e2) {      return new Nx(new Tree.MOVE(e1.unEx(), e2.unEx()));   }   // ----- opExp -----   // In opExp gli operatori sono identificati dai seguenti numeri interi:   // PLUS=0, MINUS=1, MUL=2, DIV=3, EQ=4, NE=5, LT=6, GT=8, LE=7, GE=9   // str serve per vedere se i parametri sono stringhe o no   public Exp opExp(int op,Exp e1, Exp e2,boolean str) {      switch(op) {         case 0: case 1: case 2: case 3: return intOp(op,e1,e2);         case 4: case 5: case 6: case 7: case 8: case 9: return compOp(op,e1,e2,str);      }   return null;   }   // ----- whileExp ----   // vedere pag. 156 A.W.Appel "Modern Compiler Implementation in Java"   public Exp whileExp(Temp.Label done,Exp test,Exp body) {      Temp.Label bodyLabel = new Temp.Label();      Temp.Label testLabel = new Temp.Label();      return new Nx(                new Tree.SEQ(                   new Tree.SEQ(                      new Tree.SEQ(                      new Tree.LABEL(testLabel),                      new Tree.CJUMP(                         Tree.CJUMP.EQ,                         test.unEx(),                         intExp(0).unEx(),                         bodyLabel,                         done)),                     new Tree.SEQ(                        new Tree.LABEL(bodyLabel),                        body.unNx())),                     new Tree.SEQ(                        new Tree.JUMP(testLabel),                        new Tree.LABEL(done))));   }   // ---- breakExp ----   public Exp breakExp(Temp.Label done) { return new Nx(new Tree.JUMP(done)); }   // ---- forExp ----   /*    fatta in modo da evitare il caso in cui limit=MAXINT    come descritto a pag. 174 di A.W.Appel "Modern Compiler Implementation in Java"    In particolare e' stata apportata una piccola modifica    per gestire il caso i=MAXINT.    Il ciclo FOR viene percio' tradotto nel seguente codice:    La traduzione in pseudocodice di "for i:=lo to hi", riscritto   in termini di ciclo while e' la seguente:    let var i:=lo in if(i<=hi) then { do { body; i=i+1; } while (i<hi) } end    NOTA: se LO=MAXINT l'overflow rimane, ma chi inizializza un ciclo con maxint         merita questo e altro...   */   public Exp forExp(Access acc, Level lev,Exp lo,Exp hi,Exp body,Temp.Label done) {      Temp.Label t1=new Temp.Label();      Nx a = (Nx)assignExp(simpleVar(acc,lev),lo);      Nx c = (Nx)assignExp(simpleVar(acc,lev),new Ex(new Tree.BINOP(Tree.BINOP.PLUS,simpleVar(acc,lev).unEx(),intExp(1).unEx())));      return new Nx(                new Tree.SEQ(                   new Tree.SEQ(                      a.unNx(),                      new Tree.SEQ(                         new Tree.CJUMP(Tree.CJUMP.LE,a.unEx(),hi.unEx(),t1,done),                         new Tree.LABEL(t1))),                   new Tree.SEQ(                      new Tree.SEQ(body.unNx(), c.unNx()),                      new Tree.SEQ(                         new Tree.CJUMP(Tree.CJUMP.LT,c.unEx(),hi.unEx(),t1,done),                         new Tree.LABEL(done)))));   }   // ----- nilExp ----   // in questo caso non c'e' bisogno di allocare niente per il record   // si usa una semplice CONST(0)   public Exp nilExp() { return intExp(0); }   // ----- ifExp  -----   public Exp ifExp(Exp test,Exp thenc, Exp elsec ) { return new IfThenElseExp(test,thenc,elsec); }   // ----- callExp -----   /* bisogna semplicemente mettere una CALL, dove pero'      il primo parametro e' lo static link (da ricercare)      Inoltre se la chiamata e' ad una funzione di libreria (es. print"ciao")      lo static link non va messo come primo parametro!   */   public Exp callExp(Level curr,Level levf,Vector Vargs,boolean isVoid) {      // costruisco l'Explist ( el ) per gli argomenti della funzione      Tree.ExpList el = null;      // primo caso

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -