: new-word 1 1 + . ;
а более удобно:
new-word: 1 1 + . ;
просто объявив : как корень.
Как считаете, сильно это усложнит восприятие кода? Можно, вообще говоря, и:
:new-word 1 1 + . ;
сделать, чтобы обратную польскую не ломать.
Аналогично с помощью знаков равенства можно будет и переменные создавать.
Пока по запуску потоков есть идеи:
есть специальный набор суффиксов, которые указывают что слово нужно запустить в отдельном потоке, а также из стека извлечь его аргументы и это будет новый стек. Если стек реализован двусвязным списком, то создание нового стека из куска имеющегося — очень быстрая операция, но вообще и из массива можно копировать довольно быстро (на МК это можно поручить DMA).
Классический подход такой что запущенному потоку присваивается токен, и его уже программа может использовать для управления потоком и обменом с ним данными, однако можно ввести суффикс, который сохранит токен под именем. Например, как-то так:
в слове Й’хан-тлеи корень хан исполнится в отдельном потоке (префикс й), а токен сохранится под именем тлеи. Точнее даже не так, хан-тлеи будет возвращать токен, а различные суффиксы помогут собрать слово ожидания результата, остановки потока, пересылки потока на другую машину, и т.д.
richardhaskell.com
коротко, хардварная имплементация раз в 10 быстрее чем реализация на ЯП, Си как обычно тормозит, FORTH-процессоры это ня, надо зопейлить таковой на своей плисине, можно попробовать уходить в крайности RISC/CISC и посмотреть что — лучше, а что — хуже.
Интересный текст коротко, хардварная имплементация раз в 10 быстрее чем реализация на ЯП, Си как обычно тормозит, FORTH-процессоры это ня, надо зопейлить таковой на своей плисине, можно попробовать уходить в крайности RISC/CISC и посмотреть что — лучше, а что — хуже.
стеки и обратная польская нотация — в общем случае начинающий фортер думает также и о том, чтобы сделать в форте всё как у людей. Но через некоторое время начинает уже у людей всё делать как в форте.
torth.us
Сразу оговорюсь, экспериментальный язык, это поиграться а не писать на нём промышленный код.
Что посоветуете по системе типов на попробовать? Заявленные идеи по типам у меня только по синтаксису есть, а вот может есть что прорывное или просто интересное, которое мало применяется в распространённых языках программирования? Можно с заметными недостатками, нам с тортом не на луну лететь.
Ну допустим как-то так это будет Сразу оговорюсь, экспериментальный язык, это поиграться а не писать на нём промышленный код.
Что посоветуете по системе типов на попробовать? Заявленные идеи по типам у меня только по синтаксису есть, а вот может есть что прорывное или просто интересное, которое мало применяется в распространённых языках программирования? Можно с заметными недостатками, нам с тортом не на луну лететь.
там всего несколько вариантов для самого начала:
1) компиляция в байткод — я использовал, довольно приятно.
2) интерпретация — не так приятно потому что контекст меняется, но легко делается поверх (1) потом.
3) компиляция в машинный код — сложно с поддержкой потом, ну разве только LLVM взять.
Также надо определиться с форматом шитого кода, реализациями словарей и стеков.
Дальше ерунда, взял во входном потоке слово, нашёл в словаре, иначе — ошибка. Если слово нативное (реализованное тобой на языке реализации) — вызвал стандартным механизмом языка, если нет — послал туда интерпретатор байткода если (1), просто интерпретатор если (2), ну а если (3) то все слова нативные. Дли ненативных слов не забываем слежить за стеком возвратов.
эм.. по большей части всё. Для реализации нативных слов не помешают функции работы со входным потоком и управлением интерпретатором. Байткод не жадитесь, берите от 32 бит на команду — что не потратите эффективно, сожмёт архиватор.
конкретнее можно спрашивать в комментариях.
Начал кодить Tox-клиент на 8th (коммерческий кроссплатформенный forth), затестил FFI, довольно мило: "tox" lib tox tox drop "N" "tox_version_major" func: tox_version_major "N" "tox_version_minor" func: tox_version_minor "N" "tox_version_patch" func: tox_version_patch "NNNN" "tox_version_is_compatible" func: tox_version_is_compatible "Pn" "tox_options_new" func: tox_options_new tox_version_minor . tox_version_major . tox_version_patch . 1 2 3 tox_version_is_compatible .
В #2787846 обещал для SP-Forth синтаксического сахара в виде: : lala 1 . ; lala 1 Ok lala` 1 Ok lala`lka 1 Ok Как сделать: берём библиотеку cafeins.f (я думаю вам она всё равно понадобится, чтобы ЯЗЫК НА ВАС НЕ КРИЧАЛ), и там перед CEQUAL-U вставляем следующий код: 2SWAP 2DUP S" `" SEARCH IF NIP - ELSE 2DROP THEN Вообще надо было в другом месте править, заодно с цифрами и прочим, но как-то с документацией у SP-Forth не очень, библиотеки проще прочитать. К сожалению, `вотэто будет незнакомым словом по-прежнему, как и 1`единичка, как раз поэтому. В парсер надо лезть. Но главного я доби`лся , хорошо хоть форт легко позволяет этого доби`ваться .
а что если variable a 2 1024 pow dup a ! 0 do a @ 1 — a ! loop a @ .
что выведется?
ну я не знаю того языка потому использовал forth в качестве псевдокода
blinker @ not blinker !Блинкер , собака такая , не блинкер .
Ещё поймал себя на том что в комментариях к коду пару раз поставил пробелы перед знаками препинания . То ли ещё будет ;
Очевидны минусы, главный пожалуй — делегация не экономит особо времени, если только слова не какие-то зубодробительные, однако оно не для того, а например для доступа к железу, которое есть у подчинённой программы, и нету у ведущей.
Сложности тоже ясны, главная — области видимости. Решается либо аккуратным программированием, но тогда ведущая программа, как и программист, должна знать всё что знает делегат (не круто), либо чистыми функциями — но тогда с доступом к инфе неясно, либо с явным указанием, что берётся из словаря подчинённого, а что переносится с ведущего.
И вообще пока очень размытая концепция, надо думать или кодить.
Суть такова:
Запускаете интерпретатор. Описываете объекты "мира", ну там например домики, ботов. Описываете персонажа, даёте ему методы и прочее. Ну и начинаете "играть", выполняя задания этим персонажем. Можно так рпгшить, можно экшонить, да что заблагорассудится. Что из взаимодействий "честно" что нет — решаете сами.
А потом, если понравилось, логи процесса "игры" сохраняете, анализируете, пилите нормальную игру на любом языке и выпускаете. А если и нет, вы поиграли в игру, в которую никто никогда не играл — уникальную, которую "написали" за часик.
Чем-то DnD и прочие словески напонинает.
habrahabr.ru в ответ на каждый комментарий автора, восхваляющий OBERON, писать что-то вроде "но это есть и в FORTH!", просто так.
Или я мог бы не писать, а почитать FORTH vs OBERON дискасс, а то война древности с современностью и современности с другой современностью это мейнстрим и скучно. Можно прямо здесь. Есть оберонеры на жуйке? Велкам и рецомменд.
Иногда мне хочется иметь аккаунт на хабре. Например, в комментариях к статье Или я мог бы не писать, а почитать FORTH vs OBERON дискасс, а то война древности с современностью и современности с другой современностью это мейнстрим и скучно. Можно прямо здесь. Есть оберонеры на жуйке? Велкам и рецомменд.
Это не единственное применение, так можно и кратко комментировать в середине строки гораздо менее громоздко нежели скобочками. Может показаться странным, но когда писал код — действительно было удобно.
В процессе написания #2786776 подумал что можно это и в парсеры других фортов форт-кодом добавлять. Хотя для отдыха ленивовато таким заниматься, но с другой стороны — интересненько. Может для SPF и Amforth сделаю
вынесу из комментов к #2785629, пожалуй. Наивная, конечно, реализаци, ну и не запускал так что могут быть ошибки уровня опечаток. variable Печь : поставить ; : на ; : градусов, swap ! ; 0 1+ dup value Яйца, 1+ dup value муку 1+ dup value сахар, drop create котёл 3 allot : в ; : В ; : всего ; ; все ; : ингредиента ; : поместить, swap 0 do tuck ! loop ; котёл value котле defer вязкость ' > is вязкость ( взято с http://rosettacode.org/wiki/Sorting_algorithms/Bubble_sort#Forth ) : перемешать. ( addr cnt -- ) dup 1 do 2dup i - cells bounds do i 2@ вязкость if i 2@ swap i 2! then cell +loop loop ; Печь поставить на 300 градусов, Яйца, сахар, муку - всего 3 ингредиента в котёл поместить, В котле все 3 ингредиента перемешать.
docs.python.org
наименование видя форта следы питоне в вижу я функции
math.expm1(x)
Return e**x — 1. For small floats x, the subtraction in exp(x) — 1 can result in a significant loss of precision; the expm1() function provides a way to compute this quantity to full precision
наименование видя форта следы питоне в вижу я функции
ЕДА ГОТОВА? ЕСЛИ КУШАТЬ ТОГДА
FOOD READY? IF EAT THEN
С ELSE проблема в том, что оно меняет общую постфиксную логику на префиксную. Мы говорим не ДЕЙСТВЕ ИНАЧЕ, а ИНАЧЕ ДЕЙСТВИЕ. Это и сбивает с толку.
ЕДА ГОТОВА? ЕСЛИ КУШАТЬ ИНАЧЕ ЖДАТЬ ТОГДА
Это одна из немногих Форт-нелогичностей, продиктованная упрощением транслятора.
Вариант ... IF ... THEN ... ELSE был бы логичнее:
ЕДА ГОТОВА? ЕСЛИ КУШАТЬ ТОГДА ЖДАТЬ ИНАЧЕ
Но такой вариант не реализуется столь примитивно, как то, чтоб вошло в стандарты. На сегодняшний день разница смехотворная, но стандарт — есть стандарт. Вот когда реализуешь Форт не глядя на стандарты, это можно учитывать. В моём JBForth2 так и было запланировано, но он так и не состоялся :)
// для habrahabr.ru
Скоро меня запарили проблемы расширения новым функционалом решений на qbasic и я написал парсер на SP-Forth. Написал так, что исходный файл с разметкой без переделки был полноценной программой на Форте :) Вот в таком виде оно полноценно и развернулось.
Уже потом были переход на Perl вместе с выходом в онлайн, перевод платформы на PHP, более 10 лет развития движка… Но прикольно вспоминать, что корни некоторых решений уходят ещё в Forth-прошлое :) // для habrahabr.ru
Решение задачи из #2745090 на gforth. На оптимальность решения не претендую (оно наивное), также интересно было самому написать - в реализации стандартных слов (например, .) не подглядывал. Замечания приветствуются. Комментариями снабжать сперва начал (первая строка), но это выглядело странно, так что оставил только карты стека. Выполнять например так: -234 n>s type \ create string buffer with 20 cells alloting create string-buffer 20 cells allot : n>s ( n -- c-addr u ) dup 0< if negate '-' swap else 0 swap then 0 ( minus-char number length ) begin 1+ swap 10 /mod swap '0' + -rot tuck 0= until nip 1+ dup roll swap ( chars length ) dup begin 2dup - string-buffer + 1 4 roll fill 1- dup 0= until drop string-buffer swap ;
balancer.ru
~~~
Внезапно на форуме оживилась тема по Форту. Народ горячо спорит уже на 6+ страниц с начала месяца ~
~~~
VARIABLE cp
1 cp !
: cp
cp @
1 = IF
16 IXORST
0 cp !
." DONE"
ELSE
16 IOXSET
."DONE
1 cp !
THEN ;
Битый час пытаюсь накодить элементарщину,пока все безысходно.
Ну что я делаю не так )
: cupenable
." cupol now enable"
1 VARIABLE cup
: cupdisable
." cupol now disable"
0 VARIABLE cup
: cupol
IF cup 1=
cupdisable
then
cupenable
retroforth.org . А тут оказывается такой приятный ч/б дизайн стал. Проект, смотрю, не забросили, более того, расширили, сделав реализации транслятора на нескольких языках. Это не Factor, но тоже кое-для чего пригодится. Поглядим-поглядим.
Давно не заходил на "Теперь про Форт. То, что программируют на Форте, на C++ запрограммировать ВООБЩЕ НЕВОЗМОЖНО. Физически. И задачи они решают в среднем гораздо более сложные чем то, что встречается плюсистам — поскольку в этой индустрии как правило задачи реального времени, а что либо писать для очень ограниченной железяки еще и в условиях требований жесткого реального времени — это дело для настоящих мастеров. Оно и оплачивается соответственно гораздо лучше — такие мастера — редкость."
Что невозможно запрограммировать на других языках?
В качестве базы я возьму rx core — ядро RetroForth до 9'ой версий включительно. Низкоуровневых слов в rx core всего 31 штука. В rx core (как и в большинстве классических фортов) используется два стека (первый называется stack, второй — return stack) и хип. Также замечу, что из 31'ого слова только 5 работают с return stack'ом (при этом они не работают с хипом) и только 4 работают с хипом.
Рассмотрим следующее выражение в обратной польской записи «2 3 4 +». Если рассматривать его как работу со стеком, то оно не берёт ничего, и кладёт в стек 2 числа. Т.е. его можно рассматривать как функцию от 0 параметров, возвращающую пару значений. Аналогично форт-выражение «dup *» это функция от 1 параметра с единичным возвратом. Теперь важно заметить, что все стандартные слова, кроме if-семейства и then, можно описать в таком виде (значит и их композицию тоже). Единственным тонким местом является выражение «if бла бла бла then». Если бла бла бла изменяет размер стека, то теряется детерминированность результатирующего слова и его уже не выразить не прибегая к стеку.
Ну и наконец пример. В rx core выражение «dup *» откомпилируется во что-то такое (rx core держит верхушку стека в eax, использует esi как указатель стека):
mov [esi-4], eax
lea esi, [esi-4]
mul dword [esi]
add esi, 4
В оптимизирующем компиляторе же (параметры лежат в eax, ecx, edx, возврат там же):
call dup ( если dup inline, то mov ecx, eax )
imul eax, ecx
P.S. Сразу извиняюсь за корявости
forthfreak.net и forthfreak.net Человек реализовал в несколько строк алгебраические типы данных (с паттерн-матчингом, зачем они без него?) и привёл примеры использования. Всё генерится на этапе компиляции, так что никаких рантайм оверхедов. Всё-таки форт превосходный язык
gen.lib.rus.ec 97% может осилить любой технарь, ещё 3% осилит любой хоть капельку разумный. Информация там устаревшая, абсолютно не учитывающая современные диалекты, inspired by color forth, но основопалагающие принципы легко понимаются
Очень интересная методичка по Форту —