Forth

от Уикипедия, свободната енциклопедия
Forth
Парадигмапроцедурен, стеково ориентиран, рефлективен, обединяващ език
Реализиране през1970 г.;
преди 54 години
 (1970)
АвторЧарлз Мур
Типизация на даннитенетипизиран
ИмплементацияSwiftForth (Forth, Inc.)
Gforth (Free software)
VFX Forth (MicroProcessor Engineering)
Повлиян отB5000, Lisp, APL
ПовлияваFactor, PostScript, RPL, REBOL
Уебсайтwww.forth.com
Forth в Общомедия

Forth (чете се „форт“) е императивна стеково базирана среда за програмиране, създадена от Чарлз „Чък“ Мур. Характеризира се със структурно програмиране, рефлексия (способността да се модифицира структурата на програмата по време на изпълнението ѝ), свързано програмиране (функциите са подредени една до друга) и гъвкавост (програмистът може да създава нови команди). Въпреки че не е акроним, името на езика понякога се изписва с главни букви „FORTH“, следвайки обичайната практика от по-ранните години.

Като процедурно програмен език без Типизация на данните, Форт се характеризира с интерактивно изпълнение на команди (което го прави подходящ като команден интерпретатор за системи без операционна система) и със способност да компилира последователност от команди за по-късно изпълнение. Някои Форт имплементации (обикновено първите версии или написаните изключително като портативни) компилират нишков код, но много имплементации генерират оптимизиран машинен език подобно на други езикови компилатори.

Форт се използва за Open Firmware (стандарт на фърмуер) за първоначално зареждане на ОС в космически приложения,[1] като космическия апарат Филе и при различни видове хардуерни системи. Най-продаваната за 1986 игра Starflight, работеща под DOS, създадена от Електроник Артс, е написана на Форт.[2]

Преглед[редактиране | редактиране на кода]

Средата за разработка на Форт съчетава компилатора с интерактивен потребителски интерфейс, където потребителят определя и изпълнява подпрограми, наречени думи. Думите могат да бъдат тествани, предефинирани, и отстраняването на грешките може да се осъществи без прекомпилиране или рестартиране на цялата програма. Всички синтактични елементи, включително променливи и основни оператори са дефинирани като думи. Форт средите се различават по това как се съхранява получената програма, но в идеалния случай изпълнението на програмата има същия резултат, както ръчно да въведеш изходния код.

Стекове[редактиране | редактиране на кода]

Повечето среди за разработка с рекурсивни подпрограми използват „стек“ за контрол на потока, който съхранява локални променливи, включително и параметри на подпрограмата (в системи с извикване по стойност (Call by value), като например C). Форт често няма локални променливи, нито такива извиквани по стойност. Вместо това междинните стойности се съхраняват във втори „стек“. Думите оперират с най-горните стойности в първия стек, който поради това може да се нарече „стек“ от параметри или „данни“, но по-често се нарича просто „стек“. Вторият стек се нарича „linkage“ or „return“ „стек“, с абревиатура „rstack“. Ядрото на ОС се грижи за манипулирането на стека, като позволява той да се използван за временно съхранение в рамките на думата, но освен в тези случаи той не може да се използва за подаване на параметри или манипулиране на данни.

Повечето команди са специфицирани по начина си на въздействие върху „стека“. Обикновено параметрите са разположени на върха на „стека“, преди командата да се изпълни. След изпълнението параметрите се изтриват и заменят от връщаните стойности. За аритметичните оператори се следва правилото на обратната полска нотация. Вижте по-долу примери за използването на „стек“.

Поддръжка[редактиране | редактиране на кода]

Форт е прост, но допускаш разширение език. Неговата модулност и разширяемост позволява писането на програми от високо ниво като CAD системи. Форт е бил използван успешно в създаването на големи, сложни проекти. Разработените приложения са доказали в продължение на десетилетия, че са лесни за поддръжка в еволюиращи хардуерни платформи.[3] Forth has a niche both in astronomical and space applications.[4] Форт се използва в астрономически и космически приложения. Днес Форт все още се употребява в много вградени системи заради преносимостта му, ефективното използване на паметта, краткото време за развитие, както и бързата скорост на изпълнение.

Вграден е успешно в модерни RISC процесори, а също така са произведени процесори, които използват Форт като машинен език.[5]

Други приложения на Форт включват: boot ROM, използван от Apple Inc., Sun и OLPC XO-1, FICL – първият етап на BTX (boot_loader) на операционната система FreeBSD.

История[редактиране | редактиране на кода]

Форт еволюира от лична система за програмиране на Чарлз Мур, като се е развивала непрекъснато от 1968 г.[6]

За първи път Форт е предоставен на други програмисти през 1970 г., започвайки с Елизабет Радър от Националната радио астрономическа обсерватория на САЩ.[6] След работата си в NRAO, Чарлз Мур и Елизабет Радър създават компанията FORTH през 1973 г., усъвършенстват и пренасят Форт системи за десетки други платформи през следващото десетилетие.

Forth е наречен така през 1968 г. по името на обяснителния файл – FOURTH. Тъй като IBM_1130 позволява имена на файлове само до 5 знака е модифицирано на „Forth“.[7] Мур вижда Форт като наследник на трето поколение езици за програмиране, или като софтуер за хардуер „четвърто поколение“.

Тъй като Чарлз Мур често е сменял своята работа през кариерата си, ранният натиск върху развиването на програмния език е бил върху това да се улесни пренасянето му на различни компютърни архитектури. Системата Форт често се е използвала за въвеждане на нов хардуер. Например Форт е първият резидентен софтуер на новия чип Intel 8086 през 1978 г. и MacFORTH е първата развита система за първия Macintosh на Apple през 1984 г.[6]

MicroFORTH е разработена за микропроцесорите Intel 8080, Motorola 6800 и Zilog Z80, които започват да се произвеждат през 1976 г. MicroFORTH по-късно се използва от любители да произвеждат Форт системи за други архитектури, като 6502 през 1978 г. Широкото разпространение на езика води до неговата стандартизация. Общото приложение е стандартизирано в стандартите Форт-79[8] and FORTH-83[9] и Форт-83, съответно през годините 1979 г. и 1983 г. Тези стандарти са обединени от ANSI през 1994 г., обяснени в ANS Форт.[10][11]

Форт става много популярен през 1980 г.,[12] тъй като е подходящ за малките микрокомпютри по онова време, поради своята компактност и преносимост. Понр един домашен компютър, британската Юпитер ACE, е имал заложен Форт в ROM операционната си система, използвал също Форт за своя система за програмиране. Rockwell, също произвеждат едночипови микрокомпютри с Форт ядра, на R65F11 и R65F12. Пълното „родословно“дърво е в Технически университет – Виена. Insoft Garforth е версия на Форт с графични разширения. А ASYST е Форт разширение за измерване и контролиране на персонални компютри.[13] ASYST was a Forth expansion for measuring and controlling on PCs.[14]

Перспектива на програмиста[редактиране | редактиране на кода]

Форт силно разчита на изрично ползване на „стек“ данни и на обратна полска нотация (RPN или постфиксната нотация), често се използва в калкулатори отHewlett-Packard. В RPN операторът се намира след неговите операнди, за разлика от общо използваната инфискна нотация, където операторът се намира между неговите операнди. Postfix нотация прави езика по-лесен за разбор и разширяване. Гъвкавостта на Форт прави статичната БНФ граматика неуместна, и не разполага с монолитен компилатор. Разширяването на компилатора изисква само написването на нова дума, вместо модифициране на граматиката и промяна на основната имплементация.

Използването на RPN, може да намери резултата на математическия израз (25 * 10 + 50) по този начин:

25 10 * 50 + CR . 300 ok

Този команден ред първо слага 10 и 25 в скрития стек,

а думата *умножава двете числа на върха на стека и ги заменя с тяхното произведение.

След, което числото 50 е сложено в стека.

Думата +го добавя към произведението. CR премества резултата на нов ред (това е от гледна точка на форматирането и може да бъде пропуснато но – при повечето имплементации без тази дума ще изкарат резултата на един и същи ред с входните данни, поради което ще се наруши четимостта). Накрая командата . отпечатва резултата на потребителския терминал. След, което ако всичко е преминало успешно, текстовия редактор изписва „Ок“ и минава на нов ред, за да вземе още входна информация, без да е нужно изрично да му се дава команда за това.

Дори структурните характеристики на Форт са стеково базирани. Например:

: FLOOR5 (n -- n') DUP 6 < IF DROP 5 ELSE 1 – THEN ;

Този код дефинира нова дума наречена FLOOR5 използваща следните команди: DUP копира числото в стека; 6 слага 6 в началото на стека; < сравнява първите две числа в стека (6 и копирания вход), и ги заменя с булева стойност „вярно“ или „не вярно“; IF взима тази булева стойност и избира да изпълни командата веднага или да премине към ELSEDROP игнорира стойността на стека. След, което THEN приключва условието. Текстът в кавичките е коментар, който те подсеща, че тази дума очаква число в стека и ще върне вероятно променено число. Думата FLOOR5 е равностойна на същата функция написана на програмния език „C“ използващ тернарен оператор:

int floor5(int v) {
  return (v < 6) ? 5 : (v  1);
}

Тази функция е написана по сбито по следния начин

: FLOOR5 (n -- n') 1 – 5 MAX ;

Можете да изпълните тази думата така:

1 FLOOR5 CR . 5 ok 8 FLOOR5 CR . 7 ok

Първо интерпретатора слага число (1 или 8) в стека, след което вика думата FLOOR5, която изкарва резултата. CR мести изходните данни на нов ред. Накрая „.“ извиква резултата и го принтира на потребителския терминал.

Възможности[редактиране | редактиране на кода]

Форт няма категорична формална граматика. Интерпретаторът чете ред от потребителското входно устройство, след което се прави разбор на реда, използвайки шпацията като разграничител, като някои системи разпознават допълнителните празни символи. Когато интерпретаторът отдели една дума, той я проверява в речника. Ако намери думата, интерпретаторът изпълнява кода асоцииран с думата, след което се връща да прави разбора на останалата част от входния поток. Ако не намери думата, приема че е число и прави опит да я превърне в число, като я избутва в стека; ако действието е успешно, интерпретаторът продължава разбора на входния поток. В противен случай, ако проверката и опита за превръщането и в число се провали, интерпретаторът отпечатва думата последвана от съобщение за грешка, което показва, че не разпознава думата, премахва я от входния поток и чака за ново въвеждане от потребителя.[15]

Дефинирането на нова дума дума започва със символа : (двоеточие) и завършва с ; (точка и запетая). Например,

: X DUP 1+ . . ;

ще компилира думата X, и ще направи името откриваемо в речника. Когато операцията се изпълни след като се въведе 10 X, в конзолата ще се отпечата 11 10.[16]

Повечето Форт системи включват асемблер, който позволява да се определят точно думите, щадейки ресурсите на процесора. Обикновено асемблерът ги складира в отделно именно пространство (wordlist), тъй като се ползват рядко от потребителите. Асемблерите на Форт също могат да използват обратен полски запис.

Типичния асемблер подготвя операнди в стека като накрая помага копирането на цялата команда в паметта. Асемблерът на Форт в същността си е макро асемблер, така че е лесно да се определят псевдоними на регистри в зависимост от тяхната роля в системата на Форт: например „Datastackpointer“ използван като стек указател (променлива, съдържаща адрес в паметта) за регистъра.[17]

ОС, файлове, едновременно изпълнение[редактиране | редактиране на кода]

Повечето Форт системи работят под хост операционни системи като Microsoft Windows, Linux или версия на Unix, като за източник на файлове с данни използва системните файлове на съответната хост операционна система; стандартът на Форт ANSI описва използваните входящи и изходящи компютърни думи. Всичко модерни Форт системи използват нормални текстови файлове за източник, дори ако те са вградени. Вградената система с резидентен компилатор взима своя източник чрез серийна линия.

Класическите Форт системи традиционно не използват операционна система или файлова система. Вместо да се съхранява във файлове, изходния код се складира в дискови блокове, записани на адреса на физическия диск. Машинната дума BLOCK се използва за трансформирането на броя на един k-размерен блок в дисковото пространство от буфера, който съдържа данните, който се управлява автоматично от Форт системата. Блокът започва да се използва от средата на 1990-те години. В хост системите тези блокове също са разпределени в нормален файл.

На разположение е изпълняването на няколко команди едновременно, най-често съвместно циклично планиране. Машинната дума PAUSE най-често се използва за запаметяване на възпроизведения контекст на текущите задачи, за локализиране на следващата задача и за възстановяване на възпроизведения контекст. Всяка задача има свои собствени стекове, собствени копия на някои контролирани променливи и нулева зона. Смяната на задачите е проста и ефективна и в резултат на което изпълняването на няколко команди едновременно при Форт е възможно дори на много обикновени микроконтролери, като Intel 8051, Atmel AVR, и TI MSP430.[18]

Други по-нестандартни устройства разполагат с механизъм за издаване на повиквания до хост операционни системи или windows системи, и много от тях осигуряват разширения, които използват планирането, осигурено от операционната система. Обикновено те имат по-голям и по-различен набор от машинни думи от самостоятелната машинна дума на Форт PAUSE за създаване на задачи, ограничаване, унищожаване и промяна на приоритета.

Собствена компилация и обратна компилация[редактиране | редактиране на кода]

Пълнофункционалната система на Форт с всички изходни кодове ще се обединят, техника която обичайно се нарича мета-компилация от програмистите на Форт (въпреки че термина не отговаря точно на израза мета-компилация). Обичайният метод е да предефинира малката част от машинни думи, които поставят компилираните битове в паметта. Компилираните машинни думи използват специално наименувани версии за извличане и съхраняване, които могат да бъдат пренасочени към буферна зона в паметта. Буферната зона симулира зоната в паметта, която започва с различен адрес от този на буфера на кода. Такива компилатори определят машинни думи за да получат достъп до компютърната памет и тази на хоста.[19]

След извличането и съхраняването операциите са предефинирани за кодовото пространство, компилатора, алемблера и т.н. са прекомпилирани, използвайки новите определения за извличане и съхраняване. Тази ефективна повторна употреба на всички кодове в компилатора и интерпретатора. Така е компилиран системния код на Форт, но тази версия се съхранява в буфера. Буферът в паметта е записан на диск като са осигурени начини да бъде възпроизведен временно в паметта за тестване. Когато новата версия заработи, тя се презаписва върху старата версия.

Множество варианти на такива компилатори съществуват в различни среди. За вградени системи, кодът може вместо това да бъде написан на друг компютър, техника позната като целева компилация върху серийния порт или дори един-единствен бит ТТЛ (транзисторно транзисторна логика), докато запазва имената на машинните думи и други неизпълняващи части от речника в начално компилиращия компютър. Минималните определения за такъв компилатор на Форт са машинните думи които извличат и съхраняват един байт, и машинната дума, която дава командата машинната дума на Форт да бъде изпълнена. Обикновено частта, която отнема най-много време при писането на отдалечен порт е конструирането на главната програма за да въведе извличането, съхраняването и изпълнението, но много модерни микропроцесори имат вградена инструменти за отстраняване на грешки (като при Motorola CPU32), което елиминира тази задача.[20]

Структука на езика[редактиране | редактиране на кода]

Основната структура от данни, която се използва в езика Форт е „речника“. Той преобразува „думи“ в код, който може да бъде изпълнен. Речникът е изложен в паметта като дърво на свързани списъци с връзки, преминаващи от най-новата дефинирана дума до най-старата, докато стойността, която в повечето случаи е нулев указател (null pointer), не се появи. Търсенето по свързания списък продължава като клонът продължава да се слива в основата на ствола, като рано или късно се връща обратно към sentinel-а, а именно корена. Може да има повече от един брой речници. В редки случаи, като например по време на мета-компилация, речника може да бъде изолиран и самостоятелен. Ефектът наподобява този на вкарване на един namespace в друг, и може да презапише ключови думи в зависимост от контекста.

Дума, която има определение, обикновено се състои от глава и тяло, като главата съдържа полето за име (name field) и полето за връзка (link field), а тялото съдържа областта, в която се намира самия код (code field), както и областта на параметъра (parameter field).

„Главата и тялото“ на даден речник се разглеждат поотделно, тъй като те не могат да си граничат. Например, когато програма написана на Форт се прекомпилира за нова платформа, главата може да остане на компютъра, който компилира, докато тялото преминава на новата платформа. В някои програмни среди (като в областта на вградените системи) главите заемат ненужна памет. Въпреки това, някои компилатори, който работят на няколко платформи, могат да поставят главите в целта, ако целта, сама по себе си, се очаква да поддържа интерактива версия на Форт. [21]

Вписване в речника[редактиране | редактиране на кода]

Няма точен формат при вписване на данни в речника – и реализацията, и имплементацията варират. Въпреки това, някои компоненти са почти винаги налице, но също могат да варират по размер и ред. Ако трябва да го опишем като структура, вписването в речника изглежда по следния начин:[22]

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

Полето, което съдържа името, започва с префикс, което се дефинира от дължината на името на думата (обикновено до 32 байта), и няколко допълнителни бита за флагове. Думата се представя като символен низ, след което следва префикса. В зависимост от конкретната имплементация на Форт, може да има един или повече NUL (‘\0’) байта за подравняване.

Полето „link“ съдържа указател към предварително определена дума. Указателят може да играе ролята на изместител или на абсолютен адрес, който сочи към следващия най-възрастен събрат.

Структура на компилатора[редактиране | редактиране на кода]

Компилаторът не е монолитна програма. Състои се от Форт „думи“, които са видими за системата, и могат да се използват от програмиста. Това позволява на програмиста да променя думите на компилатора, ако иска да постигне определени цели.

Флагът на времето за компилация в полето „name“, е настроено за думи с „компилационно поведение“. Повечето прости думи, изпълняват един и същ код, независимо дали са писани в конзола, или са изпълнени в среда за разработка. При компилация, компилаторът просто поставя кода, или указател към думата.

Класическите примери за компилационни думи са контролните структури IF и WHILE. Почти всички контролни струрктури на езика Форт и почти всички компилатори са реализирани като компилационни думи. Освен някои рядко изплозвани контролни думи, които имат приложение само в някои имплементации, като например условното връщане. Всичките контролни думи на езика Форт се изпълняват по време на компилация, за да се направят различни комбинации от примитивни думи, заедно с техните разклоняващи се адреси. Например IF и WHILE, и думите, които съответстват с тези, създават BRANCH и ?BRANCH. Броени цикли на контролните думи, работят по подобен начин, но създават комбинации от примитивни думи, които работят с брояч. По време на компилация, стека с данни се използва за подпомагането на контролната структура, влагането, както и за обратно пачване на браншовите адреси. Пример:

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

Ще бъде компилиран в следната последователност:

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

Числата след BRANCH представляват относителните адреси. LIT е примитивната дума за бутане на „буквално“ число върху стека от данни.

Състояние на компилацията и състояние на интерпретацията[редактиране | редактиране на кода]

Думата : (двоеточие) парсва дадено име като параметър, вписва данни в речника и влиза в състояние на компилация. Интерпретаторът продължава да чете думи разделени с разстояние от потребителския вход. Ако се намери дума, интерпретаторът осъществавя компилация, свързана с думата, вместо семантичната интерпретация на думата.

Думата ; (точка и запетая) завършва настоящата дефиниция и се връща към състояние на интерпретация. Това е пример за дума, чиято компилационна семантика се различава от стойността по подразбиране на думата. Семантичното тълкуване на ;(точка и запетая), и на някои други думи са неопределени в ANS Forth, което означава, че те трябва да се използват само в рамките на определения, а не чрез интеракция с конзолата.

Състоянието на интерпретатора може да се променя ръчно, чрез думите [ (лява квадратна скоба) и ] (дясна квадратна скоба), които съответно влизат в състояние на интерпретация или в състояние на компилация. Тези думи могат да се използват в комбинация с думата LITERAL за изчисление на стойност по време на компилация, и за вмъкването на тази вече изчислена стойност в конкретната дефиниция на : (многоточие). LITERAL има компилационната семантика да вземе даден обект от стека с данни и да добавя семантика към конкретната дефиниция, за да постави този обект в стека с данни.

В ANS Forth, сегашното състояние на интерпретатора, може да бъде прочетен от флага STATE, който е TRUE по време на компилация и FALSE в противен случай. Това позволява имплементацията на така наречените state-smart words (пазещи състоянието си думи) с поведение, което се променя според текущото състояние на интерпретатора.

Непосредствени думи[редактиране | редактиране на кода]

Думата IMMEDIATE (непосредствен) маркира последната дефиниция дадена от конкретната дефиниция на : (двоеточие), ефективно замествайки неговата компилационна семантика с неговата тълковна семантика.[23] Непосредствените думи обикновено се изпълняват по време на компилация, не напълно компилирани, но това може да бъде презаписано или отхвърлено от програмиста, в което и да е състояние. ; (точка и запетая) е пример за непосредствена дума. В ANS Forth, думата POSTPONE (отлагам), взима дадено име като параметър и добавя компилационната семантика на същата дума към текущата дефиниция дори и думата да е маркирана като непосредствена. Forth-83 дефинира отделните думи COMPILE (компилирам) и [COMPILE], за да предизвика компилирането съответно на непосредствени и обикновени думи.

Думи без наименование и символи на изпълнение[редактиране | редактиране на кода]

В ANS Forth, думи без наименование могат да бъдат дефиниране с думата :NONAME (без име), като се компилират всички думи до следващата ; (точка и запетая), като оставя символи на изпълнение в стека с данни. Този символ на изпълнение осигурява семантичното компилиране, подобно на функционалните указатели на езика за програмиране C.

Символите на изпълнение(execution tokens) могат да се съхраняват в променливи. Думата EXECUTE (изпълнявам) взима даден символ на изпълнение от стека с данни и изпълнява свързаната семантика. Думата COMPILE (компилирам), взима символа на изпълнение (execution token) от стека с данни и добавя към текущата дефиниция свързаната семантика.

Думата (апостроф) взима името на дадена дума като параметър и връща низ от символи, които е свързан с думата в стека с данни. В състояние на интерпретация ‘RANDOM-WORD EXECUTE е равно на RANDOM-WORD.[24]

Правене на разбор на машинни думи и коментари[редактиране | редактиране на кода]

Машинните думи : (двоеточие), POSTPONE, ' (апостроф) са примери за правене на разбор на машинни думи, които прилагат техните аргументи от потребителското входиращо устройство вместо от данните на стека. Друг пример е машинната дума ( (скоба), която чете и игнорира следващите машинни думи до и включително следващата дясна скоба и се използва за да се напишат коментари в двоеточна дефиниция. Също така машинната дума \ (наклонена черта) се използва за коментари, които продължават до края на реда. За да бъде правилно направен разборът ( (скоба) и \(наклонена черта) трябва да бъдат разделени с разстояние от следващия текст на коментара.

Структура на кода[редактиране | редактиране на кода]

В повечето Форт системи, тялото на дадена кодова дефиниция се състои или от машинен език или от някаква форма на нишков код. Оригиналният Форт, който следва неформалния FIG стандарт (Forth Interest Group), е нишковотълкователен език. Това се нарича индиректнонишков код, но директнонишкови и подпрограмнонишкови Форт кодове също са станали популярни в днешно време. Най-бързите и модерни Форт реализации превръщат подпрограмите в нишки, вмъквайки „думи“ като макроси и изпълняват шпионкова оптимизация или други оптимизиращи стратегии, за да направят кода по-кратък и бърз.[25]

Обекти от данни[редактиране | редактиране на кода]

Когато една дума е променлива или друг обект от данни, кодовото поле сочи към кода, изпълняван по време на работа, който е свързан с дефиниращата дума, която го е създала. Дефиниращата дума има характерно „дефиниращо поведение“ (създавайки речник и евентуално заделяйки и инициализирайки пространство в паметта) и също така определя поведението на дадена инстанция от класа от думи, създадени от дефиниращата дума. Примери включват:

VARIABLE
Наименува неинициализирана едноклетъчна локация в паметта. Инстанционното поведение на дадена променлива VARIABLE връща нейния адрес в стека.
CONSTANT
Наименува стойност (уточнена като аргумент към константата CONSTANT). Инстанционното поведение връща стойността.
CREATE
Наименува локация; мястото може да бъде заделено за дадената локация или може да бъде направено да съдържа низ или друга инициализирана стойност.

Инстанционното поведение връща адреса на началото на това място.

Форт също така предоставя инструмент, чрез който програмистът може да дефинира нови, специфични за дадена апликация, дефиниращи думи, посочвайки както специфично дефиниращото поведение, така и инстанционното поведение. Някои примери включват кръгови буфери, наименувани битове на даден I/O порт и автоматично индексирани масиви.

Обектите от данни, дефинирани от тези и подобни думи, са с глобален обхват. Функцията, която се осигурява от локалните променливи в други езици, е осигурена от купчината от данни във Форт (въпреки че Форт също разполага с реални локални променливи). Стилът на програмиране на Форт използва много малко наименувани обекти от данни в сравнение с други езици; обикновено подобни обекти от данни се използват за съдържането на информация, която се използва от множество думи и обекти (в една многообектна имплементация).[26]

Форт не налага последователност в употребата на обектите от данни; програмистът носи отговорност да използва подходящите оператори, да взима и запазва стойност или да изпълнява други операции с информацията.

Програмиране[редактиране | редактиране на кода]

Думите, написани на Форт, се компилират в изпълним файл. Класическите реализации с „индиректни нишки“ компилират списъци на адреси на думи, които да бъдат изпълнени последователно; много съвременни системи генерират реален машинен код (включително повиквания към някои външни думи и код за други, разширени в място). Някои системи притежават оптимизиращи компилатори. Най-общо казано, програма, написана на Форт, се записва като образ на паметта на компилираната програма с една-единствена команда (например, RUN), който се изпълнява, когато компилираната версия е заредена.

По време на разработката, програмистът използва преводача в режим REPL за изпълнение и тестване на всеки малък детайл, докато се разработва. Поради това повечето програмисти на Форт препоръчват свободен дизайн отгоре-надолу, и разработка отдолу-нагоре с непрекъснато тестване и интеграция.[27]

Дизайнът отгоре-надолу обикновено представлява разделяне на програмата в „речници“, които след това се използват като комплекти от инструменти на високо равнище за написване на окончателната програма. Една добре проектирана Форт програма се чете като естествен език, и имплементира не само едно-единствено решение, но и инструменти за решаване на свързани проблеми.[28]

Примери за код[редактиране | редактиране на кода]

Примерът „Здравей, свят!“[редактиране | редактиране на кода]

В този пример на конзолен екран се извежда текстът „Здравей, свят!“:

Една възможна имплементация:

: HELLO (--) CR ." Hello, world!" ;
HELLO <cr>
Hello, world!

Думата CR (Carriage Return) кара следващия изход да се изведе на нов ред. Думата, правеща разбор ." (точка-двойни кавички) чете „двойни кавички“ от разграничения низ и добавя код към настоящото определение, така че обработеният низ ще бъде показан по време на изпълнение. Интервал (празен символ), делящ думата ." от низа Hello, World! не е включен като част от низа. Той е необходим, така че парсерът разпознава ." като Форт дума.

Една стандартна Форт система играе ролята на преводач и същия изход може да се получи, като въведете следния фрагмент от код във Форт конзолата:

CR .(Hello, world!)

.( (точка-скоба) е непосредствена дума, която прави разбор на низ, който е разграничен чрез скоби, и го показва на екрана. Както при думата ." интервалът (празен символ) след думата .( не е част от низа Hello, World!.

Думата CR се използва преди текста за печат. По установена практика, Форт преводачът не изкарва изхода на нов ред. Друга установена практика е преводачът да изчаква входа в края на предишния ред, след ok диалог. Не съществува имплицитно „флъш-буфер“ (на английски: flush-buffer) действие в думата CR на Форт, както е понякога в други езици за програмиране.

Смесване на състояния на компилиране и интерпретация[редактиране | редактиране на кода]

Ето дефиницията на думата EMIT-Q, която при изпълнение издава единствената буква Q:

: EMIT-Q 81 (the ASCII value for the character 'Q') EMIT ;

Това определение е написано, за да използва ASCII стойността на Q (81) директно. Текстът между скобите е коментар и се игнорира от компилатора. Думата EMIT приема стойност от стека от данни и показва съответния символ.

Следващото предефиниране на EMIT-Q използва думите [ (лява скоба), ] (дясна скоба), CHAR и LITERAL, за да смени състоянието на интерпретатора временно, да изчисли ASCII стойността на Q символа, да се върне към състояние на компилация и да добави изчислената стойност към настоящата двоеточна дефиниця:

: EMIT-Q [ CHAR Q ] LITERAL EMIT ;

Думата за разбор CHAR приема разделена чрез интервали дума като параметър и поставя стойността на първия ѝ символ в стека от данни. Думата [CHAR] е пряка версия на CHAR. Използвайки [CHAR], примерната дефиниция на EMIT-Q може да бъде пренаписана по следния начин:

: EMIT-Q [CHAR] Q EMIT ; \ Emit the single character 'Q'

Това определение използва \ (обратна наклонена черта) за описване на коментара.

И двете CHAR и [CHAR] са предварително определени ANS Форт. Използвайки IMMEDIATE и POSTPONE, [CHAR] може да се дефинира по следния начин:

: [CHAR] CHAR POSTPONE LITERAL ; IMMEDIATE

Пълна RC4 шифър програма[редактиране | редактиране на кода]

През 1987 г. Рон Ривест разработва RC4 шифър-системата за RSA Data Security, Inc. Кодът е изключително прост и може да бъде написан от повечето програмисти, следвайки описанието:

Имаме масив от 256 байта, от които всички са различни. Всеки път, когато масива се използва, той се променя, като размества два байта. Размените се контролират от броячи i и j, като всеки първоначално е 0. За да получите новия i, добавете 1. За да получите новия j, добавете байт масива на новото i. Разменете байт масивите на i и j. Кодът е байт масив от сумата от байт масивите на i и j. После се използва метода на изключване с един байт от обикновения текст, за да се кодира, или от шифър текста за декриптиране. Масивът се инициализира като се прави да бъде равен на 0 до 255. След това се преминава през него, използвайки i и j, получавайки новото j, като се добавя към него байт масива на i и ключов байт, и разменяйки байтовете на масиви на i и j. Накрая, i и j се правят да бъдат равни на 0. Всички прибавяния са по модул от 256.

Следната стандартна Форт версия използва само основни и основни разширени думи.

0 value ii        0 value jj
0 value KeyAddr   0 value KeyLen
create SArray   256 allot   \ state array of 256 bytes
: KeyArray      KeyLen mod   KeyAddr ;

: get_byte      + c@ ;
: set_byte      + c! ;
: as_byte       255 and ;
: reset_ij      0 TO ii   0 TO jj ;
: i_update      1 +   as_byte TO ii ;
: j_update      ii SArray get_byte +   as_byte TO jj ;
: swap_s_ij
    jj SArray get_byte
       ii SArray get_byte  jj SArray set_byte
    ii SArray set_byte
;

: rc4_init (KeyAddr KeyLen --)
    256 min TO KeyLen   TO KeyAddr
    256 0 DO   i i SArray set_byte   LOOP
    reset_ij
    BEGIN
        ii KeyArray get_byte   jj +  j_update
        swap_s_ij
        ii 255 < WHILE
        ii i_update
    REPEAT
    reset_ij
;
: rc4_byte
    ii i_update   jj j_update
    swap_s_ij
    ii SArray get_byte   jj SArray get_byte +   as_byte SArray get_byte  xor
;

Това е един от многото начини за тестване на кода:

hex
create AKey   61 c, 8A c, 63 c, D2 c, FB c,
: test   cr   0 DO  rc4_byte . LOOP  cr ;
AKey 5 rc4_init
2C F9 4C EE DC  5 test   \ output should be: F1 38 29 C9 DE

Имплементации[редактиране | редактиране на кода]

Поради това, че виртуалната машина на Форт е лесна за имплементация и няма стандартна референтна имплементация, има множество реализации на езика. В допълнение към поддръжката на стандартните видове десктоп компютърни системи (POSIX, Microsoft Windows, Mac OS X), много от тези Форт системи също така са насочени към различни вградени системи. Изброени са някои от най-важните системи, които съответстват на 1994 ANS Forth стандарта.

  • Gforth – преносима ANS Forth имплементация от проекта GNU
  • SwiftForth – настолни и вградени Форт системи от Forth, Inc., инициаторите на езика;
  • VFX Forth – високооптимизиращ естествен Форт код
  • SP-Forth – портативно Форт изпълнение от Russian Forth Interest Group
  • Open Firmware – буутлоудър и BIOS стандарт, базиран на ANSI Forth

Източници[редактиране | редактиране на кода]

  1. Space-Related Applications of Forth // Архивиран от оригинала на 2010-10-24. Посетен на 16 ноември 2016.
  2. Starflight // The Digital Antiquarian. 28 октомври 2014.
  3. Forth Success Stories // Посетен на 9 юни 2006.
  4. Space Related Applications of Forth // Архивиран от оригинала на 2011-02-04. Посетен на 4 септември 2007.
  5. Forth Chips Page // с. 54. Посетен на 9 юни 2006.
  6. а б в The Evolution of Forth // ACM SIGPLAN Notices, Volume 28, No. 3. March 1993. ACM SIGPLAN History of Programming Languages Conference, April 1993.
  7. Moore, Charles H. Forth – The Early Years // 1991. Архивиран от оригинала на 2006-06-15. Посетен на 3 юни 2006.
  8. The Forth-79 Standard (PDF) // Архивиран от оригинала на 2011-07-13. Посетен на 2016-04-26.
  9. The Forth-83 Standard
  10. Programming Languages: Forth // ANSI technical committee X3J14, 24 март 1994. Посетен на 3 юни 2006.
  11. Standard Forth (ANSI INCITS 215 – 1994) Reference // Quartus Handheld Software, 13 септември 2005. Посетен на 14 април 2013.
  12. The Forth Language. BYTE Magazine. Т. 5. 1980.
  13. GraFORTH II Language Reference (PDF)[неработеща препратка]
  14. Campbell et al, „Up and Running with Asyst 2.0“, MacMillan Software Co., 1987
  15. Brodie, Leo. Starting Forth. Second. Prentice-Hall, 1987. ISBN 0-13-843079-9. с. 14.
  16. Brodie, Leo. Starting Forth. Second. Prentice-Hall, 1987. ISBN 0-13-843079-9. с. 16.
  17. Rodriguez, Brad. B.Y.O.ASSEMBLER // Архивиран от оригинала на 2006-06-23. Посетен на 19 юни 2006.
  18. Rodriguez, Brad. MULTITASKING 8051 CAMELFORTH (PDF) // Архивиран от оригинала на 2006-06-22. Посетен на 19 юни 2006.
  19. Rodriguez, Brad. MOVING FORTH // July 1995. Архивиран от оригинала на 2006-06-23. Посетен на 19 юни 2006.
  20. Shoebridge, Peter. Motorola Background Debugging Mode Driver for Windows NT // 21 декември 1998. Посетен на 19 юни 2006.
  21. Martin, Harold M. Developing a tethered Forth model // ACM Press, March 1991. Посетен на 19 юни 2006.
  22. Brodie, Leo. Starting Forth. Second. Prentice-Hall, 1987. ISBN 0-13-843079-9. с. 200 – 202.
  23. Brodie, Leo. Starting Forth. Second. Prentice-Hall, 1987. ISBN 0-13-843079-9. с. 273.
  24. Brodie, Leo. Starting Forth. Second. Prentice-Hall, 1987. ISBN 0-13-843079-9. с. 199.
  25. Ertl, M. Anton, Gregg, David. Implementation Issues for Superinstructions in Gforth. Посетен на 19 юни 2006. Архив на оригинала от 2006-06-25 в Wayback Machine.
  26. Brodie, Leo. Under The Hood // Starting Forth. 2nd. Prentice-Hall, 1987. ISBN 0-13-843079-9. с. 241. To summarize, there are three kinds of variables: System variables contain values used by the entire Forth system. User variables contain values that are unique for each task, even though the definitions can be used by all tasks in the system. Regular variables can be accessible either system-wide or within a single task only, depending upon whether they are defined within OPERATOR or within a private task.
  27. Brodie, Leo. Thinking Forth. Prentice-Hall, 1984. ISBN 0-13-917568-7.
  28. The classic washing machine example describes the process of creating a vocabulary to naturally represent the problem domain in a readable way.

Външни препратки[редактиране | редактиране на кода]

  Тази страница частично или изцяло представлява превод на страницата Forth в Уикипедия на английски. Оригиналният текст, както и този превод, са защитени от Лиценза „Криейтив Комънс – Признание – Споделяне на споделеното“, а за съдържание, създадено преди юни 2009 година – от Лиценза за свободна документация на ГНУ. Прегледайте историята на редакциите на оригиналната страница, както и на преводната страница, за да видите списъка на съавторите. ​

ВАЖНО: Този шаблон се отнася единствено до авторските права върху съдържанието на статията. Добавянето му не отменя изискването да се посочват конкретни източници на твърденията, които да бъдат благонадеждни.​