📄 semant.java
字号:
recout="Campi del record \"" + dichiarazione.name + "\":\n"; Types.Type tipo=transTy(dichiarazione.ty); recout=""; // azzera la stringa per il debug // lega al Types.NAME "campo" (un header), il tipo appena creato con transTy(dichiarazione.ty) Types.NAME campo=(Types.NAME)env.tenv.get(dichiarazione.name); campo.bind((Types.RECORD)tipo); } else { Types.Type tipo=transTy(dichiarazione.ty); // lega al Types.NAME "campo" (un header), il tipo appena creato con transTy(dichiarazione.ty) Types.NAME campo=(Types.NAME)env.tenv.get(dichiarazione.name); campo.bind(tipo); if(campo.isLoop()==true) env.errorMsg.error(dichiarazione.pos, "Ciclo illegale nelle dichiarazioni."); } } // per Translate if(env.errorMsg.num_error==0) { return trans.typeDec(); } return null; } /*** FunctionDec ***/ // (NOTA: "d" e' una lista di dichiarazioni, per eventuale ricorsione) Translate.Exp transDec(Absyn.FunctionDec d) { // stringhe per il debug String out = "", outinizio = "", par = ""; // test: funzione o procedura? (...viene restituito un valore?) boolean isProc = false; // per il corpo della funzione ExpTy temp = null; Types.Type result = null; Types.RECORD formals = null; // scorre e crea tutti gli header (i vari FunEntry) for (Absyn.FunctionDec dichiarazione=d;dichiarazione!=null;dichiarazione=dichiarazione.next) { out="Function header: " + dichiarazione.name; // crea una BoolList per gli "escape" dei parametri formali // che verra' sovrascritta e riempita in transTypeFields Util.BoolList bl = new Util.BoolList(true,null); // controllo "ad hoc" per risolvere il problema delle dichiarazioni // multiple nello stesso blocco con lo stesso nome for (Absyn.FunctionDec dInLista=dichiarazione.next; dInLista!=null; dInLista=dInLista.next) { if (dichiarazione.name==dInLista.name) env.errorMsg.error(dichiarazione.pos, "Nome duplicato in dichiarazioni di funzioni nello stesso blocco."); } if (dichiarazione.params!=null) { par = "\t Parametri della funzione:"; formals = transTypeFields(dichiarazione.params,bl); // stampa tutto il fieldlist per debug for (Types.RECORD temprec=formals; temprec!=null; temprec=temprec.tail) par = par+"\n\t " + temprec.fieldName + ": " + nomeClasse(temprec.fieldType); } else { formals = null; par = "\t Nessun parametro."; } out = out+"\n"+par; stampaDeb(dichiarazione.pos, out+"\n"); out = par = ""; // azzera le stringhe // prende il Tipo restituito (se esiste) if (dichiarazione.result!=null) result = transTy(dichiarazione.result); else result = null; // crea un nuovo livello e una nuova label out = out +"\n\tLivello precedente: " + level.frame.name; level = new Translate.Level(level,dichiarazione.name,bl); Temp.Label label = new Temp.Label(); // debug outinizio = "Function info: " + level.frame.name; out = out +"\n\tLivello funzione: " + level.frame.name + "\n\tLabel funzione: " + label; // inserisce la FunEntry env.venv.put(dichiarazione.name,new FunEntry(level,label,formals,result)); stampaDeb(dichiarazione.pos,outinizio+out+"\n"); out = par = ""; } // scorre e processa tutti i corpi for (Absyn.FunctionDec dichiarazione=d;dichiarazione!=null;dichiarazione=dichiarazione.next) { env.venv.beginScope(); for (Absyn.FieldList p=dichiarazione.params; p!=null; p=p.tail) { env.venv.put(p.name,new VarEntry(level.allocLocal(p.escape),(Types.Type)env.tenv.get(p.typ))); } // recupera la funEntry inserita prima FunEntry fe=(FunEntry)env.venv.get(dichiarazione.name); // processa il corpo della funzione temp = transExp(dichiarazione.body); env.venv.endScope(); // prende il Tipo restituito (se esiste) if(dichiarazione.result!=null) result = transTy(dichiarazione.result); else result=null; // controlla "nella forma lunga"==funzione se il Tipo restituito // della espr. combacia con il tipo restituito dalla funzione if (result!=null) { if (!(result.actual()==temp.ty.actual())) { env.errorMsg.error(dichiarazione.pos, "Tipo restituito " + nomeClasse(result.actual()) +" non compatibile con " + nomeClasse(temp.ty.actual())); } } // controlla, se e' una procedura, che restituisca un VOID e non un valore if (result == null) { // e' una procedura isProc=true; if (temp.ty!=VOID) { // non esegue actual() di null if(temp.ty!=null) env.errorMsg.error(dichiarazione.pos,"La procedura restituisce un valore di tipo \"" + nomeClasse(temp.ty.actual()) + "\""); } } if (result!=null) out=out+"tipo restituito dalla funzione " + dichiarazione.name +": " + nomeClasse(result.actual()); else out=out+"tipo restituito dalla funzione "+ dichiarazione.name +": VOID (procedura)"; // inserisce i frags per ogni funzione trans.functionDec(fe.level,temp.exp,isProc); if (debflag==1) System.out.println(""); stampaDeb(dichiarazione.pos, out+"\n"); out=par=""; // azzera le stringhe } if (env.errorMsg.num_error==0) { return trans.functionDec(); } return null; } /**************************** * TIPI * ****************************/ Types.Type transTy(Absyn.Ty t) { if (t instanceof Absyn.NameTy) return transTy((Absyn.NameTy)t); if (t instanceof Absyn.RecordTy) return transTy((Absyn.RecordTy)t); if (t instanceof Absyn.ArrayTy) return transTy((Absyn.ArrayTy)t); throw new Error("transTy"); // rimuovere questa riga di codice? } // NameTy Types.Type transTy(Absyn.NameTy t) { Types.NAME nome= new Types.NAME(t.name); // controlla il tipo se esiste, altrimenti do' errore Types.Type tipo=checkType(t.name,t.pos); // se il tipo esiste if (tipo!=null) { nome.bind(tipo); } else { nome = null; } return nome; } // RecordTy Types.Type transTy(Absyn.RecordTy t) { Types.RECORD rec; // se e' il caso "type c={} " allora crea un tipo record vuoto if(t.fields==null) return new Types.RECORD(null,null,null); rec=transTypeFields(t.fields); // Stamps tutto il fieldlist per debug for(Types.RECORD temprec=rec; temprec!=null; temprec=temprec.tail) recout=recout+"\t " + temprec.fieldName + ": " + nomeClasse(temprec.fieldType) + "\n"; stampaDeb(t.pos, recout); return rec; } // ArrayTy Types.Type transTy(Absyn.ArrayTy t) { // controlla il tipo se esiste, altrimenti do' errore return new Types.ARRAY(checkType(t.typ,t.pos)); } // transTypeFields Types.RECORD transTypeFields(Absyn.FieldList f) { Types.RECORD result; Types.RECORD temp; Types.RECORD coda; // --- PASSO BASE // controlla il tipo del primo campo Types.Type tc = checkType(f.typ,f.pos); result = new Types.RECORD(f.name, tc, null); temp=result; // --- PASSO ITERATO for(f=f.tail;f!=null;f=f.tail) { // controlla il tipo del campo tc = checkType(f.typ,f.pos); coda = new Types.RECORD(null,null,null); coda.fieldName=f.name; coda.fieldType=tc; temp.tail=coda; // questo per togliere l'ultima tripla (null,null,null) if(!(f.tail==null)) { coda.tail= new Types.RECORD(null,null,null); temp=coda; } } return result; } // transTypeFields: ( FieldList, BoolList ) // Overloading della principale. // Usata solo in FunctionDec per settare la BoolList da // passare a FunEntry. Types.RECORD transTypeFields(Absyn.FieldList f, Util.BoolList bl) { Types.RECORD result; Types.RECORD temp; Types.RECORD coda; // --- PASSO BASE // controlla il tipo del primo campo Types.Type tc = checkType(f.typ,f.pos); result = new Types.RECORD(f.name, tc, null); bl = new Util.BoolList(f.escape,null); temp=result; // --- PASSO ITERATO for(f=f.tail;f!=null;f=f.tail) { // controlla il tipo del campo tc = checkType(f.typ,f.pos); coda = new Types.RECORD(null,null,null); coda.fieldName=f.name; coda.fieldType=tc; temp.tail=coda; // aggiunge un nuovo booleano alla BoolList bl.tail=new Util.BoolList(f.escape,null); // questo per togliere l'ultima tripla (null,null,null) if(!(f.tail==null)) { coda.tail= new Types.RECORD(null,null,null); temp=coda; } } return result; } // transTypeFields2 // 2 parametri: record su cui lavorare == tipo da legare, nome a cui legare il tipo Types.RECORD transTypeFields2(Types.RECORD r,Types.NAME n) { Types.RECORD result=r; for(Types.RECORD tempr=r;tempr!=null;tempr=tempr.tail) { if (tempr.fieldType==n) { Types.NAME campo=(Types.NAME)tempr.fieldType; campo.bind(tempr); } } return result; } /********************************* * SUPPORTO * *********************************/ // Funzione getName (restituisce il nome di un Types.NAME) String getName(Types.NAME tipo) { return tipo.name.toString(); } // Funzione checkInt // controlla se l'exp denota un intero. Translate.Exp checkInt(ExpTy et, int pos) { if(!(et.ty.actual()==INT)) env.errorMsg.error(pos, "Intero richiesto"); return et.exp; } // Funzione checkType // controlla il tipo se esiste, altrimenti da' errore e restituisce null Types.Type checkType(Symbol.Symbol s, int pos) { // prende il tipo del simbolo... Types.Type tc = (Types.Type)env.tenv.get(s); // se non esiste nella tabella do' errore if(tc==null) env.errorMsg.error(pos, "Tipo \"" + s.toString() + "\" indefinito"); return tc; } // Funzione checkComp // per la comparazione di due ExpTy void checkComp(int pos, ExpTy left, ExpTy right, String op) { String out="Comparazione di tipi incompatibili (\"" + nomeClasse(left.ty.actual()) + "\" e \"" + nomeClasse(right.ty.actual()) +"\")"; stampaDeb(pos,"OpExp: " + nomeClasse(left.ty.actual()) + " " + op + " " + nomeClasse(right.ty.actual()) ); if((left.ty.actual()==INT)) { if(!(right.ty.actual()==INT)) { env.errorMsg.error(pos, out); } } else if((left.ty.actual()==STRING)) { if(!(right.ty.actual()==STRING)) { env.errorMsg.error(pos, out); } } else env.errorMsg.error(pos, "Comparazione non consentita per tipi \"" + nomeClasse(left.ty.actual())+ "\""); } // Funzione checkEq // per la comparaziore di due ExpTy void checkEq(int pos ,ExpTy left, ExpTy right, String op) { String out="Comparazione di tipi incompatibili (\"" + nomeClasse(left.ty.actual()) + "\" e \"" + nomeClasse(right.ty.actual()) +"\")"; stampaDeb(pos,"OpExp: " + nomeClasse(left.ty.actual()) + " " + op + " " + nomeClasse(right.ty.actual()) ); if(left.ty.actual()==INT ) { if(!(right.ty.actual()==INT)) env.errorMsg.error(pos,out); } else if(left.ty.actual()==STRING) { if(!(right.ty.actual()==STRING)) env.errorMsg.error(pos,out); } else if((left.ty.actual()==NIL) && (right.ty.actual()==NIL)) { env.errorMsg.error(pos,"nil = nil non permessa !"); } else if((left.ty.actual() instanceof Types.RECORD)||(left.ty.actual() instanceof Types.ARRAY)) { if(!(left.ty.actual()==right.ty.actual())) { if(!( ((left.ty.actual() instanceof Types.RECORD) && (right.ty.actual()==NIL)) || ((right.ty.actual() instanceof Types.RECORD) && (left.ty.actual()==NIL)) )) { out="Comparazione tipi \"" + nomeClasse(left.ty.actual()) + "\" non valida"; env.errorMsg.error(pos,out); } } } } // Funzione nomeClasse // Restituisce il nome della classe levando tutti gli // eventuali package (es. Ciao.Types.STRING --> STRING) public String nomeClasse(Object o) { String temp; String result=""; if(o==null) result="null"; else { temp=o.getClass().getName(); for(int i=0;i<temp.length();i++) { if(temp.charAt(i)=='.') result=temp.substring(i+1); } } return result; } // Funzione stampaDeb: stampa i messaggi di Debug (con la posizione) public void stampaDeb(int pos, String msg) { if (debflag == 1) System.out.println("(" + pos + ") > " + msg); } // Funzione che stampa la tabella dei tipi finali, // da usare solo nel caso in cui non ci siano errori. public void stampaTenv() { System.out.println("\nTABELLA DEI TIPI: simbolo (nome) -> tipo -> tipo effettivo (.actual())"); System.out.println(""); java.util.Enumeration e= env.tenv.keys(); while(e.hasMoreElements()) { Symbol.Symbol nome=(Symbol.Symbol)e.nextElement(); Types.Type tipo=(Types.Type)env.tenv.get(nome); System.out.println(" " + nome + " -> " + nomeClasse(tipo) + " -> " + nomeClasse(tipo.actual())); } } // Funzione che stampa la tabella delle variabili, // da usare solo nel caso in cui non ci siano errori. public void stampaVenv() { System.out.println("\nTABELLA DELLE VARIABILI E DELLE FUNZIONI"); System.out.println(""); java.util.Enumeration e= env.venv.keys(); while(e.hasMoreElements()) { Symbol.Symbol nome=(Symbol.Symbol)e.nextElement(); Entry entr=(Entry)env.venv.get(nome); System.out.println(" " + nome + " -> " + nomeClasse(entr)); } System.out.println(""); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -