Brain-o-Zap

BrainF_ck-interpreter (Win 98)

Comments to
Gottfried Helms,
Uni Kassel
mailto:helms@uni-kassel.de

Screenshot     Einführung        Download         Tech-defs        Versions/Techinfo(english)

Techdefs

1) Konzeption
2) Technische Daten der Engine:
2.1) Speicher
2.2) Prozeduren
2.3) Verwendung
3) Gültige Codes
4) IDE
4.1)  "Fenster"
4.2) Compile & Run
4.3) Dateneingabe während der Programmausführung:
4.4) Datenausgabe während der Programmausführung:
4.5) Break
4.6) Formatter
4.7) Quelltextdateien
4.8) Disassemblierung
         Optimierungen:
4.8.1) Zusammenfassung von Wiederholungen
4.8.2) Sequenzen
5) Beispiel einer INI-Datei:


1) Konzeption

IDE und Engine sind separate Einheiten; die Engine ist als Delphi-6-Unit
ausgelegt, wird aber demnächst auch als Windows/C-dll verfügbar sein.


2) Technische Daten der Engine:

2.1) Speicher

2.2) Prozeduren

    constructor create;
    destructor destroy;

    function GetCode(const s:string):integer; // allocates code-array
    function CmpJmp:integer;                  // allocates jmp-array

    function exec:integer;              // allocates dataarray
    procedure FreeData;                // allocates dataarray with length 0

    function disassemble:string;

    procedure DfltPutch(const d:byte);// does nothing
    function  DfltGetCh:byte;   // Gets value 0
    procedure DfltDoEvents;     // does nothing. meaningful is: application.processmessages
    procedure DfltDebug(const status:integer;
                        const aCP,aDP:integer;
                        const ACode:tcodeArr;
                        const AJmp :tjmpArr;
                        const AData:tDataArr;
                        const aQa,qQe:byte;
                        const aQueue:tqueue_arr);
   end;


Die Dflt-Prozeduren stellen leere Behälter dar; sie tun praktisch nichts.
Eine Applikation implementiert sinnvolle Prozeduren und lenkt nach dem
Erzeugen einer Engine-Instanz (bf:=tbf.create) deren diesbezügliche
Prozedurvariablen PutCH, GetCH und DoEvents auf ihre Implementierungen.

2.3) Verwendung

Eine minimale Sequenz von Aufrufen zeigt das folgende:
 

  //initalization ------------------------------
    bf:=tbf.create;

    // assign communication-channels between engine & application
    bf.putch:=myfrm_putchImplementation;
    bf.getch:=myfrm_GetchImplementation;
    bf.doevents:=myfrm_DoeventsImplementation ;
                  //only if abort-mechanism is required



  // using: compiling some code -------------------------
     //pass your code to bf to be compiled

    bf.Getcode(',++.') ;      // interpret BF-code provided by a long-string
                              // the string can contain comments etc.
    bf.CmpJmp ;               // comptes jump-table for block-control by brackets "[]"
                                                            // code is in array CODE[]

  //running: ---------------------------------------------
       // execute your code, getting eventually errormessages

       errcode:=bf.exec;

       if errcode<>0 then application.messagebox('error:',errmsg[errcode]);

      //optionally you can free the data-array after execution
      freedata;

  //deleting
     // if no more compiles or executes wished, instance must be freed
     bf.destroy;




3) Gültige Codes

Die ursprüngliche Sprachdefinition erklärt 8 Codes:

     "," =(komma) 1 Zeichen vom Anwender (über Inputkanal) erhalten 
     "." =(punkt) 1 Zeichen über Outputkanal ausgeben

    ">" = 1 Adresse hochzählen
    "<" = 1 Adresse herunterzählen

    "+" = am Datenpointer 1 hinzuzählen
    "-" = am Datenpointer 1 abziehen

    "[" = wenn am Datenpointer=0, hinter zugehörige "]" springen
    "]" = wenn am Datenpointer>0, hinter zugehörige "[" springen



4) IDE

4.1)  "Fenster"

Codefenster und Outputfenster sind Richedit-Fenster, die beliebig
große Ausgaben verwalten können, und  -außer dem anwendungsspezifischen
Popup-Menü- die üblichen Tastenkürzel für Markieren, Copy&Paste verwenden.

4.2) Compile & Run

Bevor ein Code ausgeführt werden kann, muß er compiliert werden.
Danach kann er beliebig oft (z.B. mit wechselnden Dateneingaben) aus-
geführt werden, ohne ihn neu zu compilieren.

4.3) Dateneingabe während der Programmausführung:

es wird eine einzelne Tastatureingabe, abgeschlossen mit Eingabetaste erwartet
oder aber die Eingabe einer Nummer zwischen 0 und 255 in der Form
 #nnn   z.B. #0 oder  #10  oder #255
Der ASCII-code der Tastatureingabe oder aber die durch #nnn angegebene Zahl
wird an die Engine übergeben, nicht die Zahl 1 bei Tastendruck "1" !

4.4) Datenausgabe während der Programmausführung:

Die von der Engine angelieferten Bytes werden als Ansi-Characters angezeigt.
Dies schließt die Wirkung der Zeilenumbruchssequenzen, Tabulatoren etc. ein;
dieser Effekt wird nicht kompensiert.
Nur die Ausgabe der Ascii-Null wird übersetzt in Ascii 180 (kleiner mittlerer
Punkt, da die Ansi-Stringoperationen unter Windows die Ascii-Null als Begrenzer
behandeln.

4.5) Break

Bei fehlerhaften Läufen, im Eingabe-Wartezustand kann der Programmlauf
abgebrochen werden. Dies wird durch Zuweisung einer Process-Messages-
Prozedur an den DOEVENTS-Channel /Prozedurvariable ermöglicht.
In der IDE erhält man dazu einen Knopf, der nur aufscheint, wenn das programm
läuft, und den man während der programmausführung drücken kann.

4.6) Formatter

 Code kann im codefenster komprimiert werden indem alle Zeichen außer den
BrainFuck-tokens entfernt werden und jede Zeile auf 64 Zeichen umgebrochen
wird. Hierzu dient ein Eintrag im Code-Popup-Menu.

4.7) Quelltextdateien

 brainfuck-Quelltext-Dateien können gelesen und geschrieben werden.

4.8) Disassemblierung

 Der Disassembler liefert folgenden Output:
     
    BF-Opcode   Assm
       +        INC
       -        DEC
       >        FOC +1      // Fokus  ist der Data-Pointer
       <        FOC -1
       .        PUT
       ,        GET
       [        WHILE [FOC]>0 BEGIN
       ]        END

 Die Assembler-Token sind über die BF.INI-Datei konfigurierbar, s.u. .    

  Optimierungen:

  4.8.1) Zusammenfassung von Wiederholungen

   Folgen mehrere gleichartige Opcodes (außer Klammern) hintereinander
  werden diese zu der geeigneten Mnemo-Codierung plus einer Zählangabe zusammen-
  gefaßt:

      ++++     INC 4
      <<<      FOC -3
      ..       PUT *2
  

  4.8.2) Sequenzen

  bestimmte im Code erkannte Sequenzen werden bereits zu komplexeren
  Menmocodes zusammengefaßt:

     [-]                   CLR                  //clears current position


     [->>>>+<<<<]          MOV +4               //moves value to 4 positions right
     [->>>>++++<<<<]       MUL *4 TO +4         //multiplication into new position
     [-->>>>+++++<<<<]     MUL *5 div 2 TO +4   //rational multiplication into new position

                       //For MOV and MUL the following rules are in effect:
                       //* initial position will be cleared
                       //* all 4 variations of all these themes are detected
                       //  example given: the four variations of MOV +2
                       //    MOV +2  [->>+<<]
                       //            [>>+<<-]
                       //    MOV -2  [-<<+>>]
                       //            [<<+>>-]

    Etwas präziser ausgedrückt enthalten MOV/MUL-Instruktionen einen zusätzlichen INC:

       wenn auf DATA[DP] ein MOV +4 folgt so ist das Ergebnis

                             vor MOV    nach MOV
                DATA[DP]   =  x          0
                DATA[DP+4] =  ?          ?+x

       wenn auf DATA[DP] ein MUL *3 TO +4 folgt so ist das Ergebnis

                             vor MOV    nach MOV
                DATA[DP]   =  x          0
                DATA[DP+4] =  ?          ?+3*x




5) Beispiel einer INI-Datei:


[Defaults]
; DON'T CHANGE THE DEFAULTS
ErrMsgCount=3
DefaultProgsCount=0
Language = "DE"
ownerLabel ="Doros Brain-F*ck"


[Languages]
;if you localize messages for other countries, add entries here
LANG1 = "DE"
LANG2 = "EN"



[Globals]
; Start here, if you want change something
;for example-programs at the end; must correspond to this number
DefaultProgsCount=2
;select one of the provided languages
Language = "DE"



[PopupMenuDE]
Code_fileopen="ein&lesen BF-Programmdatei"
Code_fileSave="&speichern BF-Programmdatei"
Code_FilterCode="&Filter Code"
Output_Clear = "&Lösche Ausgabe"
input_blank ="#32 Leerzeichen"
input_null = "#0 Null-Zeichen"
input_newline = "#10 Neue Zeile"
input_255 ="#255 maxbyte"
input_tab ="#9 Tabulator"



[PopupMenuEN]
Code_fileopen="&load code from file"
Code_fileSave="&save code to file"
Code_FilterCode="&filter code"
Output_Clear = "&clear output"
input_blank ="#32 blank"
input_null = "#0 null-char"
input_newline = "#10 newline"
input_255 ="#255 maxbyte"
input_tab ="#9 tabulator"


[ButtonsDE]
BTN_COMPILE = "&Brain-O-"
BTN_RUN     = "&ZAP"

[ButtonsEN]
BTN_COMPILE = "&Brain"
BTN_RUN     = "&F_ck"





[dialogsDE]
filefilter = "BrainF*ck-Code (*.bf;*.b)|*.bf;*.b|Alle Dateien(*.*)|*.*"
DefaultExt = 'bf'
InitialDir = '.\examples'

[dialogsEN]
filefilter = "BrainF*ck-Code (*.bf;*.b)|*.bf;*.b|all files(*.*)|*.*"
DefaultExt = 'bf'
InitialDir = '.\examples'



[HintsDE]
compile="Zum Kompilieren BRAIN drücken"
run="Zum Starten F*CK drücken"
input="Taste oder numerischen Code mit # eingeben (z.B. #19) mögl. Bereich:0..255"
code="rechte Maustaste für Code-Beispiele oder Codedatei.Operationen"
adviceButtons="Code eingeben, zum Kompilieren BRAIN drücken und dann F*CK!"
adviceInput="Taste oder #ascii-code, Eingabe"

[HintsEN]
compile="click BRAIN to compile"
run="click F*CK to run program"
input="input key or numerical code preceded by # (i.e. #19) range:0..255"
code="right mouseclick for code-examples or codefile-operations"
adviceButtons="Enter Code, press BRAIN and then F*CK!"
adviceInput="Input key or #asci-number, return"







[ErrMsgDE]
;number cannot be changed!
Errmsg1="Upps. You tried to access above data-area(too many >>> going above 65000)";
Errmsg2="Snor. You tried to access below data-area(too many <<< going below 1)";
Errmsg3="Arrg! You have too many closing brackets";

[ErrMSGEN]
Errmsg1="Upps. You tried to access above data-area(too many >>> going above 65000)";
Errmsg2="Snor. You tried to access below data-area(too many <<< going below 1)";
Errmsg3="Arrg! You have too many closing brackets";


[AssembDE]
 Assemb1= 'Raufzählen '
 Assemb2= 'Runterzählen '
 Assemb3= 'Speicherstelle +'
 Assemb4= 'Speicherstelle -'
 Assemb5= 'Schreiben '
 Assemb6= 'Kriegen '
 Assemb7= 'WHILE [SpSt]>0 BEGIN '
 Assemb8= 'END'
 Assemb9= 'Löschen '
 Assemb10='Verschieben '
 Assemb11='Mult '
 Assemb12=' TO '


[AssembEN]
 Assemb1= 'INC '
 Assemb2= 'DEC '
 Assemb3= 'FOC +'
 Assemb4= 'FOC -'
 Assemb5= 'PUT '
 Assemb6= 'GET '
 Assemb7= 'WHILE [FOC]>0 BEGIN '
 Assemb8= 'END'
 Assemb9= 'CLR '
 Assemb10='MOV '
 Assemb11='MUL '
 Assemb12=' TO '






[About]
;can be localized, need not be rtf, should not be more than 22 lines
line1 ="{\rtf1\ansi\deff0\deftab720{\fonttbl{\f0\fswiss MS Sans Serif;}"
line2 ="{\f1\froman\fcharset2 Symbol;}"
line3 ="{\f2\fswiss\fcharset1 Tahoma;}"
line4 ="{\f3\fswiss\fcharset1 MS Sans Serif;}"
line5 ="{\f4\fswiss\fcharset1 MS Sans Serif;}}"
line6 ="{\colortbl\red0\green0\blue0;\red0\green128\blue128;}"
line7 ="\deflang1031\pard\qc\plain\f2\fs32\cf1\b BrainF*ck"
line8 ="\par - IDE/Interpreter for Win98 - "
line9 ="\par \plain\f2\fs32\b "
line10 ="\par \plain\f2\fs20 written in Delphi by "
line11 ="\par "
line12 ="\par Gottfried Helms"
line13 ="\par Kassel"
line14 ="\par "
line15 ="\par for"
line16 ="\par "
line17 ="\par \plain\f2\fs20\b  Doro @ d0r0 de\plain\f2\fs20 "
line18 ="\par 5.1.2004/8.1.2004"
line19 ="\par \plain\f4\fs16 "
line20 ="\par V 1.2 "
line21 ="\par }"


; you can add as may examples as you like, but think of reasonable size
; of popup-menu!
; two kind sources for code:
; http://koeln.ccc.de/prozesse/zombies/brainfuck/index.en.xml
; http://www.hevanet.com/cristofd/brainfuck/

[Example1]
titleDE = "Hello World"
titleEN = "Hello World"
line1 = ";BrainF*ck : Hello World! "
line2 = "; "
line3 = ">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[  "
line4 = "-]>++++++++[<++++>-]<.>+++++++++++[<++++++++>-]<-.--------.  "
line5 = "+++.------.--------.[-]>++++++++[<++++>-]<+.[-]++++++++++.   "
line6 = " "



[Example2]
titleDE = "Hallo Doro"
titleEN = "Hallo Doro"
line1 = ";BrainF*ck: Hallo doro! "
line2 = ";   "
line3 = ";START "
line4 = ">+++++++++[<++++++++>-]<. "
line5 = ">+++++++[<++++>-]<+----. "
line6 = "+++++++++++.. "
line7 = "+++.[-] "
line8 = ">++++++++[<++++>-]<. "
line9 = ">+++++++++[<++++++++>-]<----. +++++++++++. +++. "
line10 = "---.[-] >++++++++[<++++>-]<+. "
line11 = "[-]++++++++++. "
line12 = ";ENDE  "



Gottfried Helms, Uni Kassel
mailto://helms@uni-kassel.de