Ist Go-Template perfekt zum Tuling? Ich habe ein Brainf * ck-Verarbeitungssystem gemacht

TL;DR

Einführung

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.

Wie es funktioniert

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 ~~)

Speichern Sie den Quellcode von brainf \ * ck in der Manifestdatei

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.

Ausführungsablauf

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!

go-template Programmiermuster (?)

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.

Fülle die Lücken aus

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!

Schleife

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.

Addition und Subtraktion

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

Speicheraktualisierung

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 -}}

abschließ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

Ist Go-Template perfekt zum Tuling? Ich habe ein Brainf * ck-Verarbeitungssystem gemacht
〇✕ Ich habe ein Spiel gemacht
Ist das ein Systemhandel?
Was ist ein Systemaufruf?
Ich habe einen Python-Text gemacht
Ich habe einen Zwietrachtbot gemacht
Ich habe einen lo-Befehl erstellt, der nützlicher ist als ls
i! i! ← Dies ist eine Formel
Ich habe eine C ++ - Lernseite erstellt
Ich habe einen Line-Bot mit Python gemacht!
Ich habe ein CUI-basiertes Übersetzungsskript erstellt (2)
Ich habe einen Wikipedia Gacha Bot gemacht
Ich habe mit Python eine Lotterie gemacht.
Ich habe ein CUI-basiertes Übersetzungsskript erstellt
Ich habe mit Python einen Daemon erstellt
Ich habe eine Art einfaches Bildverarbeitungswerkzeug in der Sprache Go erstellt.
[C Sprache] Meine Lokomotive ist zu langsam ~ Ich habe einen Sl-Befehl gegeben ~