HP 48 RPL e ...l'arte della programmazione dei calcolatori tascabili di cui fece tesoro un famoso linguaggio
Il modello Hewlett-Packard 48 (HP48) fu una serie di modelli di calcolatrici pensate per studenti ed ingegneri, costruite tra il 1990 e il 2003. Nel 1993, quando iniziai l'università costava molto di più della HP42 che poi scelsi, ed era la punta di diamante nella vetrinetta dei calcolatori che potevate trovare nelle cartolerie o nelle librerie specializzate. Mi è sempre rimasta la curiosità di sapere com'era programmare con questa calcolatrice, che vidi "dal vivo", solo una volta in modo fugace. Così mi sono documentato e ho pensato di scrivere questo breve articolo, scoprendo che forse la HP48 ha ispirato uno dei linguaggi di programmazione nato nel 1995 che è ancora sulla cresta dell'onda dopo oltre 27 anni...
Il contesto
[caption id="attachment_10302" align="alignleft" width="300"] Le calcolatrici pre-HP48[/caption]La HP aveva già sviluppato una serie di calcolatori scientifici programmabili come la serie HP-41 e la sua evoluzione HP42S. Questo calcolatori possedevano uno "stack" di quattro livelli, e gli operatori agivano su tali stack. Per esempio per effettuare
5+2+3
Vanno premuti
[5], [Enter], [2],[enter],[3], [+],[+]
Questa notazione era chiamata RPN, e sopperiva alle limitazioni dei display, consentendo anche di effettuare calcoli complessi. Le calcolatrici HP4X avevano un chip custom, chiamato Saturn, che forniva già la possibilità di effettuare calcoli in virgola mobile in modo "nativo".
Siamo negli anni'90, e la RAM è ancora una risorsa costosa: lo si evince dal fatto che i chip Saturn erano sì a 64bit, ma indirizzavano la memoria a "nibbles" di 4 bit, e quindi potenzialmente potevano creare strutture dati che occupavano anche 12,5 bytes (!) anziché 13. Mi risulta che neppure la Commodore dei primi anni ottanta abbia mai sviluppato chip con questa caratteristica: il MOS6502 indirizzava a 8bit. Il primo modello (HP48S) aveva 32KB di RAM, mentre il modello GX arrivava a 128KB, e la frequenza del chip era intorno ai 2 Mhz.
Le calcolatrici precedenti alla HP48 avevano una dotazione software di tutto rispetto, soprattutto nel comparto del calcolo numerico: potevano effettuare sia integrazioni numeriche, che risolvere equazioni applicando metodi numerici. Gestivano tipi di dati evoluti come numeri complessi, matrici, stringhe.
[caption id="attachment_12164" align="alignright" width="299"] HP48GX da Wikipedia, al grido di tastone enter, shift<- e shift->[/caption]
La HP48 aggiunge anche la possibilità di risolvere simbolicamente gli integrali e le derivate, (anche se in modo rudimentale) e la possibilità di gestire l'enorme display grafico.
Il nuovo linguaggio RPL
In particolare viene esteso il linguaggio RPN introducendo concetti legati ai linguaggi funzionali (il nuovo linguaggio viene chiamato Reverse Polish (notation) Lisp).RPL è un buon compromesso tra l'esigenza di rendere la calcolatrice ancora più programmabile, ma bilanciando anche con i limiti della tastiera e la necessità di immediatezza nei calcoli: tra poco vi sarà più chiaro.
Rispetto a RPN, RPL ha uno stack "infinito" e aumenta il numero di tipi nativi che si possono mettere sullo stack. Oltre ai tipi precedenti (numeri reali, stringhe, ecc) è possibile memorizzare in una sola cella dello stack interi programmi, oggetti grafici, ecc
La memoria è organizzata attraverso namespace gerarchici ("directory"), in cui una variabile definita in un livello è visibile anche ai livelli nidificati.
Un programma senza input può essere memorizzato in una variabile P, e applicato allo stack semplicemente "richiamando" la variabile P con il tasto "RCL": molto comodo per piccoli programmi che magari effettuano calcoli fissi abbastanza semplici.
Per es un programma che raddoppia il numero sulla posizione 1 dello stack è espresso come la prima riga dell'esempio sotto:
<< 2 * >> << -> x y << x y - >> >> << -> x y 'x-y' >>
I programmi possono essere nidifcati, cioé contenere altri programmi. Come in Lisp, è possibile effettuare il binding di variabili libere prelevando i valori dello stack e assegnandoli a valori simbolici: in riga (2) sopra vedete proprio questo uso: un programma che prende i primi due numeri sullo stack, e li sostituisce con la loro differenza.
E' supportata anche la forma "algebrica", per cui la riga (3) mostra lo stesso esempio della linea (2).
Le strutture di controllo (IF,FOR LOOP, WHILE...END, ecc) sono tutte stack-based, e strutturate (non esiste il concetto di "GO-TO")
Questo modo di strutturare i programmi in pratica è LISP, solo che gli input vengono presi da uno stack anziché da una lista di parametri, risparmiando l'overhead di chiamata a sotto funzione. Se i parametri in input vanno manutenuti nello stack a fine chiamata, vanno copiati esplicitamente prima, ma spesso questo non è richiesto e quindi il modello di calcolo è un pelino più veloce di altri.
La HP48 è anche la prima calcolatrice che ha un sistema di comunicazione con l'esterno che consente lo scambio di programmi, l'uso di "cartucce" di espansione sia di software che di RAM.
PRO/CONS
Il livello di attenzione verso l'utente finale è molto alto: la funzione "BYTES" che ritorna l'occupazione di un programma, calcola anche un "CHECKSUM", che può essere usato per verificare la corretta digitazione del programma!Erano supportati ben 30 tipi diversi di oggetti, tra cui "librerie", "backup objects", "Tagged objects"...forse un po' troppi rispetto ad approcci "minmalisti" del LISP, dove ci sono pochissimi tipi primitivi.
Tra i lati negativi, c'è da dire che la gestione della dinamica della memoria basata su Garbage Collection poteva costringere a "pause" di elaborazione un po' lunghette di tanto in tanto, e questo limitava l'ambito applicativo.
La nascita di uno stack-language write-once, run anyware nel 1995
Il linguaggio Java viene reso disponibile nel 1995 e ha caratteristiche molto simili al sistema operativo delle HP48:- La macchina virtuale (JVM) è stack-based e le operazioni sono tutte stack-oriented.
- il codice è organizzato in namespace (package) che sono memorizzati come directory nidificate nel filesystem
- La JVM ha un Garbage Collector (caratteristica ora è diffusa, ma ai tempi era meno frequente in linguaggi derivati dal C/PASCAL)