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. aodnosi 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 Apomocą 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 BCDkaż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, cokreś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 ajest „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 bjest 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?