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 ist eine einfache Spaghetti-Stack- basierte Sprache, die ich speziell für diese Herausforderung entwickelt habe. Der Basisinterpreter ist blockscript.c .
Beispielprogramm (druckt die ersten 15 Fibonacci-Zahlen):
{[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!
;
Der Interpreter liest sowohl den Quellcode als auch die Programmeingabe von der Standardeingabe in dieser Reihenfolge. Dies bedeutet, dass Sie zum Ausführen eines Interpreters innerhalb eines Interpreters einfach Folgendes kopieren und einfügen:
# 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!
;
Wie im Film Inception kann man nicht tiefer als drei Ebenen gehen. Es ist keine Frage der Zeit, sondern des Raums. BlockScript leckt den Speicher stark, und dies hängt davon ab, wie die Sprache selbst gestaltet ist.
Sprach-Referenz:
Holen Sie sich den Dolmetscher hier
In BlockScript ist der "Stapel" kein Array, das durch nachfolgende Operationen überschrieben wird, wie Sie es möglicherweise gewohnt sind. Es ist tatsächlich als unveränderliche verknüpfte Liste implementiert, und ein Stapel bleibt für die Dauer des Programms bestehen. Außerdem entfernt kein Operator (außer @
) Werte aus dem Stapel. Stapeländerungen wirken sich jedoch nur auf den Block aus, in dem sie auftreten.
Werteauswahl
a
durch z
Nimm den 0-25ten Gegenstand vom Stapel und lege ihn auf den Stapel. a
bezieht sich auf den Kopf oder das zuletzt geschobene Objekt des Stapels.
A
durch Z
Holen Sie sich das 0-25ste Element des aktuellen Frames und schieben Sie es auf den Stapel.
[
Öffnen Sie einen "Rahmen", um Elemente aus der Stapelreferenz (siehe unten) auf dem Stapelkopf auszuwählen. [
erfordert keine Übereinstimmung ]
, aber Frames haben einen lexikalischen Gültigkeitsbereich. In BlockScript wird "scope" durch geschweifte Klammern ( {
... }
) bestimmt, die Blöcke bilden. Daher hat das Öffnen eines Frames innerhalb eines Blocks keine Auswirkung auf den Code außerhalb des Blocks.
]
Schließen Sie das aktuelle Bild und kehren Sie zum vorherigen Bild zurück (falls vorhanden).
Blöcke
{
... }
Erstellen Sie einen "Block" und legen Sie ihn auf den Stapel. Innerhalb eines Blocks beginnt der Stapel an der Stelle, an der er sich vor dem Block befand, mit der Ausnahme, dass der Stapel des Aufrufers nach oben verschoben wird. Stacks sind in BlockScript persistent und unveränderlich, sodass Blöcke Closures sind. Die Redewendung {[
bedeutet, einen Block zu öffnen und dann einen Rahmen zu öffnen, um mit der Auswahl der Argumente zu beginnen (Verwendung von A
through Z
). Der Rückgabewert eines Blocks ist der Kopf des Stapels, wenn er }
erreicht ist.
Beispiel:
'3 '2 '1 {[ b. d. f. B. C. D. A! } 'D 'C 'B d!;
Dies wird gedruckt 123BCD123DCB123BCD123DCB…
. Die Kleinbuchstaben beziehen sich auf Stapelwerte, während sich die Großbuchstaben auf Argumente beziehen (da der Frame auf den Stapel des Aufrufers festgelegt ist). A!
Nimmt den Kopf des Aufrufers (der garantiert der aufgerufene Block ist) und ruft ihn auf. Wenn Sie sich fragen, warum es sich BCD
jedes Mal umkehrt , müssen Sie B. C. D.
diese Argumente in umgekehrter Reihenfolge eingeben, bevor der Block sich selbst aufruft.
!
Rufen Sie einen Block auf. Schieben Sie den Rückgabewert auf den Stapel.
Stapelreferenzen
&
Erstellen Sie eine Stapelreferenz und verschieben Sie sie in den Stapel. Stellen Sie sich dies als "Super-Nachteile" vor, da es effektiv jeden Gegenstand auf dem Stapel aufnimmt und daraus ein "Tupel" bildet. Die Redewendung &[
bedeutet das, was auch immera
, b
, c
genannt , bevor sie kann nun mit zugegriffen werden A
, B
, C
(für den Rest des Blockes oder bis ]
festgestellt wird).
Zum Teil, weil &
mehr Werte erfasst werden, als normalerweise benötigt werden, verliert BlockScript von Entwurf an Speicher.
@
Wechseln Sie zu dem Stapel, auf den die Stapelreferenz zeigt a
. Dieser Operator ist ziemlich seltsam, aber der BlockScript-Selbstinterpreter verwendet ihn ein paarmal, um zu vermeiden, dass dieselben Argumente zweimal übergeben werden müssen. Die Auswirkungen @
(oder im Übrigen jede Stapeloperation) sind auf den Block beschränkt, in dem sie aufgerufen werden. Außerdem bleibt der Frame davon unberührt @
, sodass Sie mit dem Frame die Werte erfassen können, die Sie nach dem Umschalten der Stapel benötigen.
Bedingter Ausdruck
?
<on true> :
<on false>
Bedingter Ausdruck, genau wie der ternäre Operator in C. Das heißt, wenn a
"wahr" ist (dh nicht gleich der ganzen Zahl Null ist), dann mache <on wahr> , andernfalls mache <auf falsch> .
I / O
Hinweis: Die Ein- und Ausgabe erfolgt in UTF-8. Ein "Zeichen" ist eine Ganzzahl, die einem Unicode-Index entspricht.
,
Holen Sie sich das nächste Zeichen der Eingabe und schieben Sie es auf den Stapel. Wenn das Ende der Eingabe erreicht ist, drücken Sie stattdessen -1.
.
Geben Sie das Zeichen auf dem Kopf des Stapels aus.
Ganzzahl- / Zeichenliterale
Hinweis: Ganzzahlen und Zeichen sind in BlockScript identisch.
Arithmetik
Diese Operatoren arbeiten nur mit ganzzahligen Werten.
+
Berechnen Sie b
+a
(drücke das Ergebnis, aber verwerfe keinen der beiden Werte).
-
Berechnen b
-a
.
*
Berechnen b
*a
.
/
Rechnen b
/a
(ganzzahlige Division; rundet gegen negative Unendlichkeit).
%
Berechnen Sie b
% a
(ganzzahliger Modul; rundet gegen negative Unendlichkeit).
Vergleichsoperatoren
Diese Operatoren arbeiten nur mit ganzzahligen Werten.
<
Wenn b
kleiner ist als a
, drücke 1, sonst drücke 0.
>
=
Sonstiges
#
Kommentar zum Zeilenende
- Das Programm muss mit enden
;
- Alle anderen Zeichen werden ignoriert.
/usr/bin/cat
) was ist mit Turing-Vollständigkeit?