LINUX.ORG.RU

Ещё один Форт

 


1

3

Здравствуйте, коллеги!

Любите ли вы язык Форт так же, как полюбил его я? До недавнего времени его не любил. Уважал - да, но любви не было. Как к какому-то забытому старичку из прошлого к нему относился. Лабораторные когда-то в древности на Форте делал. Сделал и забыл. Но так произошло, что в недавнем времени пришлось нудно и долго писать на ассемблере. Иногда такое бывает, тогда и вспомнился язык Форт. И чем больше вспоминаю узнаю Forth, тем он мне кажется интересней и интересней. И кажется незаслуженно забытым.

В общем, ежели вдруг кто захочет освежить память или ознакомиться с языком Форт, то загляните сюда - https://github.com/L4OS/yaforth

Если понравилось - дайте как-нибудь знать. Найдёте ошибку - вдвойне дайте знать.

Если кто желает покритиковать код, стиль, алгогитмы, поучить программировать/жить - то почему бы и не в этой теме, но в пределах правил.

Спасибо за внимание, ведь именно его так не хватает.

★★★

Странный язык, на котором зачем-то написали скрипты бут-лоадера фрибсд. Больше нигде не встречал и надеюсь не встречу.

firkax ★★★★★
()
Ответ на: комментарий от spbzip

Фортов десятки, если не сотни. На все расцветки и вкусы. Мне понадобился, я написал. Точнее - пишу. Это, возможно, проще, чем выбирать из десятков популярных реализаций.

alman ★★★
() автор топика

Кринж, у меня ассемблер для форта уместился в 40 строк, написан он был на самом форте. Базовые операции реализованные с помощью stl контейнеров это насмешка над идеей форта.

Попробуй взять ассемблер.

Хотелось бы посмотреть на бенчмарки этого. Особенно где много циклов, конец цикла я увидел в коде, поразился до глубины души!

MOPKOBKA ★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 4)
Ответ на: комментарий от MOPKOBKA

Кринж, у меня ассемблер для форта уместился в 40 строк, написан он был на самом форте.

Верю. Мог бы посоревноваться, но мне важнее не компактность исходников Форта, а компактность оптимальность сгенерированного им кода.

Кстати, руки чешутся ещё и оптимизатор прикрутить, но не осилю. Да и вренемени на такую фичу нет.

Ах да, чуть не забыл - там на сайте в разделе дискуссий есть вопрос насчёт геерации кода для x86-32. Мне он как бы не нужен, но если голосовалка наберёт какое-то количество голосов, то добавлю кодогенерацию в asm для этой архитектуры.

А взглянуть на Форт, который в 40 строчек, можно? Люблю такие вещи. Старая школа.

alman ★★★
() автор топика
Ответ на: комментарий от alman

А взглянуть на Форт, который в 40 строчек, можно? Люблю такие вещи. Старая школа.

Не форт, а ассемблер для amd64. Из интересного открытого можно взглянуть на colorForth https://github.com/narke/colorForth/blob/master/cf2019.asm

К сожалению нормальных ассемблеров на форте я не нашел, позже выложу свой.

Верю. Мог бы посоревноваться, но мне важнее не компактность исходников Форта, а компактность оптимальность сгенерированного им кода.

Но ты генерируешь очень медленный код! Неужели он обгоняет хотя бы Python?

Кстати, руки чешутся ещё и оптимизатор прикрутить, но не осилю.

Советую посмотреть на другие компиляторы, коммерческие.

Я много не смотрел твой код, но у меня будет два совета

1. У тебя для циклов есть только i и j, верно? Храни их в фиксированных регистрах, что бы на каждую итерацию не подгружать их из памяти.

2. У всех нормальных реализаций, верхнее значение стека лежит не в стеке, а в регистре, и для инкремента, можно не делать

mov rax, [rsp]
inc rax
mov [rsp], rax
А сразу просто выполнить
inc rax

Это очень простые исправления, которые заметно улучшат скорость.

MOPKOBKA ★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 2)
Ответ на: комментарий от MOPKOBKA

В режиме интерпретатора скорость ограничена STL’ной std::map Я не гнался за скоростью, мне нужна была простота и удобный способ генерации в assembler.

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

alman ★★★
() автор топика
Ответ на: комментарий от MOPKOBKA
  1. У тебя для циклов есть только i и j, верно? Храни их в фиксированных регистрах, что бы на каждую итерацию не подгружать их из памяти.

Спасибо! Это очень дельный совет. Вот, ради такого и имело смысл создавать тему.

alman ★★★
() автор топика
Ответ на: комментарий от alman

Так как я пишу на ассемблере, то мне не нужно разделять слова на те что будут в режиме компиляции, и те что в режиме интерпретации. Я просто когда читаю слово, проверяю в каком я режиме (переменная state), и если это режим интерпретации, то я тут же вызываю это слово, если в режиме компиляции, то я вставляю в буфер генерации машинного кода опкод call. И ничего не дублирую. Ну не так все просто, у меня есть оптимизатор, но суть я думаю понятна.

Если у тебя микроконтроллер, то ты можешь просто в него загружать выходной буфер компиляции машинного кода, и базовые слова.

MOPKOBKA ★★★
()
Ответ на: комментарий от alman

Заметь что из цикла может вызывать функция где тоже есть цикл, между такими переходами надо их сохранять все же в промежуточное место. Но если тебе не хочется что то сложное городить, то можешь просто перед циклом сохранять текущие i, j, а после цикла вынимать их значения. А во время итераций ничего уже выгружаться не будет. Постоянная загрузка i j из памяти это ужасное замедление.

MOPKOBKA ★★★
()
Ответ на: комментарий от MOPKOBKA

Типа микроконтроллера. Про него в другой раз тему создам. Не скоро. :)

У этого 32-битного микроконтроллера 16 регистров общего назначения. Только последний регистр, он называется R15, умеет переход на адрес по значению регистра. Другие регистры так не могут.

Вокруг этого всё построено. В этом Форте ABI простой - R14 - указатель на стек возвратов, R11 - у указатель на стек Форта.

alman ★★★
() автор топика
Ответ на: комментарий от CrX

Стек лучшее решение для передачи и возврата значений. Стек пытаются воспроизводить другие языки программирования, часто неосознанно, функциональные, или например Clojure через оператор стрелки. С ним удобно объединять функции, с ним удобно перекидывать значения.

А форт просто некая среда, чистый лист, где есть все необходимое для начала. Писать на нем сайт не стоит, лучше взять питон, пхп, жаваскрипт, там есть библиотеки, там есть ориентированность под веб.

Мне нравится драйвер IDE, вот его код, первая строка комментарий, в ColorForth значение слова зависит от того как ты его раскрасил https://colorforth.github.io/ide.html

IDE hard disk driver
bsy 1f7 p@ 80 and if bsy ; then ;
rdy 1f7 p@ 8 and if 1f0 a! 256 ; then rdy ;
sector 1f3 a! swap p!+ /8 p!+ /8 p!+ /8 e0 or p!+ drop p!+ drop 4 * ;
read 20 sector 256 for rdy insw next drop ;
write bsy 30 sector 256 for rdy outsw next drop ;

MOPKOBKA ★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 4)
Ответ на: комментарий от alman

Учитывая то, каким легким может быть форт, возможно у тебя мог бы быть «клиент» на компьютере, и «сервер» на микроконтроллере. Это довольно обыденный способ программирования.

MOPKOBKA ★★★
()
Ответ на: комментарий от MOPKOBKA

Спасибо тебе, добрый человек!

Вот эти слова в прямом смысле наблюдаю в сгенерированном коде. Там реально встречаются, например, взаимоисключающии операции рядом, типа икремента и тут же декремента одного и того же регистра.

По-идее такие сочетания можно безболезненно выкидывать из кода?

p.s. Чую тут в теме можно залипнуть надолго в интересной беседе. Таки закрою вкладку и только ночью зайду проверить реакции.

alman ★★★
() автор топика
Ответ на: комментарий от alman

Это ты отвечаешь на мой комментарий про хранение top-stack-value в регистре? Да, полезная оптимизация.

А насчет неоптимальности операций в машинном коде, самое простое это https://en.wikipedia.org/wiki/Peephole_optimization

Во всех коммерческих компиляторах можно посмотреть на ассемблерный выхлоп, иногда даже заглянуть в оптимизатор, так что прям настоятельно советую посмотреть на лидеров, SwiftForth, VFXforth.

MOPKOBKA ★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 3)

всё понравилось, кроме :

static std::stack<word_t>           integer_stack;
static std::stack<word_t>           return_stack;
static std::stack<word_t>           condition_stack;
static std::vector<word_t>          leave_counts;
static registry_t                   words;
static std::string                  func_name;
static ram_memory                   memory;
static int                          line_no;
static word_t                       base_address;

static на ровном месте :-) если запустить 2 в разных нитях будет сами знаете что..это ставит крест (хотя может для от того и плюс-плюс) на «встроить в какую софтинку».

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

Принял. Понял. Спасибо!

В одной из следующих версий вынесу интерпретатор в отдельный класс и помещу это в поля этого класса. Без static, конечно.

alman ★★★
() автор топика
Ответ на: комментарий от MOPKOBKA

Да уж, оптимизация кода это ж целый мир.

А вот как бы прикрутить простейшую оптимизацию? Мне видится такой алгоритм - ассемблерные инструкции писать не в текстовый файл, а вместо этого заполнять ими список. Элементы списка - описатели инструкций.

Затем на этот список можно натравить алгоритм, который будет «выкусывать» peepholes, а после оптимизации из списка генерировать ассемблерный код. Если понадобится кросс-компиляция, то уже из оптимизированно списка. Вот что-то такое попробую, если сил хватит.

alman ★★★
() автор топика
Ответ на: комментарий от alman

Да уж, оптимизация кода это ж целый мир.

Достаточно применить самые эффективные, сорвать низко висящие плоды.

Затем на этот список можно натравить алгоритм

Ну примерно так это и делается, так что можешь реализовывать, это довольно просто, самое сложное наделать правил.

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

MOPKOBKA ★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA

Спасибо. Теперь вот раздумываю как бы релизовать.

Ещё вопросы назрели:

  1. Как вообще реализовано в разных Фортах подключение функций из libc? Что-такое видел, но показалось что стандарта на это нет? Или есть?

  2. Как ввести зарезервированное слово, не меняя синтаксис?

Например, занёс в словарь : ? @ . ; При этом желаю зарезервированными словами менять тип этого определения - например, говорить компилятору как генерировать из него код - разворачивать ? в последовательность команд или сгенерировать ? как подпрограмму.

Пока в голову ничего не приходит, кроме как в ввести зарезервированные слова в комментаии. С префиксом.

Нечто-типа такого ( #inline ) Нормально? Тогда при обнаружении такой конструкции можно выставлять флаг, определяющий что слово из словаря будет рассматриваться как инлайновое.

alman ★★★
() автор топика
Последнее исправление: alman (всего исправлений: 1)
Ответ на: комментарий от alman

Как вообще реализовано в разных Фортах подключение функций из libc? Что-такое видел, но показалось что стандарта на это нет? Или есть?

Стандартные слова, и то что они делают можно удобно посмотреть тут https://forth-standard.org/standard/words

Стандарта нету, каждый дает свое, примеры:

https://vfxforth.com/flag/extern/externVFX.html

https://www.complang.tuwien.ac.at/forth/gforth/Docs-html/Declaring-C-Function...

Это подключение функций из любых динамических библиотек. Что бы вызывать функции C библиотек, твоя программа должна запускаться через main() и быть слинкована с libc, иначе все поломается, перед main() происходит инициализация, а после нее libc передает управление твоей программе.

А сам вызов функций из .so можно делать как обычно, через https://man7.org/linux/man-pages/man3/dlopen.3.html

Только сначала нужно почитать про ABI, https://wiki.osdev.org/System_V_ABI первый аргумент это регистр rdi, второй rsi и так далее.

Я функции на С не вызываю, у меня есть только слово SYSCALL, оно принимает номер системного вызова, и количество аргументов, при его вызове оно удаляет 2 этих значений со стека, плюс указанное количество аргументов, и помещает их по регистрам, и делает SYSCALL. Так у меня обернуты различные вызовы:

...

: ioctl 3 16 syscall ;
: nanosleep 2 35 syscall ;
: pool 3 7 syscall ;

...

Как ввести зарезервированное слово, не меняя синтаксис?

Что то вопрос не понял, но ты вроде про inline спрашиваешь? У меня inline пишется после определения слова, и меняет его атрибуты в словаре, точно так же как и IMMEDIATE, у меня несколько разных возможных атрибутов на слова есть.

: ^2 dup * ; inline

И теперь всегда ^2 будет инлайнится. Если тебе нужно инлайнить слово лишь в некоторых ситуациях, то можно сделать слово [inlinе], и использовать так:

: some-word 5 [inlinе] ^2 . ;

MOPKOBKA ★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA

У меня inline пишется после определения слова, и меняет его атрибуты в словаре, точно так же как и IMMEDIATE, у меня несколько разных возможных атрибутов на слова есть.

Тогда повторю твое поведение inline. А какие ещё атрибуты используешь?

А как в Форте реализован аналог сишного #include? Пока реализовал списком файлов в командной строке, которые в один словарь транслируются, но это как-то некрасиво. А как это вообще делается?

alman ★★★
() автор топика
Ответ на: комментарий от alman

А какие ещё атрибуты используешь?

Из интересного только constant, тогда вместо указателя на слово, в словаре хранится само значение константы. Это полезно что бы не трогать память под код слов при определении константы, и можно без проблем во время определения нового слова создавать константы которые не будут влиять на тело создаваемого определения.

А как в Форте реализован аналог сишного #include

У меня стек включаемых файлов (их контента), INCLUDE добавляет файл в этот стек. Функция чтения исходного кода читает по этому стеку с конца как и полагается, как прочитает один файл, делает DROP, читает другой.

Стек это вообще удобно. Повышает удобство, и типобезопасность. Если float в отдельном стеке, это удобнее, не мешаются на общем стеке. Так же можно завести стек для строк отдельный. Строка это два значения на стеке, жутко неудобно, а если сделать свой стек, то можно это все удобно представить, указатель + длинна будет одним значением для стека строк.

Я заметил флоатов у тебя нету. Может и не будет? Тогда нужно добавить функцию https://forth-standard.org/standard/core/TimesDiv

7 / 2.5 = 2.8

Через эту функцию, можно первым аргументом указать где стоит запятая в дроби, 10 это после первого символа, 100 после второго итд, вторым аргументом указывается делимое, третьим на что делим.

10 70 25 */
= 28

На Forth-83 стандарт поменьше, все требуемые слова умещаются в одну страницу https://forth.sourceforge.net/standard/fst83/fst83-12.htm

В классическом форте файлов не было, он вместо ОС загружался. Вместо файлов просто загружали блоки (секторы диска).

MOPKOBKA ★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 5)

Посмотрел еще набор твоих слов, не особо внимательно, может пропустил.

1. Но не нашел у тебя слова .s https://forth-standard.org/standard/tools/DotS

Без него неудобно, оно выводит все значения стека. gforth доступен под linux бесплатно, там можно посмотреть как оно работает:

Gforth 0.7.3, Copyright (C) 1995-2008 Free Software Foundation, Inc.
Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `bye' to exit
1 2 3 4 5  ok
+  ok
*  ok
.s <3> 1 2 27  ok

2. Так же у меня есть слово see https://forth-standard.org/standard/tools/SEE

Декомпилятор я пока не сделал, поэтому печатает hex слова. Но все равно удобнее чем вручную выковыривать.

3. Вывод числа на самом деле стоит начинать реализовывать в компиляторе не со слова ., а со слов форматирования <# sign # #>: https://forth.sourceforge.net/standard/fst83/fst83-12.htm#less-sharp

Если их реализуешь, то слово . будет выглядеть так:

: #u ( вывод unsigned ) # dup 0 <> if rec then #r ;
: #n ( вывод signed ) sign #u ;
: . <# #n #> type space ;

<# - просто инициализирует указатели на буфер временный, для строк и форматирования

# - делит свой аргумент на переменную BASE, и добавляет в буфер символ, который берет из CH:=NUMTABLE[Остаток]. NUMTABLE это 0123456789ABCDEF..., если остаток=0, то добавит символ нуля, если остаток 10, а такое может быть только если BASE>10, то добавит символ A, так уже выводятся hex-числа.

#r - ну этой мой костыль, оно просто переворачивает буфер, потому что цифры пишутся задом наперед у меня из за алгоритма

sign - если число отрицательное, то пишет в буфер знак -, и делает число положительным

#> - выдает строку которая получилась из буфера

type - печатает строку

space - печатает пробел

В чем преимущество? Возможностей большей, можно делать свое форматирование, и не будет ограничение на значения BASE. Я например часто BASE устанавливаю в двойку, что бы посмотреть бинарное представление числа. Можно устанавливать в 24, не знаю какая у этого может быть цель, просто прикольно.

MOPKOBKA ★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 4)
Ответ на: комментарий от alman

Да уж, оптимизация кода это ж целый мир.

но не факт что актуальный :-)

у вас пока нет слов c double float, а без как-бы никуда.

Про системные и библиотечные вызовы выше сказали

нет фичи - снять снепшот, загрузить и продолжить снепшот.

при всём этом стараться по прежнему «держать код в чистоте» - максимально компактным,ясным и читаемым. Если короткую функцию можно ускорить но она станет длинной, то лучше не надо. Что-то не видел у вас требований «100500 инструкцию за миллисекунду» :-)

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

у вас пока нет слов c double float, а без как-бы никуда.

Вообще, каноны Форта предписывали работать с действительными числами через типы с фиксированной точкой, в необходимых местах добавляя масштабирующие множители. Теоретически это имеет смысл, позволяет работать очень эффективно и контролировать всю арифметику, особенно на железе без математического сопроцессора. Но мне уже тогда, 30+ лет назад, показалось, что овчинка выделки не стоит.

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

Еще есть история от автора форта, где он обсчитывал свой процессор, и подбирал подходящие единицы измерения, что бы ускорить операции через сдвиг, и пришел к всего двум операциям деления на транзистор.

MOPKOBKA ★★★
()
Ответ на: комментарий от MOPKOBKA

Часто хватает и фиксированной точки, а для этого только слово */ и нужно.

хоть какое-то гипотетичное целеполагание наверное у проекта наверное есть. Помимо just-for-fun

каждый со своей колокольни воспринимает, по моему мнению - если есть язык, то на нём можно вести рассчёты. Повсеместно это ieee754 double и отчасти float, слава богу стандартов - они одинаковые везде.

Мне Форт интересен что он маленький и его можно легко встраивать в софт. (при том что в плане возможностей - он сильно интереснее например lua) Чтобы использовать как непосредственно интерпретатор «скриптов» или как целевой язык для более high-level. Но софт как правило считает :-)

MKuznetsov ★★★★★
()
Ответ на: комментарий от MOPKOBKA

Очень много полезного в твоих ответах. Огромное спасибо!

А что будет, если inline после константы стоит? Или после вывода строки. Например вот так 6 inline или так ." test" inline ?

alman ★★★
() автор топика
Ответ на: комментарий от alman

Например вот так 6 inline или так ." test" inline ?

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

MOPKOBKA ★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от alman

ещё посмотри на тему форта, ассемблера, фортассемблера:

Julian V. Noble. Freedom of Assembly ссылка

как часть курса от него же

от него же: Adventures in the Forth Dimension

от Taygeta:

FORTH Scientific Library, fsl

scilib

где-то там был парсер алгебраических выражений в форт, как бы не компилирующими словами написан.

в итоге форт использовался примерно как фортран или фокал (интерпретируемый фортран)

ну и известный 486asm.f и более полноценная реализация есть в SPforth, что ли (от автора nncron)

в gforth впрочем, тоже есть

странно, что про jonesforth.S ещё никто не написал, классический же

описалово его было у rigidus где-то внутрях сайта rigidus.ru

где-то здесь

relaforth

в общем, успехов.

что с твоей L4OS? заглох проект или есть что-то новое?

anonymous
()
Ответ на: комментарий от anonymous

Freedom of Assembly page 18

[quote]

Clearly, converting so many equations to assembler is quite a > chore. This led me to invest in a time-and energy saving mini-compiler. As I had already written the FORmula TRANslator employed above, it seemed a small additional step to write a translator that would generate Intel assembler mnemonics, suitable for incorporating into CODE definitions. It turned out to be surprisingly easy to do this. (The only difficulty I encountered was a mental blind spot: I persistently overlooked the fact that dx is the name of a register, so it cannot be used as the step size in an assembly language differential equation solver!) I call the code translator CTRAN. It can be found on the Computational Methods Web page1, under the heading Forth system and example programs.

Basically, CTRAN provides two facilities to simplify creating large blocks of assembly code: • assembler macros to assemble functions inline; • translation of simple algebraic formulas into assembler mnemonics.

[/quote] – блин, убрали что-ли цитирование из разметки?

где-то там нужно искать исходники, в районе FSL/Scilib/CTRAN

; вспоминаю, как на втором курсе где-то году в 1996 обнаружил этот форт ; книга В.Дьяконова про численные методы (тоже на форте) ; вычисление дифуров методом Рунге-Кутта

у него это строчек 6 заняло, сплошных иероглифов в духе APL

; хотя вот сейчас перечитывал Бекуса нашего «Can programming be liberated from von-Neuman Style» про tacit programming и point-free notation

; внезапно, открыл для себя J и K, вот это всё

полный метапрог головного мозга:

  1. существительные – это массивы или скаляры, данные, объекты

  2. глаголы – это комбинАторы, то есть, функторы высшего порядка над такими объектами

  3. есть наречия которые влияют на то, как применять комбинАторы

в общем, на этом тоже можно что-то написать метапрого-матлабовое в духе Jupiter Notebook style

только нужно много медитировать над каждой строчкой и комбинацией иероглифов.

я столько не выпью чтобы на этом что-то большое запрограммировать.

форт, и далее – ретрофорт, фактор, 8th как-то более объектно-функционально ориентированы, и более человекочитаемы и человекописуемы.

а то как у того же Дьяконова про Рунге-Кутту:

  1. инженер запросто наколбасит 6-8 строчек иероглифов на самом форте, написанных в WRITE ONLY стиле

  2. нормальный программист вроде J.V. Noble для этого – придумает свой метапрог для трансляции формул в форт, и будет

спокойно себе писать на собственном метапроге.

anonymous
()
Ответ на: комментарий от anonymous

у него это строчек 6 заняло, сплошных иероглифов в духе APL

Есть Forth вдохновленный APL https://cosy.com/CoSy/4th.CoSy.html

Идеи сделать из форта другой язык, мне кажутся сомнительными, не проще тогда сразу взять фортран? Компилятор открыт, если что то нужно добавить, то можно добавить. Форт хорош своими особенностями, делать из него другой язык, значит отказываться от них.

Как развитие, интересным выглядит ColorForth, CosyForth как хорошая реализация SwiftForth.

MOPKOBKA ★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от anonymous

ну и известный 486asm.f и более полноценная реализация есть в SPforth, что ли (от автора nncron)

https://github.com/rufig/spf/blob/master/lib/asm/486asm.f

Ничего хорошего там нету, в идеале это хорошо описать декларативно, что бы заодно получить дизассемблер.

MOPKOBKA ★★★
()
Ответ на: комментарий от MOPKOBKA

форт это прежде всего интерпретирующе-компилирующая среда, в которой можно интерактивно расширять её саму.

JV Noble пишет, «с нашим конституционным правом ассемблировать» – то есть, писать форт-слова сразу на ассемблере

далее он показывает что

  1. парсер выражений или компилятор формул в форт написать не так уж и сложно, и что
  2. их можно при необходимости сделать «компилирующими словами»

он не знает других языков, где их было бы писать так же просто

я знаю: HLA by Randall Hyde с нормальным CTFE; D2; Converge c СTMP метапрограммированием поверх чего-то вроде питона

github.com/kragen/stoneknifeforth HN

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

тут можно только добавить про «Давайте напишем компилятор» – цикл статей от Джека Креншоу:

  1. классический
    1.5. более HTML-ный xmonader
  2. вариант на С github.com/lotabout/Let-s-build-a-compiler
  3. вариант на форте home.iae.nl/users/mhx/crenshaw/tiny.html tinykiss.frt

начали с реализации компилятора Паскаля на самом Паскале

затем переписали на Си, затем на форт

ещё в книгах Баранова про форт было про реализацию компилятора Паскаля на форте

в той ссылке на FD-V21N1,2.pdf про «A call to Assembly» by JV Noble на журнал «Forth Dimensions» есть ещё одна интересная статья про реализацию объектной модели Оберон-2 на форте:

page 60/80 Object-Oriented Programming in Forth «Better Than Oberon»

это можно объединить с реализацией вроде компилятора Джека Креншоу tinykiss.frt

переписать этот классический простой конпелятор Паскаля на Паскале - Паскаля на Форте в конпелятор Оберона на форте

отличия Оберона от Паскаля не такие уж и большие

в итоге – получить реализацию в духе компилятора Баранова или tinykiss.frt Оберона на форте

форт прежде всего это интерактивная инкрементально расширяемая среда исполнения с твоим конституционным правом ассемблировать – и метапрограммировать тоже, $USERNAME!

а синтаксис там (как и в лиспе) можно прикрутить любой – поверх этой среды.

anonymous
()
Ответ на: комментарий от MOPKOBKA

отказываться то и не надо – надо как-то разумно интегрировать этот DSL поверх форт-среды исполнения.

например, форт-ассемблеры про форт-подобный синтаксис ассемблера на форте.

язык-носитель: форт реализует eDSL другого языка (ассемблера)

хотя можно и fasm.dll вызывать с трансляцией строк – преимущества форт-ассемблера что транслировать можно не строки-асм в строки-кода или строки-асм в форт-выражения, а форт-выражения-асм в форт-выражения-макросов (или компилирующих слов)

ну и с паскале-оберонами тоже самое – как-то разумно встроить как eDSL поверх форта

например, в CTRAN есть eval" формула" который разворачивается в строчки на форте откомпилированной формулы, либо в строчки на форт-ассемблере либо встраиваемом через CODE...END-CODE

а может и в CREATE...DOES.. компилирующие слова – то есть, в макросы.

anonymous
()
Ответ на: комментарий от MOPKOBKA

retroforth ForthHub/ForthFreak HN тоже выглядит интересно.

это не совсем форт, скорее – его дальнейшее развитие (как и 8th)

но там есть, например, литературное программирование: unu

и настоящие, литературно-грамотные исходники

исходники, достойные истинного метапрога

anonymous
()