TL;DR
C ++ - Vorlagen, Python-Einschlüsse, ... es gibt eine Sprachfunktion, die aufgrund der schwarzen Magie, die durch die zusätzliche Freiheit hervorgerufen wird, vollständig von selbst zerstört wurde.
Und hier erklären wir, dass sich ** go-template den Reihen der schwarzen Magie angeschlossen hat **.
Apropos go-template, es gibt ein starkes Bild einer Minisprache für Vorlagen wie "gins" HTML und "kubectls" Antwortformung (obwohl dies mit dieser Absicht im Namen ~~ gemacht wird). Folgendes kann ** alles möglich ** sein [^ 1].
Referenz (offiziell): template --GoDoc
Also habe ich versucht, das Verarbeitungssystem von brainf \ * ck, das das Tor zur Vollständigkeit von Turing darstellt, mit go-template (nur Standardfunktion / Syntax [^ 2] ohne Verwendung der Go-Sprache) zu implementieren.
Verwenden Sie kubectl
.
Fügen Sie den Quellcode von brainf \ * ck in die Manifestdatei von pod ein, und wenn Sie ihn mit kubectl
erhalten, verwenden Sie go-template zum Formen (= bewerten Sie mit brainf \ * ck Interpreter von go-template). Ich bin.
Repository: go-template-bf-interpreter
(Ich habe kubectl
verwendet, weil ich go-template zum ersten Mal mit kubectl
kannte. ~~ Ich schrieb am Anfang, dass" ich mit der HTML-Generation von gin
vertraut bin ", aber Airp tut mir leid ~~)
Da jeder Schlüssel und Wert (Zeichenkette) in "metadata.annotations" gespeichert werden kann, wird hier der Quellcode gespeichert. Lassen Sie uns auch die Standardeingabe für brainf \ * ck eingeben.
hello.yaml
metadata:
name: bf-source-pod
# add dummies to make annotations long enough to loop (see bf-interpreter.tpl for details)
annotations:
# used for bf stdin
input: ""
# bf source code
src: >
+++++++++[>++++++++>+++++++++++>+++>+<<<<-]>.>++.+++++++..+++.
>+++++.<<+++++++++++++++.>.+++.------.--------.>+.>+.
dummy1: dummy1
dummy2: dummy2
#...
Der Grund, warum ich viele Dummy-Schlüssel eingefügt habe, ist übrigens, die Anzahl der Schleifen des Interpreters zu erhöhen (später beschrieben).
Ich habe den helloworld-Code von Brainfuck Super Primer --Qiita verwendet.
Ich benutze den Pod-Container sowieso nicht, also ist alles in Ordnung. Vorerst habe ich ein alpines Bild gemacht, das schnell startet.
python
#Erstellen Sie einen k8s-Cluster(Ein Beispiel ist nett)
$ kind create cluster
#Erstellen Sie einen Pod mit dem obigen helloworld-Code
$ kubectl create -f hello.yaml
pod/bf-source-pod created
#Pod-Informationen(=Quellcode)Und sein Inhalt wird zum Dolmetscher-Mit Vorlage auswerten
$ kubectl get pods -o go-template-file=bf-interpreter.tpl
Hello World!
Die Implementierung des brainf \ * ck-Interpreters sieht folgendermaßen aus. ~~ Hölle einrücken. ~~ bf-interpreter.tpl
Im Folgenden werde ich die Tricks vorstellen, die ich verwendet habe.
Sie können den Raum außerhalb der Klammern füllen, indem Sie an beiden Enden von {{}} `` -` hinzufügen. Wenn Sie dies verwenden, werden alle Einrückungen und Zeilenumbrüche außerhalb von "{{}}" ignoriert. ** Erforderlich für die Lesbarkeit ** in der Go-Template-Programmierung. ** Wenn nicht angebracht, beginnt die Einzeilerbindung **.
withspace.tpl
{{if true}}
{{println "got it!"}}
{{else}}
{{println "no..."}}
{{end}}
Verschwendeter Speicherplatz wird so ausgegeben, wie er ist
kubectl get pods -o go-template-file=withspace.tpl
got it!
trimspace.tpl
{{- if true -}}
{{- println "got it!" -}}
{{- else -}}
{{- println "no..." -}}
{{- end -}}
Verschwendeter Raum verschwindet
$ kubectl get pods -o go-template-file=trimspace.tpl
got it!
brainf \ * ck benötigt eine while-Schleife. Quellcode Wird zum Parsen jedes Zeichens und zum Springen bei der Auswertung von "[", "]" verwendet.
Leider kann string
nicht mit range
iteriert werden.
Da die einzigen Literale, die mit go-template erstellt werden können, Konstanten sind, ist es nicht möglich, neue Arrays oder Maps zu erstellen.
python
$ kubectl get pods -o go-template --template '{{range $c := "abc"}}{{println $c}}{{end}}'
...
error: error executing template "{{range $c := \"abc\"}}{{println $c}}{{end}}": template: output:1:14: executing "output" at <"abc">: range can't iterate over abc
Daher verwenden wir die Pod-Informationen "metadata.annotations" ("map [string] string") für die Schleife in "range". Ein Dummy wird mit der Anmerkung gemischt, sodass sie 16 Mal wiederholt werden kann.
hello.yaml
metadata:
name: bf-source-pod
annotations:
# used for bf stdin
input: ""
# bf source code
src: >
+++++++++[>++++++++>+++++++++++>+++>+<<<<-]>.>++.+++++++..+++.
>+++++.<<+++++++++++++++.>.+++.------.--------.>+.>+.
dummy1: dummy1
dummy2: dummy2
#...
dummy14: dummy14
Durch die Verwendung dieser Schleife in mehreren Stufen werden die Speicherinitialisierung und das Parsen des Quellcodes durchgeführt.
bf-interpreter.tpl
{{- /*Karte ersetzen und Bereichsblock verwenden*/ -}}
{{- $Looper := (index .items 0).metadata.annotations -}}
{{- /*Speicherinitialisierung(len $Looper)^Füllen Sie 2 Bytes mit 0) */ -}}
{{- $memory := "" -}}
{{- range $Looper -}}
{{- range $Looper -}}
{{- $memory = print $memory "\x00" -}}
{{- end -}}
{{- end -}}
{{- /*Quellcode lesen(len $Looper)^Perspektive von 3 Buchstaben von Anfang an) */ -}}
{{- range $Looper -}}
{{- range $Looper -}}
{{- range $Looper -}}
{{- /* NOTE: exists is implemented only in k8s parser */ -}}
{{- if exists $Source (len $parsingBytePos) -}}
{{- $tokenByte := index $Source (len $parsingBytePos) -}}
{{- $token := printf "%c" $tokenByte -}}
{{- /*Token auswerten (weggelassen)*/ -}}
{{- /* increment pos */ -}}
{{- $parsingBytePos = print $parsingBytePos " " -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
Der Grund, warum es 16-mal wiederholt wird, ist übrigens die Verbesserung der Spezifikationen des Interpreters.
256byte
( $ Looper
2-stufige Schleife)4096 Zeichen
( $ Looper
3-stufige Schleife)Leider (zum zweiten Mal) verfügt go-template nicht über ganzzahlige Additions- / Subtraktionsfunktionen oder Operatoren. Bei der Aktualisierung von Speicherwerten und Zeigern muss brainf \ * ck jedoch addiert und subtrahiert werden.
Verwenden Sie also ** die Zeichenfolgenlänge anstelle einer Ganzzahl **. Die Länge der Zeichenkette kann durch Kombinieren und Schneiden geändert werden, und die Länge kann als Ganzzahl mit der Funktion "len" erhalten werden.
--Zusatz
inc.tpl
{{- /* go-Der Vorlagendruck entspricht Go's Sprint(Keine Nebenwirkungen) */ -}}
{{- $numStr := " " -}}
{{- println (len $numStr) -}}
{{- $numStr = print $numStr " " -}}
{{- println (len $numStr) -}}
python
$ kubectl get pods -o go-template-file=inc.tpl
1
2
--Subtraktion
dec.tpl
{{- $numStr := " " -}}
{{- println (len $numStr) -}}
{{- $numStr = slice $numStr 1 -}}
{{- println (len $numStr) -}}
python
$ kubectl get pods -o go-template-file=dec.tpl
1
0
Wie oben erwähnt, können Sie mit go-template kein Array erstellen. Es ist auch nicht möglich, nur die Elemente eines vorhandenen Objekts zu aktualisieren. In Zuweisungsausdrücken können nur Variablen r-Werte sein.
python
$ kubectl get pods -o go-template --template '{{(index .items 0) := "hoge"}}'
error: error parsing template {{(index .items 0) := "hoge"}}, template: output:1: unexpected ":=" in operand
Daher wird die Zeichenfolge als Speicher verwendet. In Go wird beim Indizieren einer Zeichenfolge die Zeichenfolge als "[] Byte" behandelt, sodass die Zeichenfolge selbst als Bytezeichenfolge betrachtet werden kann.
go Sprachindex
s := "abc"
fmt.Println([]byte(s)) // [97 98 99]
fmt.Println(s[0]) // 97
fmt.Println([]byte(s)[0]) // 97
Und wenn nur ein bestimmtes Byte in der Zeichenfolge mit "+" oder "-" usw. aktualisiert wird, wird "eine neue Speicherzeichenfolge erstellt, in der nur das Byte ersetzt wird".
bf-interpreter.tpl
{{- else if eq $token "+" -}}
{{- /* ...Nimmt den Wert der Referenzadresse heraus und erhöht ihn(Kürzung) */ -}}
{{- /*Speicheraktualisierung*/ -}}
{{- /*Durch neuen Speicher ersetzen, wobei nur die Referenzadresse ersetzt wird*/ -}}
{{- /*Speicher vor der Referenzadresse*/ -}}
{{- $former := slice $memory 0 (len $memoryPtr) -}}
{{- /*Speicher nach der Referenzadresse*/ -}}
{{- /* NOTE: (len (print $memoryPtr " ")Ist die Referenzadresse+1 */ -}}
{{- $latter := slice $memory (len (print $memoryPtr " ")) -}}
{{- /*Ersetzen (Wenn Sie den Bytewert so drucken, wie er ist, wird die Ganzzahl in eine Zeichenfolge konvertiert, sodass printf sie in das entsprechende ASCII-Codezeichen konvertiert.)*/ -}}
{{- $memory = print $former (printf "%c" $incrementedValue) $latter -}}
{{- end -}}
Dies ist die Einführung des go-template brainf \ * ck-Verarbeitungssystems.
** Lass uns die Template-Programmierung starten! ** **.
[^ 1]: Wenn man das betrachtet, fühlt es sich an wie "Sie können das mit erb machen!", Aber während erb jeden Ruby-Ausdruck schreiben kann, hat go-template eine unabhängige Grammatik (nur Skalare können erstellt werden und go-Standardfunktionen sind ebenfalls verfügbar). Es gibt eine Bindung, die Sie nicht so nennen können, wie sie ist ...
[^ 2]: Einige k8s ursprüngliche Go-Template-Funktionen (index
) werden verwendet. Die Implementierung ist hier
Recommended Posts