Inizialmente per costruire velocemente una interfaccia per i nostri interpreti abbiamo deciso di sfruttare la shell del DOS. Ci siamo stupiti quando ci siamo accorti che già così si avevano notevoli funzionalità (almeno sotto windows NT):
Abbiamo così creato degli interpreti che per l'input e l'output utilizzano degli stream. Se vogliamo creare un interprete per DOS è sufficiente passargli gli stream System.in e System.out. Anche l'interfaccia grafica a finestre colloquia con gli interpreti tramite stream. Per ogni interprete si hanno 3 stream: uno da cui l'interprete prende l'input e due su cui scrive l'output (standard output e messaggi di errori). Per realizzare tutto questo è stata utilizzata una pipe unidirezionale per ogni stream: l'interfaccia scrive su un lato della pipe e l'interprete legge dall'altro lato e viceversa. Quando l'interfaccia grafica deve spedire messaggi ad un interprete sono direttamente i metodi dell'applet che scrivono sulla pipe. Quando l'interprete scrive su uno stream di output, all'altro capo della pipe c'è in attesa un thread che appende i messaggi ad una text area specifica. Esistono due thread per ogni interprete, ciascuno associato ad una delle due text area di output.
In totale, quando il programma è a regime, i thread (a parte quelli del sistema java) sono 7: uno è il main e tre ciascuno per implementare ogni interprete. Di questi tre uno esegue l'interprete vero e proprio e due sono i thread che appendono i messaggi alla text area.
All'avvio ogni thread dovrebbe avere una priorità normale (5). Quando viene resettato un interprete, poiché il metodo dell'applet è chiamato dal sistema java che ha priorità 6, verrebbero creati nuovi thread con priorità 6, cioè più alta di quella del main. Questo lascerebbe l'interfaccia bloccata mentre l'interprete è al lavoro. Per questo motivo nei costruttori degli interpreti e degli ascoltatori viene settata manualmente la priorità.
Per evitare ogni possibile conflitto abbiamo utilizzato il costrutto Syncronized su ogni sezione critica e precisamente sull'accesso ad ogni area di output.
L'interfaccia grafica è stata costruita utilizzando le swing che grazie al doppio buffering permettono una maggiore stabilità visiva ed evitano le imprecisioni riscontrate nell'AWT. Nonostante tutto qualche piccolo problemino è rimasto anche nelle swing: a causa del LineWrap, java a volte non si accorge che una text area deve essere ridisegnata. Si è provveduto anche a risolvere questo problema.
In generale sono stati curati anche i particolari dell'interfaccia grafica per offrire un sistema comodamente utilizzabile. Tra le vare "facilities":
L'unico inconveniente è che ancora non esista
un browser che supporti java 1.2.
Mostriamo di seguito il risultato ottenuto.
Interpreti Scheme e Prolog con interfaccia basata sulla shell di DOS:
Interprete Scheme
Interprete Prolog
L'interfaccia swing è invece la seguente:
Una visione d'insieme con tutte le finestre aperte è la seguente: