В качестве одного из менее популярных языков трудно найти литературу по авангарду хакерства постскриптума. Итак, какие открытия сделали игроки в гольф, чтобы использовать стековую модель (или другие особенности) для преодоления врожденного многословия Postscript?
14
Ответы:
Встроенный декодер
Программа Postscript обладает уникальной (?) Способностью считывать текст своей программы в виде данных. Это , как правило , используется
image
оператор , который принимает конверсию-процедуру передачи данных в качестве входных данных, и эта процедура часто используетcurrentfile
следуютreadline
,readstring
илиreadhexstring
. Но если смотреть по-другому,image
это просто еще один оператор цикла, поэтому любой цикл может читать вперед . Примером является эмулятор линейного принтера из Зеленой книги.С использованием
token
оператора вызывает сканер для файла или строки, вытягивая число или пробел - (или иначе -: см. Другой ответ) - неограниченное имя.Простой PS-интерпретатор в PS:
Бинарный оператор струнного декодера
Поскольку я не могу заставить работать необработанные двоичные токены (см. Другой ответ), я использовал идею «встроенного декодирования», чтобы использовать механизм двоичных токенов для упаковки кода в 8-битные строки, а затем манипулировать и разбирать команды из строки на лету .
.
Процедура занимает несколько из стека и вставляет его в качестве второго байта в строке два байта, первый байт являются префикс байтами для двоичных маркеров, который определяет исполняемое имя системы. Мы сохраняем байт в шестнадцатеричной строке, используя правило сканера, согласно которому нечетное число полубайтов в шестнадцатеричной строке дополняется дополнительным полубайтом 0, поэтому 3 шестнадцатеричных полубайта дают 2-байтовую строку. Затем строка помечается как исполняемая иexec
вызывается, с помощью которой запускается сканер, выдается имя требуемой исполняемой системы, а затем загружается имя и выполняется оператор. Это$
делается для каждого байта строки в стеке, используя.
процедуру дважды , один раз в качестве тела цикла, а затем для выполнения оператора циклаforall
по номеру.Более компактно эти процедуры выглядят так:
Таким образом, 55 символов покупают двоичные строки токенов. Или, 6 (может быть 7, если прекратить его с пробелом) символами, вы можете загрузить библиотеку G с
(G)run
которой определяет.
и ,$
как указано выше (+ несколько других , чтобы расширить диапазон ASCII-кодов достижима).Далее проиллюстрирован мой ответ на кроссворд .
источник
Когда генерация графического вывода и вывода на консоль не имеет значения, используйте
=
вместоpop
.источник
Заменить шестнадцатеричные строки на ASCII85
Возможно старые новости, но я только что узнал. :)
Вы можете сделать это, используя интерпретатор postscript в интерактивном режиме с фильтром кодирования и вырезанием и вставкой. Но я собираюсь показать, как использовать,
dc
чтобы сделать это «вручную».Итак, вот шестнадцатеричная строка. Разобьем его на 4 байта.
Запуская dc, мы вводим их как 32-битные (без знака) числа с порядком байтов в порядке байтов. Затем mod -off base-85 цифр (должно быть 5, пока вы не получите 0).
Заполнение последнего фрагмента
00 00
, приводит к (десятичному), пропуская то же количество байтов, которое мы дополнили.Добавьте 33, чтобы перейти в диапазон для печати ASCII и пуф! Ascii85.
Оберните это в
<~
...~>
, и PostScript уровня 2 может получить доступ к 8-битным данным, дешевле чем шестнадцатеричный.источник
Вот быстрый способ: оберните несколько определений,
[...>>begin
чтобы исключить ключевое словоdef
(nb.[
- то же самое, что и<<
).Итак, помните: больше, чем
тридва ... собираться вместе ! ;)источник
/a 1 def/b 2 def/c 3 def
с<</a 1/b 2/c 3>>begin
. Нам нужно больше места для определения.[/a 1/b 2/c 3>>begin
/a{pop 2 mul}def
или\b[2 3]def
, тоdef
стоит только 3 -х символов, а не 4.В то время как большинство постскрипта операторов синтаксически идентификаторы (и , следовательно , должен быть пробела (или otherwise-) с разделителями), имена
[
,]
,<<
, и>>
являются саморазграничны и сканер обнаружит их без вмешательства пространства. По той же причине вы не можете ссылаться на эти имена с обычным/literal
синтаксисом (например,/[
это два токена: пустое литеральное имя, эквивалентное()cvn cvlit
и исполняемое имя,[
эквивалентное([)cvn cvx exec
).Чтобы переопределить эти имена, которые не могут быть упомянуты по имени, мы можем использовать строки, которые неявно преобразуются в имена при использовании в качестве ключей в словаре (удобно!).
Этот пример иллюстрирует злоупотребление этими операторами для выполнения арифметики.
Также
<<
и[
(иmark
) все означают одно и то же.Мой собственный интерпретатор постскриптума xpost также предоставляет правую фигурную скобку с некоторыми ограничениями. обсуждение
источник
/
завершает предыдущий токен, так что вам не нужно пробела перед ним.Фактор многократного использования длинных имен операторов
Если вы уже используете
<<>>begin
словарь,/?{}
на переопределение накладываются постоянные накладные расходы в 4 символа. Таким образом, оператор длины n, повторенный N раз, приведет к изменению числа символов(4 + n ) - ( N * ( n - 1)).
Установка этой формулы равной 0 дает уравнение точки безубыточности . Из этого мы можем решить для каждой переменной в терминах другой, давая
n = - ( N - 4) / (1 - N ) и
N = (4 + n ) / ( n - 1).
Нет, мы можем ответить на такие вопросы, как «Для скольких видов использования« печати »стоит сокращаться?» n = 5, поэтому N = 9/4. Возьмите потолок, так как вы не можете эффективно назвать печать 1/4 раза. Итак, 3. 3 использует. И действительно,
(
<<>>begin
конечно, если вы уже заплатили за активацию определения).Разумеется, двоичные токены вызывают подобные споры, давая вам первые 255 имен из таблицы системных имен в виде 2 байтов: 0x92, 0x ??. И двоичные токены также являются саморазграничивающими, не требующими пробелов до или после, поскольку старший бит первого байта находится вне диапазона ascii.
источник
Двоичные токены
Для окончательной на молнию программы PostScript , что последний рубеж двоичные маркеры , которые позволяют удалить длинные имена операторов полностью, за счет более не имеющий ASCII-чистой программы.
Итак, начиная с компактного блока кода PostScript
Мы ищем все имена в конце PLRM (Приложение F, стр. 795-797)
А затем введите их с префиксом
146
(десятичного) байта. vim help для ввода произвольных байтовЗатем в vim сжатый файл можно набрать напрямую, поэтому:
... Вы должны ввести пробел здесь, чтобы завершить
^V
-62 и начать 1, но вы можете сделать резервную копию и удалить его позже ...... необходимо ввести пробел здесь, чтобы завершить
^V
-85 и начать 1, но вы можете сделать резервную копию и удалить его позже ...... 3-я цифра 3-значного кода завершает ввод байта, поэтому следующее
0
здесь нормально, удобно ...Который будет выглядеть на экране (в vim):
Эту часто можно полностью опустить, если целью является просто показать картинку. Ghostscript рисует большинство вещей на экране без необходимости
showpage
.[ Это на самом деле не работает. Ghostscript дает мне
undefined
иsyntaxerror
за эти жетоны. Может быть, есть какой-то режим, который мне нужно включить. ]источник
Изменить отрицательные броски на положительные
Отрицательные броски всегда можно заменить положительными бросками .
источник
3 -1 roll
или3 2 roll
? В моей ментальной модели первое должно быть более эффективным, потому что это занимает всего один ход. Правильна ли моя ментальная модель?roll
оператора.Используйте мою библиотеку G
https://github.com/luser-dr00g/G
Это текстовый файл. Без расширения, для кратчайшего синтаксиса, чтобы загрузить его.
Это позволяет эту программу Sierpinksi Triangle с 20 символами
переписать в 151 байт как
рабочий файл с комментариями
Использование функции сокращенных системных имен
1(G)run
полностью снимает бремя длинных имен операторов. Имя оператора должно быть достаточно длинным, чтобы отличить его от других.Так
add
становитсяad
mul
становитсяmu
index
становитсяi
Используйте Приложение F PLRM для стандартной таблицы имен операторов.
И функция Строки Оператора доступна, даже если сокращенные имена не выбраны. Голая библиотека имеет «базовый уровень», выбранный простым добавлением
(G)run
без дополнительных украшений.Базовый уровень включает новую функцию,
.
которая принимает целочисленный код для оператора (то же самое Приложение F, упомянутое выше) и выполняет его.Новая функция
$
перебирает строку и вызывает.
каждую. Таким образом, код ascii напрямую выбирает оператора по номеру.Новая функция
@
позволяет вам добраться до нижней части таблицы в Приложении F, обрабатывая символ пробела (Ascii 0x20) как 0.Новая функция
#
позволяет вам подняться дальше в таблицу, сначала добавив 95 (0x5F), чтобы символ пробела 0x20 обрабатывался как 127 (0x7F), самый следующий код после последнего печатаемого символа ascii~
126 (0x7E).Две новые функции
!
позволяют получить доступ к глубоко вложенной структуре массивов и / или диктов с помощью массива индексов / ключей, а не утомительных выражений многихget
(иput
) операторов.(G)run
7 символов покупает базовый уровень.1(G)run
8 символов покупает это И сокращенные системные имена.3(G)run $
9 символов сразу начинают блок неявной процедуры сканируя исходные строки до следующей пустой строки, и определяя первую строку как вызываемую процедуруA
, следующая строка определяется как вызываемая процедураB
и т. Д. Это должно удалить большинство изdef
s, необходимых для определения много вещей, без необходимости оборачивать их в словарь, и даже не давать им явно имена.источник