Вход

Просмотр полной версии : Язык Форт для ZX Spectrum



Oleg N. Cher
06.02.2017, 00:25
Форт очень интересный язык. На нём легко сделать Форт-ассемблер, Форт-Бейсик и даже Форт-Паскаль (видел), любые проблемно-ориентированные словари, низкоуровневые вещи. Я просто не люблю писать на Форте, мозги наизнанку, массаракш ;-) И вероятность допустить ошибку очень высокая, даже ИМХО выше, чем на асме.

Прошу желающих высказаться каким должен быть Форт для ZX. Я начну.

Нужна возможность порождать прямой шитый код (https://ru.wikipedia.org/wiki/%D0%A8%D0%B8%D1%82%D1%8B%D0%B9_%D0%BA%D0%BE%D0%B4) - для компактности (вызов слова будет занимать 2 байта - адрес слова) и подпрограммный код - для скорости (как в HL ZX Forth). Выглядеть это может так:

threaded 2 dup + . ( --> CALL INTERPRET : DW LITERAL, 2, DUP, PLUS, PRINT )
direct 2 dup + . ( --> CALL LITERAL : DW 2 : CALL DUP : CALL PLUS : CALL PRINT )Обязательно нужен целевой компилятор со смарт-линкером, чтобы в отчуждаемую (stand-alone) программу включались только необходимые слова, а не всё ядро.
Давайте вместе продолжим список. Как бы вы стали реализовывать свой Форт? Взяли бы какую-нить готовую реализацию и жёстко отрефакторили? Какую именно? Их много. На какой стандарт Форта нужно ориентироваться в первую очередь? FORTH-77? FORTH-83? ANSI?

Lethargeek
06.02.2017, 02:10
Прошу желающих высказаться каким должен быть Форт для ZX
Всяким разным - всё зависит от того, как на нём планируется писать (размер и % примитивов, глубина вложения процедур).


Нужна возможность порождать прямой шитый код - для компактности (вызов слова будет занимать 2 байта - адрес слова) и подпрограммный код - для скорости (как в HL ZX Forth).
См. выше, всё от стиля програмирования зависит. Прямой шитый иногда может оказаться быстрей подпрограммного.


Обязательно нужен целевой компилятор со смарт-линкером, чтобы в отчуждаемую (stand-alone) программу включались только необходимые слова, а не всё ядро.
"Компилятор" (даже оптимизирующий) в принципе воможен даже как набор макрух для ассемблера.
Я когда-то экспериментировал в ужасме на эту тему, но забросил за недостатком времени.


На какой стандарт Форта нужно ориентироваться в первую очередь? FORTH-77? FORTH-83? ANSI?
Как любой настоящий фортер - придумай свой (лучше несколько))) :v2_dizzy_roll:

Oleg N. Cher
06.02.2017, 02:30
Я согласен, прямой шитый код иногда может оказаться быстрей подпрограммного. Это когда NEXT сразу передаёт управление на следующее слово одной асмовской командой, такой случай описан у Черезова (каждется?) по мере развития его SP-Forth. Он экспериментировал и пробовал разные виды шитого кода, и версия с прямым борола по скорости подпрограммный. Но это на процессоре x86.

Однако я очень сильно сомневаюсь, что прямой шитый код будет быстрее подпрограммного именно на процессорах Z80/i8080.

- - - Добавлено - - -

Обсуждение начато, отчасти, для того, чтобы выявить заинтересованных и сопоставить с ними видение, вектор развития Форта для ZX. Чтобы не делать мёртвый, никому не интересный проект.

shurik-ua
06.02.2017, 02:34
На скорпионе прям в ПЗУ прошит Форт или его разновидность.

Patison
06.02.2017, 09:51
Я не так давно на FPGA Altera MAX10 сделал 16/32 разрядный FORTH SOFT-процессор с небольшим количеством периферии. В качестве прототипа взял процессор J1 и доработал его систему команд. Долго переделывал прошивку Форта, добавляя и удаляя оттуда слова. И этот процесс еще не завершен полностью. Форт уместился приблизительно в 6000 16 битных слов во встроенной памяти микросхемы. В ней может разместиться одновременно около 10 таких процессоров с периферией и памятью каждого процессора 16 кбайта. Процессоры могут работать на частоте до 110 мгц. Каждая команда процессора выполняется за один такт. Глубина стеков сейчас по 32 слова, но ее можно легко изменить.
Но... Я почему-то испытываю определенный дискомфорт при работе с Фортом и пытаюсь найти аналогичный процессор, поддерживающий стандартный кросс-компилятор С. Кое-что нашел. Однако Форт имеет и очень интересные черты, которые привлекают меня до сих пор. В общем, есть некоторые соображения и по форту и вокруг него в т.ч. относительно применения Форта на процессорах классической архитектуры и в частности на Z80. Если позволите, позже попробую описать эти самые соображения.

UA3MQJ
06.02.2017, 10:22
А как быть тем, кто форт ни разу не пробовал, но только читал про него? Можно было бы что-то и посоветовать. Но для этого нужен хоть какой-то опыт. Надо с чего-то начинать.

Shiny
06.02.2017, 11:38
А как быть тем, кто форт ни разу не пробовал, но только читал про него? Можно было бы что-то и посоветовать

почитать что-нибудь (http://www.oocities.org/matteo_vitturi/english/spectraforth2.htm), нет?

Бука
06.02.2017, 11:50
Пробовал пару лет назад освоить Форт - понял что рискую взорвать себе мозг и отступил...

"Йоды джедаев магистра речи тайна раскрыта — на Форте просто старый программер он есть" ;)

PATHNK
06.02.2017, 13:45
Брошюра или книга была по форту, но впечатление этот язык не произвел.
Можно почитать руководство пользователя к компьютеру Jupiter Ace (https://www.jupiter-ace.co.uk/usermanual.html).

Oleg N. Cher
06.02.2017, 15:01
Вот! Аналогичная фигня, и я под этим подпишусь:

Но... Я почему-то испытываю определенный дискомфорт при работе с Фортом и пытаюсь найти аналогичный процессор, поддерживающий стандартный кросс-компилятор С. Кое-что нашел. Однако Форт имеет и очень интересные черты, которые привлекают меня до сих пор.Я ещё тешу себя, что, может быть, можно разработать словари для безопасной работы, уйти от стека вообще, для низкого уровня сделать работу с регистрами, которая может выглядеть, например, так:

lowlevel B + C => [HL] HL++ D + E => [HL]Форт хорош тем, что позволяет создавать легко макро-языки. Но это безобразие, что в любой прикладной программе (если писать традиционно) первый попавшийся случай некорректной работы с ! приведёт к загадочному чёрному экрану. Вот и думаю: Форт - это язык для машины, а не для человека-кодера, привыкшего к комфорту. А вот в качестве машинного языка он действительно весьма интересен. Припоминаю, Кладов создал свою стековую мини-машину с Фортоподобным языком, и транслировал в её байт-код программы на Паскале, за счёт чего добился более плотной упаковки кода (его Фортовый байт-код компактнее, чем натив для 80x86).


В общем, есть некоторые соображения и по форту и вокруг него в т.ч. относительно применения Форта на процессорах классической архитектуры и в частности на Z80. Если позволите, позже попробую описать эти самые соображения.Конечно позволим!

Lethargeek
06.02.2017, 16:58
Я согласен, прямой шитый код иногда может оказаться быстрей подпрограммного. Это когда NEXT сразу передаёт управление на следующее слово одной асмовской командой, такой случай описан у Черезова (каждется?) по мере развития его SP-Forth. Он экспериментировал и пробовал разные виды шитого кода, и версия с прямым борола по скорости подпрограммный. Но это на процессоре x86.
на z80 тоже есть одна такая асмовская команда - ret :)
правда, именно для форта применить сложно, оба стека надо делать программными
этот трюк больше для специфического шитого кода (динамическая генерация например)

насчёт (псевдо)фортокомпилятора для z80 у меня была такая задумка
стек параметров - аппаратный стек, причём верхнее число храним в регистре hl
стек возвратов - как-нибудь программно организуем, вызов относительно медленный
то есть схема ради скорости выполнения длинных цепочек примитивов прежде всего
по возможности примитивы не вызывать, а вставлять короткий код напрямую
только процедуры и сложные и длинные примитивы делать через call
(и возможно, в обрамлении вспомогательных коротких команд)
вызываемая процедура с адресом возврата в СП будет разбираться сама

то есть твой пример:
2 dup + .
компилируется в:

push hl: ld hl,2: push hl: pop de: add hl,de: call DOT - без оптимизации
push hl: ld hl,4: call DOT - c максимальной оптимизацией
а еще хороший оптимизатор сможет верхнее число держать не в hl, а как там по ходу дела получится

- - - Добавлено - - -


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

- - - Добавлено - - -

я по этой книжке врубался в форт:
http://publ.lib.ru/ARCHIVES/S/SEMENOV_Yuriy_Alekseevich/_Semenov_Yu.A..html
там есть даже исходники простого интерпретатора для пц

Oleg N. Cher
06.02.2017, 18:09
на z80 тоже есть одна такая асмовская команда - retДа, сам думал о таком её применении.
Но увы, тогда придётся отказаться от прерываний и работать всегда только в режиме DI, иначе первое же прерывание испортит байт-код.

Так что указателем на программный код быть, видимо, регистру IX:

LD L,(IX+0)
INC IX
LD H,(IX+0)
INC IX
JP (HL)
В HL ZX Forth оба стека - и возвратов, и операндов - аппаратные. Там есть слово для переключения стеков, если правильно помню, STKSWAP. При этом переключение стеков относительно медленное - адрес неактивного стека хранится в переменной.

А можно адрес стека операций хранить в IX, а стека возврата - в IY.

Lethargeek
06.02.2017, 18:53
Но увы, тогда придётся отказаться от прерываний и работать всегда только в режиме DI, иначе первое же прерывание испортит байт-код.
необязательно, сам код может быть завязан на прерывания через "yield"


Так что указателем на программный код быть, видимо, регистру IX:
чем тебе PC не нравится в этой роли? :)


В HL ZX Forth оба стека - и возвратов, и операндов - аппаратные. Там есть слово для переключения стеков, если правильно помню, STKSWAP. При этом переключение стеков относительно медленное - адрес неактивного стека хранится в переменной.
это значит - оба НЕаппаратные, и на мой первый взгляд весьма неэффективно при компиляции


А можно адрес стека операций хранить в IX, а стека возврата - в IY.
если целью ставить (при неплохой компактности) максимальное быстродействие, лучше вовсе избегать операций со стеком возвратов
так, если call-процедура не вызывает другие процедуры сама, можно сделать что-то наподобие pop ix на входе jp(ix) в конце
или как-нибудь еще по контексту

Raydac
06.02.2017, 20:20
сделай кросс компилятор forth а-ля http://forth.ru/smal32.html и с поддержкой его команд и все будут рады

Oleg N. Cher
06.02.2017, 20:59
необязательно, сам код может быть завязан на прерывания через "yield"А это как?


чем тебе PC не нравится в этой роли? :)PC - как указатель на шитый код? :-)


это значит - оба НЕаппаратные, и на мой первый взгляд весьма неэффективно при компиляцииВот именно, что как раз оба аппаратные. Потому что активный стек адресуется через SP, и работа с ними происходит с помощью команд PUSH/POP, в переменной только хранится адрес другого стека и меняется местами с SP при вызове слова STKSWAP.


так, если call-процедура не вызывает другие процедуры сама, можно сделать что-то наподобие pop ix на входе jp(ix) в конце
или как-нибудь еще по контекстуНу да, что-то такое можно придумать.

Мне кажется, сложная оптимизация Форта, о которой ты говорил сейчас и ранее, это и есть самый камень преткновения. Здесь всё очень сложно реализовать. Надо заводить список слов, которые будут "разворачиваться" в прямой код (свёртка констант, стековые операции). Мысль использовать HL в качестве верхушки стека - здравая, сам думал об этом. Но я бы пошёл ещё дальше - ушёл от стека вообще.

Легко сделать примитивненький транслятор Форта с банальным шитым кодом, на основе любого из готовых Фортов для Z80/i8080, но вряд ли на нём сразу кинутся писать игры и всё остальное. Аудитория будет маловата. А в принципе и с хорошим оптимизатором он, сдаётся мне, мало кого заинтересует...

Shiny
06.02.2017, 21:29
насчет реализации ret: не знаю, уместно или нет, но пришлось использовать другое решение:

я адаптировал для Amstrad CPC музыкальный плеер. Необходимо было вызывать процедуру записи данных в AY. Но плеер использовал стек, поэтому call writeAY не прокатил бы.
Вышел вот такой изврат:


LD BC,NN
LD IX,BACK1
JP WRITEAY
BACK1:

...
WRITEAY:
;несколько действий
JP(IX)

Lethargeek
06.02.2017, 22:13
А это как?
фортокод вызывается из обработчика (чисто ради подстраховки после di)
делает что может в кадре успеть (предварительно по тактам прикинуть грубо)
после спецкомандой запоминает текущий указатель в памяти и ei:halt


PC - как указатель на шитый код? :-)
на подпрограммный с прицелом на дальнейшую компиляцию
если речь об играх, так ли нужен именно шитый код, важней скорость, а разница в размерах невелика
между прочим, твой примерчик шитым кушает 10 байт, мой (который без оптимизации) - тоже 10 ;)


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


Мне кажется, сложная оптимизация Форта, о которой ты говорил сейчас и ранее, это и есть самый камень преткновения. Здесь всё очень сложно реализовать.
совсем сложную с наскока необязательно, для начала "склеивать" 2-3 фортопримитива последних намного проще


Но я бы пошёл ещё дальше - ушёл от стека вообще.
но тогда и из этой темы уйти придётся :)

svofski
06.02.2017, 23:50
Советую обратить внимание на DX-Forth для 8080: http://dxforth.netbay.com.au/
В принципе он для CP/M, но не думаю, что перенести его на другую платформу окажется чем-то неподъемным. Это не какая-то странная древняя система, а вполне современный Форт не хуже gforth. Код открыт, последняя версия датирована октябрем 2016 года. Умеет генерировать запускаемые файлы, при этом оптимизируя словарь. Автор охотно общается и дает крайне полезные советы. Огромный ему респект.

Oleg N. Cher
07.02.2017, 02:17
фортокод вызывается из обработчика (чисто ради подстраховки после di) делает что может в кадре успеть (предварительно по тактам прикинуть грубо) после спецкомандой запоминает текущий указатель в памяти и ei:haltИнтересная идея, надо обдумать.


но тогда и из этой темы уйти придётся :)Ну зачем же. Говорим Форт - подразумеваем стек? ;-) А я там дал примерчик как можно на регистрах работать. И мне жаль, что никто до сих пор не ушёл от стека. Идея Форт-системы - превосходна. Так просто порождать новые проблемно-ориентированные языки. Но все они остаются опасными, потому что есть ! , @ HERE и ALLOT. И вот то, что остались на древних примитивах и выворачивании с их помощью мозга при кодинге - плохо, я считаю. Развивать Форт-идеологию нужно именно в сторону ухода от низкоуровневых примитивов. Никто не говорит, чтобы от них избавиться совсем. Но, по крайней мере, уменьшить их использование до задач низкого уровня (примерно как псевдомодуль SYSTEM в Обероне).

Lethargeek
07.02.2017, 05:28
Ну зачем же. Говорим Форт - подразумеваем стек?
именно, два стека - основной признак (а вот шитый код как раз и необязателен, что форт-компиляторы демонстрируют)


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


И мне жаль, что никто до сих пор не ушёл от стека.
как никто, а бейсик-вильнюс на шитом коде? :p


Идея Форт-системы - превосходна. Так просто порождать новые проблемно-ориентированные языки. Но все они остаются опасными, потому что есть ! , @ HERE и ALLOT.
а при чём тут стековость языка? есть же современный безопасный стековый Factor


Развивать Форт-идеологию нужно именно в сторону ухода от низкоуровневых примитивов. Никто не говорит, чтобы от них избавиться совсем. Но, по крайней мере, уменьшить их использование до задач низкого уровня
какой смысл заниматься этим на восьмибитке? чтобы тормозило идейно-правильно? :D

Oleg N. Cher
07.02.2017, 13:31
Всё верно, смысла нет.

- - - Добавлено - - -

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

Или "выстрелил точечно, где смог". ;-)

svofski
07.02.2017, 14:37
Не все приложения требуют ассемблерной скорости, а сложные алгоритмы разрабатывать на Форте гораздо проще, чем на ассемблере и, чем примитивней машина, тем эта разница ощутимей. На 8080 Форт заметно обгоняет Си по компактности кода. Скорость ии... теоретически было бы можно догнать хотя бы до хорошего процента от Си, особенно учитывая противоестественную похабность компиляторов Си для 8-битных машин, но на практике никто этого по-моему не сделал. Есть TCOM 2.5, который предендует, но его версия для 8080 атомно глючнá (если кто-нибудь сможет им скомпилировать что-то реальное, мне было бы интересно посмотреть на процесс).

Существуют расширения Форта, которые допускают именованные аргументы и локальные переменные. Но это отступление от идеи о том, что слова должны быть настолько просты, что и так все понятно :) Поскольку язык фактически обязывает делать слова короткими, модульное тестирование тоже организовывать проще. Вообще стековость Форта это такая красная тряпка, нелюбители Форта на нее хмурятся, а на деле она не сильно отличается от стековости Си: точно так же аргументы и локальные переменные ложатся на стек, только программируя на Форте приходится это осознавать.

Примеры коммерческого Форта в жизни: https://www.forth.com/resources/forth-apps/ и в частности https://www.forth.com/resources/space-applications/

Raydac
07.02.2017, 16:11
не надо пытаться улучшать форт, сначала просто сделали бы нормальный кросс колмпилятор forth-83 для разных осей и что бы z80 код билдил, не надо пытаться рожать "безстековый форт" или как то улучшать добавляя сахар, он неплох такой какой есть

Oleg N. Cher
07.02.2017, 19:52
Кому что интересно, Raydac.

Я оцениваю потенциал Форта для интересной мне области - разработки игр для ZX - низко. Просто не наберётся критическая масса - те самые полтора программиста ;-) Проблема та же, что и у Оберона. Тем более некому разрабатывать нормальный кросс-компилятор Forth-83 для разных осей.

Но интересно было почитать, что кто написал в этой теме.

Smalovsky
07.02.2017, 20:09
Оффтоп.
Интересует тема разработки для спектрума на яву.
Хотел бы узнать список игр разработанных на скомпилированном и интерпретируемом бейсиках с ассемблерными вставками.
Бейсики должны быть нативными.

goodboy
07.02.2017, 20:12
Хотел бы узнать список игр разработанных на скомпилированном и интерпретируемом бейсиках с ассемблерными вставками.
смотри игры от ShawBrothers и стратегии от astros
(компилированный бейсик)

Shiny
07.02.2017, 20:56
Zeb Loops - Boriel+бипер. Исходники уже в продаже.

Oleg N. Cher
07.02.2017, 21:02
Хотел бы узнать список игр разработанных на скомпилированном и интерпретируемом бейсиках с ассемблерными вставками.Подкидной дурак (http://www.worldofspectrum.org/infoseekid.cgi?id=0012827) (c) Copperfeet на Laser Basic
Invader Cube (http://www.worldofspectrum.org/infoseekid.cgi?id=0003574) из поставки Mega Basic
Ещё мне попадался простенький тетрис, скомпилированный каким-то MCoder2, компилятор был к нему пристёгнут.

Если подобные скомпилированные на Бейсике игры имеют внутри какую-то сигнатуру, то их можно поискать скопом простым поиском этой сигнатуры в .tap или .trd-файлах.


Бейсики должны быть нативными.А зачем такое ограничение? Boriel's вроде тоже штука достойная) Или на нём слишком много игр написано, все не расковырять? ;-)

Shiny
07.02.2017, 21:10
Boriel's вроде тоже штука достойная)

Еще одна печальная история: я портировал Zen Loops на Enterprise128, прямое копирование кода Randomize и Random(N) не покатит, потому что включены вызов ПЗУ и калькулятора.

Oleg N. Cher
07.02.2017, 22:26
Еще одна печальная история: я портировал Zen Loops на Enterprise128, прямое копирование кода Randomize и Random(N) не покатит, потому что включены вызов ПЗУ и калькулятора.Т.е. Вы хотите сказать, что Boriel'ные Randomize и Random(N) используют калькулятор Спектрума? Ну так это вроде не проблема для портировщика, у нас недавно была тема про случайные числа (http://zx-pk.ru/threads/27291-generatsiya-sluchajnykh-chisel-v-zadannom-diapazone.html).

Smalovsky
07.02.2017, 22:29
Посмотрел шоунбразеров. Игры по скорости неплохие. Но в них много, скорее всего, указательной(в каком-то смысле) арифметики типа n*j+k для двумерных массивов или n*j для одномерных(плюс код для записи-чтения значений из/в памяти), так как компиляторы бейсика не поддерживают массивов.

Shiny
08.02.2017, 09:20
Т.е. Вы хотите сказать, что Boriel'ные Randomize и Random(N) используют калькулятор Спектрума?

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

Shiny
09.02.2017, 08:55
кстати, о языке. Попалось в интернетах реализация Dissociated press (https://en.wikipedia.org/wiki/Dissociated_press):


6 constant mrate
6 constant mlen
4000 constant rbs
create rb rbs 4 + allot
rb codesegment rbs bl mfill
variable r 0 r !

: |r+| r @ 1+ dup rbs > if drop 1 then r ! ; ( -- )
: !r+ rb r @ + c! |r+| ; ( c -- )

use ..\random.frl
: mung r @ 1+ random rb + mlen random type ;
: mung? mrate dup random = if mung then ;

use ..\dos.frl
forget &open
variable cb
: ?bye ifnot bye then ;
: gc 0 cb codesegment 1 fread ?bye ?bye cb c@ ; ( -- c )

: dp begin gc dup !r+ emit mung? again ;

false messages ! false debug !
' bye errorproc !
build dp.com


Было бы интересно реализовать раритет.