Forth (linguaggio di programmazione)

La struttura dati di base di Forth è il “dizionario” che associa “parole” a codice eseguibile o strutture dati denominate. Il dizionario è disposto in memoria come un albero di liste collegate con i collegamenti che procedono dall’ultima (più recente) parola definita alla più vecchia, fino a quando non viene trovato un valore sentinella, di solito un puntatore NULLO. Un interruttore di contesto fa sì che la ricerca di un elenco inizi da una foglia diversa. Una ricerca di elenchi collegati continua mentre il ramo si fonde nel trunk principale che alla fine torna alla sentinella, la radice.Ci possono essere diversi dizionari. In rari casi, come la meta-compilazione, un dizionario potrebbe essere isolato e autonomo.L’effetto assomiglia a quello degli spazi dei nomi di nidificazione e può sovraccaricare le parole chiave a seconda del contesto.

Una parola definita consiste generalmente di testa e corpo con la testa costituita dal campo nome (NF) e il campo collegamento (LF), e il corpo costituito dal campo codice (CF) e il campo parametro (PF).

La testa e il corpo di una voce del dizionario sono trattati separatamente perché potrebbero non essere contigui. Ad esempio, quando un programma Forth viene ricompilato per una nuova piattaforma, la testa può rimanere sul computer di compilazione, mentre il corpo va alla nuova piattaforma. In alcuni ambienti (come i sistemi embedded) le teste occupano memoria inutilmente. Tuttavia, alcuni cross-compilatori possono mettere teste nel target se il target stesso dovrebbe supportare un Forth interattivo.

Dictionary entryEdit

Il formato esatto di una voce del dizionario non è prescritto e le implementazioni variano. Tuttavia, alcuni componenti sono quasi sempre presenti, anche se la dimensione esatta e l’ordine possono variare. Descritto come una struttura, una voce del dizionario potrebbe apparire in questo modo:

 structure byte: flag \ 3bit flags + length of word's name char-array: name \ name's runtime length isn't known at compile time address: previous \ link field, backward ptr to previous word address: codeword \ ptr to the code to execute this word any-array: parameterfield \ unknown length of data, words, or opcodes end-structure forthword

Il campo nome inizia con un prefisso che indica la lunghezza del nome della parola (in genere fino a 32 byte) e diversi bit per i flag. La rappresentazione del carattere del nome della parola segue quindi il prefisso. A seconda della particolare implementazione di Forth, potrebbero esserci uno o più byte NUL (‘\0’) per l’allineamento.

Il campo link contiene un puntatore alla parola precedentemente definita. Il puntatore può essere uno spostamento relativo o un indirizzo assoluto che punta al prossimo fratello maggiore.

Il puntatore del campo codice sarà l’indirizzo della parola che eseguirà il codice o i dati nel campo parametro o l’inizio del codice macchina che il processore eseguirà direttamente. Per le parole definite dal colon, il puntatore del campo codice punta alla parola che salverà l’attuale puntatore di istruzione Forth (IP) sullo stack di ritorno e caricherà l’IP con il nuovo indirizzo da cui continuare l’esecuzione delle parole. Questo è lo stesso di quello che fanno le istruzioni di chiamata/ritorno di un processore.

Struttura del compilerEdit

Il compilatore stesso non è un programma monolitico. Consiste di quattro parole visibili al sistema e utilizzabili da un programmatore. Ciò consente a un programmatore di modificare le parole del compilatore per scopi speciali.

Il flag” compile time “nel campo name è impostato per le parole con comportamento” compile time”. La maggior parte delle parole semplici esegue lo stesso codice sia che siano digitate su una riga di comando o incorporate nel codice. Durante la compilazione di questi, il compilatore inserisce semplicemente il codice o un puntatore filettato alla parola.

Gli esempi classici di parole in fase di compilazione sono le strutture di controllo comeIFeWHILE. Quasi tutte le strutture di controllo di Forth e quasi tutto il suo compilatore sono implementate come parole in fase di compilazione. A parte alcune parole del flusso di controllo usate raramente che si trovano solo in alcune implementazioni, come un ritorno condizionale, tutte le parole del flusso di controllo di Forth vengono eseguite durante la compilazione per compilare varie combinazioni di parole primitive insieme ai loro indirizzi di ramo. Ad esempio, IF e WHILE, e le parole che corrispondono a quelle, impostare BRANCH (ramo incondizionato) e ?BRANCH (pop un valore fuori dallo stack, e ramo se è falso). Le parole del flusso di controllo del ciclo contato funzionano in modo simile, ma impostano combinazioni di parole primitive che funzionano con un contatore e così via. Durante la compilazione, lo stack di dati viene utilizzato per supportare il bilanciamento della struttura di controllo, l’annidamento e il back-patching degli indirizzi delle filiali. Il frammento:

 ... DUP 6 < IF DROP 5 ELSE 1 - THEN ...

vorresti essere compilato al seguente sequenza all’interno di una definizione:

 ... DUP LIT 6 < ?BRANCH 5 DROP LIT 5 BRANCH 3 LIT 1 - ...

I numeri dopo BRANCH rappresentano relativi indirizzi di salto. LIT è la parola primitiva per spingere un numero” letterale ” nello stack di dati.

Stato di compilazione e stato di interpretazioneedit

La parola: (due punti) analizza un nome come parametro, crea una voce del dizionario (una definizione di due punti) ed entra nello stato di compilazione. L’interprete continua a leggere parole delimitate dallo spazio dal dispositivo di input dell’utente. Se viene trovata una parola, l’interprete esegue la semantica di compilazione associata alla parola, invece della semantica di interpretazione. La semantica di compilazione predefinita di una parola deve aggiungere la sua semantica di interpretazione alla definizione corrente.

La parola ; (punto e virgola) termina la definizione corrente e ritorna allo stato di interpretazione. È un esempio di una parola la cui semantica di compilazione differisce da quella predefinita. La semantica dell’interpretazione di; (punto e virgola), la maggior parte delle parole del flusso di controllo e molte altre parole non sono definite in ANS Forth, il che significa che devono essere utilizzate solo all’interno delle definizioni e non sulla riga di comando interattiva.

Lo stato dell’interprete può essere modificato manualmente con le parole (parentesi a destra) che entrano rispettivamente nello stato di interpretazione o nello stato di compilazione. Queste parole possono essere utilizzate con la parola LITERAL per calcolare un valore durante una compilazione e per inserire il valore calcolato nella definizione corrente dei due punti. LITERAL ha la semantica di compilazione per prendere un oggetto dallo stack di dati e aggiungere la semantica alla definizione corrente dei due punti per posizionare quell’oggetto nello stack di dati.

In ANS Forth, lo stato corrente dell’interprete può essere letto dal flag STATE che contiene il valore true quando è in stato di compilazione e false altrimenti. Ciò consente l’implementazione delle cosiddette parole intelligenti di stato con un comportamento che cambia in base allo stato corrente dell’interprete.

Immediate wordsEdit

La parolaIMMEDIATE segna la definizione dei due punti più recente come parola immediata, sostituendo efficacemente la sua semantica di compilazione con la sua semantica di interpretazione. Le parole immediate vengono normalmente eseguite durante la compilazione, non compilate, ma questo può essere sovrascritto dal programmatore in entrambi gli stati. ; è un esempio di una parola immediata. In ANS Forth ,la parola POSTPONE prende un nome come parametro e aggiunge la semantica di compilazione della parola nominata alla definizione corrente anche se la parola è stata contrassegnata immediata. Forth-83 ha definito parole separate COMPILEe per forzare la compilazione di parole non immediate e immediate, rispettivamente.

Parole senza nome e tokensEdit di esecuzione

In ANS Forth, le parole senza nome possono essere definite con la parola:NONAME che compila le seguenti parole fino al successivo; (punto e virgola) e lascia un token di esecuzione nello stack di dati. Il token di esecuzione fornisce un handle opaco per la semantica compilata, simile ai puntatori di funzione del linguaggio di programmazione C.

I token di esecuzione possono essere memorizzati in variabili. La parola EXECUTE prende un token di esecuzione dallo stack di dati ed esegue la semantica associata. La parola COMPILE, (compile-comma) prende un token di esecuzione dallo stack di dati e aggiunge la semantica associata alla definizione corrente.

La parola ' (tick) prende il nome di una parola come parametro e restituisce il token di esecuzione associato a quella parola nello stack di dati. Nello stato di interpretazione,' RANDOM-WORD EXECUTE è equivalente aRANDOM-WORD.

Modifica

Le parole: (due punti),POSTPONE' (tick) sono esempi di analisi di parole che prendono i loro argomenti dal dispositivo di input dell’utente anziché dallo stack di dati. Un altro esempio è la parola ( (paren) che legge e ignora le seguenti parole fino alla successiva parentesi destra e viene utilizzata per inserire commenti in una definizione di due punti. Allo stesso modo, la parola \ (barra rovesciata) viene utilizzata per i commenti che continuano fino alla fine della riga corrente. Per essere analizzato correttamente, ( (paren) e \ (backslash) devono essere separati da spazi bianchi dal seguente testo di commento.

Struttura di codeEdit

Nella maggior parte dei sistemi Forth, il corpo di una definizione di codice è costituito da un linguaggio macchina o da una qualche forma di codice filettato. L’originale Forth che segue lo standard FIG informale (Forth Interest Group), è un TIL (Linguaggio interpretativo filettato). Questo è anche chiamato codice filettato indiretto, ma anche i forti filettati diretti e subroutine sono diventati popolari nei tempi moderni. I Forth moderni più veloci, come SwiftForth, VFX Forth e iForth, compilano il codice macchina nativo.

Data objectsEdit

Quando una parola è una variabile o un altro oggetto dati, il CF punta al codice di runtime associato alla parola che lo definisce. Una parola che definisce ha un caratteristico “comportamento di definizione” (creando una voce del dizionario più eventualmente allocando e inizializzando lo spazio dati) e specifica anche il comportamento di un’istanza della classe di parole costruite da questa parola di definizione. Gli esempi includono:

VARIABLEIndica una posizione di memoria non inizializzata a una cella. Il comportamento dell’istanza di unVARIABLErestituisce il suo indirizzo nello stack.CONSTANTIndica un valore (specificato come argomento perCONSTANT). Comportamento istanza restituisce il valore.CREATENomina una posizione; lo spazio può essere allocato in questa posizione o può essere impostato per contenere una stringa o un altro valore inizializzato. Comportamento istanza restituisce l’indirizzo dell’inizio di questo spazio.

Forth fornisce anche una funzione con cui un programmatore può definire nuove parole di definizione specifiche dell’applicazione, specificando sia un comportamento di definizione personalizzato che un comportamento di istanza. Alcuni esempi includono buffer circolari, bit denominati su una porta I/O e array indicizzati automaticamente.

Gli oggetti dati definiti da queste parole e simili sono di portata globale. La funzione fornita dalle variabili locali in altre lingue è fornita dallo stack di dati in Forth (sebbene Forth abbia anche variabili locali reali). Lo stile di programmazione Forth utilizza pochissimi oggetti dati con nome rispetto ad altri linguaggi; in genere tali oggetti dati vengono utilizzati per contenere dati che vengono utilizzati da un numero di parole o attività (in un’implementazione multitasked).

Forth non impone la coerenza dell’utilizzo del tipo di dati; è responsabilità del programmatore utilizzare operatori appropriati per recuperare e memorizzare valori o eseguire altre operazioni sui dati.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.