index | project | pods | responsabili

NOME

perlcompile - Introduzione al Traduttore-Compilatore Perl


DESCRIZIONE

Perl ha da sempre un compilatore: il vostro codice viene compilato in un formato interno (un albero sintattico [parse tree, NdT]) che è poi ottimizzato prima di essere eseguito. Fin dalla versione 5.005, Perl è stato distribuito con un modulo capace di ispezionare l'albero sintattico ottimizzato (B), e questo è stato utilizzato per scrivere molte utilità, incluso un modulo che vi permette di convertire il vostro codice Perl in codice C in modo che possa essere compilato in un eseguibile nativo.

Il modulo B fornisce accesso all'albero sintattico, e altri moduli (detti ``back end'' [che si occupano della parte terminale del procedimento, NdR]) lavorano sull'albero. Alcuni di questi lo esportano come bytecode, codice C, o un testo semi-leggibile per l'uomo. Un altro attraversa l'albero sintattico per costruire una guida di riferimento [cross reference, NdT] di quali funzioni, formati, e variabili vengono usate, e dove. Un altro controlla il vostro codice alla ricerca di costrutti di dubbia natura. Un altro back end, ancora, salva l'albero sintattico come codice Perl, agendo come un miglioratore [beautifier, NdT] o deoffuscatore di codice.

Poiché il suo scopo originario era quello di produrre codice C corrispondente ad un programma Perl e di trasformarlo in un eseguibile nativo, il modulo B e i suoi back end associati sono noti come ``il compilatore'', anche se essi in realtà non compilano niente. Parti diverse del compilatore sono più propriamente un ``traduttore'', o un ``ispettore'', ma la gente vuole che Perl abbia una ``opzione compilatore'' non un ``ispettore gadget''. Cosa potete farci?

Questo documento ricopre l'uso del compilatore Perl: quali moduli comprende, come usare i moduli back end più importanti, che problemi ci sono e come li si aggira.

Struttura

I back end sono nella gerarchia di B:: e il front-end (il modulo con cui voi, utenti del compilatore, avrete qualche volta a che fare [dunque ciò che ha a che fare con la parte iniziale del procedimento, NdR]) è il modulo O. Alcuni back end (per esempio B::C) hanno programmi (come perlcc) che nascondono la complessità dei moduli.

Ecco i back end importanti da conoscere, con il loro status espresso come un numero da 0 (linea guida per implementazione futura) a 10 (se ci fosse un bug, ne saremmo molto sorpresi):

B::Bytecode
Salva l'albero sintattico in un formato indipendente dall'architettura, che può essere ricaricato in seguito attraverso il modulo ByteLoader. Status: 5 (qualcosa funziona, qualcosa no, qualcosa deve ancora essere testato).

B::C
Crea un file sorgente C contenente il codice per ricostruire l'albero sintattico e richiama l'interprete. Status: 6 (molte cose funzionano adeguatamente, inclusi programmi che usano Tk).

B::CC
Crea un codice sorgente C corrispondente al run time code path [``percorso del codice a tempo di esecuzione'', NdR] nell'albero sintattico. Questo è quello che più si avvicina ad un traduttore Perl-C, ma il codice generato è quasi incomprensibile perché traduce l'albero sintattico in una enorme struttura a switch [commutatori, NdR] che manipola strutture Perl. Un possibile miglioramento sarebbe ridurre (date sufficienti informazioni all'interno del programma Perl) alcune delle manipolazioni di strutture dati Perl in manipolazioni di interi, float, ecc. a livello C. Status: 5 (alcune cose funzionano, inclusi esempi non complicati in Tk).

B::Lint
Protesta se trova costrutti di dubbia natura nel vostro codice sorgente. Status: 6 (funziona adeguatamente, ma ha un numero molto limitato di aree che è in grado di controllare).

B::Deparse
Ricrea il codice sorgente Perl, tentando di formattarlo coerentemente. Status: 8 (funziona abbastanza bene, ma mancano alcune cose di natura oscura).

B::Xref
Effettua un riepilogo della dichiarazione e uso di funzioni e variabili. Status: 8 (funziona abbastanza bene, ma ha ancora diversi vecchi bug da risolvere).


Usare i back end

Questa sezione spiega come usare i vari back end del compilatore. Essi sono presentati approssimativamente in ordine di maturità in modo tale che i back end più stabili e testati siano descritti per primi, e quelli più sperimentali e incompleti siano descritti per ultimi.

Il modulo O abilita automaticamente il flag -c in Perl, il che gli impedisce di eseguire il vostro codice prima che esso venga compilato. Questo è il motivo per cui tutti i back end stampano:

  ilmioprogrammaperl syntax OK

prima di produrre ulteriore output.

Il back end per la guida di riferimento [cross reference, NdT]

Il back end per la costruzione della guida di riferimento (B::Xref) produce un rapporto riguardante il vostro programma, sviscerando le dichiarazioni e le chiamate alle funzioni, alle variabili ed ai formati, dividendoli per file e funzione. Per esempio, ecco una porzione del rapporto costruito sul programma pod2man incluso nella distribuzione di Perl:

  Subroutine clear_noremap
    Package (lexical)
      $ready_to_print   i1069, 1079
    Package main
      $&                1086
      $.                1086
      $0                1086
      $1                1087
      $2                1085, 1085
      $3                1085, 1085
      $ARGV             1086
      %HTML_Escapes     1085, 1085

Ciò mostra le variabili usate nella funzione clear_noremap. La variabile $ready_to_print è una variabile lessicale di tipo my(), Introdotta (dichiarata precedentemente con my()) alla linea 1069, e utilizzata alla linea 1079. La variabile $& proveniente dal package main è usata alla linea 1086, e così via.

Un numero di linea potrebbe essere preceduto da una singola lettera:

i
Variabile lessicale introdotta (dichiarata con my()) per la prima volta.

&
Funzione o chiamata a un metodo.

s
Funzione definita.

r
Formato definito.

L'opzione più utile del modulo per la guida di riferimento è quella di poter salvare il rapporto in un file separato. Per esempio, per salvare il rapporto riguardante ilmioprogrammaperl nel file rapporto è sufficiente digitare:

        $ perl -MO=Xref,-orapporto ilmioprogrammaperl

Il back end per la decompilazione

Per back end per la decompilazione trasforma il codice Perl in codice Perl. Esso è in grado di riformattare il codice durante il processo, comportandosi di fatto come un deoffuscatore. Il modo più semplice di utilizzarlo è:

  $ perl -MO=Deparse ilmioprogrammaperl

Noterete immediatamente che Perl non sa come mettere in paragrafi il vostro codice. Dovrete separare in seguito i pezzi di codice l'uno dall'altro a mano utilizzando l'andata a capo. Ciononostsante, guardate come si comporta con i programmi one-liner [su una sola riga, NdR]:

  $ perl -MO=Deparse -e '$op=shift||die "uso: $0
  codice [...]";chomp(@ARGV=<>)unless@ARGV; for(@ARGV){$era=$_;eval$op;
  die$@ if$@; rename$era,$_ unless$era eq $_}'
  -e syntax OK
  $op = shift @ARGV || die("uso: $0 codice [...]");
  chomp(@ARGV = <ARGV>) unless @ARGV;
  foreach $_ (@ARGV) {
      $era = $_;
      eval $op;
      die $@ if $@;
      rename $era, $_ unless $era eq $_;
  }

Il decompilatore ha diverse opzioni riguardanti il codice che genera. Per esempio, potete impostare la dimensione di ogni rientro da 4 a 2 spazi (come sopra) in questo modo:

  $ perl -MO=Deparse,-si2 ilmioprogrammaperl

L'opzione -p aggiunge parentesi dove esse sono generalmente omesse:

  $ perl -MO=Deparse -e 'print "Ciao, mondo\n"'
  -e syntax OK
  print "Ciao, mondo\n";
  $ perl -MO=Deparse,-p -e 'print "Ciao, mondo\n"'
  -e syntax OK
  print("Ciao, mondo\n");

Si veda the B::Deparse manpage per maggiori informazioni sulle opzioni di formattazione.

Il back end Lint

Il back end di controllo dello stile (B::Lint) analizza i programmi alla ricerca di porzioni di codice dallo stile povero. Lo scarso stile di un programmatore può essere uno strumento molto utile per un altro programmatore, per questo le opzioni vi lasciano scegliere su cosa bisogna impuntarsi.

Per eseguire il controllo di stile sul vostro codice sorgente usate:

  $ perl -MO=Lint ilmioprogrammaperl

Per disabilitare controlli di contesto e funzioni non definite:

  $ perl -MO=Lint,-context,-undefined-subs ilmioprogrammaperl

Si veda the B::Lint manpage per maggiori informazioni sulle opzioni.

Il back end per C semplice

Questo modulo trasforma lo stato compilato interno del vostro programma Perl in un file sorgente C, che può poi essere compilato in un eseguibile nativo per una particolare piattaforma usando un compilatore C. Il programma risultante si collega alla libreria dell'interprete Perl, quindi non vi farà risparmiare né spazio sull'hard disk (a meno che voi non compiliate Perl tramite una libreria condivisa) né dimensione del programma. Tuttavia potrebbe farvi risparmiare tempo nell'esecuzione.

Lo strumento perlcc genera tale eseguibile di default.

  perlcc ilmioprogramma.pl

Il back end per il Bytecode

Questo back end è utile solo se avete già un modo per caricare ed eseguire il codice bytecode che produce. Il modulo ByteLoader fornisce proprio questa funzionalità.

Per trasformare un programma Perl in un codice bytecode eseguibile, utilizzate perlcc con l'opzione -B:

  perlcc -B ilmioprogrammaperl.pl

Il bytecode è indipendente dall'architettura, quindi se avete un modulo o un programma compilato, esso sarà portabile quanto un codice sorgente Perl (posto che l'utente del modulo o del programma abbia un interprete Perl abbastanza moderno per eseguire il codice bytecode)

Si veda B::Bytecode per maggiori informazioni sulle opzioni per controllare l'ottimizzazione e il tipo di codice generato dal modulo Bytecode.

Il back end per C ottimizzato

Il back end per C ottimizzato trasformerà il run time code path del vostro programma perl in un programma C equivalente (ma ottimizzato) che manipola direttamente le strutture dati Perl. Il programma continuerà comunque a collegarsi alla libreria dell'interprete Perl per utilizzare eval(), s///e, require, ecc.

Lo strumento perlcc genera questo tipo di eseguibili se viene utilizzata l'opzione -O. Per compilare un programma Perl (con estensione .pl o .p) utilizzate il comando:


  perlcc -O ilmioprogrammaperl.pl

Per produrre una libreria condivisa a partire da un modulo Perl (con estensione .pm) usate:

  perlcc -O Ilmiomoduloperl.pm

Per maggiori informazioni, si veda perlcc e B:CC.


Lista di moduli per la suite [insieme di componenti, NdR] del compilatore

B
Questo è il modulo introspettivo (``riflessivo'' in termini Java), che permette ad un programma Perl di ispezionare il proprio stesso codice. Tutti i moduli back end utilizzano questo modulo per ottenere accesso all'albero sintattico compilato. Voi, come utenti di un modulo back end, non avrete mai bisogno di interagire direttamente con B.

O
Questo modulo è il front end al back end del compilatore. Normalmente richiamato con un comando come questo:
  $ perl -MO=Deparse ilmioprogrammaperl

Che è come dire use O 'Deparse' nel vostro programma Perl.

B::Asmdata
Questo modulo è utilizzato dal modulo B::Assembler, che è a sua volta usato dal modulo B::Bytecode, che salva un albero sintattico come bytecode per un caricamento successivo. Non è propriamente un back end, ma piuttosto un componente di un back end.

B::Assembler
Questo modulo trasforma l'albero sintattico in una struttura dati comoda per essere salvata e in seguito ritradotta in albero sintattico. Non è propriamente un back end, ma piuttosto il componente di un back end. È utilizzato dal programma l<assemble> che produce bytecode.

B::Bblock
Questo modulo è utilizzato dal back end B::CC. Esegue ``blocchi base''. Un blocco base è una serie di operazioni che sono eseguite dall'inizio alla fine, senza possibilità di effettuare salti o essere fermate.

B::Bytecode
Questo modulo è un back end che genera bytecode dall'albero sintattico di un programma. Questo bytecode viene scritto su un file, da cui può venire poi ripristinato ad albero sintattico. Lo scopo è di eseguire subito la costosa compilazione del programma, salvare lo stato dell'interprete in un file e poi ripristinare lo stato dal file quando il programma deve essere eseguito. Si veda Il back end Bytecode per maggiori dettagli sull'utilizzo.

B::C
Questo modulo scrive codice C corrispondente all'albero sintattico e ad altre strutture interne dell'interprete. Voi compilate il file C corrispondente, otterrete un file eseguibile che ripristinerà le strutture interne e l'interprete Perl inizierà ad eseguire il programma. Si veda Il back end per C semplice per maggiori dettagli sull'utilizzo.

B::CC
Questo modulo dà in output del codice C corrispondente alle operazioni del vostro programma. A differenza di B::C, che salva essenzialmente l'interprete ed il suo stato in un programma C, il modulo B::CC genera un programma C che non dipende dall'interprete. Una conseguenza è che i programmi tradotti in C da B::CC vengono eseguiti più velocemente dei normali programmi interpretati. Si veda Il back end per C ottimizzato per maggiori dettagli sull'utilizzo.

B::Concise
Questo modulo stampa una sintetica (ma completa) versione dell'albero sintattico di Perl. Il suo output è più personalizzabile di quello di B::Terse o di B::Debug (e può emularli). Questo modulo è utile per chi sta scrivendo i propri personali back end, o per chi deve imparare il funzionamento interno di Perl. Non è molto utile per il programmatore medio.

B::Debug
Questo modulo esporta l'albero sintattico di Perl con un livello di dettaglio ``verboso'' sullo STDOUT. È utile per chi sta scrivendo i propri back end, o chi deve imparare il funzionamento interno di Perl. Non è molto utile per il programmatore medio.

B::Deparse
Questo modulo produce codice sorgente Perl dall'albero sintattico compilato. È utile per effettuare del debug e per smontare il codice prodotto da altri, agisce anche come strumento di stampa per il proprio codice. Si veda </``Il back end per la decompilazione''> per maggiore dettagli sull'utilizzo.

B::Disassembler
Questo modulo ritraduce il bytecode in un albero sintattico. Non è propriamente un back end ma piuttosto un componente di un back end. È utilizzato dal programma l<disassemble> associato al bytecode.

B::Lint
Questo modulo ispeziona il codice compilato a partire dal vostro codice sorgente alla ricerca di costrutti che non siano abbastanza gravi da giustificare un warning. Per esempio l'utilizzo di un array in un contesto scalare senza dire scalar(@array) è una di quelle cose che Lint è in grado di identificare. Si veda Il back end Lint per maggiori dettagli sull'utilizzo.

B::Showlex
Questo modulo stampa la lista delle variabili my() utilizzate in una funzione o in un file. Per ottenere la lista di tutte le variabili my() utilizzate in una funzione definita in un programma, usate:
  $ perl -MO=Showlex,lamiafunzione ilmioprogrammaperl

Mentre per ottenere una lista delle variabili my() utilizzate in un programma, usate:

  $ perl -MO=Showlex ilmioprogrammaperl

[BROKEN]

B::Stackobj
Questo modulo è usato dal modulo B::CC. Non è propriamente un back end ma piuttosto un componente di un back end.

B::Stash
Questo modulo è utilizzato dal programma perlcc, che compila un modulo in un eseguibile. B::Stash stampa la tabella di simboli utilizzata da un programma, ed è utilizzata per evitare che B::CC produca codice C per i moduli B::* e O. Non è propriamente un back end ma piuttosto un componente di un back end.

B::Terse
Questo modulo stampa il contenuto dell'albero sintattico, ma senza tutte le informazioni che fornisce B::Debug. Per esempio: print "Hello, world." ha prodotto 96 linee di output con B::Debug, ma solo 6 con B::Terse.

Questo modulo è utile per chi sta scrivendo i propri back end, o per chi deve imparare il funzionamento interno di Perl. Non è molto utile per il programmatore medio.

B::Xref
Questo modulo stampa un rapporto di dove le variabili, le funzioni e i format sono definiti e utilizzati all'interno di un programma e nei moduli che questi utilizza. Si veda Il back end per la guida di riferimento per maggiori dettagli sull'utilizzo.


PROBLEMI NOTI

Il back end per C semplice attualmente salva i typeglobs solo con nomi alfanumerici.

Il back end per C ottimizzato produce codice per più moduli di quelli che dovrebbe (per esempio DirHandle). C'è anche la possibilità che gestisca correttamente goto LABEL fuori dalla subroutine in esecuzione (goto &sub funziona bene). goto LABEL attualmente non funziona affatto in questo back end. Genera anche una enorme funzione di inizializzazione che confonde il compilatore C. Altri problemi includono: la matematica senza segno non funziona correttamente; alcuni opcode sono gestiti non correttamente dal meccanismo di gestione degli opcode predefiniti.

I blocchi BEGIN{} sono eseguiti mentre il codice viene compilato. Ogni stato esterno che è inizializzato in BEGIN{}, come l'apertura di files, l'inizializzazione di connessioni a database ecc., non si comporta correttamente. Per far funzionare tutto ciò, Perl ha un blocco INIT{} che corrisponde al codice che viene essere eseguito prima del vostro programma ma dopo che il vostro programma è stato compilato. Ordine d'esecuzione: BEGIN{}, (possibile salvataggio di stato attraverso il back end del compilatore), INIT{}, esecuzione del programma, END{}.


AUTORE

Questo documento è stato scritto originariamente da Nathan Torkington, ed è attualmente mantenuto dalla mailing list perl5-porters. perl5-porters@perl.org.


TRADUZIONE

Versione

La versione su cui si basa questa traduzione è ottenibile con:

   perl -MPOD2::IT -e print_pod perlcompile

Per maggiori informazioni sul progetto di traduzione in italiano si veda http://pod2it.sourceforge.net/ .

Traduttore

Traduzione a cura di tunnuz.

Revisore

Revisione a cura di dree.


Mon Jun 11 22:02:13 2012