Копался в папке 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?
Пример использования макроопределений так и не нашел...
Нашел в главе пример ввода и манипулирования вещественными числами – но в SP-Forth это пример не прокатил...
Попробовал оболочку использовать. Удобно. Идея хорошая. Подстветки нет, но жить можно :). Но! КАК удалить предыдущее слово? Он же его не заносит в словарь?
Чем еще книга неудобна – очень много места отводится разъяснению различий стандарта 79 от 83 – это при том что на сейчас оба устарели! Лишние сведения.
Писал первое определение слова в оболочке. Отсутсвие удаления ранее определенного слова или его перезапись не дают нормально работать с ней.
( Целочисленное возведение в степень ) : **1 ( число степень ) DUP 0< IF DROP DROP ABORT" Отрицательная степень!" THENDUP 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 ;
Интересное слово WORD
: R 34 ( " ) WORD COUNTCR TYPE ; R owqoei qw owei oewiroelwjerwj
Слово R читает всю строку дальше за собой пока либо не встретится окончание строки, либо указанный разделитель – ".
А вот где WORD размещает строки, пока загадка – но явно не по адресу HERE и PAD. Они имеют различные адреса.
Полученную подстроку нужно сразу использовать – куда-то ее переместить, т.к. последующие слова ее затрут. Как, впрочем, и новые определения.
Слово IMMEDIATE позволяет выполнять действия в момент разбора и компиляции текста – что-то вроде активного макроопределения.
: .(( 41 WORD COUNT TYPE ; IMMEDIATE: R .(( owqoei qw owei oewiroelwjerwj ) 12 . ;
В момент компиляции слова R слово .(( выведет сообщение, но в откомпилирвоанный образ эта подстрока не попадет.
<<< Предыдущий | Начало | Следующий >>> |
При цитировании, ссылка на оригинальный текст обязательна. Допускается копирование материалов только целиком, без внесения каких-либо изменений в оригинальный текст, меняющих смысл, структуру материала и проч. |