Newsgroup: it.comp.programmare
Titolo: IL LINGUAGGIO IDEALE

Come vorreste che fosse un linguaggio (di programmazione)?
Dovrò implementare un linguaggio di programmazione per il mio micro-sistema
operativo/debugger.
Vorrei sapere come vorreste che fosse il vostro linguaggio ideale.
La mia idea attuale è quella di fare un linguaggio a vari livelli: dal più
basso al più alto.
Il più basso è l'asm e il più alto.....troverò un nome prima o poi.
In pratica, scrivendo codice a livello 3, il compilatore/IDE produrrà e
mostrerà (in tempo reale) il relativo codice a livello 2, 1 e 0 (asm).
A questo punto si potrà modificare il codice a qualsiasi livello,
ricordandosi che ogni modifica si propagherà ai livelli inferiori.
Che cosa ne pensate?
Ho pensato anche a un linguaggio a sintassi aperta, ma alla fine non è poi
così utile (in pratica è un linguaggio tramite il quale è possibile definire
la sintassi di un altro linguaggio o modificarla a proprio piacimento
durante il progetto, ma questo porterebbe a moltissimi problemi tipo la
facilità di commettere errori, ecc...)
Aspetto consigli di qualsiasi genere (costruttivi e/o distruttivi!)
Kiuhnm

 Vorrei sapere come vorreste che fosse il vostro linguaggio ideale.
Questa frase fa veramente schifo, ma sono molto stanco...
Kiuhnm

> Come vorreste che fosse un linguaggio (di programmazione)?
Diciamo che il miglior linguaggio di programmazione e' quello in cui un dato
algoritmo X puo' essere implementato scrivendo il minor numero di righe di
codice (produttivita', P), che venga eseguito nel minor tempo possibile
(efficienza temporale, T) e occupi la minor quantita' di spazio fisico
possibile (efficienza spaziale, S).
Ovviamente, come in tutte le cose fisicamente realizzabili, puoi scegliere
solo due di queste variabili contemporaneamente, mentre la terza e' derivata
dalle prime due.
Puoi scegliere un linguaggio produttivo ed efficiente (P + T), ma occupera'
molto spazio (S), ad esempio i vari interpreti con run-time calibrati e
varie librerie a corredo (Python, Perl, PHP).
Puoi scegliere un linguaggio efficiente (S + T), ma scriverai molte righe di
codice (P), ad esempio Assembly o C.
Puoi scegliere un linguaggio produttivo e che occupa poco spazio (P + S), ma
ci mettera' molto tempo ad eseguire il tuo algoritmo (T), ad esempio i vari
interpreti di altissimo livello di astrazione (ad esempio ML, SML, LISP),
Un caso a parte merita il C++, che forse e' l'unico che riesce a minimizzare
P il piu' possibile, a parita' di T ed S grazie alla sua natura ibrida, ma
qui andiamo su un terreno di difficile valutazione oggettiva.
Ciao!
*** Azimuth ***

 quantita' di spazio fisico possibile (efficienza spaziale, S).
Un linguaggio multi-livello (quello a cui accennavo) potrebbe risolvere
questo problema (voglio vedermi a programmare il compilatore real-time!)
Praticamente si potrebbe iniziare dai livelli alti per poi magari eseguire
qualche modifica ai livelli più bassi. A me sembra un'idea molto buona.
Cosa ne pensi?
Kiuhnm

 Cosa ne pensi?
Che, almeno per quello che attiene un sistema a tre livelli (2...0), se la
memoria non mi inganna, e' il criterio di funzionamento attuale del GCC 3.0:
C -> metalinguaggio -> ASM.
Se lo introduciamo nel modello precedente, dobbiamo stare attenti che:
a) Il passaggio da un livello (n) ad un livello (n-1) abbia un deltaS minore
o pari a 0.
b) Il passaggio da un livello (n) ad un livello (n-1) abbia un deltaT minore
o pari a 0.
c) Il passaggio da un livello (n) ad un livello (n-1) abbia un deltaP
superiore a 0.
Il punto (c) e' facilmente dimostrabile: basta che il linguaggio di livello
(n) non sia equipotente rispetto a (n-1). Ad esempio, e' facile passando da
C a ASM, perche' esiste almeno un costrutto in C che non viene tradotto in
equal numero di istruzioni in ASM, ovvero la chiamata a funzione.
I punti (a) e (b) sono dimostrabili solo statisticamente, applicando un
controllo sul determinato algoritmo X.
Potrebbe funzionare nel momento in cui tu potessi alterare la codifica di
ogni istruzione e quindi potessi "pilotare" le misure statistiche verso il
tuo obiettivo di un deltaT e deltaS minori o uguali a zero.
Direi che sarebbe il caso di tentare...
*** Azimuth ***

Kiuhnm wrote:

Linguaggi esistenti che grosso modo adottano questo approccio sono
Dylan e Common Lisp (e altri, ma assolutamente non diffusi come
questi due).  Dylan anzi si impernia su questo concetto come vero
e proprio cardine, mentre per Common Lisp e` solo uno fra una vera
e proprie miriade di paradigmi e sotto-paradigmi (per certi versi
non c'e` linguaggio piu` ricco, grosso, e complicato di CLisp).
Non so perche` ne` Common Lisp ne` Dylan abbiano goduto di un
significativo successo pratico; le ragioni possono essere tante,
dai problemi di sintassi, ai sistemi di macro (altra idea che
appare affascinante ma nella prassi da` sempre problemi), alle
ricadute negative del fatto di essere vagamente connessi ad aree
applicative che tirano poco (AI, per il Lisp) o ad aziende che
hanno subito un po' di crisi (Apple, per il Dylan).  Ma tanti
altri linguaggi sono sopravvissuti a tutti questi problemi: la
sintassi strana [control-T e` un nome di variabile...?] non ha
ad esempio impedito la diffusione di Perl, gli abusi di macro
di preprocessore (benche` ora deplorati, pur sempre diffusi)
non hanno ad esempio impedito la diffusione di C e C++, il fatto
di essere nato in IBM (che ha passato crisi tremende) non ha
impedito la diffusione di SGML e dei suoi figli (HTML, XML),
il fatto di essere stato usati anche per "insegnare a programmare
a tutti" (progetto che oggi pare interessi poco, soprattutto
commercialmente) non ha impedito la diffusione di linguaggi
come Cobol, Basic, Pascal, Python.
Forse, quindi, se diversi linguaggi basati su di una stessa idea
affascinante hanno problemi di diffusione e di successo pratico,
e` meglio esaminare criticamente quell'idea, piuttosto che non
affannarsi a cercare spiegazioni eterologhe rispetto ad essa.
Tutto sommato, in generale, pare che gli esseri umani si trovino
meglio ad usare una gamma di strumenti differenziati per una
serie di compiti connessi fra loro ma non identici, piuttosto
che un solo strumento "multi-livello" in grado di svolgere tutta
una serie di compiti diversi -- probabilmente perche` il singolo
strumento, o risulta troppo grosso/pesante/fragile/costoso/
complicato..., o necessariamente deve fare troppi compromessi
fra le diverse esigenze relative ai vari compiti, cosi` che non
risulta ottimale per nessuno di essi, mentre i vari strumenti
della gamma differenziata sono ciascuno meglio specializzato
per il proprio specifico ruolo.
E` un'ipotesi ragionevole, visto che si applica a tanti campi
diversi.  Non pretendo che lo stesso paio di scarpe sia buono
per arrampicarmi sulla roccia, giocare a basket, passeggiare
in citta`, E danzare il flamenco; preferisco avere svariate
paia di scarpe, ognuna per il suo ruolo.  Esempi del tutto
analoghi si possono portare in tanti altri campi.
Forse, dunque, questa stessa ipotesi si applica anche ai
linguaggi di programmazione: cercare di coprire tutti i livelli
entro lo stesso linguaggio puo` renderlo estremamente complesso
(e` certo il caso di Common Lisp e di C++, benche`, direi, non
di Dylan, che in effetti a differenza degli altri rinuncia almeno
ad alcuni campi, come i sistemi operativi e i driver [Common
Lisp li supportava sulle famose Lisp Machines di una volta]);
e/o puo` comunque non permettere al linguaggio di essere 
altrettanto buono di altri piu` specializzati almeno per
alcuni ambiti.  C++ mi pare che possa a buon diritto essere
considerato, complessita` a parte, altrettanto buono di C
per i bassissimi livelli: ma molti non sono d'accordo con me,
tanto e` vero che i sistemi operativi liberi come Linux, BSD
vari, ecc, continuano a usare soprattutto C, non C++.  Per gli
alti livelli, tipici della  programmazione applicativa, penso 
che si possa parlare di un crescente consenso contro l'uso
esclusivo di C++, con migrazioni, di massa o d'elite, verso
Java, Python, C#, e chi piu` ne ha piu` ne metta.
Non ho assolutamente altrettanta esperienza in Common Lisp e
in Dylan come in C++, e in particolare non li ho mai usati
per lo sviluppo di codice di produzione.  Quindi, in particolare,
non posso dire con sicurezza quanto bene facciano il lavoro di
alto livello.  Sospetto pero` che i loro problemi li abbiano,
anche al di la` delle storie delle macro e della sintassi.
Come minimo, meriterebbe studiarli a fondo (entrambi sono
scaricabili anche in ottime implementazioni open-source, e i
libri non mancano, anche in rete) prima di proporre un altro
linguaggio basato anch'esso sul concetto di "multi-livello".
Suggerirei dei due Dylan, che e` assai piu` semplice e piu`
mirato su questa idea-cardine.
Alex

 LISP),
Correzione dell'N-esimo errore di fatto: sia per SML sia per Common
Lisp esistono fior di compilatori, non solo interpreti.  I piu` noti
fra quelli gratuiti sono SML/NJ e Poly/ML (per altre notizie su SNL 
partire da 
http://cm.bell-labs.com/cm/cs/what/smlnj/sml97.html
), CLISP, 
CLiCC, etc.  Per entrambi i linguaggi esistono inoltre vari compilatori
commerciali (Harlequin ML-Works per SML, tanti per Common Lisp).
Non e` certo la carenza di compilatori che ha inibito il successo
"di pubblico" di ML (Standard o meno) e Lisp (Common o meno).
Alex

 Lisp esistono fior di compilatori, non solo interpreti.  I piu` noti
Non cambia il nocciolo del problema che stiamo affrontando, comunque grazie.
*** Azimuth ***

 mirato su questa idea-cardine.
Lo farò: studierò almeno Dylan.
Comunque la mia idea di multi-livello forse è un po' diversa.
Voglio che il linguaggio sia semplice e abbia pochissime parole chiave (è
difficile, ma non impossibile).
La mia idea è quella di creare un linguaggio che riduca in modo naturale la
ridondanza del codice. Questo dovrebbe facilitare la programmazione e
ridurre notevolmente le dimensioni del codice (ovviamente bisogna vedere
come).
Non voglio un linguaggio che permetta di usare vari livelli perchè sarebbe
quasi come usare il C con dell'asm inline.
M'interessa poter editare direttamente codice creato con poca fatica.
Al livello 5 scrivo 4 righe che generano 100 righe di codice a livello 4 e
così via.
Dal livello 5 non sarà possibile per esempio decidere se usare puntatori o
altri strumenti. Diciamo che il compilatore prenderà delle decisioni al
posto del programmatore. Scendendo di livello potremo vedere queste
decisioni e cambiare quelle che non ci piacciono (e non solo).
E' un po' come programmare in C e poi editarne il file obj in codice asm,
solo che qui la cosa si potrebbe fare a livelli molto più alti e il tutto
sarebbe *legato* e non separato in processi di fase1, compilazione, fase2,
"assemblamento", ecc...
La regola principale è che i livelli più alti devono nascondere dettagli ai
livelli più bassi. Non dovrebbe essere un fatto di librerie o di funzioni,
ma di sintassi e semantica.
Per esempio ad alto livello non ci si dovrebbe preoccupare di allocare
memoria (come già accade in Python mi sembra di capire), di come strutturare
i dati (fantascienza? forse no...), ecc....
Kiuhnm


Sì, comunque la mia idea di multi-livello è un po' diversa da quella che ho
trovato su alcuni libri (adesso non ricordo assolutamente i titoli) e alla
quale forse ti riferisci.
Non voglio poter solo utilizzare più "linguaggi" nello stesso codice, per
es:
start_livello1
.....
end_livello1
start_livello2
.....
end_livello2
altrimenti sarebbe come usare asm in linea.
M'interessa qualcosa del genere:
livello5:
.
.
.
Automaticamente vengono generate 1000 righe di codice che costituiranno per
esempio lo scheletro del nostro programma (la cui struttura è stata scritta
al livello 5).
A questo punto completeremo, modificheremo ecc... le 1000 righe ottenute
senza troppa fatica (almeno si spera).
Sta al programmatore decidere quanto vuole scendere di livello...
Ovviamente si potrà scendere di livello in qualsiasi momento e punto del
codice di alto livello. Il codice ad alto livello verrà modificato
leggermente in modo da segnalare in quali punti il codice più a basso
livello è stato modificato (non importa indicare come (sarebbe pressochè
impossibile), ma basta indicare dove).
Kiuhnm

vari, ecc, continuano a usare soprattutto C, non C++. 
tra le ipotesi possibile credo che sia dovuto al fatto che usare in
modo produttivo ed efficiente il C++ non è "facile" quanto il C
--
Rhymes (
rhymes_...@myself.com
)
http://www26.brinkster.com/rhymes
http://bw-crema.blogspot.com

 impossibile), ma basta indicare dove).
Ok. Ma come la mettiamo con eventuali "riordini" a livello (n - 1) ?
Esempio:
SORG[ 2 ]:
    ...
    100:  if ( a == 0 && b != 0 ) {
    101:    do_it( )
    102: }
    ...
SORG[ 1 ]:
    ...
    555: bool flag_a = compare( a, 0 );
    556: bool flag_b = not_compare( b, 0 );
    557: bool result = and( flag_a, flag_b );
    558: if_false( result ) goto 560
    559: call_routine( do_it )
    560: ...
    ...
LINEE[ 1 ]:
    ...
    100, 555 - 558
    101, 559
    ...
Se adesso modifico, ad esempio (per questioni di efficienza):
SORG'[ 1 ]:
    ...
    555: bool flag_a = compare( a, 0 );
    556: if_false( a ) goto 562
    557: bool flag_b = not_compare( b, 0 );
    558: call_routine( do_other )
    559: if_true( b ) goto 562
    560: bool result = and( flag_a, flag_b );
    561: call_routine( do_it )
    562: ...
    ...
Come fa il sistema a sapere quali linee del livello 2 sono state coinvolte?
Ciao!
*** Azimuth ***

 coinvolte?
Non ho mai detto che sarà facile ;-)
Quando sarà il momento ci penserò.
Per adesso sto solo esponendo idee :-)
(sto abusando del ng!!!)
Kiuhnm

 grazie.
Prego!   E` un piacere.
Alex

 Prego!   E` un piacere.
Prego, la prossima volta che vuoi sembrare saccente, accomodati.
Ma guarda.
*** Azimuth ***

 "assemblamento", ecc...
Mentre mi sembra possibile senza grossi problemi passare dall'altro al 
basso livello la vedo dura a fare il contrario.
Ad esempio se il codice di alto livello fosse:
variabile = Oggetto(a, b, c)
variabile.funzione(d, e)
Si potrebbe tradurre in un livello più basso come:
variabile = malloc(sizeof(Oggetto))
variabile.inizializza_tutte_i_membri()
variabile.inizializza(a, b, c)
variabile.funzione(d, e)
variabile.distruggi()
free(variabile)
E se nella versione a basso livello cancellassi una istruzione come la 
renderesti nell'altro livello?
-- 
Marco Barisione (ICQ 84277092)

 renderesti nell'altro livello?
La renderebbe "modificata" (anche se la natura della modifica sarebbe
incognita).
*** Azimuth ***

 incognita).
Non ho capito. Nel senso che nell'alto livello non potresti più 
modificarla?


 modificarla?
Ma questo è voluto!
L'alto livello deve nascondere dettagli, altrimenti il programmatore
scriverebbe le stesse identiche cose (con gli stessi dettagli), ma
semplicemente in modo diverso.
Una cosa che puoi modificare a livello 3 non puoi modificarla a livello 4,
altrimenti non avrebbe senso essere scesi a livello 3.
Ovviamente la cosa va un'attimo studiata e qualsiasi idea (tranne quella di
lasciar perdere tutto) è ben accetta, altrimenti non avrei scritto su questo
ng.
Kiuhnm
P.S. Si potrebbe anche fare un piccolo decompilatore, ma il fatto è che il
tutto viene mostrato e calcolato in tempo reale e quindi il programmatore
può intervenire se il compilatore è in difficoltà. Ogni volta che si scrive
qualcosa a un certo livello, il "compilatore" mostra un risultato parziale
ai livelli più bassi. Lo stesso vale per il contrario. Quando si modifica un
livello più basso, il livello più alto verrà modificato aggiungendo magari
HINT sul tipo di modifica effettuata.
Tipicamente una modifica eseguita a basso livello non dovrà essere così
drastica da modificare il codice ad alto livello, ma servirà soltanto a
esprimere dettagli non esprimibili ad alto livello.
E' come se ogni livello servisse a impostare soltanto alcune cifre di un
numero.
Prima scrivi
10.000000
Se la precisione è sufficiente ti fermi, altrimenti scendi di un livello:
10.900000
Come vedi il "codice" di livello superiore è rimasto invariato.
Le modifiche a basso livello non dovrebbero avere lo scopo di ottimizzare il
codice, ma soltanto di definire i dettagli. E' possibile ottimizzare il
codice *manualmente* soltanto se non si modifica la semantica del livello
più alto.
Kiuhnm