 3.9. Запланированное перекрытие

     Адресное  пространство  форт-системы  не  так уж велико - 64 К байт. Это
 налагает  известное  ограничение  на  общее  число  форт-слов,  одновременно
 присутствующих  в  словаре.  Для  снижения этого ограничения можно применить
 свернутый  шитый  код  или  использовать  форт-систему, в которой в качестве
 основного   вместо  16-разрядного  значения  выступает  32-разрядное.  Можно
 заметно  сократить  требуемый  объем  оперативной  памяти, если использовать
 векторное поле кода.

     Опишем   еще   один   простой  способ  снижения  требований  к  памяти -
 запланированное  перекрытие.  Группа  взаимосвязанных  определений  образует
 единый  сегмент  в  двоичном  коде,  который  может быть загружен на заранее
 заданное  место  в  словаре из внешней памяти форт-системы. Разные сегменты,
 загружаемые  на  одно  и  то  же  место оперативной памяти, перекрывают друг
 друга,  вот  почему  такая  структура и названа запланированным перекрытием.
 Благодаря  тому, что хранящийся во внешней памяти сегмент выражен в двоичном
 коде,  а  не в виде текста, его загрузка идет примерно в 50-100 раз быстрее,
 чем обычная текстовая интерпретация.

     В   приводимой   далее   реализации   каждый   сегмент   загружается  на
 фиксированный   адрес  -  значение  указателя  HERE  на  момент  начала  его
 компиляции  Определение  сегмента  включается в список FORTH. После того как
 трансляция   сегмента   завершена,   при  его  выгрузке  во  внешнюю  память
 указатель  вершины  словаря  понижается до прежнего значения с одновременным
 исключением  всех  слов  данного  сегмента  из  списка  FORTH.  При загрузке
 сегмента   на   соответствующий   адрес   указатель  вершины  словаря  вновь
 поднимается, и определения сегмента снова включаются в список FORTH.

     Для трансляции сегментов введем глобальную переменную (СЕГМ), содержащую
 адрес начала очередного компилируемого сегмента, границы которого отмечаются
 словами  СЕГМ-НАЧ  и СЕГМ-КОН. Выгрузку и загрузку сегментов выполняют слова
 СЕГМ-ВЫГР и СЕГМ-ЗАГР.

          VARIABLE (СЕГМ)
          : СЕГМ-НАЧ  ( -> НАЧАЛО ТРАНСЛЯЦИИ СЕГМЕНТА)
             HERE DUP (СЕГМ) ! 0 ,     ( НОМЕР ЭКРАНА)
              HERE  0 C,  BL C,       ( ФИКТИВНОЕ ИМЯ)
             FORTH DEFINITIONS LATEST , ( ЗВЕНО СВЯЗИ)
                CURRENT @ !     ,    ( ТОЧКА ЗАГРУЗКИ)
                0 , 0 ,    ( ДЛИНА И ПОСЛЕДНЯЯ СТАТЬЯ)
          ;
          : СЕГМ-КОН   ( -> КОНЕЦ ТРАНСЛЯЦИИ СЕГМЕНТА)
             (СЕГМ) @ >R    ( ТОЧКА ЗАГРУЗКИ СЕГМЕНТА)
             HERE R@ -    ДЛИНА) DUP  R@ 8 + !
             FORTH DEFINITIONS  LATEST R> 10 + ! ;
          : СЕГМ-ВЫГР ( N:НОМЕР ЭКРАНА->  ВЫГРУЗКА)
           DUP (СЕГМ) @ >R R@ ! ( НОМЕР)
           R@ SWAP ( A:АДРЕС СЕГМЕНТА,N) DUP R@ 8 + @
           1023 + 1024 / ( A,N,N,N1:ЧИСЛО ЭКРАНОВ)
            CR ." СЕГМЕНТ ВИГРУЖЕН НА ЭКРАНЫ: " + SWAP DO
            I . ( AI:АДРЕС СЛЕДУЮЩЕИ ПОРЦИИ) DUP I BUFFER
            1024 CMOVE UPDATE 1024 +LOOP DROP
             FLUSH R> (FORGET) ;
          : СЕГМ-ЗАГР ( N:НОМЕР ЭКРАНА-> ЗАГРУЗКА)
            DUP BLOCK ( N,A0:АДРЕС ПЕРВОГО БЛОКА СЕГНЕНТА)
            2DUP @ - IF DROP CR . ." - БЛОК ДЛЯ ЗАГРУЗКИ?"
            ABORT THEN    DUP 6 + 1 (FORGET) 2DUP
            HERE ( N,A0,N,A0,A1:НАЧАЛО) SWAP 8 + @ ( N,A0,N,A1,L)
            DUP ALLOT 1023 + 1024 / ( N,A0,N,A1,N1:ЧИСЛО ЭКР) ROT
            DUP ROT + SWAP ( ...N1+N,N) DO I BLOCK OVER 1024 CMOVE
             1024 +  LOOP 2DROP ( N) BLOCK 10 + @  CURRENT @ !  ;

     Слово  СЕГМ-НАЧ  строит  заголовок сегмента, который располагается в его
 начале  и  содержит  начальный  номер  экрана  во  внешней памяти, фиктивную
 словарную статью, адрес начала сегмента в оперативной памяти, длину сегмента
 и  адрес  начала  его  последней словарной статьи. Номер экрана определяется
 программистом при выгрузке сегмента во внешнюю память, впоследствии именно с
 этого экрана начинается его загрузка. Слово СЕГМ-ЗАГР проверяет, содержат ли
 первые 2 байта сегмента данный номер, и выдает сообщение об ошибке, если это
 не так.

     Фиктивная   словарная   статья  в  заголовке  сегмента  аналогична  полю
 параметров   для   слов,  определенных  через  VOCABULARY  ,  и  служит  для
 включения определений данного сегмента в список FORTH при загрузке сегмента.
 Она   сцепляется   с   последней  статьей  списка  FORTH  на  момент  начала
 трансляции  сегмента.  При загрузке сегмента список FORTH устанавливается на
 последнее  определение  внутри  данного  сегмента.  Таким образом, словарные
 статьи  сегмента  вновь  включаются  в  словарь форт-системы. При изменениях
 состояний  словаря,  связанных с загрузкой и выгрузкой сегментов, в качестве
 вспомогательного  используется  слово  (FORGET),  которое корректным образом
 понижает   вершину  словаря,  исключая  из  него  все  системные  ссылки  на
 исключаемые  статьи.  В  качестве параметра это слово использует новый адрес
 вершины словаря (см. модель форт-системы в приложении 1).
