Forth http://fforum.winglion.ru/ |
|
форт и мифы о нем http://fforum.winglion.ru/viewtopic.php?f=24&t=1146 |
Страница 3 из 3 |
Автор: | Ethereal [ Чт мар 10, 2011 04:26 ] |
Заголовок сообщения: | Re: форт и мифы о нем |
mOleg писал(а): Конечно, можно сказать, что это уже и есть форт, но тут позвольте не согласиться. Минимальная форт-система должна еще достаточно долго раскручиваться, чтобы с ней стало возможно более-менее серьзено работать. Кроме того, по ходу написания интерпретатора придется много времени тратить на знакомство с целевой системой, и с ее особенностями, если, конечно, речь идет о создании форт-системы на новой платформе. Позволю не согласиться с вашим несогласием. Я проделывал все это дважды - переносил Форт на новую платформу. Не за несколько дней, конечно, а за пару месяцев. Идея такая - имеем уже отработанную Форт систему для 32-разрядых embedded-платформ, этакий гибрид ANSI-Forth и Forth-79/83. Система состоит из двух частей. Первая - из низкоуровневых определений и минимального самораскручиваемого набора высокоуровневых слов. Короче, она написана так, что только и умеет вводить новые слова через двоеточие. И вторая половина - Форт-дополнение, написанное на Форте и скармливаемое первой половине по RS-232. Причем многие базовые слова типа IF THEN ELSE REPEAT UNTIL BEGIN WHILE DO LOOP , а также <# # #> . U. ,а также CONSTANT VARIABLE VALUE и прочая-прочая все это во второй половине. Я их аккуратно разложил в таком порядке, что определяю их одно за другим при скармливании по RS-232. Поэтому перенос состоит в переписывании низкоуровневых определений на ассемблере новой платформы, коротком разбирательстве как у нее RS-232 работает, чтобы к Форту подключиться терминалом, первая половина заливается во флешку, втарая половина скармливается ей через терминал и все - Форт в памяти готов к работе. Если нет, поскольку ты слепил ошибки, то они отлавливаются выводом промежуточные результатов через тот-же RS-232. Дальнейшая раскрутка Форта идет в процессе написания прикладной программы, дальнейшее изучение железа - тоже в процессе написания прикладной программы. При старте Форт-система копирует себя один к одному из флеш в ОЗУ и там запускает, слово SAVE сохраняет систему из ОЗУ во флеш и вуаля - дальнейшая работа с новой платформой через терминал идет на порядок быстрее, чем компилировать Си-шные исходники и по сто раз на дню флешку программатором переливать. Вот смотри. Порядок скармливания слов второй половины первой : HEX IMMEDIATE \ PAD */ C, CREATE ' COMPILE, [COMPILE] 0 -1 CHARS CHAR+ CHAR [CHAR] ['] >MARK <MARK <RESOLVE >RESOLVE AHEAD AGAIN IF THEN ELSE BEGIN UNTIL WHILE REPEAT DO LOOP +LOOP I ?DO CASE ENDCASE OF <=OF< ENDOF N>LINK L>NAME NAME> >NAME HOLD SIGN <# # #> #S U>D D>S D. . U. (") ", C" REFILL S" ." MOVE SOURCE POSTPONE RECURSE (;CODE) DOES> ABORT" VARIABLE ( D.R .R U.R :NONAME .( VALUE QUAN CONSTANT TO AT FROM VOCABULARY EVALUATE 2VARIABLE 2CONSTANT M+ .S ? U? ID. NLIST WORDS SLITERAL /STRING VECT U.0 DUMP FENCE FORGET UNUSED здесь каждое слово требует для определения только слов ранее определенных. А значит это - список слов, которые портировать вообще не надо, поскольку они присутствуют в виде текстового файла с Форт-определениями, который надо просто скормить первой половине Форт-системы через COM-порт. Такой подход сильно ускоряет процесс портирования. Причем этот список слов составлен так, чтобы не наносить урон быстродействию. Все, от чего зависит быстродействие Форт-системы - в первой половине Форта и на ассемблере. |
Автор: | in4 [ Чт мар 10, 2011 13:37 ] |
Заголовок сообщения: | Re: форт и мифы о нем |
Ethereal писал(а): Первая - из низкоуровневых определенийи минимального самораскручиваемого набора высокоуровневых слов. Можно список (желательно со описанием, что делает каждое)?
|
Автор: | mOleg [ Чт мар 10, 2011 18:15 ] |
Заголовок сообщения: | Re: форт и мифы о нем |
Ethereal писал(а): Позволю не согласиться с вашим несогласием. Я проделывал все это дважды - переносил Форт на новую платформу. Не за несколько дней, конечно, а за пару месяцев. ну и с чем тогда несогласие? К тому же речь шла не о портировании существующей системы, а создании с нуля. |
Автор: | Гость [ Пт мар 11, 2011 19:19 ] |
Заголовок сообщения: | Re: форт и мифы о нем |
Так правильный подход к созданию с нуля и состоит в портировании. Сначала создаешь Форт на хорошо знакомой архитектуре, например на IBM PC, которую знаешь как облупленную. А потом отработанные на ней алгоритмы портируешь на конечную платформу. Короче, мысль была такая - Форт системы можно создавать с нуля быстро, если продумать вопрос - КАК это делать. А если тупо начать создавать Форт на конечной платформе, то ничего уже быстро не получится. Я начал вообще с того, что создал Форт под MS-DOS в виде COM-файла, под впечатлением какого-то исходника скачанного с Интернета. А потом алгоритмы из этого Форта перенес на две инородных платформы. И с таким подходом получилось быстро. Т.е. быстрая создаваемость Форт-систем - это не миф, правда лишь при определенной технологии создания такой системы : - Изучаешь исходник чужой Форт-системы - Создаешь свой Форт на родной для себя архитектуре - Алгоритмы из этого Форта переносишь на целевую архитектуру |
Автор: | Гость [ Пт мар 11, 2011 19:22 ] |
Заголовок сообщения: | Re: форт и мифы о нем |
in4 писал(а): Ethereal писал(а): Первая - из низкоуровневых определенийи минимального самораскручиваемого набора высокоуровневых слов. Можно список (желательно со описанием, что делает каждое)?Сейчас подготовлю и сюда выложу. |
Автор: | WingLion [ Пт мар 11, 2011 19:29 ] |
Заголовок сообщения: | Re: форт и мифы о нем |
Кстати, создать с нуля форт-систему сейчас не получится принципиально. Просто потому, что нуля уже давно нет. И вторая причина. С нуля Форт уже был создан Ч.Муром. И второй раз войти в эту же воду никому уже не удастся. |
Автор: | Ethereal [ Пт мар 11, 2011 21:16 ] |
Заголовок сообщения: | Re: форт и мифы о нем |
in4 писал(а): Ethereal писал(а): Первая - из низкоуровневых определенийи минимального самораскручиваемого набора высокоуровневых слов. Можно список (желательно со описанием, что делает каждое)?Можно. Но значится так. Сначала пара пояснений. 1.) Я создал систему с прямым шитым кодом, потому-что он быстрее, чем косвенный шитый, а компиляция подпрограммного и тем более нативного кода - куда более сложное занятие, а я хотел сделать систему быстро. 2.) Я хотел сделать систему, которая теряла бы в быстродействии только за счет того, что в ней прямой шитый код и более не из-за чего. Поэтому низкоуровневых определений у меня много. Все, что важно оптимизировать по скорости - я кинул на ассемблерный уровень. 3.) Я сначала хотел сделать ANSI-Forth, но не понял что в этом стандарте наворочено со словарями, какая польза от MARKER вместо FORGET и в этом отношении откатился к предыдущим стандартам. Короче говоря, вышел ANSI-Forth со словарями в духе Forth-79/83 и с FORGET вместо MARKER. Также из-за следования стандарту ANSI-Forth пришлось реализовывать в низкоуровневых определениях кучу разных вариантов умножений и делений. Если бы я следовал Forth-83 было бы все проще, но что сделано - то сделано -------------------------------------------------------------------- Код: // СООТВЕТСТВИЕ СТАНДАРТУ ANS-FORTH // // Из набора CORE исключено ENVIRONMENT? // VARIABLE всегда инициализируется нулем // Из набора CORE EXT исключены // CONVERT EXPECT MARKER RESTORE-INPUT SAVE-INPUT SPAN // , впрочем CONVERT, EXPECT и SPAN легко ввести как // VARIABLE SPAN // : EXPECT ACCEPT SPAN ! ; // : CONVERT // BEGIN // CHAR+ DUP >R C@ BASE @ DIGIT // WHILE // SWAP BASE @ * ROT BASE @ UM* D+ R> // REPEAT // R> // ; // Полностью исключены наборы BLOCK и BLOCK EXT // Из набора DOUBLE не реализовано только M*/ // 2VARIABLE всегда инициализируется нулем // Наборы EXCEPTION и EXCEPTION EXT реализованы полностью // Из наборов FACILITY и FACILITY EXT реализованы только KEY? EMIT? // Из набора FILE реализовано только расширение семантики ( // Полностью исключен набор FILE EXT // Полностью исключены наборы FLOATING и FLOATING EXT // Из набора LOCAL исключены (LOCAL) LOCALS| // Полностью исключен набор MEMORY // Из набора TOOLS исключено SEE /* Из набора TOOLS EXT исключены // ;CODE ASSEMBLER CODE CS-PICK CS-ROLL EDITOR [ELSE] [IF] [THEN] // Из набора SEARCH исключены GET-ORDER SET-ORDER WORDLIST // Из набора SEARCH EXT исключены ALSO ONLY ORDER PREVIOUS // и вообще контекстные словари реализованы в духе Forth-79/83 // Набор STRING реализован полностью */ Опрелелены два макроса : COLON - шапка высокоуровневого определения в прямом шитом коде NEXT - хвост низкоуровевого определения в прямом шитом коде Низrоуровневые определения смысл которых понятен сразу : EXIT LIT 2LIT EXECUTE NOOP FALSE 1 2 CELL TRUE ?DUP DUP DROP NIP TUCK OVER SWAP ROT -ROT >R R> R@ 2>R 2R> 2R@ SP@ SP! RP@ RP! PICK ROLL RDROP CELL+ CELL- CELLS 2DUP 2OVER 2SWAP 2ROT @ ! 2DROP C@ C! 2@ 2! + - * AND OR XOR ABS DABS NEGATE DNEGATE INVERT D+ D- 1+ 1- 2* 2/ D2* D2/ LSHIFT RSHIFT 1+! 1-! 0! S>D D0= 0= 0<> D0< 0< 0> = <> < > U< U> D= D< DU< WITHIN MIN MAX UMIN UMAX DMIN DMAX +! BRANCH ?BRANCH J K L LEAVE UNLOOP M* UM* UM/MOD FM/MOD SM/REM */MOD / U/ MOD UMOD /MOD >BODY ALIGNED BL COUNT C/L -TRAILING CMOVE CMOVE> FILL BLANK ERASE COMPARE SEARCH EMIT SPACE EMIT? KEY KEY? FORTH-WORDLIST SEARCH-WORDLIST Низкоуровневые определения смысл которых надо пояснять : SAVE - сохранить Форт-систему один в один из ОЗУ во FLASH. При старте Форт-система копирует себя один в один из FLASH в ОЗУ. BYE - перегрузка системы. Заставляет сработать watch-dog процессора. ENTER - код, которая вызывается, как подпрограмма из шапки высокоуровневого определения. (DOES>) - исполняемый код DOES> VAR - код, которая вызывается, как подпрограмма из шапки переменной, созданной VARIABLE. VAL - код, которая вызывается, как подпрограмма из шапки переменной, созданной VALUE или константы, созданной CONSTANT. VOC - код, которая вызывается, как подпрограмма из шапки словаря, созданного VOCABULARY. W@ W! - разыменовать и занести для 16-разрядных (DO) (?DO) (LOOP) (+LOOP) (OF) (<=OF<) - исполняемые части соответствующих слов (FOR) (NEXT) - исполняемые части нестандартного цикла с одним параметром FOR-NEXT. Цикл отрабатывает n раз, только если n>0 знаково. Цикл FOR-NEXT помогает оптимизировать определения слов типа TYPE и SPACES IGNORE - мой эксперимент с шитым кодом. Пропускает следующий вызов шитого кода. Эквивалентно : IGNORE R> CELL+ >R ; Используется для оптимизации шитого кода по скорости. ?IGNORE - мой эксперимент с шитым кодом. Снимает со стека число и если оно - ноль, то пропускает следующий вызов шитого кода. Эквивалентно : ?IGNORE 0= IF R> CELL+ >R THEN ; Используется для оптимизации шитого кода по скорости. DIGIT ( char n1 -- n2 true | false ) n2 - значение литеры char как цифры в системе счисления по основанию n1 Высокоуровневые определения, понятные без пояснений : CR SPACES TYPE ACCEPT QUERY DROPALL DEPTH ?STACK [ ] DECIMAL >NUMBER HERE ALIGN ALLOT , LITERAL 2LITERAL CATCH THROW : ; PARSE QUIT FIND Высокоуровневые определения, требующие пояснений : : ". COUNT TYPE ; (.") (ABORT") - исполняемые части ." и ABORT" вот в таком виде : : (.") R> COUNT 2DUP TYPE + ALIGNED >R ; : (ABORT") R> COUNT ROT IF TYPE -2 THROW THEN + ALIGNED >R ; ?LITERAL - смотри SP-Forth 2.x COMPILE - смотри Forth-83 : ABORT -1 THROW : LATEST LAST @ ; : GET-CURRENT CURRENT @ ; : SET-CURRENT CURRENT ! ; : DEFINITIONS CONTEXT @ SET-CURRENT ; SKIP - смотри SP-Forth INTERPRET - снова подражание Черезову, вот в таком виде : Код: // : INTERPRET // BEGIN // BL WORD DUP C@ 0= IF DROP EXIT THEN // FIND ?DUP // IF // STATE @ = IF , ELSE EXECUTE THEN // ELSE // ?LITERAL // THEN // ?STACK // AGAIN // ; Самые важные высокоуровневые слова : Код: // : WORD ( char "<chars>ccc<char>" -- c-addr ) // DUP SKIP PARSE 31 UMIN // NP @ OVER 3 OR 1+ - DUP >R 2DUP C! 1+ SWAP CMOVE R> // ; Как видите, выделяет из входного потока слово, ограниченное разделителем и укладывает его сразу ниже вершины словаря так, что если это слово придется добавить к словарю, то его имя уже на готово лежит там где нужно. Добавление слова к словарю состоит из двух частей. Никакая техника SMUDGE не используется. Первую часть делает слово Код: // : +WORD // BL WORD DUP FIND NIP // IF // WARNING @ // IF // DUP ". SPACE ." redefined" CR // THEN // THEN // ALIGN HERE OVER CELL- GET-CURRENT @ OVER ! CELL- DUP NP ! ! LAST ! // ; оно делает все, что нужно для добавляния слова к словарю, но это слово еще не видно при поиске по словарю, поскольку ни один VOCABULARY на него еще не указывает. Вторая часть делает это слово видимым при поиске : Код: // : +NAME // LATEST GET-CURRENT ! // ; Как видите, ото всяких SMUDGE я отказался, обойдясь без них. В итоге, например : : +WORD COMPILE [ HEX 24397F00 , ] COMPILE ENTER ] ; здесь 24397F00 - опкод call-а на ENTER. : ; COMPILE EXIT +NAME [ ; IMMEDIATE Также я выкинул из Форт-системы ?COMP поскольку на встроенной системе, если ты употребил слово COMPILEONLY в режиме интерпретации, то нажать кнопку сброс на плате и перестартовать Форт - не проблема. Переменные : #TIB >IN BASE CONTEXT CURRENT DP HANDLER HLD LAST NP S0 R0 STATE VOC-LINK WARNING SOURCE-ID TIB FORTH MAIN Здесь MAIN - вектор, выполняющийся при старте Форт-системы. Словарь в системе отделен от кода, чтобы его легко можно было отрезать. Код растет от самого младшего адреса вверх и DP содержит его HERE. Словарь растет от самого старшего адреса вниз и NP содержит его HERE. VOC-LINK - указатель, который начинает цепочку, объединяющую все словари в один список. Используется при FORGET. FORGET откатывает и NP и DP и забываемые словари тоже изымает из списка VOC-LINK P.S. Вот еще распишу, как выглядит QUIT : Код: // : QUIT ( -- ) ( R: i*x ) // BEGIN // DROPALL RP0 RP! [ // BEGIN // CR QUERY ['] INTERPRET CATCH ?DUP 0= // WHILE // SPACE ." Ok" // REPEAT // 1+ 0= // IF // >IN @ 1- 1- SPACES // ." ^ -" // THEN // SPACE [CHAR] ? EMIT // AGAIN // ; P.P.S Еще покажу FIND. FIND должна искать в словарях в порядке CONTEXT->CURRENT->FORTH. С этой FIND у меня получился какой-то алгоритмический бред полный : Код: // : FIND ( c-addr -- c-addr 0 | xt 1|xt -1 )
// >R 0 FORTH-WORDLIST GET-CURRENT CONTEXT @ // >R OVER R@ = IF NIP THEN \ SpeedUp // 2DUP = IF DROP THEN \ SpeedUp // R> 2DUP = IF DROP THEN \ SpeedUp // BEGIN // DUP 0= IF R> SWAP EXIT THEN // R@ COUNT ROT SEARCH-WORDLIST ?DUP // UNTIL // RDROP 2>R // BEGIN 0= UNTIL // 2R> // ; |
Автор: | mOleg [ Пт мар 11, 2011 23:54 ] |
Заголовок сообщения: | Re: форт и мифы о нем |
Ethereal писал(а): 1.) Я создал систему с прямым шитым кодом, потому-что он быстрее, чем косвенный шитый, а компиляция подпрограммного и тем более нативного кода - куда более сложное занятие, а я хотел сделать систему быстро. гм, на самом деле не сложнее нативный, если не заниматься оптимизацией кода. Ethereal писал(а): IGNORE - мой эксперимент с шитым кодом. Пропускает следующий вызов шитого кода. Эквивалентно : IGNORE R> CELL+ >R ; Используется для оптимизации шитого кода по скорости. ?IGNORE - мой эксперимент с шитым кодом. Снимает со стека число и если оно - ноль, то пропускает следующий вызов шитого кода. Эквивалентно : ?IGNORE 0= IF R> CELL+ >R THEN ; Используется для оптимизации шитого кода по скорости. о, а вот это интересно, поподробнее можно? Это типа замена ?BRANCH и BRANCH ? Собственно ,пока IGNORE для меня наиболее загадочен |
Автор: | Ethereal [ Сб мар 12, 2011 00:17 ] |
Заголовок сообщения: | Re: форт и мифы о нем |
Можно. Собственно говоря, я обнаружил, что шитый код, хотя и есть компиляция Фортовского текста один в один, но он сам по себе представляет язык чуть более низкого уровня, чем Форт и на нем можно делать некоторые более оптимальные вещи, которые на Форте если и запишешь, то только через извращения. Пример 1 : Понятно, что ядро Форта должно быть оптимизировано. И вот имеем высокоуровневое определение. Код: : INTERPRET BEGIN BL WORD DUP C@ 0= IF DROP EXIT THEN FIND ?DUP IF STATE @ = IF , ELSE EXECUTE THEN ELSE ?LITERAL THEN ?STACK AGAIN ; А на шитом коде запишем его так : Код: INTERPRET: COLON // INTERPRET _INTERPRET: .long BL, WORD, DUPE, C_FETCH .long QUESTION_BRANCH, DROP_EXIT .long FIND, QUESTION_DUPE .long QUESTION_BRANCH, ___INTERPRET .long STATE, FETCH, EQUALS .long QUESTION_BRANCH, __INTERPRET .long COMMA .long BRANCH, _INTERPRET __INTERPRET: .long EXECUTE .long IGNORE ___INTERPRET: .long QUESTION_LITERAL .long QUESTION_STACK .long BRANCH, _INTERPRET Здесь IGNORE просто перепрыгивает через QUESTION_LITERAL сразу на QUESTION_STACK. Потому она и названа IGNORE, что заставляет игнорировать следующую команду в шитом коде. В PIC-процессорах нет команд условных переходов, а есть условные скипы, т.е условные перепрыгивания через следующую команду. Так вот IGNORE - это аналогичнй скип через следующую команду. Правда в SP-Forth слово SKIP уже было задействовано для другой цели, поэтому я использовал имя IGNORE. Да, IGNORE заменяет BRANCH, который здесь можно было бы поставить так : Код: __INTERPRET: .long EXECUTE .long BRANCH, LABEL ___INTERPRET: .long QUESTION_LITERAL LABEL: .long QUESTION_STACK .long BRANCH, _INTERPRET Фишка в том, что IGNORE исполняется быстрее - это раз, а во вторых оно не требует накладных расходов на свое создание. Потому-что IGNORE УЖЕ ЕСТЬ, как одна из веток ?BRANCH. Вот смотри : Код: QUESTION_BRANCH:tst r14, r14 // ?BRANCH ldw r14, (r0) addi r0, 4 bf BRANCH IGNORE: ldw r13, (r10, 4) addi r10, 8 jmp r13 BRANCH: ldw r10, (r10) // BRANCH NEXT Т.е. IGNORE уже и так есть, это только метка внутри ?BRANCH и ее можно использовать для оптимизации по скорости. Не бог весть какая оптимизация, но все таки оптимизация Впрочем, я сейчас приведу более интересный пример. |
Автор: | Ethereal [ Сб мар 12, 2011 00:29 ] |
Заголовок сообщения: | Re: форт и мифы о нем |
Даже два примера. Пример 2 : Итак, если мы определим как форт-слово метку IGNORE внутри ?BRANCH, и еще напишем для комплекта ?IGNORE (условный скип через команду в шитом коде), то эти слова вовсю можно использовать уже внутри текста Форт-программ для оптимизации по скорости. Например, во второй части моего Форта, которая скармливается текстовым файлом первой через терминал, имеет место быть : : S" [COMPILE] C" STATE @ ?IGNORE COMPILE COUNT ; IMMEDIATE У меня C" и S" работают и в режиме компиляции и в режиме интерпретации. В приведенном определении в режиме компиляции выполнится COMPILE COUNT ,а в режиме интерпретации просто COUNT Или вот еще : Код: : RECURSE GET-CURRENT @ LATEST <> \ Определение по : или по :NONAME ? IF LATEST NAME> IGNORE THEN DUP COMPILE, ; IMMEDIATE Не бог весть-что конечно, но эксперименты с оптимизацией шитого кода интересны. P.S. В определение ?LITERAL есть R> IF NEGATE THEN и R> IF DNEGATE THEN Они так и просят ?IGNORE Но сейчас найду самый интересный пример. |
Автор: | Ethereal [ Сб мар 12, 2011 00:51 ] |
Заголовок сообщения: | Re: форт и мифы о нем |
Пример 3 : BRANCH-ами и ?BRANCH-ами в шитом коде можно наплести такое, что потом записать это на Форте будет проблематично. Вариант Форта для i80x96 я писал весь на ассемблере и так было такое определение Код: _COLON_ 5,'>NAME',tNAME DCW tR,VOC_LINK _Name1: DCW AT_,DUP,qBRANCH,_Name3 DCW DUP _Name2: DCW DECDEC,AT_ DCW qDUP,qBRANCH,_Name1 DCW DUP,NAMEt,RAT,_EQ_ DCW qBRANCH,_Name2 DCW NIP _Name3: DCW RDROP,EXIT При написании Форта для Motorola MCORE я решил вынести это определение во вторую часть системы, написанную на Форте. И с использованием стандартных управляющих констукций Форт у меня вышел такой уродец : Код: : >NAME >R VOC-LINK BEGIN @ DUP WHILE DUP BEGIN [ SWAP ] CELL- @ ?DUP UNTIL DUP NAME> R@ = UNTIL NIP THEN RDROP ; Здесь позицией показывается к какому открывающему управляющюю конструкцию слову относится закрывающая. Здесь сначала BEGIN WHILE BEGIN ,но первая UNTIL относится к первому BEGIN, последняя UNTIL относится к последнему BEGIN, а вот THEN относится к WHILE. Но весь этот агрегат работает и генерирует именно тот шитый код, который я отработал на i80x96. Получается, что написанное в шитом коде иногда почти не переводимо на Форт. Да, я забыл сообщить, что в моем Форте выкинуты проверки парности операторов ?PAIRS ,что и позволяет городить такое. Среди всех этих экспериментов с чумовыми управляющими конструкциями, я обнаружил, что есть простая и понятная конструкция, которая записывается легко и встречается весьма часто. Это конструкция BEGIN-WHILE-UNTIL-THEN Это тот-же самый BEGIN-WHILE-REPEAT , но вместо абсолютного перехода по REPEAT ставится условный. Если срабатывает переход по UNTIL, то управление летит на BEGIN. Если срабатывает по WHILE, то летит на THEN Получается цикл и с предусловием и с постусловием. Эта конструкция настолько удачна, что для меня она почти стандартная. Вот гляньте как красиво и лаконично записывается слово левая круглая скобка Код: : ( \ CORE \ ( "ccc<paren>" -- ) \ Компиляция: выполнить семантику выполнения, данную ниже. \ Выполнение: ( "ccc<paren>" -- ) \ Выделить ccc, ограниченные правой скобкой ")". ( - слово немедленного \ исполнения. Число символов в ccc может быть от нуля до количества \ символов в разбираемой области. \ FILE : \ Расширить семантику CORE (, включив: \ Когда разбирается текстовый файл, если конец разбираемой области достигнут \ раньше, чем найдена правая скобка, снова заполнить входной буфер следующей \ строкой из файла, установить >IN в ноль и продолжать разбор, повторяя \ этот процесс до тех пор, пока не будет найдена правая скобка или не \ будет достигнут конец файла. BEGIN [CHAR] ) PARSE + TIB >IN @ + = WHILE REFILL 0= UNTIL THEN ; IMMEDIATE В данном случае между UNTIL и THEN нет форт-слов, но они там могут быть. P.S. Все это родилось в процессе оптимизации ядра Форт-системы. Я не призываю писать прикладные программы в таком стиле, это была только оптимизация ядра. Хотя после той оптимизации, я на Форте уже именно так и пишу. |
Автор: | mOleg [ Сб мар 12, 2011 10:41 ] |
Заголовок сообщения: | Re: форт и мифы о нем |
Спасибо за объяснения. Правда хочу добавить, что часть из обсуждаемого вами есть даже в ANSI94, а именно: BEGIN WHILE WHILE REPEAT THEN BEGIN WHILE UNTIL ELSE THEN причем, наличие PAIRS не влияет на их компиляцию. Да, последние топики данного обсуждения, мне кажется, стоит в отдельную тему выделить. Да, подобного вида конструкции обсуждались |
Страница 3 из 3 | Часовой пояс: UTC + 3 часа [ Летнее время ] |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |