BlockScript - 535
{[B':=?0:B';=?0:B'}=?0:B'{=?,A!,A!d1c&:B'?=?,A!,A!2e&:B''=?,,A!d3c&:B{[B'0<?0:B
'9>?0:1}!?B'0-{[,g!?c'0-B10*d+A!:Bd]A!d3c&}!:B'#=?{[,10=?,]A!:A!}!:,A!Bb&}{[AC[
B]DB?[AB{[Bh&hbhn!}{[B[AB]C?1-eA!:b}&[C1=?E[C]FHc&B!:C2=?{G?D:E[C}!FHcI!:C3=?E[
C]B!:C'!=?G[ABC]Hc&dbh&D?b@I!B!:b@I!:C'&=?HB!:C'@=?FGDI!:C'[=?GF&HDI!:C']=?F[A]
HDI!:C',=?,B!:C'.=?G.FHDI!:C'a'z{[DC<?0:DB>?0:1}!?Ce-HA!B!:C'A'Ze!?F[B]Cg-dA!B!
:{C'+=?{[CB+}:C'-=?{[CB-}:C'*=?{[CB*}:C'/=?{[CB/}:C'%=?{[CB%}:C'<=?{[CB<}:C'>=?
{[CB>}:C'==?{[CB=}:0}!?H[A][B]Ge!B!:FHDI!:c},c!0ac&0&0&0bho!;
BlockScript - это тривиальный язык на основе стека спагетти, который я создал специально для этой задачи. Базовый интерпретатор - blockscript.c .
Пример программы (печатает первые 15 чисел Фибоначчи):
{[B?B10/A!B10%d&:0}
{[B0<?'-.0B-A!:{B?Bh!{[B?B[A]A!B[B]'0+.:}!:'0.}!10.}
{[B?Dd!DC+B1-CecA!:}
0 1 15d!
;
Интерпретатор считывает как исходный код, так и программный ввод со стандартного ввода в указанном порядке. Это означает, что для запуска интерпретатора внутри интерпретатора внутри интерпретатора просто скопируйте и вставьте:
# Level 1
{[B':=?0:B';=?0:B'}=?0:B'{=?,A!,A!d1c&:B'?=?,A!,A!2e&:B''=?,,A!d3c&:B{[B'0<?0:B
'9>?0:1}!?B'0-{[,g!?c'0-B10*d+A!:Bd]A!d3c&}!:B'#=?{[,10=?,]A!:A!}!:,A!Bb&}{[AC[
B]DB?[AB{[Bh&hbhn!}{[B[AB]C?1-eA!:b}&[C1=?E[C]FHc&B!:C2=?{G?D:E[C}!FHcI!:C3=?E[
C]B!:C'!=?G[ABC]Hc&dbh&D?b@I!B!:b@I!:C'&=?HB!:C'@=?FGDI!:C'[=?GF&HDI!:C']=?F[A]
HDI!:C',=?,B!:C'.=?G.FHDI!:C'a'z{[DC<?0:DB>?0:1}!?Ce-HA!B!:C'A'Ze!?F[B]Cg-dA!B!
:{C'+=?{[CB+}:C'-=?{[CB-}:C'*=?{[CB*}:C'/=?{[CB/}:C'%=?{[CB%}:C'<=?{[CB<}:C'>=?
{[CB>}:C'==?{[CB=}:0}!?H[A][B]Ge!B!:FHDI!:c},c!0ac&0&0&0bho!;
# Level 2
{[B':=?0:B';=?0:B'}=?0:B'{=?,A!,A!d1c&:B'?=?,A!,A!2e&:B''=?,,A!d3c&:B{[B'0<?0:B
'9>?0:1}!?B'0-{[,g!?c'0-B10*d+A!:Bd]A!d3c&}!:B'#=?{[,10=?,]A!:A!}!:,A!Bb&}{[AC[
B]DB?[AB{[Bh&hbhn!}{[B[AB]C?1-eA!:b}&[C1=?E[C]FHc&B!:C2=?{G?D:E[C}!FHcI!:C3=?E[
C]B!:C'!=?G[ABC]Hc&dbh&D?b@I!B!:b@I!:C'&=?HB!:C'@=?FGDI!:C'[=?GF&HDI!:C']=?F[A]
HDI!:C',=?,B!:C'.=?G.FHDI!:C'a'z{[DC<?0:DB>?0:1}!?Ce-HA!B!:C'A'Ze!?F[B]Cg-dA!B!
:{C'+=?{[CB+}:C'-=?{[CB-}:C'*=?{[CB*}:C'/=?{[CB/}:C'%=?{[CB%}:C'<=?{[CB<}:C'>=?
{[CB>}:C'==?{[CB=}:0}!?H[A][B]Ge!B!:FHDI!:c},c!0ac&0&0&0bho!;
# Level 3
{[B?B10/A!B10%d&:0}
{[B0<?'-.0B-A!:{B?Bh!{[B?B[A]A!B[B]'0+.:}!:'0.}!10.}
{[B?Dd!DC+B1-CecA!:}
0 1 15d!
;
Как и в фильме « Начало» , вы не можете пройти глубже трех уровней. Это не вопрос времени, а пространство. BlockScript утечка памяти обильно, и это связано с тем, как сам язык разработан.
Справочник по языку:
Получить переводчика здесь
В BlockScript «стек» не является массивом, который перезаписывается последующими операциями, к которым вы привыкли. На самом деле он реализован в виде неизменяемого связанного списка, и стек сохраняется в течение всей программы. Кроме того, ни один оператор (кроме @
) не удаляет значения из стека. Однако модификации стека влияют только на блок, в котором они происходят.
Выбор значения
a
через z
Извлеките 0-25-й предмет из стека и поместите его в стек. a
относится к заголовку или к последнему добавленному элементу стека.
A
через Z
Получите 0-25-й элемент текущего кадра и поместите его в стек.
[
Откройте «рамку», чтобы выбрать элементы из стековой ссылки (см. Ниже) в начале стека. [
не требует соответствия ]
, но рамки имеют лексическую область видимости. В BlockScript «область действия» определяется фигурными скобками ( {
... }
), которые образуют блоки. Таким образом, открытие кадра внутри блока не повлияет на код вне блока.
]
Закройте текущий кадр, вернувшись к предыдущему кадру (если есть).
Блоки
{
... }
Создайте «блок» и поместите его в стек. Внутри блока стек будет начинаться с того, что был до блока, за исключением того, что стек вызывающей стороны будет помещен сверху. Стеки являются постоянными и неизменными в BlockScript, поэтому блоки являются замыканиями. Идиома {[
означает открыть блок, затем открыть фрейм, чтобы начать выбор аргументов (используя A
сквозной Z
). Возвращаемое значение блока - это заголовок стека при }
достижении.
Пример:
'3 '2 '1 {[ b. d. f. B. C. D. A! } 'D 'C 'B d!;
Это печатает 123BCD123DCB123BCD123DCB…
. Буквы в нижнем регистре относятся к значениям стека, а буквы в верхнем регистре относятся к аргументам (потому что фрейм установлен в стеке вызывающей стороны). A!
берет голову вызывающего абонента (который гарантированно будет вызываемым блоком) и вызывает его. Если вам интересно, почему он обращается вспять BCD
каждый раз, это потому, что B. C. D.
эти аргументы передаются в обратном порядке прямо перед вызовом самого блока.
!
Вызовите блок. Вставьте возвращаемое значение в стек.
Ссылки на стек
&
Создайте ссылку на стек и поместите ее в стек. Думайте об этом как о «супер-минусах», так как он эффективно отбирает каждый элемент в стеке и формирует из него «кортеж». Идиомы &[
означает , что все a
, b
, c
упомянутые до настоящего времени могут быть доступны с A
, B
, C
(для оставшейся части блока или пока ]
не встретится).
Частично потому, что &
захватывает больше значений, чем обычно требуется, BlockScript утечка памяти по своей конструкции.
@
Переключиться на стек, на который указывает ссылка на стек a
. Этот оператор довольно странный, но самоинтерпретатор BlockScript использует его пару раз, чтобы избежать необходимости выдвигать одни и те же аргументы дважды. Эффекты @
(или любая стековая операция, в этом отношении) ограничены блоком, в котором он вызывается. Кроме того, на фрейм это не влияет @
, поэтому фрейм можно использовать для получения значений, которые вам нужны после переключения стеков.
Условное выражение
?
<на true> :
<на false>
Условное выражение, как и тернарный оператор в C. То есть, если a
"true" (т. Е. Не равно целому нулю), тогда делать <on true> , иначе делать <on false> .
I / O
Примечание: ввод и вывод выполняются в UTF-8. «Символ» - это целое число, соответствующее индексу Unicode.
,
Получите следующий символ ввода и поместите его в стек. Если достигнут конец ввода, вместо этого нажмите -1.
.
Выведите символ на верхушку стека.
Целочисленные / символьные литералы
Примечание. Целые числа и символы - это одно и то же в BlockScript.
арифметика
Эти операторы работают только с целочисленными значениями.
+
Вычислить b
+ a
(сдвигая результат, но не сбрасывая ни одно из значений).
-
Compute b
- a
.
*
Вычислить b
* a
.
/
Вычислить b
/ a
(целочисленное деление; округление до отрицательной бесконечности).
%
Вычислить b
% a
(целочисленный модуль; округляет до отрицательной бесконечности).
Реляционные операторы
Эти операторы работают только с целочисленными значениями.
<
Если b
меньше чем a
, нажмите 1, иначе нажмите 0.
>
=
Разнообразный
#
Комментарий к концу строки
- Программа должна заканчиваться
;
- Все остальные символы игнорируются.
/usr/bin/cat
) как насчет полноты по Тьюрингу?