Elaboratore di testi
TRAC (Text Reckoning And Compiling) è opera di Calvin. N. Mooers e L. Paul Deutsch. La storia di TRAC è piuttosto estesa, ed origina quattro distinte versioni: TRAC-64, TRAC-84, TRAC-2001 e Tint. TRAC nasce come programma per trattare testi, a questo scopo, prima di sviluppare TRAC, Mooers aveva preso in considerazione LISP, IPL-V e COMIT.
TRAC lavora come un filtro su di un testo in cui sono presenti delle macro, queste sono riconosciute dalla presenza di un metacarattere di terminazione, usualmente “’” (apostrofo). TRAC invia in output quanto riceve in input, e le eventuali macro presenti sono sostituite con il risultato dell’esecuzione della macro stessa.
Lo sviluppo di TRAC inizia nel 1959; nel 1964, di qui il postfisso del nome, è disponibile la prima implementazione per opera di Deutsch su PDP-10. I comandi del linguaggio o macro, sono una trentina, ed hanno la forma #(mc,arg1,arg2,...) dove mc è il nome della macro seguito da eventuali argomenti. I tipi di dato sono stringhe di caratteri che semanticamente possono essere dati alfanumerici, programmi o numeri interi. Le variabili sono memorizzate in strutture dette form, contenenti la stringa di dati, il nome assegnatogli ed un puntatore per percorrere la stringa stessa. Il repertorio di macro comprende macro per l’input da tastiera e l’output su video, per operazioni aritmetiche su numeri interi, per gestire dati, per creare macro utente e richiamarle con parametri, macro di tipo logico e di confronto fra stringhe e numeri ed infine di diagnostica. Le macro utente sono, di fatto, delle funzioni. Le macro aritmetiche operano su stringhe in cui nella parte di destra è presente un numero, eventualmente segnato; se la macro ha la forma #(op,alfa1num1,alfa2num2), con alfa1 e alfa2 alfanumerici, num2 e num2 numeri, il risultato sarà: alfa1num3 dove num3 = num1 op num2. L’ampiezza dei numeri dipendeva dalle caratteristiche della macchina, in genere 216, tuttavia con macchine in cui l’aritmetica era implementata non con valori binari, ma con digit, poteva essere virtualmente illimitata. Una limitazione del linguaggio è la mancanza di macro per la reiterazione, cosa che può essere eseguita con la ricorsione:
C:\cygwin\home>perl trac #(ds,ris,1) #(ds,fatt, (#(gr,#(cl,count),1,
(#(ds,ris,#(ml,#(cl,count),#(cl,ris)))
#(ds,count,#(su,#(cl,count),1))
#(cl,fatt))) ))' #(ds,count,#(rs)) #(cl,fatt) #(ps, #(cl,ris))' 8' 40320 #(ex)' C:\cygwin\home> |
Form ris
contiene 1 fatt contiene
script confronto
di fine ciclo calcolo
fattoriale decremento
contatore richiamo
ricorsivo di fatt Form count: valore da input Richiamo
di fatt Visualizzazione
risultato Valore
immesso Fattoriale Uscita
da TRAC |
L’input ed output su file è possibile solo per le form.
Il “The Retrocomputing Museum” ha reso disponibile un interprete di TRAC-64, scritto in Perl (con limitate estensioni e la possibilità di usare nomi di macro più espressivi).
TRAC-84 o TR2 è una versione di TRAC del tutto diversa da TRAC-64, in comune i due linguaggi hanno il meccanismo di funzionamento:
· le macro sono oltre ottanta.
· I nomi delle macro sono stati razionalizzati, nel senso che il primo carattere individua la famiglia di macro; inoltre il comando è ulteriormente qualificabile tramite un suffisso.
· Le macro aritmetiche esigono operandi numerici.
·
E’ possibile inserire commenti (solo nel corpo delle macro
utente).
·
E’ stata introdotta una macro di iterazione.
·
Sono presenti macro per il trattamento di files.
·
Si possono creare famiglie di variabili con struttura ad albero,
di fatto un embrione di oggetto.
Identificatore |
Famiglia |
a |
Aritmetiche
|
b |
Manipolazione
di bit |
f |
Manipolazione
di files |
i |
Input
e comunicazione con la porta seriale |
o |
Output |
m |
Gestione
della memoria: variabili, macro utente,… |
n |
Comunicazione
in rete |
p |
Iterazione,
richiamo programmi e servizi OS |
t |
Operazioni
su stringhe di testo |
x |
Diagnostica,
data e ora |
l |
Collegamento
a librerie esterne |
r |
Richiamo
di variabile o di procedura |
s |
Memorizza
variabile o script (form) |
e |
Confronto
fra stringhe |
g |
Uscita
da TRAC |
Tabella
3
Le macro hanno la forma :(mcs,arg1,arg2,...), dove mc è il nome della macro, seguito da zero o più argomenti ed s è un eventuale suffisso che specifica ulteriormente il comportamento della macro. Nella Tabella 4 sono elencati i suffissi, quali macro li prevedono ed il loro significato.
Suffisso |
Si
applica a |
Azione |
i |
r,i |
Interpreta la stringa prodotta |
d |
Macro
che generano output |
Elimina la stringa prodotta |
0,1,... |
o,i,n,f |
Indica un canale di input/output |
Tabella
4
:(ri,decnum.aq,123,11)'11.18 :(ri,decnum.sqrt,7000)'83.66 :(ri,decnum.pigreco)'3.141592 :(s,decnum.dec,3)' :(ri,decnum.aq,1,3)'.333 :(mt)' |
<base node> =rem =sqrt0 +decnum
lav
op
dec
buf1
dummy
buf3
buf2
buf4
=sqrt0
=pigreco
=aq
=sqrt =decgen |
Nell’esempio che segue è stato costruito un abbozzo di “oggetto” decnum. per aritmetica su numeri interi, con risultato decimale. L’oggetto contiene decnum.dec un campo con il numero di decimali richiesto, decnum.aq una macro per la divisione, decnum.sqrt una macro per il calcolo della radice quadrata e decnum.pigreco che fornisce il valore di pigreco con sei decimali.
Figura
36
|
Nella Figura 36 ci sono degli esempi di richiamo delle macro e la struttura di decnum. ottenuta tramite la macro mt. Lo script di Figura 37 è una macro utilizzata dalla macro decnum.sqrt per iterare nella ricerca del risultato, nellaFigura 38 è riportato lo script con la macro per generare la struttura dell’oggetto.
:(mm,sqrt0,(
<* media fra massimo e minimo *> :(s,decnum.lav,:(aq,:(aa,:(r,decnum.buf1),:(r,decnum.buf2)),2)) :(s,decnum.buf3,:(am,:(r,decnum.lav),:(r,decnum.lav))) <* calcolo nuovi limiti *>
:(s,decnum.dummy, :(ag,:(r,decnum.buf3),:(r,decnum.op),
(:(s,decnum.buf1,:(r,decnum.lav))),(),
(:(s,decnum.buf2,:(r,decnum.lav))))
) :(ri,decnum.dummy) <* esegue istruzione
*> <* calcolo intervallo *> :(s,decnum.buf3,:(as,:(r,decnum.buf1),:(r,decnum.buf2))) <* verifico se è il caso di proseguire
*>
:(s,decnum.dummy, :(ag,:(r,decnum.buf4),:(r,decnum.buf3),
(:(s,decnum.buf4,:(r,decnum.buf3))),
(:(px)), (:(px)))) :(ri,decnum.dummy) <* esegue istruzione
*> )) <*
salvo lo script nel file sqrt0.mff *> :(mp,sqrt0,sqrt0.mff) :(g)' |
Figura
37
:(mm,rem,(<*
TRAC Version of 11 Feb 1992 *>)) :(mm,decgen,(
<* macro per generare la struttura decnum *> :(s,decnum.) :(s,decnum.sqrt0) <* macro usata da sqrt *> :(s,decnum.dec,2) <* numero decimali *> :(s,decnum.op)
<* operando
*> :(s,decnum.lav)
<* area di lavoro *> :(s,decnum.buf1) <*
area di lavoro *> :(s,decnum.buf2) <*
area di lavoro *> :(s,decnum.buf3) <*
area di lavoro *> :(s,decnum.buf4) <*
area di lavoro *> )) :(ri,decgen) :(mm,decnum.sqrt,( :(s,decnum.op,<1>:(pc,0,:(am,2,:(r,decnum.dec))))
<* aggiungo decimali *> <* intervallo fra cui cade la radice *> :(s,decnum.buf1,:(pc,3,:(aa,:(aq,:(tl,decnum.op),2),1)))
<* 33...3 *> :(s,decnum.buf2,1:(pc,0,:(aq,:(as,:(tl,decnum.op),1),2)))
<* valore minimo radice 10...0 *> :(s,decnum.buf4,:(as,:(r,decnum.buf1),:(r,decnum.buf2)))
<* controllo differenza *> <* area controllo convergenza *> :(pc,(:(ri,decnum.sqrt0)),-1)
<* esegue ciclo iterazioni *> <* calcolo posizione decimali *> :(tps,decnum.lav,:(as,:(tl,decnum.lav),:(r,decnum.dec))) :(o,:(tpb,decnum.lav).:(tpe,decnum.lav)) )) :(mm,decnum.aq,( :(s,decnum.op,<1p>:(pc,0,:(r,decnum.dec)))
<* aggiungo decimali *>
:(s,decnum.lav,:(aq,:(r,decnum.op),<2p>))
<*
calcolo posizione decimali *> :(tps,decnum.lav,:(as,:(tl,decnum.lav),:(r,decnum.dec))) :(o,:(tpb,decnum.lav).:(tpe,decnum.lav)) )) :(mm,decnum.pigreco,(:(s,decnum.buf1,:(r,decnum.dec))
:(s,decnum.dec,6)
:(ri,decnum.aq,355,113)
:(s,decnum.dec,:(r.decnum.buf1)))) :(mm,rem,(<*
mf,... legge form memorizzata *>)) :(mf,,sqrt0.mff) :(mm,rem,(<*
inserisco in struttura decnum. sqrt0 *>)) :(mm,decnum.sqrt0,:(r,sqrt0))
|
Figura
38
TRAC T2001 è implementato in Java.
Tint è l’evoluzione di TRAC con supporto di TRAC T2001, ambiente grafico interattivo, programmazione ad oggetti, supporto TCP, espressioni regolari. Gestita ancora solamente l’aritmetica intera.
<*
Tint version 0.17 *> Def:Proc:fatt(%n) [*] #(=,%n,1,1,(#(*,%n,#(fatt,#(-,%n,1))))) [*] Def:Eval: [*] #(#(tint.console).put,fattoriale
di 10: #(fatt,10)) [*] |
C:\Tintware\release>tintc fatt.tnt
fattoriale di 10: 3628800
|