📄 semant.java
字号:
} stampaDeb(e.pos,out); if (env.errorMsg.num_error==0) { return new ExpTy(trans.ifExp(check.exp,thenc.exp,elsec.exp), thenc.ty); } else return new ExpTy(null, thenc.ty); } // WhileExp ExpTy transExp(Absyn.WhileExp e) { // crea una nuova etichetta e salva in old_done // il valore di current_done. Temp.Label new_done= new Temp.Label(); Temp.Label old_done= current_done; // aggiorna current_done alla nuova etichetta current_done=new_done; // controlla il tipo dell'espressione "test" ExpTy check=transExp(e.test); if(!(check.ty.actual()==INT)) env.errorMsg.error(e.test.pos,"Il test del ciclo WHILE deve essere di tipo INT"); // incrementa il contatore dei cicli loopDepth++; // processa il corpo della while ExpTy body=transExp(e.body); // dopo aver processato il corpo ripristina il valore precedente di current_done. current_done=old_done; // controlla che il corpo della While abbia Tipo restituito VOID ! if(!(body.ty==VOID)) { env.errorMsg.error(e.body.pos,"il corpo del ciclo WHILE deve essere di tipo VOID"); } // decrementa il contatore dei cicli loopDepth--; stampaDeb(e.pos,"WhileExp: \"" + nomeClasse(check.ty) +"\""); if(env.errorMsg.num_error==0) { return new ExpTy(trans.whileExp(new_done,check.exp,body.exp),VOID); } else return new ExpTy(null,VOID); } // NilExp ExpTy transExp(Absyn.NilExp e) { return new ExpTy(trans.nilExp(),NIL); } // IntExp ExpTy transExp(Absyn.IntExp e) { if(env.errorMsg.num_error==0) { return new ExpTy(trans.intExp(e.value),INT); } else return new ExpTy(null,INT); } // StringExp ExpTy transExp(Absyn.StringExp e) { if (env.errorMsg.num_error==0) { return new ExpTy(trans.stringExp(e.value), STRING); } else return new ExpTy(null,STRING); } // BreakExp ExpTy transExp(Absyn.BreakExp e) { // se non si trova dentro una while o una for segnala errore if (loopDepth==0) env.errorMsg.error(e.pos,"break illegale ( si trova fuori da una WHILE / FOR )"); else { stampaDeb(e.pos, "BreakExp: Label DONE del ciclo = " + current_done ); } if (env.errorMsg.num_error==0) { return new ExpTy(trans.breakExp(current_done),VOID); } else return new ExpTy(null,VOID); } // CallExp ExpTy transExp(Absyn.CallExp e) { // Vector da utilizzare in Translate // contente gli alberi del codice intermedio dei parametri. Vector paramsVector = new Vector(); // Flag per il controllo del caso anomalo: meno parametri .... boolean flag=false; // Flag per vedere se restituisce un VOID oppure no. boolean isVoid=true; Types.Type res=VOID; FunEntry fun = null; // Symbol func Explist args -> head , tail (Explist) Entry x = (Entry)env.venv.get(e.func); if (!(x instanceof FunEntry)) { // controlla se e' una funzione env.errorMsg.error(e.pos,"Funzione \"" + e.func + "\" indefinita"); } else { // e' una FunEntry // Da Env --> FunEntry [formals:Types.RECORD results:Types.Type] fun = (FunEntry)x; // Tipo restituito if (fun.results!=null) { isVoid = false; res = fun.results; } //scorre la lista dei campi dichiarati della call per controllare tutto // RECORD: fieldName , fieldType, tail for(Types.RECORD formali=fun.formals;formali!=null;formali=formali.tail) { // controlla se vengono inizializzati meno campi di quelli dichiarati... if(e.args == null) { env.errorMsg.error(e.pos,"Passati meno parametri di quelli dichiarati"); flag=true; break; } // ricava l'ExpTy del parametro ExpTy temp=transExp(e.args.head); // Aggiunge l'albero di Codice intermedio del parametro corrente // nel vettore dei parametri formali usato poi in Translate ( trans.callExp(...)) paramsVector.addElement(temp.exp); // confronta i tipi formali con quelli della call. // non esegue actual() di un null if((formali.fieldType!=null)&&(temp.ty!=null)) { if (!(formali.fieldType.actual()==temp.ty.actual())) { stampaDeb(0,"1: " + formali.fieldType.actual()); stampaDeb(0,"2: " + temp.ty.actual()); String out="Non puoi dare al parametro \"" + formali.fieldName + "\" di tipo \"" + nomeClasse(formali.fieldType.actual()) + "\" l'espr. di tipo \"" + nomeClasse(temp.ty.actual())+ "\""; env.errorMsg.error(e.args.head.pos,out); } } else env.errorMsg.error(e.args.head.pos,"Impossibile chiamare la funzione/procedura \"" + e.func + "\""); // scorre i parametri della call e.args=e.args.tail; } } // Se e' una funzione ... if((x instanceof FunEntry)) { // controlla che non vengano inizializzati piu' parametri di quelli dichiarati... if ((e.args != null) && (flag==false)) { env.errorMsg.error(e.args.head.pos,"Passati piu' parametri di quelli dichiarati"); } stampaDeb(e.pos,"CallExp: \""+ e.func + "\": " + nomeClasse(res.actual())); } if (env.errorMsg.num_error==0) { return new ExpTy(trans.callExp(level,fun.level,paramsVector,isVoid),res); } else return new ExpTy(null,res); } // RecordExp ExpTy transExp(Absyn.RecordExp e) { //Flag per il controllo del caso anomalo: meno campi .... boolean flag=false; boolean ok=true; // Vector per memorizzare tutti i campi Vector fieldsVector = new Vector(); Types.Type temp=checkType(e.typ,e.pos); Types.RECORD temp1=new Types.RECORD(null,null,null); // controlla se e.typ e' un record // non esegue actual() di un null, inoltre se il record non esiste non procede oltre if(temp!=null) { if(!(temp.actual() instanceof Types.RECORD)) { env.errorMsg.error(e.pos, "Tipo RECORD richiesto"); ok=false;} else { temp1=(Types.RECORD)temp.actual(); Types.Type typ =(Types.Type)env.tenv.get(e.typ); // scorre la lista dei campi per controllare tutto for(Types.RECORD campi_dichiarati=(Types.RECORD)typ.actual() ; campi_dichiarati!=null ; campi_dichiarati=campi_dichiarati.tail) { // controlla se non dichiariamo niente fin da subito > type c={} if(campi_dichiarati.fieldType==null) break; // controlla se vengono inizializzati meno campi di quelli dichiarati... if(e.fields == null) { env.errorMsg.error(e.pos,"Inizializzati meno campi di quelli dichiarati"); flag=true; break; } // controlla se i "nomi" combaciano if(!(campi_dichiarati.fieldName.toString().equals(e.fields.name.toString()))) env.errorMsg.error(e.pos, "Il campo \"" + e.fields.name + "\" non corrisponde a quello dichiarato \"" + campi_dichiarati.fieldName + "\""); // controlla se il tipo dell'inizializzazione dei campi e' lo stesso di quello dichiarato ExpTy temp2=transExp(e.fields.init); // questo perche' actual() di null e' impossibile! if((temp2.ty!=null)&&(campi_dichiarati.fieldType!=null)) { if(!(campi_dichiarati.fieldType.actual()==temp2.ty.actual())) { if(!((campi_dichiarati.fieldType.actual() instanceof Types.RECORD) && (temp2.ty.actual()==NIL))) { String out="Non puoi inizializzare il campo \"" + e.fields.name + "\" di tipo \"" + nomeClasse(campi_dichiarati.fieldType.actual()) + "\" con l'espr. di tipo \"" + nomeClasse(temp2.ty.actual())+ "\""; env.errorMsg.error(e.pos,out); } } } else env.errorMsg.error(e.pos,"Impossibile inizializzare il campo \"" + e.fields.name +"\""); // aggiunge il campo al vector fieldsVector.addElement(temp2.exp); // per scorrere i campi del record e.fields=e.fields.tail; } // se vengono inizializzati piu' campi di quelli dichiarati... if((e.fields != null) && (!flag)) env.errorMsg.error(e.fields.pos,"Inizializzati piu' campi di quelli dichiarati"); } } else { env.errorMsg.error(e.pos,"Tipo RECORD indefinito"); ok=false; } if (ok) { if(env.errorMsg.num_error==0) { return new ExpTy(trans.recordExp(fieldsVector),temp1); } else return new ExpTy(null,temp1); } else return new ExpTy(null,INT); } // VarExp ExpTy transExp(Absyn.VarExp e) { return transVar(e.var); } // SeqExp ExpTy transExp(Absyn.SeqExp e) { // Vettore in cui vengono memorizzati tutti i pezzi di albero intermedio Vector pezzi = new Vector(); // () e' di tipo VOID! ExpTy et = new ExpTy(null,VOID); Absyn.ExpList l = e.list; while (l!=null) { et = transExp(l.head); // aggiunge il pezzo di Cod. intermedio al vettore pezzi.addElement(et.exp); l=l.tail; } if (env.errorMsg.num_error==0) { return new ExpTy(trans.seqExp(pezzi,et.ty == VOID),et.ty); } else return et; } // ArrayExp ExpTy transExp(Absyn.ArrayExp e) { boolean ok = true; ExpTy x = null; ExpTy size = null; // prendo il tipo di e.typ (se non esiste mi da null) Types.Type temp=checkType(e.typ,e.pos); Types.ARRAY temp1=new Types.ARRAY(null); // controlla se e.typ e' un array // non esegue actual() di un null e inoltre salta tutto e restituisce un VOID. if(temp!=null) { if(!(temp.actual() instanceof Types.ARRAY)) { env.errorMsg.error(e.pos, "Tipo ARRAY richiesto"); ok=false;} else { size = transExp(e.size); checkInt(size, e.size.pos); temp1 = (Types.ARRAY)temp.actual(); x = transExp(e.init); // controlla se il tipo dell'inizializzazione e' lo stesso di quello degli elementi dell'array. // non posso eseguire actual() di null!!! if ((temp1.element!=null) && (x.ty!=null)) { if (!(temp1.element.actual()==x.ty.actual())) { String msg=""+nomeClasse(temp1.element.actual()) + " != " + nomeClasse(x.ty.actual()); env.errorMsg.error(e.pos, "Inizial. di tipo diversa: " + msg); } stampaDeb(e.pos,"ArrayExp: array of " + nomeClasse(x.ty.actual())); } else env.errorMsg.error(e.pos,"Impossibile inizializzare l'array \"" + e.typ + "\""); } } else { env.errorMsg.error(e.pos,"Tipo ARRAY indefinito"); ok=false; } if (ok) { if(env.errorMsg.num_error==0) { return new ExpTy(trans.arrayExp(size.exp,x.exp),temp1); } else return new ExpTy(null,temp1); } else return new ExpTy(null,INT); } /******************************* * DICHIARAZIONI * *******************************/ Translate.Exp transDec(Absyn.Dec d) { if(d instanceof Absyn.VarDec) return transDec((Absyn.VarDec)d); if(d instanceof Absyn.TypeDec) return transDec((Absyn.TypeDec)d); if(d instanceof Absyn.FunctionDec) return transDec((Absyn.FunctionDec)d); throw new Error("transDec"); } /*** VarDec ***/ Translate.Exp transDec(Absyn.VarDec d) { ExpTy tmp = transExp(d.init); Types.Type vt = null; // verifica se e' della forma "corta" (senza tipo) if(d.typ==null) { // controlla se l'exp. di inizial. e' nil (in caso affermativo segnala un errore) if(d.init instanceof Absyn.NilExp) { env.errorMsg.error(d.pos,"L'espr. \"Nil\" richiede la dichiarazione esplicita del tipo"); } } // se invece e' della forma "lunga" (con il tipo) else { vt = transTy(d.typ); // controlla il tipo di exp con il tipo della variabile // se l'exp e' di tipo NIL controlla che il tipo della variabile sia RECORD // non esegue actual() di null if ((vt!=null)&&(tmp.ty!=null)) { if (!(vt.actual()==tmp.ty.actual())) { if (tmp.ty==NIL) { if (!(vt.actual() instanceof Types.RECORD)) { String out="Non puoi inizializzare la var. di tipo \"" + nomeClasse(vt.actual()) + "\" con l'espr. di tipo \"" + nomeClasse(tmp.ty.actual())+ "\""; env.errorMsg.error(d.pos,out); } } else if ((tmp.ty instanceof Types.RECORD)||(tmp.ty instanceof Types.ARRAY)) { String out="Differenti tipi \"" + nomeClasse(tmp.ty) +"\""; env.errorMsg.error(d.pos,out); } else { String out="Non puoi inizializzare la var. di tipo \"" + nomeClasse(vt.actual()) + "\" con l'espr. di tipo \"" + nomeClasse(tmp.ty.actual())+ "\""; env.errorMsg.error(d.pos,out); } stampaDeb(d.pos,"VarDec: \""+d.name+"\": " + nomeClasse(tmp.ty.actual())); } } else env.errorMsg.error(d.pos,"Non posso inizializzare la variabile \"" + d.name + "\""); } // fornisce, comunque sia, il tipo dell'exp di inizializzazione // nel caso sia NIL allora prende il nome del tipo associato alla variabile. // stampa il campo escape della variabile stampaDeb(d.pos,"Escape di " + d.name + ": " + d.escape); // memorizza l'accesso alla variabile Translate.Access acc=level.allocLocal(d.escape); if(tmp.ty==NIL) env.venv.put(d.name, new VarEntry(acc,vt)); else env.venv.put(d.name, new VarEntry(acc,tmp.ty)); // per Translate if(env.errorMsg.num_error==0) { return trans.varDec(acc,level,tmp.exp); } return null; } /*** TypeDec ***/ Translate.Exp transDec(Absyn.TypeDec d) { // per il next, se esiste Types.Type tipo2 = null; Types.NAME header2 = null; // scorre e crea tutti gli header for (Absyn.TypeDec dichiarazione=d;dichiarazione!=null;dichiarazione=dichiarazione.next) { Types.NAME h = new Types.NAME(d.name); // controllo "ad hoc" per risolvere il problema delle dichiarazioni // multiple nello stesso blocco con lo stesso nome for (Absyn.TypeDec dInLista=dichiarazione.next; dInLista!=null; dInLista=dInLista.next) { if (dichiarazione.name==dInLista.name) { env.errorMsg.error(dichiarazione.pos, "Nome duplicato in dichiarazioni di tipi nello stesso blocco."); } } env.tenv.put(dichiarazione.name, h); } // scorre e processa tutti i corpi for (Absyn.TypeDec dichiarazione=d;dichiarazione!=null;dichiarazione=dichiarazione.next) { if (dichiarazione.ty instanceof Absyn.RecordTy) { // crea il record tipo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -