Forth и другие саморасширяющиеся системы программирования Locations of visitors to this page
Текущее время: Чт мар 28, 2024 19:23

...
Google Search
Forth-FAQ Spy Grafic

Часовой пояс: UTC + 3 часа [ Летнее время ]




Ответить
Имя пользователя:
Заголовок:
Текст сообщения:
Введите текст вашего сообщения. Длина сообщения в символах не более: 60000

Размер шрифта:
Цвет шрифта
Настройки:
BBCode ВКЛЮЧЕН
[img] ВЫКЛЮЧЕН
[flash] ВЫКЛЮЧЕН
[url] ВКЛЮЧЕН
Смайлики ВЫКЛЮЧЕНЫ
Отключить в этом сообщении BBCode
Не преобразовывать адреса URL в ссылки
Вопрос
Теперь гостю придется вводить здесь пароль. Не от своей учетной записи, а ПАРОЛЬ ДЛЯ ГОСТЯ, получить который можно после регистрации на форуме через ЛС.:
Этот вопрос предназначен для выявления и предотвращения автоматических регистраций.
   

Обзор темы - FORTH-рефакторинг
Автор Сообщение
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
Продолжение писания в таком стиле привело к следующим наблюдениям:
1. Хотя, списки адекватно описывают любые ситуации на игровом поле, оперировать ими можно только вручную (программист/пользователь должен сам помнить помнить, "что где лежит"). Можно, конечно, ценой применения ООП и, соответственно, потери управляемости кода, "срезать несколько углов", перейдя от списковых данных к реляционным. Или, наоборот, усложнить программу анализаторами семантики символов.
2. Наиболее удобным будет двухуровневое представление данных: на уровне списков будет осуществляться ввод и запросы детальной информации, а на уровне статистики будет накапливаться информация, нужная для основных операций игры (суммарная сила, суммарный тоннаж, суммарный бонус и т.д.). Получается некий аналог ЭЛТ: списки представляют собой некоторый многомерный набор таблиц (реляционные "кубы данных"), изменения которой немедленно пересчитываются и отображаются в "главной таблице".
3. Концепция "главной таблицы" позволяет рассматривать ее как набор регистров, в которых удобно производить вычисления над списками, что избавит от необходимости протаскивать их через обычный стек данных.
4. Естественным FORTH-представлением этой структуры является вторичная FORTH-машина, отличающаяся от изначальной заменой СТЕКА на проблемно-ориентированную регистрово-табличную модель (возможно, имеющую естественное визуальное представление); и СЛОВАРЯ - на хранилище сигналов о необходимости пересчета (ЗНАЧЕНИЕ, соответственно, будет представляться состоянием списков).
Сообщение Добавлено: Ср дек 02, 2015 13:55
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
gudleifr писал(а):
Для реализации списка

Ну, что, ничего не надумалось?
У меня получается препохабненько (в примере - начало карточной военно-морской игры на Win32Forth):
Код:
: START ;

\ СТРОКОВЫЕ КОНСТАНТЫ
: SI ( <NAME> -- ) HERE CREATE >NAME , DOES> ( -- A) @ ;
: SD ( <NAME> -- A) HERE CREATE >NAME DUP , DOES> ( -- A) @ ;

\ МАССИВ ДЛЯ ХРАНЕНИЯ СПИСКОВ
HEX 10000 DECIMAL ALLOCATE DROP CONSTANT LST
: LD ( E -- AW) 2* CELLS LST + ;
: LN ( E -- AE) LD CELL+ ;
1 0 LD ! 0 0 LN !
: LA ( -- E) 0 LN @
IF 0 LN DUP @ DUP LN @ ROT !
ELSE 0 LD DUP @ DUP 1+ ROT ! THEN
0 OVER LN ! ;
: LF ( E --) 0 LN @ OVER LN ! 0 LN ! ;

\ ДОБАВЛЕНИЕ НОВОЙ ГОЛОВЫ СПИСКА ...
: L+ ( W,E1 -- E2) LA DUP>R LN ! R@ LD ! R> ;
\ ... И СОХРАНЕНИЕ ЕЕ ПО АДРЕСУ СТАРОЙ
: @L+! ( W,AE -- ) DUP>R @ L+ R> ! ;

\ ТАСОВАНИЕ СПИСКА ПУТЕМ УДАЛЕНИЯ ...
: L- ( E1,N -- E2,W) ?DUP
IF SWAP DUP ROT 1- 0 ?DO LN @ LOOP
LN DUP @ DUP LN @ ROT !
ELSE DUP LN @ SWAP THEN
DUP LD @ SWAP LF ;
\ ... И ВСТАВКИ В НОВЫЙ СПИСОК
: L// ( E1,N -- E2) 0 SWAP BEGIN
?DUP WHILE DUP>R RANDOM ROT SWAP L- ROT L+ R> 1- REPEAT
NIP ;

\ ПЕРЕБОР ЭЛЕМЕНТОВ СПИСКА ПО ПОРЯДКУ
: LR ( E,EX --) >R BEGIN ?DUP
WHILE DUP LD @ R@ EXECUTE ( E,W-- E)
LN @ REPEAT R>DROP ;

\ СУНДУКИ - НАБОР КОРАБЛЕЙ

\ СИМВОЛЫ
SI 3" SI 5" SI 16"
SI "A" SI "B" SI "C"
SI TORPEDO SI ASW SI AIR SI BOMBER
SI DAM-CTRL SI EVASIVE SI ECM SI COVER SI AIR-DEF
SI (I) SI (II) SI (III) SI (IV) SI (V) SI (VI)
SI USSSR SI USA SI GB SI ITALY SI FRANCE SI JAPAN
SI КРУПНЫЙ SI АВИАНОСЕЦ SI ПОДЛОДКА SI ЖИВУЧЕСТЬ SI ОЧКОВ
SI BB SI CVN

\ КАРТА - СПИСОК ТРИПЛЕТОВ (ИМЯ, СИМВОЛЫ, ПАРАМЕТРЫ), ГДЕ
\ СИМВОЛЫ - СПИСОК СИМВОЛОВ, А
\ ПАРАМЕТРЫ - СПИСОК ПАР (СИМВОЛ, ЗНАЧЕНИЕ)
: КАРТА+ ( E1 <NAME> -- E2) 0 0 0 L+ L+ SD SWAP L+ SWAP L+ ;
: S+ ( E,S -- E) OVER LD @ LN @ LD @L+! ;
: P= ( E,N,S -- E) SWAP 0 L+ L+ OVER LD @ LN @ LN @ LD @L+! ;

\ КАРТА С ТЕМИ ЖЕ ПАРАМЕТРАМИ, СПИСКИ, СРОСШИЕСЯ ХВОСТАМИ
: СИСТЕРШИП+ ( E1 <NAME> -- E2) DUP
LD @ LN @ DUP LD @ SWAP LN @ LD @ 0 L+ L+ SD SWAP L+ SWAP L+ ;

0 КАРТА+ IOWA BB S+ (I) S+ USA S+ КРУПНЫЙ S+ 5" S+ 16" S+ "B" S+ "C" S+ 10 ЖИВУЧЕСТЬ P= 14 ОЧКОВ P=
СИСТЕРШИП+ NEW-JERSEY
КАРТА+ CONSTELLATION CVN S+ (I) S+ USA S+ АВИАНОСЕЦ S+ КРУПНЫЙ S+ 12 ЖИВУЧЕСТЬ P= 22 ОЧКОВ P= 2 AIR P= 4 AIR-DEF P=
СИСТЕРШИП+ NIMITZ
СИСТЕРШИП+ KENNEDY
5 L//
CONSTANT КОРАБЛИ

\ ПРОВЕРКА
: EX5 8 SPACES DUP LD @ COUNT TYPE SPACE LN @ LD @ . CR ;
: EX4 ['] EX5 LR ;
: EX3 8 SPACES COUNT TYPE CR ;
: EX2 ['] EX3 LR ;
: EX1 DUP LD @ COUNT TYPE CR DUP LN @ LD @ EX2 LN @ LN @ LD @ EX4 CR ;
CR КОРАБЛИ ' EX1 LR
FORGET START

Пример работы:

NIMITZ
        КРУПНЫЙ
        АВИАНОСЕЦ
        USA
        (I)
        CVN
        AIR-DEF 4
        AIR 2
        ОЧКОВ 22
        ЖИВУЧЕСТЬ 12

NEW-JERSEY
        "C"
        "B"
        16"
        5"
        КРУПНЫЙ
        USA
        (I)
        BB
        ОЧКОВ 14
        ЖИВУЧЕСТЬ 10

CONSTELLATION
        КРУПНЫЙ
        АВИАНОСЕЦ
        USA
        (I)
        CVN
        AIR-DEF 4
        AIR 2
        ОЧКОВ 22
        ЖИВУЧЕСТЬ 12

KENNEDY
        КРУПНЫЙ
        АВИАНОСЕЦ
        USA
        (I)
        CVN
        AIR-DEF 4
        AIR 2
        ОЧКОВ 22
        ЖИВУЧЕСТЬ 12

IOWA
        "C"
        "B"
        16"
        5"
        КРУПНЫЙ
        USA
        (I)
        BB
        ОЧКОВ 14
        ЖИВУЧЕСТЬ 10

ok

Т.е. дальше L+ и @L+! дело не идет - только свапинг увеличивается. Проще в голове список представить и через них выразить, чем какие-то умные списковые слова измыслить.
Сообщение Добавлено: Сб ноя 28, 2015 11:26
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
Еще одна задачка на рефакторинг.
Для реализации списка очевидно необходимы всего 4 слова: LD - адрес поля данных элемента, LN - адрес поля связи элемента, LA - выделение места под новый элемент, LF - освобождение места удаляемого элемента (мы не эстеты и слово ATOM - проверку, что в LD - "просто значение" или ссылка на вложенный список - не используем).
Требуется из этих четырех слов собрать (с минимизацией DUP-ов и SWAP-ов) слова для работы со следующими типами списков.
1. Просто список. Операции вставки и удаления.
2. Список структур. Каждый элемент списка верхнего уровня - ссылка на список определенной длины, каждый элемент которого "ассоциируется" с некоторым "полем структуры". Операции добавления/удаления новой "структуры", доступа к ее "полям".
3. Список параметров. Каждый элемент списка верхнего уровня - ссылка на список, первый элемент которого содержит идентификатор параметра, а остальные - его значение. Операции добавления/удаления параметра, доступ к его значению.
Сообщение Добавлено: Пн ноя 02, 2015 11:43
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
Hishnik писал(а):
А CASE смотрится вполне изящно и сопровождаемо.
Изящных не встречал. Обычно - источник ошибок и причина полной нечитаемости кода. Впрочем, я не видел, чтобы какому нибудь PASCAL-исту CASE помешал бы плодить циклы.

Hishnik писал(а):
Из кинематики выводится время до грунта.
Его и отсчитываем. (В позднихх версиях "Лунолета", правда, этот блок не поместился в память калькулятора, и его заменили на "итерактивное самовыкапывание" (с забавными побочными эффектами)).
Сообщение Добавлено: Ср фев 25, 2015 02:00
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
gudleifr писал(а):
Ну, как бы, хорошо откомпилированный конечный автомат (не претендующий на гомеостатичность) превращается просто в набор IF...GOTO.

А CASE смотрится вполне изящно и сопровождаемо. Он внутри, конечно, тоже в какой-то степени IF.. GOTO, но по большому счету это относится к любой управляющей конструкции.

gudleifr писал(а):
зарылись в грунт - отсчитываем время назад с тем же ускорением

Да ну зачем же? Из кинематики выводится время до грунта.
Сообщение Добавлено: Ср фев 25, 2015 01:28
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
Hishnik писал(а):
Конечный автомат, по крайней мере, в некоторых случаях.
Ну, как бы, хорошо откомпилированный конечный автомат (не претендующий на гомеостатичность) превращается просто в набор IF...GOTO. Что на FORTH обычно смотрится препохабнейше и может быть оправдано только желанием разбиратьр егулярные выражения.
Конечно, можно вовремя вспомнить, что сам FORTH является конечным автоматом, но решений, использующих этот факт я не встречал (хотя, сам писать пытался).

P.S. Из "Лунолета" пришла идея организовать гомеостаз в виде "вычислительного управляющего воздействия" блока "обработки флагов" на "вычислительный блок (зарылись в грунт - отсчитываем время назад с тем же ускорением, кончилось топливо - выполняем расчет за сверхбольшой интервал и т.д.)
Сообщение Добавлено: Ср фев 25, 2015 01:07
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
gudleifr писал(а):
И речь не о том, как сделать "менее страшно", а как вообще туда не ходить... Большинство циклов в структурных программах - от лукавого.

Конечный автомат, по крайней мере, в некоторых случаях.
Сообщение Добавлено: Ср фев 25, 2015 00:43
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
Hishnik писал(а):
И так, в принципе, на каждом уровне - если мне на этом уровне важно видеть, что действие выполняется в цикле, цикл будет виден. Если нет - спрячу внутрь.
И я об том же. Если циклов много - будет страшно. И речь не о том, как сделать "менее страшно", а как вообще туда не ходить... Большинство циклов в структурных программах - от лукавого.
Сообщение Добавлено: Вт фев 17, 2015 13:27
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
1)
Код:
10 0 DO I ОЧИСТИТЬ-ЯЧЕЙКУ LOOP

2)
Код:
ОЧИСТИТЬ-МАССИВ

Во втором случае мне неинтересны детали очистки. Может быть, там и еще что-то делается, кроме записи в ячейки, неважно. И так, в принципе, на каждом уровне - если мне на этом уровне важно видеть, что действие выполняется в цикле, цикл будет виден. Если нет - спрячу внутрь.
Сообщение Добавлено: Вт фев 17, 2015 03:42
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
P.P.S. На неразрешимость проблемы "правильности зацикливания" как бы намекает старая C-фича "курица или яйцо".
Допустим наша программа:
Код:
main()
{
A;
for (i=...) { B; }
}

Со временем наборы операторов A и B разрастаются до размеров, требующих их выделения в отдельные подпрограммы:
Как правильно?
Код:
b(i)
{
B;
}
main()
{
A;
for (i=...) { B(i); }
}

или
Код:
b(i)
{
for (i=...) { B }
}
main()
{
A;
b;
}

Понятно, что если цикл один, то делаем как удобнее/логичнее/нагляднее. Да и какая разница?..
А если в матрешке десяток циклов и способы выделения процедур внутри или снаружи цикла чередуются? Черт ногу сломит...
Сообщение Добавлено: Пн фев 16, 2015 15:04
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
Продолжение оттуда же:
Цитата:
В PASCAL-играх "стратегические" части - это набор вложенных циклов (вульгарно олицетворяющих кибернетическое понятие "сверхустойчивости"). Когда "бой" заканчивается, его результаты принимаются и проверяется их невыход за границы разумного. Превышение "пределов" вызывает прекращение текущего цила повторения "боев", и проверку более слабых условий, если и они нарушаются, то прерывается следующий цикл...
По мере погружения в циклы, условия должны становиться все строже и строже, чтобы "бои" проводились в строго заданных условиях, а каждый цикл должен добавлять к этим условиям все новые, исправляя ошибки, возникающие при работе его внутренних частей.
Например, внешний цикл Mario.bas перебирает игроков, а вложенный в него - уровни игры. Если уровень проходится игроком благополучно, игрок переходит к следующему, а если нет - цикл прервывается и очередь переходит к другому игроку.
Если бы PASCAL-программист имел в голове "схему вложенности условий", непротиворечивую и достаточную, все было бы очень красиво - программа "думала бы сама собой", разумно реагируя на все неприятности... Однако, всегда бывает наоборот: общий набор условий берется "как у всех", а затем, при необходимости что-то добавить, программист выбирает "примерно подходящий" цикл и обвешивает новый блок кучей новых условий/флагов (и никто не гарантирует, что они не будут конфликтовать с другим). Вплоть до добавления новых циклов, противоречащих изначальному плану.
Если считать, что самый нижний уровень все-таки связан с ЭВМ (ведь, должна же программа делать что-то полезное), то вся остальная программа - многоступенчатый перевод c "языка PASCAL" на "язык машины". Отсюда - и дикий размер кода (даже, с учетом излишней универсальности на всех уровнях и хранения данных в виде PASCAL-процедур).

От "нормального гомеостата" эта конструкция радикально отличается тем, что как бы не "переключались лампочки" на верхних уровнях, работает-то все равно только один самый внутренний цикл, только в разных условиях. Т.е. очевидно, существует возможность установки нужных условий/флагов, не поднимаясь "до самого верха", а тут же "по месту" (как АВАРИЯ в "Лунолете").

В FORTH все еще хуже (или наоборот?), ведь у него и так есть внешний цикл от которого не уйти - Цикл Управления. И, даже, применяется схожая матрешка циклов вокруг WORD. Так, может, в FORTH-программировании можно перенести часть этих "гомеостатов" на сам FORTH? Или придумать другой способ написания диалоговых программ?

P.S. Кстати, невозможность организовать "матрешку циклов" в визуальных программах привела к тому, что "визуальные программисты" вообще ничего не могут написать...
Сообщение Добавлено: Пн фев 16, 2015 12:26
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
Еще одна задачка на рефакторинг: http://www.gudleifr.h1.ru/c84.html.
Вычлененные там операторы - СЛУЧАЙ, ПЕРЕХОД, ВЫДАЧА, КОНЕЦ, ХОД-ИГРОКА, ХОД-БАРТА - в нормальных языках реализуются, разве что, макросами (или дурацкими объектами).
А на FORTH?
Попутно хорошо бы:
1. Добавить симметрию игрок-компьютер; или, наоборот, полностью отказаться от нее в пользу улучшения играбельности (книжности).
2. Структурировать программу таким образом, что бы упомянутые ошибки стали более явными, и добавление новых фич стало бы более простым.
3. Навесить средства сбора статистики/выбора стратегии.
Сообщение Добавлено: Чт окт 23, 2014 19:30
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
gudleifr писал(а):
Это, конечно, подтверждает мои догадки о стремлении Rus-FIG привести FORTH к нормам "обычных языков", но, все равно, обидно. Говорим о самодокументированности, о лексиконах, о интерпретации на всех этапах... А на деле - полная беспомощность...

Да, это одна из проблем. Быть лидером в какой-то области не так уж просто. Всем хочется иметь какой-то якорь. Вот и берется за основу Си или даже Бейсик.
Сообщение Добавлено: Вт авг 12, 2014 00:31
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
Тут коллега KPG облыжно обвинил меня в неуважении к национальному достоянию - материалам RusFIG. Воспользуюсь наводкой и попробую поискать там что-то то теме (недаром же, наверное, коллега true-gue как-то заметил, что я пишу старомодно). Найденные "выводы" принадлежат если я не ошибаюсь к мейнстриму: один из непоследних людей написал библиотеку, а другой на ее примере показал, как надо чужие программы читать. Раз я рассуждаю здесь о писании кода, то ожидания читателей должны бы мне помочь.
Итак:
Цитата:
* Для подхода к изучению чужого кода нужно во-первых иметь хотя бы примерное знакомство с предметной областью, теорией (совсем необязательно досконально знать, достаточно хотя бы "плавать" в терминах, а непосредственные детали реализации можно будет уяснить из самого кода). Если не отходить далеко от нашего примера — к началу конкретного этого разбора я знал в чём состоит задача "сборки мусора", знал что она обозначается как gc, имел смутное представление о том "как оно работает".
* Правило "читай с конца" применённое в самом начале разбора обосновывается технологическими особенностями Форта. Так как forward-ссылки в форте из-за однопроходности компилятора не используются, то определения (процедуры) идут в тексте по мере нарастания сложности, из-за чего "главные", наиболее мощные слова оказываются в конце текста. Отсюда и идёт правило что разбирать программу на форте надо с конца и разматывать клубок нужно, начиная с "торчащей нитки" — главного слова или одного из них.
* Последовательность разбора каждой процедуры примерно такая: имя, комментарии, код. Если смысл слова становится понятен на более раннем этапе, то остальные делать соответственно незачем.
* Авторы всегда стараются давать говорящие названия своим процедурам (по крайней мере — говорящие им), ваша задача — постараться понять что имелось в виду. Есть стихийно сложившийся "пиратский кодекс" по построению названий форта, который был обзорно описан в "Этимологии", он может помочь. Также можно посмотреть советы по именованию от ~pinka. Но главное подспорье — это здравый смысл (как впрочем и всегда).
* Проверяйте ваши "догадки", осознанные предположения о структуре/работе программы эмпирически — то есть непосредственно запуская програму и прогоняя тестовые куски.

И что? Где здесь FORTH? Есть ли здесь хоть что-то, чего не знают "не-FORTH-программисты"? Нет.
Это, конечно, подтверждает мои догадки о стремлении Rus-FIG привести FORTH к нормам "обычных языков", но, все равно, обидно. Говорим о самодокументированности, о лексиконах, о интерпретации на всех этапах... А на деле - полная беспомощность...
По крайней мере, на поставленные в теме вопросы ответа я не получил.
Может, кто-то, сможет копнуть материалы Rus-FIG более удачно?

P.S. Прошу мне простить некоторую категоричность. Она объясняется тем, что мне достаточно часто приходилось читать чужой код. И смею, вас заверить, там все по-другому. См., например, игрушечный пример того, с чем приходится иметь дело: http://www.gudleifr.h1.ru/4i.html, с середины.
Сообщение Добавлено: Пн авг 11, 2014 21:33
  Заголовок сообщения:  Re: FORTH-рефакторинг  Ответить с цитатой
Ладно, раз никто не предложил ничего путного, делаем очевидное:
Код:
VARIABLE RESULT
: CN0 ( N, 0 -- -1) 2DROP 1 RESULT +! -1 ;
: CN1 ( N, 1 -- -1) DROP RESULT +! -1 ;
: CNK ( N, K -- N-1, K, N-1, K-1, 1)
  SWAP 1- SWAP 2DUP 1- 1 ;
: NORM ( N, K -- N, K | N, N-K)
  2DUP 2* - DUP 0< IF + ELSE DROP THEN ;
: REDUCTION ( N, K -- N-1, K, N-1, K-1, 1 | -1)
  NORM DUP IF DUP 1- IF CNK ELSE CN1 THEN ELSE CN0 THEN ;
: COMPUTE ( N, K -- CNK)
  0 RESULT ! 1 BEGIN >R REDUCTION R> + ?DUP 0= UNTIL RESULT @ ;

Очевидно? Очевидно!
Но, как бы, непонятно, как от первого варианта перейти ко второму, не зная "смысла задачи"?
И, конечно, чем дальше, тем больше скрупулезных проверок типа "а точно ли мы не порушили стек в этой ветке?"
Кто знает более симпатичные варианты причесывания?
Сообщение Добавлено: Пн авг 04, 2014 23:10

Часовой пояс: UTC + 3 часа [ Летнее время ]


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
phpBB сборка от FladeX // Русская поддержка phpBB