День четвертый. Управление порядком исполнения программ

День четвертый. Управление порядком исполнения программ

Копался в папке devel – там лежат наработки разработчиков SP-Forth Всего, судя по количеству подпапок, их 12. Впечатления среднего уровня паршивости. М... скажем так, структура орагнизации файлов там у каждого своя. Единообразия как-то не наблюдается. Что лежит для чего, если и есть описания – то куцые и краткие. Примеров использования очень мало. Библиотеки, а там в основном лежат личные библиотеки каждого разработчика, дублируются, есть несколько версий. И как в этом разобраться? Ощущение барахолки – вывали а тебе надо ты и разбирайся. Мне если и надо, то в чужом небрежно оформленном коде я разбираться точно не буду. И везде эти CVS директории. Аут! И это-то назвали дистрибутивом. Лично для себя решил, что ее можно смело если уж не снести, то отправит в архив, это точно.

На этом фоне, конечно, порадовали исходники самого SP-Forth – оформлены, документированы, есть логичная структура.

Немножко повозившись, сделал минидистрибутив:

  spf4.exe
  spf.ini
  ~ff
     word.f
  book
     здесь книжка Келли и Спайса, которую и читаю
  work
     тут мои рабочие програмки на которых и тренируюсь

Кажется, нарушаю лицензию, но нашел токо ссылку на нее – GNU PL Блин, а сам текст лицензии? Впервые такое встречаю. Конечно, хотелось бы ее видеть на русском.

Блин, ну ляпы уже стали, честно говоря, доставать... Читаем книгу дальше.

Я на седьмой главе, а потратил уже три дня! И это языка, который рекламируется как простой для изучения... Нет, не правильно, тормоза идут из-за отсутствия нормального начального пособия, написанного конкретно под этот дистрибутив.

 =       n1 n2   да          истина,  если n1 = n2
 <>      n1 n2   нет         истина,  если n1=/=n2
 <       n1 n2   да          истина,  если n1 < n2
 >       n1 n2   да          истина,  если n1 > n2
 <=      n1 n2   нет         истина,  если n1 <= n2
 >=      n1 n2   да          истина,  если n1 >= n2
 0=      n       да          истина,  если n = 0
 0<      n       да          истина,  если n < 0
 0>      n       да          истина,  если n > 0

Заморчоки с двойными числами решил выкинуть, не хочу тормозитья на мелочах.

Задрачивает сброс стека после каждой ошибки!

Вот еще один пример "удачного" именования опеарторов – 0< означает число большее нуля или меньшее? Мне, например, отгадать(!) не удалось.

А вот слова 0> в SP-Forth нет! А в книге есть. И логика требует его наличия. NOT тоже нет, и как мне сконструировать 0> ? Разбираться как представлены логические типы данных в SP-Forth ? Ага, вместо NOT используем INVERT – уродство!

Протсенькая программка, а промучался час, с чтением документации, с выяснением отсутсвующих операторов, с экспериментами.

: wt             ( 0 < A and A < 299 )
 DUP 0< INVERT
 OVER 299 >
  AND
 IF
 DROP ." В диапазоне"
 ELSE
 DROP ." Вышли за пределы диапазона"
 THEN
;

23 wt

м-да, не очень-то понятно, привычная запись и короче будет и лаконичней. Попробуем переписатьт ее в таком виде.

: between? ( a min max )
   2 cpN   ( a min max a )
   >       ( a min fl1 )
   mvB     ( a fl1 min )
   2 mvN   ( fl1 min a )
   <       ( fl1 fl2 )
   AND
; ( flag )

: wt ( 0 < A and A < 299 ) 2 299 between? IF ." В диапазоне" ELSE ." Вышли за пределы диапазона" THEN ;

Пришлось написать служебное слово. Прогармма стала более короче и более понятной. Слово вынесем в библиотеку.

Видно, основную работу заняло манипулирование со стеком – пришлось расписывать состояние стека (вершина стека справа!).

EXIT – прекращает выполнение текущего слова и управление передается следуущему слову. Подавляет вывод слова ок.

QUIT – прекращает выполнение текущей программы и выходит в оболочку. Подавляет вывод слова ок.

ABORT – идеинтичен QUIT, но еще и очищает стек

Множественный выбор ветвления. Идея понятна – через запоминание в массиве адресов слов и их вызову по номерам ячеек.

Мне таки не нравится этот метод – он работает только в частном случае, для целых чисел, и далеко небезопасный. Вариант полного перебора через IF гораздо универсальнее и безопаснее. Поэтому, я остановился на этом варианте.

: mmm ( n –  )

DUP 1 = IF ." Message 1" CR EXIT THEN

DUP 2 = IF ." Message 2" CR EXIT THEN

DUP 3 = IF ." Message 3" CR EXIT THEN

\ Other case ." Other case" CR ; ;

12 mmm

Пришлось выбор вариантов "завернуть" в отдельное слово, чтоб можно было выходить по EXIT и не перебирать дальше варианты и не запутаться в IF и ELSE , а также иметь возможность обработки пропущенных вариантов. Он смотрится несколько тяжеловато из-за обилия служебных слов, но это можно подправить макроподстановкой, правда, я пока не знаю как :(

Пока искал примеры использования макроподстановок, нашел среду правки скриптов, такую примерно, как я хотел: samples\win\spfwc\spf4wc.f Ее нужно запустить – она скомпилиться в spf4wc.exe – нормальный графический клиент, с подержкой истории редактирования, простейшим редактором. Правда гарячие клавиши не поддерживаются. Блин, ну почему бы его не вынести откомпилированный в корень и не написать про него в Readme?

Пример использования макроопределений так и не нашел...

Глава 8 Циклы

Нашел в главе пример ввода и манипулирования вещественными числами – но в SP-Forth это пример не прокатил...

Попробовал оболочку использовать. Удобно. Идея хорошая. Подстветки нет, но жить можно :). Но! КАК удалить предыдущее слово? Он же его не заносит в словарь?

Чем еще книга неудобна – очень много места отводится разъяснению различий стандарта 79 от 83 – это при том что на сейчас оба устарели! Лишние сведения.

Писал первое определение слова в оболочке. Отсутсвие удаления ранее определенного слова или его перезапись не дают нормально работать с ней.

( Целочисленное возведение в степень )
: **1 ( число степень )
 DUP 0< IF
 DROP DROP ABORT" Отрицательная степень!"
 THEN

DUP 0= IF DROP DROP 1 EXIT THEN

DUP 1 = IF DROP EXIT THEN ( число степень ) SWAP DUP ROT ( число число степень ) 1 DO cpB * LOOP ( число результат )

SWAP DROP ; ( результат )

Желательна комбинация клавиш для быстрого запуска набираемого скрипта. Не помешал бы автоотступ.

Циклы с произвольным шагом.

: R
 11 0 DO
   I .
 -5 +LOOP
;  R

Неестествеенная запись – шаг цикла пишется не в его заголовке, возле слова DO ? а в конце – возле слова +LOOP . И к этому привыкнуть можно. А вотсовеообразный контроль окончания работы цикла в случае отрицательного шага – "... когда он совершает переход от значения, равного пределу, к значению на единицу меньше предела ...". И программа реально влетает в бесконечный цикл. Лучше потерять на скорости работы программы, чем на ее надежности. А потом вылавливать баги...

LEAVE – принудительный выход из цикла. Что-то тоже обсуждалось на предмет нюансов. Устаешь от них – за деревьями и леса невидно.

Про стек возвратов вроде понятно – R> , >R , R@ – только лучше его в пользовательских программах не использовать. Очень высокая вероятность трудноуловимых ошибок. Считаю, что надежность имеет более высокий приоритет, чем быстродействие.

Цикл UNTIL – что-то я не понял, цикл выполняется пока условие ложно, т.е. перед словом UNTIL не встретится ноль...

: R
 BEGIN
 DUP
   .
   1+
 DUP
   10
   >
 UNTIL
;
2 R

Печатаем числа от 2 до 10. Ну и понятно, что цикл выполняется хотя бы один раз.

Цикл BEGIN ... WHILE ... REPEAT тоже понятен.

: R
 BEGIN
 DUP
   10 <
 WHILE
 DUP
   .
   1+
 REPEAT
;

Глава 9. Строки

Интересное слово WORD

: R
 34 ( " )
 WORD
 COUNT

CR TYPE ; R owqoei qw owei oewiroelwjerwj

Слово R читает всю строку дальше за собой пока либо не встретится окончание строки, либо указанный разделитель – ".

А вот где WORD размещает строки, пока загадка – но явно не по адресу HERE и PAD. Они имеют различные адреса.

Полученную подстроку нужно сразу использовать – куда-то ее переместить, т.к. последующие слова ее затрут. Как, впрочем, и новые определения.

Слово IMMEDIATE позволяет выполнять действия в момент разбора и компиляции текста – что-то вроде активного макроопределения.

: .((
  41
 WORD
 COUNT
 TYPE
; IMMEDIATE

: R .(( owqoei qw owei oewiroelwjerwj ) 12 . ;

В момент компиляции слова R слово .(( выведет сообщение, но в откомпилирвоанный образ эта подстрока не попадет.

<<< Предыдущий Начало   Следующий >>>
Copyright © Alex Furashev 2004

При цитировании, ссылка на оригинальный текст обязательна. Допускается копирование материалов только целиком, без внесения каких-либо изменений в оригинальный текст, меняющих смысл, структуру материала и проч.

Hosted by uCoz