den grundläggande datastrukturen för Forth är ”ordboken” som kartlägger ”ord” till körbar kod eller namngivna datastrukturer. Ordboken läggs ut i minnet som ett träd med länkade listor med länkarna som går från det senaste (senast) definierade ordet till det äldsta, tills ett sentinelvärde, vanligtvis en NULL-pekare, hittas. En kontextbrytare gör att en listsökning börjar på ett annat blad. En länkad listsökning fortsätter när grenen går samman i huvudstammen som leder så småningom tillbaka till sentinel, the root.Det kan finnas flera ordböcker. I sällsynta fall som meta-kompilering kan en ordbok vara isolerad och fristående.Effekten liknar den för att häcka namnrymder och kan överbelasta nyckelord beroende på sammanhanget.
ett definierat ord består i allmänhet av huvud och kropp med huvudet som består av namnfältet (NF) och länkfältet (LF) och kropp som består av kodfältet (CF) och parameterfältet (PF).
huvud och kropp i en ordbokspost behandlas separat eftersom de kanske inte är sammanhängande. Till exempel, när ett Forth-program kompileras om för en ny plattform, kan huvudet stanna kvar på kompileringsdatorn, medan kroppen går till den nya plattformen. I vissa miljöer (t.ex. inbyggda system) upptar huvuden minnet i onödan. Vissa korskompilatorer kan dock sätta huvuden i målet om själva målet förväntas stödja en interaktiv Forth.
Dictionary entryEdit
det exakta formatet för en ordbokspost är inte föreskrivet, och implementeringarna varierar. Vissa komponenter är dock nästan alltid närvarande, även om den exakta storleken och ordningen kan variera. Beskriven som en struktur kan en ordbokspost se ut så här:
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
namnfältet börjar med ett prefix som ger längden på ordets namn (vanligtvis upp till 32 byte) och flera bitar för flaggor. Teckenrepresentationen av ordets namn följer sedan prefixet. Beroende på den specifika implementeringen av Forth kan det finnas en eller flera nul (’\0’) byte för justering.
länkfältet innehåller en pekare till det tidigare definierade ordet. Pekaren kan vara en relativ förskjutning eller en absolut adress som pekar på nästa äldsta syskon.
kodfältpekaren är antingen adressen till ordet som kommer att utföra koden eller data i parameterfältet eller början på maskinkoden som processorn kommer att utföra direkt. För kolondefinierade ord pekar kodfältpekaren på ordet som sparar den aktuella Forth instruction pointer (IP) på returstacken och laddar IP med den nya adressen för att fortsätta exekvera ord. Detta är detsamma som vad en processors samtal/returinstruktioner gör.
kompilerens Strukturredigera
kompilatorn i sig är inte ett monolitiskt program. Den består av Forth ord synliga för systemet, och kan användas av en programmerare. Detta gör det möjligt för en programmerare att ändra kompilatorns ord för speciella ändamål.
flaggan ”kompileringstid ”i namnfältet är inställd för ord med” kompileringstid ” – beteende. De flesta enkla ord kör samma kod oavsett om de skrivs på en kommandorad eller inbäddad i kod. När du sammanställer dessa placerar kompilatorn helt enkelt kod eller en gängad pekare till ordet.
de klassiska exemplen på kompileringstidsord är kontrollstrukturerna som IF
och WHILE
. Nästan alla Forths kontrollstrukturer och nästan alla dess kompilatorer implementeras som kompileringstidsord. Bortsett från några sällan använda kontrollflödesord som bara finns i några få implementeringar, såsom en villkorlig retur, exekveras alla Forths kontrollflödesord under kompilering för att kompilera olika kombinationer av primitiva ord tillsammans med deras filialadresser. Till exempel IF
och WHILE
, och orden som matchar dem, ställer in BRANCH
(ovillkorlig gren) och ?BRANCH
(pop ett värde från stacken och gren om det är falskt). Räknade slingkontrollflödesord fungerar på samma sätt men skapar kombinationer av primitiva ord som fungerar med en räknare och så vidare. Under sammanställningen används datastacken för att stödja kontrollstrukturbalansering, häckning och back-patching av grenadresser. Utdraget:
... DUP 6 < IF DROP 5 ELSE 1 - THEN ...
skulle sammanställas till följande sekvens i en definition:
... DUP LIT 6 < ?BRANCH 5 DROP LIT 5 BRANCH 3 LIT 1 - ...
siffrorna efter BRANCH
representerar relativa hoppadresser. LIT
är det primitiva ordet för att trycka ett” bokstavligt ” nummer på datastacken.
Kompileringstillstånd och tolkningstillståndredigera
ordet :
(kolon) tolkar ett namn som en parameter, skapar en ordbokspost (en kolondefinition) och går in i kompileringstillstånd. Tolken fortsätter att läsa rymdavgränsade ord från användarinmatningsenheten. Om ett ord hittas utför tolken kompileringssemantiken associerad med ordet, istället för tolkningssemantiken. Standardsammanställningssemantiken för ett ord är att lägga till dess tolkningssemantik till den nuvarande definitionen.
ordet ;
(semikolon) avslutar den aktuella definitionen och återgår till tolkningstillstånd. Det är ett exempel på ett ord vars kompileringssemantik skiljer sig från standard. Tolkningssemantiken för ;
(semikolon), de flesta kontrollflödesord och flera andra ord är odefinierade i Ans Forth, vilket innebär att de bara måste användas inuti definitioner och inte på den interaktiva kommandoraden.
tolktillståndet kan ändras manuellt med orden (höger konsol) som anger tolkningstillstånd respektive kompileringstillstånd. Dessa ord kan användas med ordet
LITERAL
för att beräkna ett värde under en sammanställning och för att infoga det beräknade värdet i den aktuella kolondefinitionen. LITERAL
har kompileringssemantiken för att ta ett objekt från datastacken och lägga till semantik till den aktuella kolondefinitionen för att placera det objektet på datastacken.
i ANS Forth kan tolkens nuvarande tillstånd läsas från flaggan STATE
som innehåller värdet sant när det är i kompileringstillstånd och falskt annars. Detta möjliggör implementering av så kallade statssmartord med beteende som ändras enligt tolkens nuvarande tillstånd.
omedelbar wordsEdit
ordet IMMEDIATE
markerar den senaste kolon definition som en omedelbar ord, effektivt ersätta sin sammanställning semantik med dess tolkning semantik. Omedelbara ord körs normalt under kompilering, inte sammanställd, men detta kan åsidosättas av programmeraren i båda staterna. ;
är ett exempel på ett omedelbart ord. I ANS Forth tar ordet POSTPONE
ett namn som en parameter och lägger till kompileringssemantiken för det namngivna ordet till den aktuella definitionen även om ordet markerades omedelbart. Forth-83 definierade separata ord COMPILE
och för att tvinga sammanställningen av icke-omedelbara respektive omedelbara ord.
Namnlösa ord och utförande tokensEdit
i ANS Forth kan namnlösa ord definieras med ordet :NONAME
som sammanställer följande ord fram till nästa ;
(semikolon) och lämnar en exekveringstoken på datastacken. Exekveringstoken ger ett ogenomskinligt handtag för den kompilerade semantiken, liknande funktionspekarna i C-programmeringsspråket.
Exekveringstoken kan lagras i variabler. Ordet EXECUTE
tar en exekveringstoken från datastacken och utför tillhörande semantik. Ordet COMPILE,
(kompilera-komma) tar en exekveringstoken från datastacken och lägger till tillhörande semantik till den aktuella definitionen.
ordet '
(tick) tar namnet på ett ord som en parameter och returnerar exekveringstoken som är associerad med det ordet på datastacken. I tolkningstillstånd motsvarar ' RANDOM-WORD EXECUTE
RANDOM-WORD
.
redigera
orden :
(kolon), POSTPONE
'
(tick) är exempel på att tolka ord som tar sina argument från användarinmatningsenheten istället för datastacken. Ett annat exempel är ordet (
(paren) som läser och ignorerar följande ord till och med nästa högra parentes och används för att placera kommentarer i en kolondefinition. På samma sätt används ordet \
(backslash) för kommentarer som fortsätter till slutet av den aktuella raden. För att tolkas korrekt måste (
(paren) och \
(backslash) separeras med blanksteg från följande kommentartext.
struktur av codeEdit
i de flesta Forth-system består kroppen av en koddefinition av antingen maskinspråk eller någon form av gängad kod. Den ursprungliga Forth som följer den informella FIG standard (Forth intressegrupp), är en TIL (gängade tolkande språk). Detta kallas också indirekt gängad kod, men direktgängade och subrutingängade forth har också blivit populära i modern tid. De snabbaste moderna Forterna, som SwiftForth, VFX Forth och iForth, kompilerar fram till inbyggd maskinkod.
data objectsEdit
När ett ord är en variabel eller ett annat dataobjekt pekar CF på runtime-koden som är associerad med det definierande ordet som skapade det. Ett definierande ord har ett karakteristiskt” definierande beteende ” (skapa en ordbokspost plus eventuellt allokera och initiera datautrymme) och specificerar också beteendet hos en instans av klassen av ord konstruerade av detta definierande ord. Exempel inkluderar:
VARIABLE
namnger en oinitierad, encellsminnesplats. Instansbeteende för ettVARIABLE
returnerar adressen på stacken.CONSTANT
namnger ett värde (anges som ett argument tillCONSTANT
). Instansbeteende returnerar värdet.CREATE
namnger en plats; utrymme kan tilldelas på den här platsen, eller det kan ställas in för att innehålla en sträng eller annat initialiserat värde. Instansbeteende returnerar adressen till början av detta utrymme.
Forth ger också en möjlighet genom vilken en programmerare kan definiera nya applikationsspecifika definierande ord, som anger både ett anpassat definierande beteende och instansbeteende. Några exempel inkluderar cirkulära buffertar, namngivna bitar på en I/O-port och automatiskt indexerade matriser.
dataobjekt som definieras av dessa och liknande ord är globala. Funktionen som tillhandahålls av lokala variabler på andra språk tillhandahålls av datastacken i Forth (även om Forth också har verkliga lokala variabler). Forth programmeringsstil använder mycket få namngivna dataobjekt jämfört med andra språk; vanligtvis används sådana dataobjekt för att innehålla data som används av ett antal ord eller uppgifter (i en multitaskad implementering).
Forth upprätthåller inte konsekvens av datatypsanvändning; det är programmerarens ansvar att använda lämpliga operatörer för att hämta och lagra värden eller utföra andra operationer på data.