RCSNUSP/AutoHotkey

From Rosetta Code
Revision as of 20:29, 15 April 2014 by rosettacode>AndiPersti (→‎{{header|AutoHotkey}}: "header" template isn't necessary on this page)

<lang autohotkey>;---------------------------------------------------------------------------

SNUSP Interpreter.ahk
by wolf_II
---------------------------------------------------------------------------
interpreter for SNUSP code
---------------------------------------------------------------------------


---------------------------------------------------------------------------

Code = ; Goodbye, World!

---------------------------------------------------------------------------
   (

Example taken from RosettaCode.org

$@\G.@\o.o.@\d.--b.@\y.@\e.>@\comma.@\.<-@\W.+@\o.+++r.------l.@\d.>+.! #

 |   |     \@------|#  |    \@@+@@++|+++#-    \\               -
 |   \@@@@=+++++#  |   \===--------!\===!\-----|-------#-------/
 \@@+@@@+++++#     \!#+++++++++++++++++++++++#!/
   )


---------------------------------------------------------------------------

AutoExecute: ; auto-execute section of the script

---------------------------------------------------------------------------
   #SingleInstance, Force          ; only one instance allowed
   #NoEnv                          ; don't check empty variables
   ;-----------------------------------------------------------------------
   AppName := "SNUSP"
   Gosub, GuiCreate
   Gui, Show,, %AppName%

Return


---------------------------------------------------------------------------

GuiCreate: ; create the main window

---------------------------------------------------------------------------
   ; GUI options
   Gui, Margin,, 10
   Gui, Add, Edit, y0 h0 ; catch the focus
   Gui, Add, Checkbox, vWatch, Watch
   ; SNUSP Code
   Gui, Add, GroupBox, w554 h265, SNUSP Code
   Gui, Font, s8, Courier New
   Gui, Add, Edit, xp+10 yp+20 w534 r15 -Wrap +HScroll vCode HwndhCode, %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 w554 h248, Output
   Gui, Font, s8, Courier New
   Gui, Add, Edit, xp+10 yp+20 w534 r15 ReadOnly vOutput HwndhOut
   Gui, Font ; normal

Return


---------------------------------------------------------------------------

ButtonLoadCode: ; load code from file

---------------------------------------------------------------------------
   Gui, +OwnDialogs
   FileSelectFile, CodeFile,,, Load SNUSP Code, *.snusp
   If (ErrorLevel = 1) {
       ; user dismissed the dialog
       Gui, Show
       Return
   }
   If Not SubStr(CodeFile, -5) = ".snusp"
       CodeFile .= ".snusp"
   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,, SNUSP Code, *.snusp
   If (ErrorLevel = 1) {
       ; user dismissed the dialog
       Gui, Show
       Return
   }
   If Not SubStr(CodeFile, -5) = ".snusp"
       CodeFile .= ".snusp"
   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
   ;~ GuiControl, Disable, Code
   GuiControl, Disable, Output
   GuiControl, Disable, &Load
   GuiControl, Disable, &Save
   GuiControl, Disable, &Run
   Gosub, PadCode
   ;~ GuiControl, Enable, Code
   GuiControl, Enable, Output
   GuiControl, Enable, &Load
   GuiControl, Enable, &Save
   GuiControl, Enable, &Run

Return


---------------------------------------------------------------------------

PadCode: ; pad code with spaces

---------------------------------------------------------------------------
   mL := 0 ; max length
   Loop, Parse, Code, `n
       If (Len := StrLen(A_LoopField)) > mL
           mL := Len
   PaddedCode := ""
   Loop, Parse, Code, `n
       PaddedCode .= A_LoopField Repeat(" ", mL - StrLen(A_LoopField)) "`r`n"
   GuiControl,, Code, % Code := PaddedCode
   ml += 2
   ; find code entry point
   InstrPtr := (pos := InStr(Code, "$")) ? pos : 1
---------------------------------------------------------------------------

Interpreter: ; this is the SNUSP Interpreter

---------------------------------------------------------------------------
   ; setup SNUSP environment
   VarSetCapacity(SNUSP_MEM, 4096, 0)
   DataPtr := InstrDir := 0
   ControlFocus,, ahk_id %hCode%
   Loop {
       ; read next instruction
       getNext(InstrPtr)
       CMD := SubStr(Code, InstrPtr, 1)
       Data@Ptr := NumGet(SNUSP_MEM, DataPtr, "Char")
       If Watch {
           Highlight(InstrPtr)
           Sleep, 25
           ;~ ListVars
           ;~ Pause
       }
       If (CMD = "+") ; increment the data at DataPointer
           NumPut(Data@Ptr + 1, SNUSP_MEM, DataPtr, "Char")
       Else If (CMD = "-") ; decrement the data at DataPointer
           NumPut(Data@Ptr - 1, SNUSP_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(), SNUSP_MEM, DataPtr, "Char")
       Else If (CMD = "\") ; LURD
           LURD(InstrDir)
       Else If (CMD = "/") ; RULD
           RULD(InstrDir)
       Else If (CMD = "!") ; SKIP
           getNext(InstrPtr)
       Else If (CMD = "?") { ; SKIPZ
           If (Data@Ptr = 0)
               getNext(InstrPtr)
       } Else If (CMD = "@") { ; ENTER
           Push("Stack", InstrPtr)
           Push("Stack", InstrDir)
       } Else If (CMD = "#") { ; LEAVE
           InstrDir := Pop("Stack")
           InstrPtr := Pop("Stack")
           If (ErrorLevel = -1)
               Break
           Else
               getNext(InstrPtr)
       } Else If (CMD = "") ; this is the end of code
           Break
   }

Return


---------------------------------------------------------------------------

getNext(ByRef InstrPtr) { ; get next instruction pointer

---------------------------------------------------------------------------
   ;    instruction directions
   ;         Up = 3
   ;     Left = 2   0 = Right
   ;              1 = Down
   ;-----------------------------------------------------------------------
   global InstrDir, mL
   InstrPtr += (InstrDir > 1 ? -1 : 1) * (InstrDir & 1 ? mL : 1)

}


---------------------------------------------------------------------------

LURD(ByRef InstrDir) { ; reflect the instruction direction "\"

---------------------------------------------------------------------------
   ;~ case 0 -> 1
   ;~ case 1 -> 0
   ;~ case 2 -> 3
   ;~ case 3 -> 2
   ;-----------------------------------------------------------------------
   InstrDir += (InstrDir & 1 ? -1 : 1)

}


---------------------------------------------------------------------------

RULD(ByRef InstrDir) { ; reflect the instruction direction "/"

---------------------------------------------------------------------------
   ;~ case 0 -> 3
   ;~ case 1 -> 2
   ;~ case 2 -> 1
   ;~ case 3 -> 0
   ;-----------------------------------------------------------------------
   InstrDir := 3 - InstrDir

}


---------------------------------------------------------------------------

Repeat(String,Count) {

---------------------------------------------------------------------------
   Loop, %Count%
       Result .= String
   Return, Result

}


---------------------------------------------------------------------------

GetChar() { ; retrieve a single char from StdIn (keyboard)

---------------------------------------------------------------------------
   Progress, b2 w150 zh0 fs9, SNUSP 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--

}


---------------------------------------------------------------------------

Highlight(InstrPtr) { ; select current command in code

---------------------------------------------------------------------------
   global hCode
   SendMessage, 0xB1, InstrPtr-1, InstrPtr,, ahk_id %hCode% ; EM_SETSEL

}


---------------------------------------------------------------------------

Output(Text) { ; append text to output

---------------------------------------------------------------------------
   ; for non-interruptable output
   ;-----------------------------------------------------------------------
   global hOut
   SendMessage, 0xC2,, &Text,, ahk_id %hOut% ; EM_REPLACESEL

}


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

</lang>