ContentsIndex
ArghInterpreter
Contents
Data structures
Constants
Argh! interpreter
Command processing
Stack operations
Grid operations
Code validation
Miscellaneous
User interface
Description

An interpreter for the Argh! programming language in wxHaskell. Argh! is an esoteric programming language created by Sascha Wilde. An Argh! program is a two-dimensional grid (80x40 cells) and each cell contains an integer that can be interpreted as such or as a command that can be executed. A stack is used to store values and to do calculations. For more information about Argh!, see http://www.sha-bang.de/index.php?page=12_eso (in German).

This implementation (v0.8) is based on the following language specification: http://www.sha-bang.de/content/12_eso/Argh-Spec.txt. All commands are supported except e and E (these are used for inserting EOF in cells). Existing Argh! programs may or may not behave as expected: the e and E commands will produce an error and other language elements, such as the g and G commands that use input from stdin (a TextEntry in this case), may also differ.

Available under the GNU General Public License. For more information, see http://www.gnu.org/licenses/.

For more information about wxHaskell, see http://wxhaskell.sourceforge.net/.

Tested on Windows XP using GHCi 6.4.1 and wxHaskell 0.9.4. The window of the program has a fixed size suited for 1024*768 resolution. This can be changed by removing resizeable := False in the interpreter function yet the window still has a minimum size because the code widget has a minimum size. Of course, this can be modified if you want to run it on 800*600 or lower.

Notes:

  • Zero is considered to be both positive and negative when executing the x and X commands (see turnCond) - this is based on the fact that the tenhello.agh example in the official Argh! distribution (version 0.2.3) would print Hello world only 9 times if 0 is not considered a negative value.
  • Checking the Run even invalid code option doesn't turn this implementation into Aargh! (that's Argh! without the maximum of 40 lines). When checked, the interpreter will ignore the size limitations (80x40) and/or invalid characters and run anyway. The makeGrid function makes use of the maxWidth and maxHeight constants so the grid might not have the expected size if you use longer lines or more than the specified 40. As such, storing values in non-existant cells will result in undefined behaviour. The option can be useful, for example, when comments in the program contain invalid characters. Using it is not recommended, however.

February 2007, Simeon Visser

For comments, bugs, etc: svisser@cs.uu.nl

Synopsis
data ArghStack = Stack [Int]
data ArghGrid = Grid [[ArghCell]]
data ArghCell
= Cell Int
| Undefined
data ArghDirection
= ArghUp
| ArghRight
| ArghDown
| ArghLeft
data ArghPointer = Pointer ArghDirection Coordinate Coordinate
type Coordinate = Int
type ErrorMessage = String
type ArghProgram = [String]
version :: Float
maxWidth :: Int
maxHeight :: Int
openFiles :: [(String, [String])]
saveFiles :: [(String, [String])]
outputFiles :: [(String, [String])]
main :: IO ()
interpreter :: IO ()
run :: TextCtrl () -> TextCtrl () -> TextCtrl () -> Var ArghStack -> Var Bool -> Var Bool -> Var Bool -> IO ()
exec :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack -> Bool -> Bool -> IO ()
gridMove' :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack -> Bool -> Bool -> IO ()
turnCond :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack -> Bool -> (Int -> Bool) -> (ArghDirection -> ArghDirection) -> Bool -> IO ()
store :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack -> Bool -> (Coordinate -> Coordinate) -> Bool -> IO ()
dupDel :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack -> Bool -> (ArghStack -> Maybe ArghStack) -> Bool -> IO ()
addRed :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack -> Bool -> (Coordinate -> Coordinate) -> (ArghStack -> Int -> Maybe ArghStack) -> Bool -> IO ()
popStack :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack -> Bool -> (Coordinate -> Coordinate) -> Bool -> IO ()
showCell :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack -> Bool -> (Coordinate -> Coordinate) -> Bool -> IO ()
readStore :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack -> Bool -> (Coordinate -> Coordinate) -> Bool -> IO ()
move :: ArghDirection -> ArghPointer -> ArghPointer
move' :: (Coordinate -> Coordinate) -> (Coordinate -> Coordinate) -> ArghDirection -> ArghPointer -> ArghPointer
viewS :: ArghStack -> [Int]
viewStack :: ArghStack -> TextCtrl () -> IO ()
getTop :: ArghStack -> Maybe Int
push :: ArghStack -> Int -> ArghStack
pop :: ArghStack -> (Maybe Int, ArghStack)
dupl :: ArghStack -> Maybe ArghStack
delst :: ArghStack -> Maybe ArghStack
redst :: ArghStack -> Int -> Maybe ArghStack
addst :: ArghStack -> Int -> Maybe ArghStack
opst :: (Int -> Int -> Int) -> ArghStack -> Int -> Maybe ArghStack
setGrid :: ArghGrid -> Coordinate -> Coordinate -> Int -> Maybe ArghGrid
gridMove :: ArghGrid -> ArghPointer -> Maybe Int -> Maybe (Coordinate, Coordinate)
makeGrid :: ArghProgram -> ArghGrid
getRow :: ArghGrid -> Int -> Maybe [ArghCell]
getGrid :: ArghGrid -> Coordinate -> Coordinate -> Maybe ArghCell
validPos :: Coordinate -> Coordinate -> Bool
arghCompliant :: ArghProgram -> Maybe ErrorMessage
checkWidth :: ArghProgram -> Maybe ErrorMessage
checkLength :: [Int] -> ErrorMessage
checkHeight :: ArghProgram -> Maybe ErrorMessage
checkLine :: String -> Maybe ErrorMessage
checkChar :: ArghProgram -> Maybe ErrorMessage
validChar :: Char -> Bool
checkToMaybe :: [a] -> b -> Maybe b
checkToMaybe' :: Bool -> a -> Maybe a
turnRight :: ArghDirection -> ArghDirection
turnLeft :: ArghDirection -> ArghDirection
restoreSettings :: TextCtrl () -> IO ()
buttonCheckCode :: Frame () -> TextCtrl () -> TextCtrl () -> IO ()
arghError :: Bool -> TextCtrl () -> Coordinate -> Coordinate -> IO ()
makeFileMenu :: Frame () -> Var String -> Var String -> TextCtrl () -> TextCtrl () -> IO (Menu ())
makeHelpMenu :: Frame () -> IO (Menu ())
makeEditMenu :: Frame () -> TextCtrl () -> IO (Menu ())
onFileNew :: Frame () -> Var String -> TextCtrl () -> IO ()
onFileOpen :: Frame () -> Var String -> TextCtrl () -> IO ()
onFileSave :: Frame () -> Var String -> TextCtrl () -> IO ()
onFileSaveAs :: Frame () -> Var String -> TextCtrl () -> IO ()
onFileSaveOutput :: Frame () -> Var String -> TextCtrl () -> IO ()
onFileSaveOutputAs :: Frame () -> Var String -> TextCtrl () -> IO ()
onEditAppend :: Frame () -> TextCtrl () -> IO ()
onHelpAbout :: Frame () -> IO ()
Data structures
data ArghStack
Constructors
Stack [Int]The stack.
show/hide Instances
data ArghGrid
Constructors
Grid [[ArghCell]]An Argh! program is a two-dimensional grid of ArghCell elements.
show/hide Instances
data ArghCell
Constructors
Cell IntEvery cell of the ArghGrid can store an Int.
UndefinedAn existing but undefined cell (cells outside the ArghGrid don't exist).
show/hide Instances
data ArghDirection
Valid directions (control flow of an Argh! program).
Constructors
ArghUp
ArghRight
ArghDown
ArghLeft
show/hide Instances
data ArghPointer
Constructors
Pointer ArghDirection Coordinate CoordinateThe pointer stores an ArghDirection and a position (x,y).
show/hide Instances
type Coordinate = Int
type ErrorMessage = String
type ArghProgram = [String]
Constants
version :: Float
Version number.
maxWidth :: Int
Maximum width; the interpreter complains when a line is longer than this number of characters. Default maximum width is 80.
maxHeight :: Int
Maximum height; the interpreter complains when the program consists of more than this number of lines. Default maximum height is 40.
openFiles :: [(String, [String])]
This is used to specify the files the user can open in the Open dialogs.
saveFiles :: [(String, [String])]
This is used to specify the files the user can save in the Save dialogs.
outputFiles :: [(String, [String])]
This is used to specify the output files.
Argh! interpreter
main :: IO ()
The main function. Call this to start the interpreter.
interpreter :: IO ()
The program; initializes variables to store state, creates the controls for the user interface and creates the layout.
run :: TextCtrl () -> TextCtrl () -> TextCtrl () -> Var ArghStack -> Var Bool -> Var Bool -> Var Bool -> IO ()
This function does preparations before the execution of the program begins (see exec). It checks if the Argh! program is valid and creates an ArghGrid to execute the program using the settings specified by the variables (i.e., showing error location yes/no and outputting every command yes/no).
exec :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack -> Bool -> Bool -> IO ()
The main loop. Reads the value from the current ArghCell, calls a function to execute the command (if needed) and moves in the current execution direction.
Command processing
gridMove' :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack -> Bool -> Bool -> IO ()
Used for the H, J, K and L commands. It moves over the grid looking for a specific value; it outputs an error if it's not found, else it'll continue the execution of the program. The actual moving is done by gridMove.
turnCond
:: ArghGrid
-> ArghPointer
-> TextCtrl ()The main TextCtrl (containing the source code).
-> StringThe input (not the source code).
-> ArghStack
-> BoolShow error location in error message yes/no.
-> (Int -> Bool)The condition to turn (e.g., (>= 0), (<= 0)).
-> (ArghDirection -> ArghDirection)Turning function (see turnLeft and turnRight).
-> BoolOutput all executed commands yes/no.
-> IO ()
Used for the x and X commands. It checks the value of the stack and turns depending on a condition (the Int -> Bool function). Zero is considered to be both positive and negative. See the notes above for an explanation.
store
:: ArghGrid
-> ArghPointer
-> TextCtrl ()The main TextCtrl (containing the source code).
-> StringThe input (not the source code).
-> ArghStack
-> BoolShow error location in error message yes/no.
-> (Coordinate -> Coordinate)Used to calculate new y-coordinate.
-> BoolOutput all executed commands yes/no.
-> IO ()
Used for the s and S commands. Pushes the value in the ArghCell above or below the current one on the stack.
dupDel
:: ArghGrid
-> ArghPointer
-> TextCtrl ()The main TextCtrl (containing the source code).
-> StringThe input (not the source code).
-> ArghStack
-> BoolShow error location in error message yes/no.
-> (ArghStack -> Maybe ArghStack)The stack operation, see dupl and delst.
-> BoolOutput all executed commands yes/no.
-> IO ()
Used for the d and D commands. Duplicates or deletes the value on top off the stack, if it exists.
addRed
:: ArghGrid
-> ArghPointer
-> TextCtrl ()The main TextCtrl (containing the source code).
-> StringThe input (not the source code).
-> ArghStack
-> BoolShow error location in error message yes/no.
-> (Coordinate -> Coordinate)Used to calculate the new y-coordinate.
-> (ArghStack -> Int -> Maybe ArghStack)The stack operation, see addst and redst.
-> BoolOutput all executed commands yes/no.
-> IO ()
Used for the a, A, r and R commands. Adds or reduces the value on top of the stack with the value in the ArghCell above or below the current one.
popStack
:: ArghGrid
-> ArghPointer
-> TextCtrl ()The main TextCtrl (containing the source code).
-> StringThe input (not the source code).
-> ArghStack
-> BoolShow error location in error message yes/no.
-> (Coordinate -> Coordinate)Used to calculate the new y-coordinate.
-> BoolOutput all executed commands yes/no.
-> IO ()
Used for the f and F commands. Pops the value from the top of the stack and stores it in the ArghCell above or below the current one.
showCell
:: ArghGrid
-> ArghPointer
-> TextCtrl ()The main TextCtrl (containing the source code).
-> StringThe input (not the source code).
-> ArghStack
-> BoolShow error location in error message yes/no.
-> (Coordinate -> Coordinate)Used to calculate the new y-coordinate.
-> BoolOutput all executed commands yes/no.
-> IO ()
Used for the p and P commands. Showing the value of the ArghCell above or below the current one.
readStore
:: ArghGrid
-> ArghPointer
-> TextCtrl ()The main TextCtrl (containing the source code).
-> StringThe input (not the source code).
-> ArghStack
-> BoolShow error location in error message yes/no.
-> (Coordinate -> Coordinate)Used to calculate the new y-coordinate.
-> BoolOutput all executed commands yes/no.
-> IO ()
Used for the g and G commands. Reads a value from the input (a String) and stores it in the ArghCell above or below the current one. It outputs an error if the input is empty or if the ArghCell above or below the current one doesn't exist.
move :: ArghDirection -> ArghPointer -> ArghPointer
Returns an ArghPointer that has been moved in the given ArghDirection.
move'
:: (Coordinate -> Coordinate)Will be applied to the x-coordinate.
-> (Coordinate -> Coordinate)Will be applied to the y-coordinate.
-> ArghDirection
-> ArghPointer
-> ArghPointer
Applies the two functions to the location of the ArghPointer. It returns a new ArghPointer with the given ArghDirection and the new position.
Stack operations
viewS :: ArghStack -> [Int]
Returns the contents of an ArghStack.
viewStack :: ArghStack -> TextCtrl () -> IO ()
Outputs the contents of the ArghStack to the specified TextCtrl.
getTop :: ArghStack -> Maybe Int
Returns the value on top of the stack (Just), else Nothing.
push :: ArghStack -> Int -> ArghStack
Pushes the value on the ArghStack.
pop :: ArghStack -> (Maybe Int, ArghStack)
Pops the value off the ArghStack. It returns the popped value (if it exists) and the new stack.
dupl :: ArghStack -> Maybe ArghStack
Duplicates the value on top of the ArghStack, if it exists.
delst :: ArghStack -> Maybe ArghStack
Deletes the value on top of the ArghStack, if it exists.
redst :: ArghStack -> Int -> Maybe ArghStack
Redures the value on top of the ArghStack, if it exists, by the given value.
addst :: ArghStack -> Int -> Maybe ArghStack
Add the given value to the value on top of the ArghStack, if it exists.
opst :: (Int -> Int -> Int) -> ArghStack -> Int -> Maybe ArghStack
Applies the function and the value to the value on top of the ArghStack. Returns the new stack if succesful.
Grid operations
setGrid :: ArghGrid -> Coordinate -> Coordinate -> Int -> Maybe ArghGrid
Sets the value of a value in the ArghGrid. It returns the new grid if succesful.
gridMove :: ArghGrid -> ArghPointer -> Maybe Int -> Maybe (Coordinate, Coordinate)
Moves the ArghPointer over the ArghGrid, looking for a specific value. Returns the location of the cell where it is found, else Nothing.
makeGrid :: ArghProgram -> ArghGrid
Creates an ArghGrid for a given ArghProgram. This function performs no checks to see if the program is valid. Running the interpreter with an invalid Argh! program could result in undefined behaviour. This function makes use of the maxWidth and maxHeight constants so the produced grid might not have the expected size when constructed from an invalid ArghProgram.
getRow :: ArghGrid -> Int -> Maybe [ArghCell]
Returns a row in the ArghGrid, if it exists.
getGrid :: ArghGrid -> Coordinate -> Coordinate -> Maybe ArghCell
Returns the value of a specific ArghCell in the ArghGrid, if it exists.
validPos :: Coordinate -> Coordinate -> Bool
Returns True if it's a valid position (x,y).
Code validation
arghCompliant :: ArghProgram -> Maybe ErrorMessage
Returns an ErrorMessage if the specified String (the Argh! program) is invalid. This error message is a combination of the error messages produced by checkHeight, checkWidth and checkChar.
checkWidth :: ArghProgram -> Maybe ErrorMessage
Checks the width of the ArghProgram.
checkLength :: [Int] -> ErrorMessage
Checks the length of the list of Int (each Int is the length of a specific line).
checkHeight :: ArghProgram -> Maybe ErrorMessage
Checks the height of the ArghProgram. Returns an ErrorMessage if needed, else Nothing.
checkLine :: String -> Maybe ErrorMessage
Checks a line for invalid characters. Returns an ErrorMessage if needed, else Nothing.
checkChar :: ArghProgram -> Maybe ErrorMessage
Checks an ArghProgram for invalid characters. Returns an ErrorMessage if needed, else Nothing.
validChar :: Char -> Bool
Returns True for valid characters. Valid characters have ASCII value 32 - 127 or newline (10).
Miscellaneous
checkToMaybe :: [a] -> b -> Maybe b
Returns Just b if the list is not empty, else Nothing.
checkToMaybe' :: Bool -> a -> Maybe a
Returns Just a if False, else Nothing.
turnRight :: ArghDirection -> ArghDirection
Turns right.
turnLeft :: ArghDirection -> ArghDirection
Turns left.
User interface
restoreSettings :: TextCtrl () -> IO ()
Restores the settings (font, wrapping) of the TextCtrl.
buttonCheckCode
:: Frame ()
-> TextCtrl ()TextCtrl containing the Argh! source code
-> TextCtrl ()TextCtrl containing the output.
-> IO ()
Used for the Validate button (outputs if the Argh! program is valid or not).
arghError :: Bool -> TextCtrl () -> Coordinate -> Coordinate -> IO ()
Outputs the Argh! error message. If the Bool value is True, it appends the location (x,y) where the error occurred (the two Int parameters).
makeFileMenu :: Frame () -> Var String -> Var String -> TextCtrl () -> TextCtrl () -> IO (Menu ())
Creates the File menu.
makeHelpMenu :: Frame () -> IO (Menu ())
Creates the Help menu.
makeEditMenu :: Frame () -> TextCtrl () -> IO (Menu ())
Creates the Edit menu.
onFileNew :: Frame () -> Var String -> TextCtrl () -> IO ()
Handles the New option in the File menu.
onFileOpen :: Frame () -> Var String -> TextCtrl () -> IO ()
Handles the Open option in the File menu.
onFileSave :: Frame () -> Var String -> TextCtrl () -> IO ()
Handles the Save option in the File menu.
onFileSaveAs :: Frame () -> Var String -> TextCtrl () -> IO ()
Handles the Save as option in the File menu.
onFileSaveOutput :: Frame () -> Var String -> TextCtrl () -> IO ()
Handles the Save output option in the File menu.
onFileSaveOutputAs :: Frame () -> Var String -> TextCtrl () -> IO ()
Handles the Save output as option in the File menu.
onEditAppend :: Frame () -> TextCtrl () -> IO ()
Handles the Append output option in the Edit menu.
onHelpAbout :: Frame () -> IO ()
Handles the About option in the Help menu.
Produced by Haddock version 0.8