⚠️ Warning: This is a draft ⚠️

This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.

If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.

;---------------------------------------------------------------------------
; Brainfuck Interpreter.ahk
; by wolf_II
;---------------------------------------------------------------------------
; interpreter for Brainfuck code
;---------------------------------------------------------------------------



;---------------------------------------------------------------------------
Code = ; Goodbye, World!
;---------------------------------------------------------------------------
    (LTrim
        Example taken from RosettaCode:org

        ++++++++++[>+>+++>++++>+++++++>++++++++>+++++++++>++++++++++
        >+++++++++++>++++++++++++<<<<<<<<<-]>>>>+.>>>>+..<.<++++++++
        .>>>+.<<+.<<<<++++.<++.>>>+++++++.>>>.+++.<+++++++.--------.
        <<<<<+.<+++.---.
    )



;---------------------------------------------------------------------------
AutoExecute: ; auto-execute section of the script
;---------------------------------------------------------------------------
    #SingleInstance, Force          ; only one instance allowed
    #NoEnv                          ; don't check empty variables
    ;-----------------------------------------------------------------------
    AppName := "Brainfuck"
    Gosub, GuiCreate
    Gui, Show,, %AppName%

Return



;---------------------------------------------------------------------------
GuiCreate: ; create the main window
;---------------------------------------------------------------------------
    ; GUI options
    Gui, Margin,, 10
    Gui, Add, Edit, y0 h0 ; catch the focus

    ; Brainfuck Code
    Gui, Add, GroupBox, w462 h248, Brainfuck Code
    Gui, Font, s8, Courier New
    Gui, Add, Edit, xp+10 yp+20 w442 r15 vCode, %Code%
    Gui, Font ; normal

    ; buttons
    Gui, Add, Button, xm w101 h30, &Load Code
    Gui, Add, Button, x+19 wp hp, &Save Code As
    Gui, Add, Button, x+19 wp hp Default, &Run Code
    Gui, Add, Button, x+19 wp hp, E&xit

    ; Output
    Gui, Add, GroupBox, xm w462 h248, Output
    Gui, Font, s8, Courier New
    Gui, Add, Edit, xp+10 yp+20 w442 r15 ReadOnly vOutput HwndhOut
    Gui, Font ; normal

Return



;---------------------------------------------------------------------------
ButtonLoadCode: ; load code from file
;---------------------------------------------------------------------------
    Gui, +OwnDialogs
    FileSelectFile, CodeFile,,, Load Brain*** Code, *.bf
    If (ErrorLevel = 1) {
        ; user dismissed the dialog
        Gui, Show
        Return
    }
    If Not SubStr(CodeFile, -2) = ".bf"
        CodeFile .= ".bf"
    If FileExist(CodeFile) {
        FileRead, Code, %CodeFile%
        GuiControl,, Code, %Code%
    } Else
        MsgBox, 16, Error - %AppName%, File not found:`n`n"%CodeFile%"
    GuiControl,, Output ; clear all output
    Gui, Show

Return



;---------------------------------------------------------------------------
ButtonSaveCodeAs: ; save code to file
;---------------------------------------------------------------------------
    Gui, +OwnDialogs
    Gui, Submit, NoHide
    FileSelectFile, CodeFile, S16,, Brain*** Code, *.bf
    If (ErrorLevel = 1) {
        ; user dismissed the dialog
        Gui, Show
        Return
    }
    If Not SubStr(CodeFile, -2) = ".bf"
        CodeFile .= ".bf"
    FileDelete, %CodeFile%
    FileAppend, %Code%, %CodeFile%
    Gui, Show

Return



;---------------------------------------------------------------------------
GuiClose:   ; {Alt-F4} pressed, [X] clicked
;---------------------------------------------------------------------------
ButtonExit: ; Exit button clicked
;---------------------------------------------------------------------------
    ExitApp

Return



;---------------------------------------------------------------------------
ButtonRunCode: ; run the code from the edit field
;---------------------------------------------------------------------------
    Gui, Submit, NoHide         ; get code from GUI
    Gosub, set_JumpPointers     ; set jump pointers
    GuiControl, Disable, Output
    GuiControl, Disable, &Load
    GuiControl, Disable, &Save
    GuiControl, Disable, &Run
    Gosub, Interpreter          ; do your stuff, kid
    GuiControl, Enable, Output
    GuiControl, Enable, &Load
    GuiControl, Enable, &Save
    GuiControl, Enable, &Run

Return



;---------------------------------------------------------------------------
Interpreter: ; This is the Brainfuck Interpreter
;---------------------------------------------------------------------------
    ; setup BF environment
    VarSetCapacity(BF_MEM, 4096, 0)
    DataPtr := InstrPtr := 0

    Loop {

        ; read next instruction
        CMD := SubStr(Code, ++InstrPtr, 1)
        Data@Ptr := NumGet(BF_MEM, DataPtr, "Char")

        If (CMD = "+") ; increment the data at DataPointer
            NumPut(Data@Ptr + 1, BF_MEM, DataPtr, "Char")

        Else If (CMD = "-") ; decrement the data at DataPointer
            NumPut(Data@Ptr - 1, BF_MEM, DataPtr, "Char")

        Else If (CMD = ">") ; increment the DataPointer
            DataPtr++

        Else If (CMD = "<") ; decrement the DataPointer
            DataPtr--

        Else If (CMD = ".") ; print the char at DataPointer
            Output(Chr(Data@Ptr))

        Else If (CMD = ",") ; get a char from stdin (keyboard)
            NumPut(GetChar(), BF_MEM, DataPtr, "Char")

        Else If (CMD = "[") { ; conditional jump
            If (Data@Ptr = 0)
                ; continue after the corresponding "]"
                InstrPtr := Jump[%InstrPtr%]

        } Else If (CMD = "]") { ; conditional jump
            If (Data@Ptr != 0)
                ; continue after the corresponding "["
                InstrPtr := Jump[%InstrPtr%]

        } Else If (CMD = "") ; this is the end of code
            Break
    }

Return



;---------------------------------------------------------------------------
set_JumpPointers: ; setup all the jump pointers in two passes
;---------------------------------------------------------------------------
    Loop, % Len := StrLen(Code) ; first pass
        If (CMD := SubStr(Code, A_Index, 1)) = "["
            Push("Stack", A_Index)
        Else If (CMD = "]")
            Jump[%A_Index%] := Pop("Stack")

    Loop, % Len ; second pass goes backwards
        If (CMD := SubStr(Code, Index:=Len-A_Index, 1)) = "]"
            Push("Stack", Index)
        Else If (CMD = "[")
            Jump[%Index%] := Pop("Stack")

Return



;---------------------------------------------------------------------------
GetChar() { ; retrieve a single char from StdIn (keyboard)
;---------------------------------------------------------------------------
    Progress, b2 w150 zh0 fs9, Brainfuck Interpreter waits for input ...
    Input, InKey$, L1
    Progress, Off
    Return, Asc(InKey$)
}



;---------------------------------------------------------------------------
Push(Stack, x) { ; push x onto stack named "Stack"
;---------------------------------------------------------------------------
    local pos
    %Stack%_0 := pos := %Stack%_0 ? %Stack%_0 + 1 : 1
    %Stack%_%pos% := x
}



;---------------------------------------------------------------------------
Pop(Stack) { ; pop value from stack named "Stack"
;---------------------------------------------------------------------------
    local pos
    If (pos := %Stack%_0) < 1 ; already empty
        Return,, ErrorLevel := -1
    Return, %Stack%_%pos%, %Stack%_0--
}



;---------------------------------------------------------------------------
Output(Text) { ; append text to output
;---------------------------------------------------------------------------
    ; for non-interruptable output
    ;-----------------------------------------------------------------------
    global hOut
    SendMessage, 0xC2,, &Text,, ahk_id %hOut% ; EM_REPLACESEL
}



;---------- end of file ----------------------------------------------------

[[Image:BrainfGUI.png]]