|
|
|
|
|
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 structures
|
|
data ArghStack |
Constructors | | Instances | |
|
|
data ArghGrid |
Constructors | Grid [[ArghCell]] | An Argh! program is a two-dimensional grid of ArghCell elements.
|
| Instances | |
|
|
data ArghCell |
Constructors | Cell Int | Every cell of the ArghGrid can store an Int.
| Undefined | An existing but undefined cell (cells outside the ArghGrid don't exist).
|
| Instances | |
|
|
data ArghDirection |
Valid directions (control flow of an Argh! program).
| Constructors | ArghUp | | ArghRight | | ArghDown | | ArghLeft | |
| Instances | |
|
|
data ArghPointer |
Constructors | | 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).
| -> String | The input (not the source code).
| -> ArghStack | | -> Bool | Show 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).
| -> Bool | Output 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).
| -> String | The input (not the source code).
| -> ArghStack | | -> Bool | Show error location in error message yes/no.
| -> (Coordinate -> Coordinate) | Used to calculate new y-coordinate.
| -> Bool | Output 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).
| -> String | The input (not the source code).
| -> ArghStack | | -> Bool | Show error location in error message yes/no.
| -> (ArghStack -> Maybe ArghStack) | The stack operation, see dupl and delst.
| -> Bool | Output 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).
| -> String | The input (not the source code).
| -> ArghStack | | -> Bool | Show 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.
| -> Bool | Output 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).
| -> String | The input (not the source code).
| -> ArghStack | | -> Bool | Show error location in error message yes/no.
| -> (Coordinate -> Coordinate) | Used to calculate the new y-coordinate.
| -> Bool | Output 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).
| -> String | The input (not the source code).
| -> ArghStack | | -> Bool | Show error location in error message yes/no.
| -> (Coordinate -> Coordinate) | Used to calculate the new y-coordinate.
| -> Bool | Output 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).
| -> String | The input (not the source code).
| -> ArghStack | | -> Bool | Show error location in error message yes/no.
| -> (Coordinate -> Coordinate) | Used to calculate the new y-coordinate.
| -> Bool | Output 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' |
|
|
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 |