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>
// ;