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 to trywialny język oparty na stosach spaghetti , który stworzyłem specjalnie na to wyzwanie. Podstawowym tłumaczem jest blockcript.c .
Przykładowy program (drukuje pierwsze 15 liczb Fibonacciego):
{[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!
;
Interpreter odczytuje zarówno kod źródłowy, jak i program z standardowego wejścia, w tej kolejności. Oznacza to, że aby uruchomić tłumacza w tłumaczu, po prostu skopiuj i wklej:
# 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!
;
Podobnie jak w filmie Incepcja , nie można zejść głębiej niż trzy poziomy. To nie jest kwestia czasu, ale przestrzeni. BlockScript obficie wycieka pamięć, a to ma związek ze sposobem zaprojektowania samego języka.
Odniesienie językowe:
Uzyskaj tłumacza tutaj
W BlockScript „stos” nie jest tablicą, która jest zastępowana kolejnymi operacjami, do których możesz być przyzwyczajony. W rzeczywistości jest on implementowany jako niezmienna lista połączona, a stos utrzymuje się przez cały czas trwania programu. Ponadto żaden operator (oprócz @
) nie usuwa wartości ze stosu. Jednak modyfikacje stosu wpływają tylko na blok, w którym występują.
Wybór wartości
a
przez z
Weź 0-25 przedmiot ze stosu i pchnij go na stos. a
odnosi się do głowy lub ostatnio pchanego przedmiotu stosu.
A
przez Z
Pobierz 0-25 pozycję bieżącej klatki i pchnij ją na stos.
[
Otwórz „ramkę”, aby wybrać elementy z odnośnika stosu (patrz poniżej) na szczycie stosu. [
nie wymaga dopasowania ]
, ale ramki mają zasięg leksykalny. W BlockScript „zakres” jest określany przez nawiasy klamrowe ( {
... }
), które tworzą bloki. Zatem otwarcie ramki wewnątrz bloku nie będzie miało wpływu na kod poza blokiem.
]
Zamknij bieżącą ramkę, wracając do poprzedniej ramki (jeśli istnieje).
Bloki
{
... }
Utwórz „blok” i wepchnij go na stos. Wewnątrz bloku stos zacznie się od tego, co było przed blokiem, z wyjątkiem tego, że stos wywołującego zostanie przesunięty na wierzch. Stosy są trwałe i niezmienne w BlockScript, więc bloki są zamknięciami. Ten idiom {[
oznacza otwórz blok, a następnie otwórz ramkę, aby rozpocząć wybieranie argumentów (za A
pomocą Z
). Zwracana wartość bloku jest szczytem stosu, gdy }
zostanie osiągnięta.
Przykład:
'3 '2 '1 {[ b. d. f. B. C. D. A! } 'D 'C 'B d!;
To drukuje 123BCD123DCB123BCD123DCB…
. Małe litery odnoszą się do wartości stosu, podczas gdy duże litery odnoszą się do argumentów (ponieważ ramka jest ustawiona na stos wywołującego). A!
przejmuje głowę dzwoniącego (co z pewnością jest wywoływanym blokiem) i dzwoni do niego. Jeśli zastanawiasz się, dlaczego odwraca się za BCD
każdym razem, to dlatego, że B. C. D.
wypycha te argumenty w odwrotnej kolejności tuż przed wywołaniem samego bloku.
!
Zadzwoń na blok. Wciśnij wartość zwracaną na stos.
Referencje stosu
&
Utwórz odniesienie do stosu i popchnij je do stosu. Potraktuj to jako „super-przeciw”, ponieważ skutecznie bierze każdy przedmiot ze stosu i tworzy z niego „krotkę”. Idiomu &[
środki, niezależnie a
, b
, c
określone wcześniej mogą być dostępne z A
, B
, C
(w dalszej części bloku, aż ]
spotyka).
Po części dlatego, że &
przechwytuje więcej wartości, niż zwykle potrzebuje, BlockScript przecieka pamięć z założenia.
@
Przełącz się na stos wskazywany przez odniesienie do stosu a
. Ten operator jest dość dziwny, ale interpreter BlockScript korzysta z niego kilka razy, aby uniknąć konieczności dwukrotnego przekazywania tych samych argumentów. Efekty @
(lub dowolnej operacji stosu, jeśli o to chodzi) są ograniczone do bloku, w którym są wywoływane. Ramka pozostaje nienaruszona @
, więc można jej użyć do przechwytywania potrzebnych wartości po zmianie stosów.
Wyrażenie warunkowe
?
<on true> :
<on false>
Wyrażenie warunkowe, podobnie jak operator trójskładnikowy w C. To znaczy, jeśli a
jest „prawda” (to znaczy, że nie jest równe zeru całkowitemu), to wykonaj <na true> , w przeciwnym razie <na false> .
I / O
Uwaga: Wprowadzanie i wysyłanie odbywa się w UTF-8. „Znak” to liczba całkowita odpowiadająca indeksowi Unicode.
Liczby całkowite / literowe
Uwaga: Liczby całkowite i znaki są takie same w BlockScript.
Arytmetyka
Te operatory działają tylko na wartościach całkowitych.
+
Oblicz b
+ a
(wypychając wynik, ale nie odrzucając żadnej wartości).
-
Oblicz b
- a
.
*
Oblicz b
* a
.
/
Oblicz b
/ a
(dzielenie liczb całkowitych; zaokrągla w kierunku ujemnej nieskończoności).
%
Oblicz b
% a
(moduł całkowity; zaokrągla w kierunku ujemnej nieskończoności).
Operatorzy relacyjni
Te operatory działają tylko na wartościach całkowitych.
<
Jeśli b
jest mniejsze niż a
, naciśnij 1, w przeciwnym razie naciśnij 0.
>
=
Różne
#
Komentarz do końca linii
- Program musi kończyć się na
;
- Wszystkie pozostałe znaki są ignorowane.
/usr/bin/cat
) co z kompletnością Turinga?