Jaja, das ist dumm, ich weiß.
Trotzdem hier: v2.1 des FABSIL Interpreters.
Den Programmcode schreibt man in das Array $MEM eine Datei, die Daten mit Zeilenumbruch getrennt. Die möglichen Befehle stehen in dem längeren Kommentar.
Spoiler anzeigen
[autoit;FABSIL AutoIt based stupid interpreter Language
#include <Array.au3>
#include <File.au3>
Global $V=False, $MEM, $POINTER=0, $DIR=1
If $CMDLINE[0] Then
For $i = 1 To $CMDLINE[0]
Switch $CMDLINE[$i]
Case '-?','--help'
MsgBox(0x40000, 'FABSIL Commandline Options', _
'The only possible switch oder than -? / --help is -v / --versatile before the filename to output everything that''s happening')
Exit
Case '-v','--versatile'
$V = True
Case Else
If not FileExists($CMDLINE[$i]) Then Exit MsgBox(16,"FABSIL Error","File doesn't exist")
$FILE=$CMDLINE[$i]
EndSwitch
Next
Else
$FILE=FileOpenDialog("FABSIL Interpreter",@WorkingDir,"FABSIL File (*.fabsil)|All files (*.*)",1)
If not FileExists($FILE) Then Exit
EndIf
_FileReadToArray($FILE,$MEM)
If $MEM[0] = 0 Then Exit MsgBox(16,"FABSIL Error","The file is empty")
_ArrayDelete($MEM,0)
Func w($data)
;Write Data to the current pointer position
guarantee($POINTER)
$MEM[$POINTER] = $data
EndFunc
Func r()
;Read Data from the current pointer position
If UBound($MEM) > $POINTER Then Return $MEM[$POINTER]
Return 0
EndFunc
Func i()
$POINTER += $DIR
EndFunc
Func d()
$POINTER -= $DIR
EndFunc
#cs commands
NET = NextElement'sTarget
0 do nothing
1 put the element from the next in the element of the following element (1,2,3: put content from 2 in 3)
2 change the direction
3 quit
4 output the data of the next element ( 4,2: output $MEM[2]
5 input data into next element ( 5,2: input into $MEM[2]
6 jump to position of the next element
7 relative jump of the number of the next element
8 increment the element of the next element
9 decrement the element of the next element
10 if next elements target is zero, jump to the next but one. otherwise jump to next but second one.
#ce
;Interpreter:
ConsoleWrite(@CRLF & @CRLF)
While 1
Switch r()
Case 0;do nothing
V("Doing nothing" & @CRLF)
Case 1;put
i()
$from=r()
guarantee($from)
V("Copying from " & $POINTER & " (" & r() & ") to")
i()
guarantee(r())
$MEM[r()]=$MEM[$from]
V(r() & @CRLF)
Case 2;decrease
$DIR *= -1
V("Changing direction (now " & $DIR & ")" & @CRLF)
Case 3;quit
V("Exiting")
ConsoleWrite(@CRLF & @CRLF)
ExitLoop
Case 4;output
i()
V("Outputting the data from " & r() & ":" & @CRLF)
$oldP = $POINTER
guarantee($POINTER)
$POINTER = r()
ConsoleWrite(StringReplace(r(),"@CRLF",@CRLF))
$POINTER = $oldP
Case 5;input
i()
$oldP=$POINTER
$POINTER=r()
guarantee($POINTER)
V("Demanding input")
w(InputBox("Machine","Eingabe verlangt:"))
V(" (" & r() & ")" & @CRLF)
$POINTER=$oldP
Case 6;jumpto
i()
$POINTER = r()-$DIR
V("Jumping to " & $POINTER+$DIR & @CRLF)
If UBound($MEM) <= $POINTER Then
V("Exiting because of pointer beyond memory")
Exit
EndIf
Case 7;jumprelative
i()
V("Jumping " & r() & " steps forward (now ")
$POINTER += (r()-$DIR)
If UBound($MEM) <= $POINTER Then
V(@CRLF & "Exiting because of pointer beyond memory")
Exit
EndIf
V($POINTER+$DIR & ")" & @CRLF)
Case 8;increment
i()
$oldP=$POINTER
$POINTER=r()
guarantee($POINTER)
V("Incrementing " & $POINTER & " (now " & r()+1 & ")" & @CRLF)
w(r()+1)
$POINTER=$oldP
Case 9;decrement
i()
$oldP=$POINTER
$POINTER=r()
guarantee($POINTER)
V("Decrementing " & $POINTER & " (now " & r()-1 & ")" & @CRLF)
w(r()-1)
$POINTER=$oldP
Case 10
i()
V("If " & $MEM[r()] & "is zero (is")
If $MEM[r()] = 0 Then
i()
$POINTER = r()-$DIR
V("), thus jumping to " & $POINTER+$DIR & @CRLF)
If UBound($MEM) <= $POINTER Then
V(@CRLF & "Exiting because of pointer beyond memory")
Exit
EndIf
Else
i()
i()
$POINTER = r()-$DIR
V(" not), thus jumping to " & $POINTER+$DIR & @CRLF)
If UBound($MEM) <= $POINTER Then
V(@CRLF & "Exiting because of pointer beyond memory")
Exit
EndIf
EndIf
EndSwitch
i()
WEnd
Func V($data)
If $V Then ConsoleWrite($data)
EndFunc
Func guarantee($num)
While UBound($MEM) <= $num
_ArrayAdd($MEM,0)
WEnd
EndFunc[/autoit]
Alter Beispielcode
Edit: Erklärung des Beispielcodes:
[4,2,"Wie heißt du?",5,14,4,7,@CRLF & "Hallo, ",4,14,4,13,3,"!",0]
4,2: Gib den Inhalt von Position 2 aus.
Danach ist der Pointer auf dem String, aber da der Interpreter keinen Befehl sieht, überspringt er es.
5,14: Verlange eine Eingabe und speichere sie in Position 14.
4,7: Gib den Inhalt von Position 7 aus (@CRLF & "Hallo ")
String wird wieder übersprungen.
4,14: Gib Position 14 aus (den Namen)
4,13: Und jetzt das Ausrufezeichen von Position 13.
3: Skript wird beendet.
edit: Interpreter verbessert und eine Fehlerquelle behoben. Springt man zu einem noch nicht existierenden Speicherplatz, wird er automatisch erzeugt.
Man kann nun die Kommandozeilenoption -v mitgeben, dann ist der Interpreter besonders ausführlich. Der Befehl 2 ist komplett neu: Richtungswechsel. Das ermöglicht einen netten Effekt:
Gibt achtmal "Test" aus:
"@CRLF" wird beim Ausgeben automatisch zum Zeilenumbruch geändert.
Die komplette FABSIL-Spezifikation für Leute, die selbst einen Interpreter schreiben wollen, findet sich auf http://www.l3viathan.de/fabsil.
Ich habe die Bedeutung der Abkürzung außerdem von "AutoIt Based" zu "Array Based" geändert, weil ich als Übung plane, den Interpreter in einer anderen Sprache umzusetzen.