RCSNUSP/AutoHotkey
Appearance
< RCSNUSP
;---------------------------------------------------------------------------
; 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 ----------------------------------------------------