Execute Brain****/AutoHotkey
<lang autohotkey>;---------------------------------------------------------------------------
- Brainf*** Interpreter.ahk
- by wolf_II
- ---------------------------------------------------------------------------
- interpreter for Brainf*** 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 := "Brainf***" Gosub, GuiCreate Gui, Show,, %AppName%
Return
- ---------------------------------------------------------------------------
GuiCreate: ; create the main window
- ---------------------------------------------------------------------------
; GUI options Gui, Margin,, 10 Gui, Add, Edit, y0 h0 ; catch the focus
; Brainf*** Code Gui, Add, GroupBox, w462 h248, Brainf*** 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 Brainf*** 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, Brainf*** 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 ----------------------------------------------------