Автор |
Сообщение |
|
|
Заголовок сообщения: |
Re: форт и мифы о нем |
|
|
Спасибо за объяснения. Правда хочу добавить, что часть из обсуждаемого вами есть даже в ANSI94, а именно: BEGIN WHILE WHILE REPEAT THEN BEGIN WHILE UNTIL ELSE THEN причем, наличие PAIRS не влияет на их компиляцию. Да, последние топики данного обсуждения, мне кажется, стоит в отдельную тему выделить. Да, подобного вида конструкции обсуждались
Спасибо за объяснения. Правда хочу добавить, что часть из обсуждаемого вами есть даже в ANSI94, а именно: BEGIN WHILE WHILE REPEAT THEN BEGIN WHILE UNTIL ELSE THEN причем, наличие PAIRS не влияет на их компиляцию.
Да, последние топики данного обсуждения, мне кажется, стоит в отдельную тему выделить. Да, подобного вида конструкции [url=http://www.fforum.winglion.ru/viewtopic.php?f=25&t=2100&p=21696#p21696]обсуждались[/url]
|
|
|
|
Добавлено: Сб мар 12, 2011 10:41 |
|
|
|
|
|
Заголовок сообщения: |
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. Все это родилось в процессе оптимизации ядра Форт-системы. Я не призываю писать прикладные программы в таком стиле, это была только оптимизация ядра. Хотя после той оптимизации, я на Форте уже именно так и пишу.
Пример 3 :
BRANCH-ами и ?BRANCH-ами в шитом коде можно наплести такое, что потом записать это на Форте будет проблематично.
Вариант Форта для i80x96 я писал весь на ассемблере и так было такое определение [code] _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[/code] При написании Форта для Motorola MCORE я решил вынести это определение во вторую часть системы, написанную на Форте. И с использованием стандартных управляющих констукций Форт у меня вышел такой уродец : [code]: >NAME >R VOC-LINK BEGIN @ DUP WHILE DUP BEGIN [ SWAP ] CELL- @ ?DUP UNTIL DUP NAME> R@ = UNTIL NIP THEN RDROP ;[/code] Здесь позицией показывается к какому открывающему управляющюю конструкцию слову относится закрывающая. Здесь сначала BEGIN WHILE BEGIN ,но первая UNTIL относится к первому BEGIN, последняя UNTIL относится к последнему BEGIN, а вот THEN относится к WHILE. Но весь этот агрегат работает и генерирует именно тот шитый код, который я отработал на i80x96.
Получается, что написанное в шитом коде иногда почти не переводимо на Форт.
Да, я забыл сообщить, что в моем Форте выкинуты проверки парности операторов ?PAIRS ,что и позволяет городить такое.
Среди всех этих экспериментов с чумовыми управляющими конструкциями, я обнаружил, что есть простая и понятная конструкция, которая записывается легко и встречается весьма часто. Это конструкция BEGIN-WHILE-UNTIL-THEN Это тот-же самый BEGIN-WHILE-REPEAT , но вместо абсолютного перехода по REPEAT ставится условный. Если срабатывает переход по UNTIL, то управление летит на BEGIN. Если срабатывает по WHILE, то летит на THEN Получается цикл и с предусловием и с постусловием. Эта конструкция настолько удачна, что для меня она почти стандартная. Вот гляньте как красиво и лаконично записывается слово левая круглая скобка [code]: ( \ CORE \ ( "ccc<paren>" -- ) \ Компиляция: выполнить семантику выполнения, данную ниже. \ Выполнение: ( "ccc<paren>" -- ) \ Выделить ccc, ограниченные правой скобкой ")". ( - слово немедленного \ исполнения. Число символов в ccc может быть от нуля до количества \ символов в разбираемой области. \ FILE : \ Расширить семантику CORE (, включив: \ Когда разбирается текстовый файл, если конец разбираемой области достигнут \ раньше, чем найдена правая скобка, снова заполнить входной буфер следующей \ строкой из файла, установить >IN в ноль и продолжать разбор, повторяя \ этот процесс до тех пор, пока не будет найдена правая скобка или не \ будет достигнут конец файла. BEGIN [CHAR] ) PARSE + TIB >IN @ + = WHILE REFILL 0= UNTIL THEN ; IMMEDIATE[/code] В данном случае между UNTIL и THEN нет форт-слов, но они там могут быть.
P.S. Все это родилось в процессе оптимизации ядра Форт-системы. Я не призываю писать прикладные программы в таком стиле, это была только оптимизация ядра. Хотя после той оптимизации, я на Форте уже именно так и пишу.
|
|
|
|
Добавлено: Сб мар 12, 2011 00:51 |
|
|
|
|
|
Заголовок сообщения: |
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 Но сейчас найду самый интересный пример.
Даже два примера.
Пример 2 :
Итак, если мы определим как форт-слово метку IGNORE внутри ?BRANCH, и еще напишем для комплекта ?IGNORE (условный скип через команду в шитом коде), то эти слова вовсю можно использовать уже внутри текста Форт-программ для оптимизации по скорости. Например, во второй части моего Форта, которая скармливается текстовым файлом первой через терминал, имеет место быть : [b]: S" [COMPILE] C" STATE @ ?IGNORE COMPILE COUNT ; IMMEDIATE[/b] У меня C" и S" работают и в режиме компиляции и в режиме интерпретации. В приведенном определении в режиме компиляции выполнится COMPILE COUNT ,а в режиме интерпретации просто COUNT
Или вот еще : [code]: RECURSE GET-CURRENT @ LATEST <> \ Определение по : или по :NONAME ? IF LATEST NAME> IGNORE THEN DUP COMPILE, ; IMMEDIATE[/code] Не бог весть-что конечно, но эксперименты с оптимизацией шитого кода интересны.
P.S. В определение ?LITERAL есть R> IF NEGATE THEN и R> IF DNEGATE THEN Они так и просят ?IGNORE
Но сейчас найду самый интересный пример.
|
|
|
|
Добавлено: Сб мар 12, 2011 00:29 |
|
|
|
|
|
Заголовок сообщения: |
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 и ее можно использовать для оптимизации по скорости. Не бог весть какая оптимизация, но все таки оптимизация Впрочем, я сейчас приведу более интересный пример.
Можно. Собственно говоря, я обнаружил, что шитый код, хотя и есть компиляция Фортовского текста один в один, но он сам по себе представляет язык чуть более низкого уровня, чем Форт и на нем можно делать некоторые более оптимальные вещи, которые на Форте если и запишешь, то только через извращения.
Пример 1 : Понятно, что ядро Форта должно быть оптимизировано. И вот имеем высокоуровневое определение. [b][code]: INTERPRET BEGIN BL WORD DUP C@ 0= IF DROP EXIT THEN FIND ?DUP IF STATE @ = IF , ELSE EXECUTE THEN ELSE ?LITERAL THEN ?STACK AGAIN ;[/code][/b] А на шитом коде запишем его так : [code]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 [/code] Здесь IGNORE просто перепрыгивает через QUESTION_LITERAL сразу на QUESTION_STACK. Потому она и названа IGNORE, что заставляет игнорировать следующую команду в шитом коде. В PIC-процессорах нет команд условных переходов, а есть условные скипы, т.е условные перепрыгивания через следующую команду. Так вот IGNORE - это аналогичнй скип через следующую команду. Правда в SP-Forth слово SKIP уже было задействовано для другой цели, поэтому я использовал имя IGNORE. Да, IGNORE заменяет BRANCH, который здесь можно было бы поставить так : [code]__INTERPRET: .long EXECUTE .long BRANCH, LABEL ___INTERPRET: .long QUESTION_LITERAL LABEL: .long QUESTION_STACK .long BRANCH, _INTERPRET [/code] Фишка в том, что IGNORE исполняется быстрее - это раз, а во вторых оно не требует накладных расходов на свое создание. Потому-что IGNORE УЖЕ ЕСТЬ, как одна из веток ?BRANCH. Вот смотри : [code]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 [/code] Т.е. IGNORE уже и так есть, это только метка внутри ?BRANCH и ее можно использовать для оптимизации по скорости. Не бог весть какая оптимизация, но все таки оптимизация ;-)
Впрочем, я сейчас приведу более интересный пример.
|
|
|
|
Добавлено: Сб мар 12, 2011 00:17 |
|
|
|
|
|
Заголовок сообщения: |
Re: форт и мифы о нем |
|
|
Ethereal писал(а): 1.) Я создал систему с прямым шитым кодом, потому-что он быстрее, чем косвенный шитый, а компиляция подпрограммного и тем более нативного кода - куда более сложное занятие, а я хотел сделать систему быстро. гм, на самом деле не сложнее нативный, если не заниматься оптимизацией кода. Ethereal писал(а): IGNORE - мой эксперимент с шитым кодом. Пропускает следующий вызов шитого кода. Эквивалентно : IGNORE R> CELL+ >R ; Используется для оптимизации шитого кода по скорости. ?IGNORE - мой эксперимент с шитым кодом. Снимает со стека число и если оно - ноль, то пропускает следующий вызов шитого кода. Эквивалентно : ?IGNORE 0= IF R> CELL+ >R THEN ; Используется для оптимизации шитого кода по скорости. о, а вот это интересно, поподробнее можно? Это типа замена ?BRANCH и BRANCH ? Собственно ,пока IGNORE для меня наиболее загадочен
[quote="Ethereal"]1.) Я создал систему с прямым шитым кодом, потому-что он быстрее, чем косвенный шитый, а компиляция подпрограммного и тем более нативного кода - куда более сложное занятие, а я хотел сделать систему быстро.[/quote] гм, на самом деле не сложнее нативный, если не заниматься оптимизацией кода.
[quote="Ethereal"]IGNORE - мой эксперимент с шитым кодом. Пропускает следующий вызов шитого кода. Эквивалентно : IGNORE R> CELL+ >R ; Используется для оптимизации шитого кода по скорости. ?IGNORE - мой эксперимент с шитым кодом. Снимает со стека число и если оно - ноль, то пропускает следующий вызов шитого кода. Эквивалентно : ?IGNORE 0= IF R> CELL+ >R THEN ; Используется для оптимизации шитого кода по скорости.[/quote] о, а вот это интересно, поподробнее можно? Это типа замена ?BRANCH и BRANCH ? Собственно ,пока IGNORE для меня наиболее загадочен 8)
|
|
|
|
Добавлено: Пт мар 11, 2011 23:54 |
|
|
|
|
|
Заголовок сообщения: |
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> // ;
[quote="in4"][quote="Ethereal"]Первая - из низкоуровневых определенийи минимального самораскручиваемого набора высокоуровневых слов.[/quote]Можно список (желательно со описанием, что делает каждое)?[/quote] Можно. Но значится так. Сначала пара пояснений.
1.) Я создал систему с прямым шитым кодом, потому-что он быстрее, чем косвенный шитый, а компиляция подпрограммного и тем более нативного кода - куда более сложное занятие, а я хотел сделать систему быстро. 2.) Я хотел сделать систему, которая теряла бы в быстродействии только за счет того, что в ней прямой шитый код и более не из-за чего. Поэтому низкоуровневых определений у меня много. Все, что важно оптимизировать по скорости - я кинул на ассемблерный уровень. 3.) Я сначала хотел сделать ANSI-Forth, но не понял что в этом стандарте наворочено со словарями, какая польза от MARKER вместо FORGET и в этом отношении откатился к предыдущим стандартам. Короче говоря, вышел ANSI-Forth со словарями в духе Forth-79/83 и с FORGET вместо MARKER. Также из-за следования стандарту ANSI-Forth пришлось реализовывать в низкоуровневых определениях кучу разных вариантов умножений и делений. Если бы я следовал Forth-83 было бы все проще, но что сделано - то сделано
--------------------------------------------------------------------
[code]// СООТВЕТСТВИЕ СТАНДАРТУ 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 реализован полностью */[/code]
[b]Опрелелены два макроса :[/b]
[b]COLON[/b] - шапка высокоуровневого определения в прямом шитом коде [b]NEXT[/b] - хвост низкоуровевого определения в прямом шитом коде
[b]Низrоуровневые определения смысл которых понятен сразу :[/b]
[b]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[/b]
[b]Низкоуровневые определения смысл которых надо пояснять :[/b]
[b]SAVE[/b] - сохранить Форт-систему один в один из ОЗУ во FLASH. При старте Форт-система копирует себя один в один из FLASH в ОЗУ. [b]BYE[/b] - перегрузка системы. Заставляет сработать watch-dog процессора. [b]ENTER[/b] - код, которая вызывается, как подпрограмма из шапки высокоуровневого определения. [b](DOES>)[/b] - исполняемый код DOES> [b]VAR[/b] - код, которая вызывается, как подпрограмма из шапки переменной, созданной VARIABLE. [b]VAL[/b] - код, которая вызывается, как подпрограмма из шапки переменной, созданной VALUE или константы, созданной CONSTANT. [b]VOC[/b] - код, которая вызывается, как подпрограмма из шапки словаря, созданного VOCABULARY. [b]W@ W![/b] - разыменовать и занести для 16-разрядных [b](DO) (?DO) (LOOP) (+LOOP) (OF) (<=OF<)[/b] - исполняемые части соответствующих слов [b](FOR) (NEXT)[/b] - исполняемые части нестандартного цикла с одним параметром FOR-NEXT. Цикл отрабатывает n раз, только если n>0 знаково. Цикл FOR-NEXT помогает оптимизировать определения слов типа TYPE и SPACES [b]IGNORE[/b] - мой эксперимент с шитым кодом. Пропускает следующий вызов шитого кода. Эквивалентно : IGNORE R> CELL+ >R ; Используется для оптимизации шитого кода по скорости. [b]?IGNORE[/b] - мой эксперимент с шитым кодом. Снимает со стека число и если оно - ноль, то пропускает следующий вызов шитого кода. Эквивалентно : ?IGNORE 0= IF R> CELL+ >R THEN ; Используется для оптимизации шитого кода по скорости. [b]DIGIT[/b] ( char n1 -- n2 true | false ) n2 - значение литеры char как цифры в системе счисления по основанию n1
[b]Высокоуровневые определения, понятные без пояснений :[/b]
[b]CR SPACES TYPE ACCEPT QUERY DROPALL DEPTH ?STACK [ ] DECIMAL >NUMBER HERE ALIGN ALLOT , LITERAL 2LITERAL CATCH THROW : ; PARSE QUIT FIND[/b]
[b]Высокоуровневые определения, требующие пояснений :[/b]
[b]: ". COUNT TYPE ; (.") (ABORT")[/b] - исполняемые части ." и ABORT" вот в таком виде : [b]: (.") R> COUNT 2DUP TYPE + ALIGNED >R ; : (ABORT") R> COUNT ROT IF TYPE -2 THROW THEN + ALIGNED >R ;[/b] [b]?LITERAL[/b] - смотри SP-Forth 2.x [b]COMPILE[/b] - смотри Forth-83 [b]: ABORT -1 THROW[/b] [b]: LATEST LAST @ ;[/b] [b]: GET-CURRENT CURRENT @ ; : SET-CURRENT CURRENT ! ; : DEFINITIONS CONTEXT @ SET-CURRENT ;[/b] [b]SKIP[/b] - смотри SP-Forth [b]INTERPRET[/b] - снова подражание Черезову, вот в таком виде : [b][code]// : INTERPRET // BEGIN // BL WORD DUP C@ 0= IF DROP EXIT THEN // FIND ?DUP // IF // STATE @ = IF , ELSE EXECUTE THEN // ELSE // ?LITERAL // THEN // ?STACK // AGAIN // ;[/code][/b] [b]Самые важные высокоуровневые слова :[/b] [b][code]// : 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> // ;[/code][/b] Как видите, выделяет из входного потока слово, ограниченное разделителем и укладывает его сразу ниже вершины словаря так, что если это слово придется добавить к словарю, то его имя уже на готово лежит там где нужно.
Добавление слова к словарю состоит из двух частей. Никакая техника SMUDGE не используется. Первую часть делает слово [b][code]// : +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 ! // ;[/code][/b] оно делает все, что нужно для добавляния слова к словарю, но это слово еще не видно при поиске по словарю, поскольку ни один VOCABULARY на него еще не указывает. Вторая часть делает это слово видимым при поиске : [b][code]// : +NAME // LATEST GET-CURRENT ! // ;[/code][/b] Как видите, ото всяких SMUDGE я отказался, обойдясь без них. В итоге, например [b]: : +WORD COMPILE [ HEX 24397F00 , ] COMPILE ENTER ] ;[/b] здесь 24397F00 - опкод call-а на ENTER. [b]: ; COMPILE EXIT +NAME [ ; IMMEDIATE[/b]
Также я выкинул из Форт-системы ?COMP поскольку на встроенной системе, если ты употребил слово COMPILEONLY в режиме интерпретации, то нажать кнопку сброс на плате и перестартовать Форт - не проблема.
[b]Переменные :
#TIB >IN BASE CONTEXT CURRENT DP HANDLER HLD LAST NP S0 R0 STATE VOC-LINK WARNING SOURCE-ID TIB FORTH MAIN[/b] Здесь MAIN - вектор, выполняющийся при старте Форт-системы. Словарь в системе отделен от кода, чтобы его легко можно было отрезать. Код растет от самого младшего адреса вверх и DP содержит его HERE. Словарь растет от самого старшего адреса вниз и NP содержит его HERE. VOC-LINK - указатель, который начинает цепочку, объединяющую все словари в один список. Используется при FORGET. FORGET откатывает и NP и DP и забываемые словари тоже изымает из списка VOC-LINK
P.S. Вот еще распишу, как выглядит QUIT : [b][code]// : 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 // ;[/code][/b] P.P.S Еще покажу FIND. FIND должна искать в словарях в порядке CONTEXT->CURRENT->FORTH. С этой FIND у меня получился какой-то алгоритмический бред полный : [b][code]// : 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> // ;[/code][/b]
|
|
|
|
Добавлено: Пт мар 11, 2011 21:16 |
|
|
|
|
|
Заголовок сообщения: |
Re: форт и мифы о нем |
|
|
Кстати, создать с нуля форт-систему сейчас не получится принципиально. Просто потому, что нуля уже давно нет. И вторая причина. С нуля Форт уже был создан Ч.Муром. И второй раз войти в эту же воду никому уже не удастся.
Кстати, создать с нуля форт-систему сейчас не получится принципиально. Просто потому, что нуля уже давно нет. И вторая причина. С нуля Форт уже был создан Ч.Муром. И второй раз войти в эту же воду никому уже не удастся.
|
|
|
|
Добавлено: Пт мар 11, 2011 19:29 |
|
|
|
|
|
Заголовок сообщения: |
Re: форт и мифы о нем |
|
|
in4 писал(а): Ethereal писал(а): Первая - из низкоуровневых определенийи минимального самораскручиваемого набора высокоуровневых слов. Можно список (желательно со описанием, что делает каждое)? Сейчас подготовлю и сюда выложу.
[quote="in4"][quote="Ethereal"]Первая - из низкоуровневых определенийи минимального самораскручиваемого набора высокоуровневых слов.[/quote]Можно список (желательно со описанием, что делает каждое)?[/quote] Сейчас подготовлю и сюда выложу.
|
|
|
|
Добавлено: Пт мар 11, 2011 19:22 |
|
|
|
|
|
Заголовок сообщения: |
Re: форт и мифы о нем |
|
|
Так правильный подход к созданию с нуля и состоит в портировании. Сначала создаешь Форт на хорошо знакомой архитектуре, например на IBM PC, которую знаешь как облупленную. А потом отработанные на ней алгоритмы портируешь на конечную платформу.
Короче, мысль была такая - Форт системы можно создавать с нуля быстро, если продумать вопрос - КАК это делать. А если тупо начать создавать Форт на конечной платформе, то ничего уже быстро не получится.
Я начал вообще с того, что создал Форт под MS-DOS в виде COM-файла, под впечатлением какого-то исходника скачанного с Интернета. А потом алгоритмы из этого Форта перенес на две инородных платформы. И с таким подходом получилось быстро.
Т.е. быстрая создаваемость Форт-систем - это не миф, правда лишь при определенной технологии создания такой системы : - Изучаешь исходник чужой Форт-системы - Создаешь свой Форт на родной для себя архитектуре - Алгоритмы из этого Форта переносишь на целевую архитектуру
Так правильный подход к созданию с нуля и состоит в портировании. Сначала создаешь Форт на хорошо знакомой архитектуре, например на IBM PC, которую знаешь как облупленную. А потом отработанные на ней алгоритмы портируешь на конечную платформу.
Короче, мысль была такая - Форт системы можно создавать с нуля быстро, если продумать вопрос - КАК это делать. А если тупо начать создавать Форт на конечной платформе, то ничего уже быстро не получится.
Я начал вообще с того, что создал Форт под MS-DOS в виде COM-файла, под впечатлением какого-то исходника скачанного с Интернета. А потом алгоритмы из этого Форта перенес на две инородных платформы. И с таким подходом получилось быстро.
Т.е. быстрая создаваемость Форт-систем - это не миф, правда лишь при определенной технологии создания такой системы : - Изучаешь исходник чужой Форт-системы - Создаешь свой Форт на родной для себя архитектуре - Алгоритмы из этого Форта переносишь на целевую архитектуру
|
|
|
|
Добавлено: Пт мар 11, 2011 19:19 |
|
|
|
|
|
Заголовок сообщения: |
Re: форт и мифы о нем |
|
|
Ethereal писал(а): Позволю не согласиться с вашим несогласием. Я проделывал все это дважды - переносил Форт на новую платформу. Не за несколько дней, конечно, а за пару месяцев. ну и с чем тогда несогласие? К тому же речь шла не о портировании существующей системы, а создании с нуля.
[quote="Ethereal"]Позволю не согласиться с вашим несогласием. Я проделывал все это дважды - переносил Форт на новую платформу. Не за несколько дней, конечно, а за пару месяцев.[/quote] ну и с чем тогда несогласие? К тому же речь шла не о портировании существующей системы, а создании с нуля.
|
|
|
|
Добавлено: Чт мар 10, 2011 18:15 |
|
|
|
|
|
Заголовок сообщения: |
Re: форт и мифы о нем |
|
|
Ethereal писал(а): Первая - из низкоуровневых определенийи минимального самораскручиваемого набора высокоуровневых слов. Можно список (желательно со описанием, что делает каждое)?
[quote="Ethereal"]Первая - из низкоуровневых определенийи минимального самораскручиваемого набора высокоуровневых слов.[/quote]Можно список (желательно со описанием, что делает каждое)?
|
|
|
|
Добавлено: Чт мар 10, 2011 13:37 |
|
|
|
|
|
Заголовок сообщения: |
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-порт. Такой подход сильно ускоряет процесс портирования. Причем этот список слов составлен так, чтобы не наносить урон быстродействию. Все, от чего зависит быстродействие Форт-системы - в первой половине Форта и на ассемблере.
[quote="mOleg"]Конечно, можно сказать, что это уже и есть форт, но тут позвольте не согласиться. Минимальная форт-система должна еще достаточно долго раскручиваться, чтобы с ней стало возможно более-менее серьзено работать. Кроме того, по ходу написания интерпретатора придется много времени тратить на знакомство с целевой системой, и с ее особенностями, если, конечно, речь идет о создании форт-системы на новой платформе.[/quote] Позволю не согласиться с вашим несогласием. Я проделывал все это дважды - переносил Форт на новую платформу. Не за несколько дней, конечно, а за пару месяцев.
Идея такая - имеем уже отработанную Форт систему для 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 сохраняет систему из ОЗУ во флеш и вуаля - дальнейшая работа с новой платформой через терминал идет на порядок быстрее, чем компилировать Си-шные исходники и по сто раз на дню флешку программатором переливать.
Вот смотри. Порядок скармливания слов второй половины первой : [b]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[/b] здесь каждое слово требует для определения только слов ранее определенных. А значит это - список слов, которые портировать вообще не надо, поскольку они присутствуют в виде текстового файла с Форт-определениями, который надо просто скормить первой половине Форт-системы через COM-порт. Такой подход сильно ускоряет процесс портирования. Причем этот список слов составлен так, чтобы не наносить урон быстродействию. Все, от чего зависит быстродействие Форт-системы - в первой половине Форта и на ассемблере.
|
|
|
|
Добавлено: Чт мар 10, 2011 04:26 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
Ничто не мешает вкладывать в термин собственный смысл, главное, чтобы это было удобно (иначе термин не нужен, можно что-то Ваней Ивановым назвать вместо метакомпилятора) и обоснованно.
Ничто не мешает вкладывать в термин собственный смысл, главное, чтобы это было удобно (иначе термин не нужен, можно что-то Ваней Ивановым назвать вместо метакомпилятора) и обоснованно.
|
|
|
|
Добавлено: Пт фев 15, 2008 21:35 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
Ищите информацию на тему:
1. S-выражения и M-выражения,
2. спор Маккарти и Рассела по поводу определения eval,
3. Эквивалентность данных и кода, трансформация и специализация програм(метапрограммирование), metacircular evaluation.
Все можно сделать на машине Тьюринга. Следует только помнить закон диалектики: переход количества в качество.
P.S. Попытки изобразить непонимание, а также переход на личности сознательно игнорирую.
Ищите информацию на тему:
1. S-выражения и M-выражения,
2. спор Маккарти и Рассела по поводу определения eval,
3. Эквивалентность данных и кода, трансформация и специализация програм(метапрограммирование), metacircular evaluation.
Все можно сделать на машине Тьюринга. Следует только помнить закон диалектики: переход количества в качество.
P.S. Попытки изобразить непонимание, а также переход на личности сознательно игнорирую.
|
|
|
|
Добавлено: Пт фев 15, 2008 20:19 |
|
|
|
|
|
Заголовок сообщения: |
|
|
|
true-grue писал(а): Уважаемый Forthware, чуть выше Вам намекнули, что смешивать понятия метаязык и метакомпилятор не следует. Где я их смешиваю? true-grue писал(а): ответ посоветовали своему оппоненту читать Мура и перестать фантазировать. Потому что Мур не считает Форт метаязыком, а компиляцию Форта мета-компиляцией. true-grue писал(а): Если для Вас «Лисп не есть метаязык», то все, что я писал на эту тему применительно к Форту автоматически теряет силу. Если для вас Лисп есть метаязык, буду рад увидеть этому какое либо подтверждение. Иначе... true-grue писал(а): Спорить с этим Вашим утверждением считаю бессмысленным. Укажите источник считающи Лисп метаязыком, спорить не надо. true-grue писал(а): Напрасно некоторые думают, что можно чему-то научиться участвуя во флеймах на форумах... Ну, ну, все дураки один тру-гру знает истину. Так поделитесь ею! Все будут рады.
[quote="true-grue"]Уважаемый Forthware, чуть выше Вам намекнули, что смешивать понятия метаязык и метакомпилятор не следует.[/quote]Где я их смешиваю? [quote="true-grue"]ответ посоветовали своему оппоненту читать Мура и перестать фантазировать.[/quote]Потому что Мур не считает Форт метаязыком, а компиляцию Форта мета-компиляцией. [quote="true-grue"]Если для Вас «Лисп не есть метаязык», то все, что я писал на эту тему применительно к Форту автоматически теряет силу.[/quote]Если для вас Лисп есть метаязык, буду рад увидеть этому какое либо подтверждение. Иначе... [quote="true-grue"]Спорить с этим Вашим утверждением считаю бессмысленным.[/quote]Укажите источник считающи Лисп метаязыком, спорить не надо.[quote="true-grue"] Напрасно некоторые думают, что можно чему-то научиться участвуя во флеймах на форумах...[/quote]Ну, ну, все дураки один тру-гру знает истину. Так поделитесь ею! Все будут рады. :D
|
|
|
|
Добавлено: Пт фев 15, 2008 19:22 |
|
|
|
|