arghwxhaskell (empty) → 0.8.1.0
raw patch · 5 files changed
+1318/−0 lines, 5 filesdep +basedep +directorydep +wxsetup-changed
Dependencies added: base, directory, wx
Files
- Argh.hs +927/−0
- GPL.txt +339/−0
- Readme.txt +22/−0
- Setup.hs +2/−0
- arghwxhaskell.cabal +28/−0
+ Argh.hs view
@@ -0,0 +1,927 @@+{- An interpreter for the Argh! programming language in wxHaskell + + Copyright (C) 2007 Simeon Visser + Contact: svisser@cs.uu.nl + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +-} +{- | +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 +-} + +-- module ArghInterpreter where +module Main where + +import System.Directory (doesFileExist) +import Data.Char (chr, ord) +import Data.Maybe (listToMaybe, catMaybes) +import Data.List (intersperse, findIndices) +import Data.Ix (inRange) +import Graphics.UI.WX + +-- * Data structures + +data ArghStack + = Stack [Int] -- ^ The stack. + deriving (Show) +data ArghGrid + -- | An Argh! program is a two-dimensional grid of 'ArghCell' elements. + = Grid [[ArghCell]] + deriving (Show) +data ArghCell + -- | Every cell of the 'ArghGrid' can store an @Int@. + = Cell Int + -- | An existing but undefined cell (cells outside the 'ArghGrid' don't exist). + | Undefined + deriving (Show) + +-- | Valid directions (control flow of an Argh! program). +data ArghDirection = ArghUp | ArghRight | ArghDown | ArghLeft +data ArghPointer + -- | The pointer stores an 'ArghDirection' and a position (x,y). + = Pointer ArghDirection Coordinate Coordinate + deriving (Show) + +instance (Show ArghDirection) where + show ArghUp = "Going up!\n" + show ArghRight = "Going right!\n" + show ArghDown = "Going down!\n" + show ArghLeft = "Going left!\n" + +type Coordinate = Int +type ErrorMessage = String +type ArghProgram = [String] + +-- * Constants + +-- | Version number. +version :: Float +version = 0.8 + +{- | +Maximum width; the interpreter complains when a line +is longer than this number of characters. Default maximum width is 80. +-} +maxWidth :: Int +maxWidth = 80 + +{- | +Maximum height; the interpreter complains when the program +consists of more than this number of lines. Default maximum height is 40. +-} +maxHeight :: Int +maxHeight = 40 + +{- | +This is used to specify the files the user can open in the Open dialogs. +-} +openFiles :: [(String,[String])] +openFiles = + [ ("Argh! programs (*.agh)",["*.agh"]) + , ("Any file (*.*)",["*.*"]) ] + +{- | +This is used to specify the files the user can save in the Save dialogs. +-} +saveFiles :: [(String,[String])] +saveFiles = [("Argh! programs (*.agh)", ["*.agh"])] + +{- | +This is used to specify the output files. +-} +outputFiles :: [(String, [String])] +outputFiles = + [ ("Text files (*.txt)", ["*.txt"]) + , ("Any file (*.*)",["*.*"]) ] + +-- * Argh! interpreter + +{- | +The main function. Call this to start the interpreter. +-} +main :: IO () +main = start interpreter + +{- | +The program; initializes variables to store state, creates the +controls for the user interface and creates the layout. +-} +interpreter :: IO () +interpreter = do + stack <- variable [ value := Stack [ ] ] + + -- variables + bRunWithErrors <- variable [ value := False ] + bShowLocation <- variable [ value := False ] + bShowFullTrace <- variable [ value := False ] + + filepath <- variable [ value := "Default.agh" ] + filepath' <- variable [ value := "Output.txt" ] + + -- the frame + f <- frame [ text := ("Argh! interpreter v" ++ (show version)) + , resizeable := False ] + + -- text controls + code <- textCtrlRich f [ font := fontFixed, wrap := WrapNone ] + console <- textCtrlRich f [ font := fontFixed, wrap := WrapNone ] + input <- textEntry f [] + + -- the buttons + check <- button f [ text := "Validate" + , on command := buttonCheckCode f code console + , tooltip := "Validates the current Argh! program " ] + run <- button f [ text := "Run" + , on command := run code console input stack + bRunWithErrors bShowLocation bShowFullTrace + , tooltip := "Runs the current Argh! program" ] + + -- checkboxes + cb1 <- checkBox f [ text := "Run even invalid code (unsafe)" + , on command := set bRunWithErrors [ value :~ not ] + , tooltip := "Enable to allow execution of invalid code" ] + cb2 <- checkBox f [ text := "Show location (x,y) when error occurs" + , on command := set bShowLocation [ value :~ not ] + , tooltip := "Enable to show the location in an error message" ] + cb3 <- checkBox f [ text := "Output all executed commands" + , on command := set bShowFullTrace [ value :~ not ] + , tooltip := "Enable to output all executed commands" + ] + + -- statusbar + status <- statusField [] + set f [ statusBar := [ status ] ] + + -- the menubar + mfile <- makeFileMenu f filepath filepath' code console + medit <- makeEditMenu f code + mhelp <- makeHelpMenu f + + set f [ menuBar := [ mfile, medit, mhelp ] ] + + -- layout + set f [ layout := margin 5 $ grid 5 5 $ + [ [ row 5 [ column 5 [ boxed "Argh!".fill.minsize (sz 550 300).widget $ code + , boxed "Input".fill.widget $ input + , boxed "Output".fill.widget $ console ] + , column 5 [ boxed "Settings" $ + column 5 [ alignCenter.row 5 $ [ widget run, widget check ] + , widget cb1 + , widget cb2 + , widget cb3 + ] + ] ] + ] + ] + ] + +{- | +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). +-} +run :: TextCtrl () -> TextCtrl () -> TextCtrl () -> Var ArghStack -> Var Bool + -> Var Bool -> Var Bool -> IO () +run code console input vstack vbRunWithErrors vbShowLocation + vbShowFullTrace = do + txt <- get code text + stack <- varGet vstack + bRunWithErrors <- varGet vbRunWithErrors + bShowLoc <- varGet vbShowLocation + bShowFullTrace <- varGet vbShowFullTrace + set console [ text := "" ] + let program = lines txt + case arghCompliant program of + Just msg -> do + case bRunWithErrors of + False -> set console [ text := "Argh! invalid:\n" ++ msg ] + True -> do + let grid = makeGrid program + input' <- get input text + exec grid (Pointer ArghLeft 1 1) console input' stack bShowLoc bShowFullTrace + Nothing -> do + let grid = makeGrid program + input' <- get input text + exec grid (Pointer ArghLeft 1 1) console input' stack bShowLoc bShowFullTrace + +{- | +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. +-} +exec :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack -> Bool + -> Bool -> IO () +exec grid ptr@(Pointer dir x y) console input stack bShowLoc bShowFullTrace = do + case getGrid grid x y of + Just (Cell s) -> do + case chr s of + ' ' -> exec grid (move dir ptr) console input stack bShowLoc bShowFullTrace + 'q' -> set console [ text :~ (++ "\nProgram terminated succesfully.\n") ] + 'h' -> do if bShowFullTrace then appendText console (show ArghLeft) else return () + exec grid (move ArghLeft ptr) console input stack bShowLoc bShowFullTrace + 'j' -> do if bShowFullTrace then appendText console (show ArghDown) else return () + exec grid (move ArghDown ptr) console input stack bShowLoc bShowFullTrace + 'k' -> do if bShowFullTrace then appendText console (show ArghUp) else return () + exec grid (move ArghUp ptr) console input stack bShowLoc bShowFullTrace + 'l' -> do if bShowFullTrace then appendText console (show ArghRight) else return () + exec grid (move ArghRight ptr) console input stack bShowLoc bShowFullTrace + 'H' -> do if bShowFullTrace then appendText console "Going left, looking for value equal to value on top of stack!\n" else return () + gridMove' grid (move ArghLeft ptr) console input stack bShowLoc bShowFullTrace + 'J' -> do if bShowFullTrace then appendText console "Going down, looking for value equal to value on top of stack!\n" else return () + gridMove' grid (move ArghDown ptr) console input stack bShowLoc bShowFullTrace + 'K' -> do if bShowFullTrace then appendText console "Going up, looking for value equal to value on top of stack!\n" else return () + gridMove' grid (move ArghUp ptr) console input stack bShowLoc bShowFullTrace + 'L' -> do if bShowFullTrace then appendText console "Going right, looking for value equal to value on top of stack!\n" else return () + gridMove' grid (move ArghDown ptr) console input stack bShowLoc bShowFullTrace + 'x' -> do turnCond grid ptr console input stack bShowLoc (>= 0) turnRight bShowFullTrace + 'X' -> do turnCond grid ptr console input stack bShowLoc (<= 0) turnLeft bShowFullTrace + 's' -> do store grid ptr console input stack bShowLoc (+1) bShowFullTrace + 'S' -> do store grid ptr console input stack bShowLoc ((+) (-1)) bShowFullTrace + 'd' -> do dupDel grid ptr console input stack bShowLoc dupl bShowFullTrace + 'D' -> do dupDel grid ptr console input stack bShowLoc delst bShowFullTrace + 'a' -> do addRed grid ptr console input stack bShowLoc (+1) addst bShowFullTrace + 'A' -> do addRed grid ptr console input stack bShowLoc ((+) (-1)) addst bShowFullTrace + 'r' -> do addRed grid ptr console input stack bShowLoc (+1) redst bShowFullTrace + 'R' -> do addRed grid ptr console input stack bShowLoc ((+) (-1)) redst bShowFullTrace + 'f' -> do popStack grid ptr console input stack bShowLoc (+1) bShowFullTrace + 'F' -> do popStack grid ptr console input stack bShowLoc ((+) (-1)) bShowFullTrace + 'p' -> do showCell grid ptr console input stack bShowLoc (+1) bShowFullTrace + 'P' -> do showCell grid ptr console input stack bShowLoc ((+) (-1)) bShowFullTrace + 'g' -> do readStore grid ptr console input stack bShowLoc (+1) bShowFullTrace + 'G' -> do readStore grid ptr console input stack bShowLoc ((+) (-1)) bShowFullTrace + '#' -> do + case (x,y) == (1,1) of + False -> arghError bShowLoc console x y + True -> do + case getGrid grid 2 1 of + Just (Cell i) -> do + case i == ord '!' of + False -> arghError bShowLoc console x y + True -> exec grid (move ArghDown ptr) console input stack bShowLoc bShowFullTrace + _ -> arghError bShowLoc console x y + _ -> do arghError bShowLoc console x y + Just Undefined -> + case validPos x y of + False -> arghError bShowLoc console x y + True -> exec grid (move dir ptr) console input stack bShowLoc bShowFullTrace + _ -> arghError bShowLoc console x y + +-- ** Command processing + +{- | +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'. +-} +gridMove' :: ArghGrid -> ArghPointer -> TextCtrl () -> String -> ArghStack + -> Bool -> Bool -> IO () +gridMove' grid ptr@(Pointer dir x y) console input stack bShowLoc bShowFullTrace = do + case gridMove grid ptr (getTop stack) of + Nothing -> arghError bShowLoc console x y + Just (a,b) -> do + if bShowFullTrace then appendText console "Found value!\n" else return () + exec grid (move dir (Pointer dir a b)) console input stack bShowLoc bShowFullTrace + +{- | +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. +-} +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 () +turnCond grid ptr@(Pointer dir x y) console input stack bShowLoc cond f bShowFullTrace = do + case getTop stack of + Nothing -> arghError bShowLoc console x y + Just n -> + case cond n of + False -> exec grid (move dir ptr) console input stack bShowLoc bShowFullTrace + True -> do + let newdir = f dir + if bShowFullTrace then appendText console (show newdir) else return() + exec grid (move newdir ptr) console input stack bShowLoc bShowFullTrace + +{- | +Used for the @s@ and @S@ commands. Pushes the value in the 'ArghCell' above or below +the current one on the stack. +-} +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 () +store grid ptr@(Pointer dir x y) console input stack bShowLoc f bShowFullTrace = do + case getGrid grid x (f y) of + Just (Cell i) -> do + let stack' = push stack i + if bShowFullTrace then viewStack stack' console else return () + exec grid (move dir ptr) console input stack' bShowLoc bShowFullTrace + _ -> arghError bShowLoc console x y + + +{- | +Used for the @d@ and @D@ commands. Duplicates or deletes the value on top off the +stack, if it exists. +-} +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 () +dupDel grid ptr@(Pointer dir x y) console input stack bShowLoc f bShowFullTrace= do + case f stack of + Nothing -> arghError bShowLoc console x y + Just stack' -> do + if bShowFullTrace then viewStack stack' console else return () + exec grid (move dir ptr) console input stack' bShowLoc bShowFullTrace + +{- | +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. +-} +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 () +addRed grid ptr@(Pointer dir x y) console input stack bShowLoc f g bShowFullTrace = do + case getGrid grid x (f y) of + Just (Cell i) -> do + case g stack i of + Nothing -> arghError bShowLoc console x y + Just stack' -> do + if bShowFullTrace then viewStack stack' console else return () + exec grid (move dir ptr) console input stack' bShowLoc bShowFullTrace + _ -> arghError bShowLoc console x y + +{- | +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. +-} +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 () +popStack grid ptr@(Pointer dir x y) console input stack bShowLoc f bShowFullTrace= do + let (pop', stack') = pop stack + case pop' of + Nothing -> arghError bShowLoc console x y + Just i -> + case validPos x (f y) of + False -> do + if bShowFullTrace then viewStack stack' console else return () + arghError bShowLoc console x y + True -> + case setGrid grid x (f y) i of + Nothing -> do + if bShowFullTrace then viewStack stack' console else return () + arghError bShowLoc console x y + Just grid' -> do + if bShowFullTrace then viewStack stack' console else return () + exec grid' (move dir ptr) console input stack' bShowLoc bShowFullTrace + +{- | +Used for the @p@ and @P@ commands. Showing the value of 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 () +showCell grid ptr@(Pointer dir x y) console input stack bShowLoc f bShowFullTrace = do + case getGrid grid x (f y) of + Just (Cell i) -> do + let c = chr i + appendText console [c] + exec grid (move dir ptr) console input stack bShowLoc bShowFullTrace + _ -> arghError bShowLoc console x y + +{- | +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. +-} +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 () +readStore grid ptr@(Pointer dir x y) console input stack bShowLoc f bShowFullTrace = do + case null input of + True -> arghError bShowLoc console x y + False -> do + case getGrid grid x (f y) of + Nothing -> arghError bShowLoc console x y + _ -> do + let value = ord.head $ input + case setGrid grid x (f y) value of + Nothing -> arghError bShowLoc console x y + Just grid' -> do + if bShowFullTrace then appendText console ("Storing: " ++ show value) else return () + exec grid' (move dir ptr) console (tail input) stack bShowLoc bShowFullTrace + +-- | Returns an 'ArghPointer' that has been moved in the given 'ArghDirection'. +move :: ArghDirection -> ArghPointer -> ArghPointer +move ArghLeft = move' ((+) (-1)) id ArghLeft +move ArghRight = move' ((+) 1) id ArghRight +move ArghUp = move' id ((+) (-1)) ArghUp +move ArghDown = move' id ((+) 1) ArghDown + +{- | +Applies the two functions to the location of the 'ArghPointer'. It returns +a new 'ArghPointer' with the given 'ArghDirection' and the new position. +-} +move' :: (Coordinate -> Coordinate) -- ^ Will be applied to the x-coordinate. + -> (Coordinate -> Coordinate) -- ^ Will be applied to the y-coordinate. + -> ArghDirection -> ArghPointer -> ArghPointer +move' f g dir (Pointer _ x y) = (Pointer dir (f x) (g y)) + +-- ** Stack operations + +-- | Returns the contents of an 'ArghStack'. +viewS :: ArghStack -> [Int] +viewS (Stack s) = s + +-- | Outputs the contents of the 'ArghStack' to the specified @TextCtrl@. +viewStack :: ArghStack -> TextCtrl () -> IO () +viewStack (Stack xs) console = + appendText console ("Stack: " ++ show xs ++ "\n") + +-- | Returns the value on top of the stack (@Just@), else @Nothing@. +getTop :: ArghStack -> Maybe Int +getTop = listToMaybe.viewS + +-- | Pushes the value on the 'ArghStack'. +push :: ArghStack -> Int -> ArghStack +push s x = Stack (x : viewS s) + +{- | +Pops the value off the 'ArghStack'. It returns the +popped value (if it exists) and the new stack. +-} +pop :: ArghStack -> (Maybe Int, ArghStack) +pop s@(Stack []) = (Nothing, s) +pop (Stack (x:xs)) = (Just x, Stack xs) + +-- | Duplicates the value on top of the 'ArghStack', if it exists. +dupl :: ArghStack -> Maybe ArghStack +dupl (Stack xs) = checkToMaybe xs (Stack ((head xs):xs)) + +-- | Deletes the value on top of the 'ArghStack', if it exists. +delst :: ArghStack -> Maybe ArghStack +delst (Stack xs) = checkToMaybe xs (Stack (tail xs)) + +-- | Redures the value on top of the 'ArghStack', if it exists, by the given value. +redst :: ArghStack -> Int -> Maybe ArghStack +redst = opst (-) + +-- | Add the given value to the value on top of the 'ArghStack', if it exists. +addst :: ArghStack -> Int -> Maybe ArghStack +addst = opst (+) + +{- | +Applies the function and the value to the value on top of the 'ArghStack'. +Returns the new stack if succesful. +-} +opst :: (Int -> Int -> Int) -> ArghStack -> Int -> Maybe ArghStack +opst f (Stack xs) i = checkToMaybe xs (Stack ((f (head xs) i):(tail xs))) + +-- ** Grid operations + +{- | +Sets the value of a value in the 'ArghGrid'. It returns the new grid if +succesful. +-} +setGrid :: ArghGrid -> Coordinate -> Coordinate -> Int -> Maybe ArghGrid +setGrid grid@(Grid list) x y value = + if not (validPos x y) + then Nothing + else + case getRow grid y of + Nothing -> Nothing + Just l -> + let newrow = [concat [(take (x-1) l), [(Cell value)], (drop x l)]] + in let newlist = concat [(take (y-1) list), newrow, (drop y list)] + in Just (Grid newlist) + +{- | +Moves the 'ArghPointer' over the 'ArghGrid', looking for a specific value. +Returns the location of the cell where it is found, else @Nothing@. +-} +gridMove :: ArghGrid -> ArghPointer -> Maybe Int -> Maybe (Coordinate, Coordinate) +gridMove _ _ Nothing = Nothing +gridMove grid ptr@(Pointer dir x y) k@(Just value) = + case getGrid grid x y of + Just (Cell c) -> + case c == value of + True -> Just (x,y) + False -> gridMove grid (move dir ptr) k + _ -> Nothing + +{- | +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'. +-} +makeGrid :: ArghProgram -> ArghGrid +makeGrid s = Grid z2 + where f = map ((.) Cell ord) + g x = let i = length x in if i < maxHeight then x ++ k i else x + k i = take (maxHeight-i) (repeat Undefined) + z = map (g.f) s + z2 = let j = length z in if j < maxWidth then z ++ replicate (maxWidth-j) (k 0) else z + +{- | +Returns a row in the 'ArghGrid', if it exists. +-} +getRow :: ArghGrid -> Int -> Maybe [ArghCell] +getRow (Grid list) n = checkToMaybe' (not.inRange (1,maxWidth) $ n) (list !! (n-1)) + +{- | +Returns the value of a specific 'ArghCell' in the 'ArghGrid', if it exists. +-} +getGrid :: ArghGrid -> Coordinate -> Coordinate -> Maybe ArghCell +getGrid _ 0 _ = Nothing +getGrid _ _ 0 = Nothing +getGrid grid@(Grid list) x y = + case getRow grid y of + Nothing -> Nothing + Just list -> + let dropped = drop (x-1) list + in checkToMaybe dropped (head dropped) + +-- | Returns @True@ if it's a valid position (x,y). +validPos :: Coordinate -> Coordinate -> Bool +validPos x y = inRange (1,maxHeight) x && inRange (1,maxWidth) y + +-- ** Code validation + +{- | +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'. +-} +arghCompliant :: ArghProgram -> Maybe ErrorMessage +arghCompliant [] = Just "There's no program!" +arghCompliant s = checkToMaybe k k + where k = concat.catMaybes $ [ isDir.head.head $ s, checkToMaybe l l ] + l = concat.catMaybes $ [checkHeight s, checkWidth s, checkChar s] + isDir x = checkToMaybe' (any (==x) "hjkl") string + string = concat [ "Character at (1,1) doesn't specify an execution direction.\n" + , "Use 'h' for left, 'j' for down, 'k' for up or 'l' for right.\n" ] + +{- | +Checks the width of the 'ArghProgram'. +-} +checkWidth :: ArghProgram -> Maybe ErrorMessage +checkWidth s = let k = checkLength.map length $ s in checkToMaybe k k + +{- | +Checks the length of the list of @Int@ (each @Int@ is the length of a specific line). +-} +checkLength :: [Int] -> ErrorMessage +checkLength s = + let f (a,b) = concat [ "Line ", show a, " has a length of " + , show b, " characters."] + in unlines [ f x | x <- (zip [1..] s), (snd x) > maxWidth ] + +{- | +Checks the height of the 'ArghProgram'. Returns +an 'ErrorMessage' if needed, else @Nothing@. +-} +checkHeight :: ArghProgram -> Maybe ErrorMessage +checkHeight s = + let k = length s + in checkToMaybe' (k <= maxWidth) (concat ["Too many lines: ", show k, ".\n"]) + +{- | +Checks a line for invalid characters. Returns an 'ErrorMessage' if needed, +else @Nothing@. +-} +checkLine :: String -> Maybe ErrorMessage +checkLine list = let x = g list in checkToMaybe x (j x) + where j = concat.intersperse ", ".map show + g = map (+1).findIndices (not.validChar) + +{- | +Checks an 'ArghProgram' for invalid characters. Returns +an 'ErrorMessage' if needed, else @Nothing@. +-} +checkChar :: ArghProgram -> Maybe ErrorMessage +checkChar s = let k = checkChar' s in checkToMaybe k (unlines k) + where checkChar' s = + let f (a,b) = (a, checkLine b) + in filter (not.null) $ [ checkChar2.f $ x | x <- (zip [1..] s) ] + checkChar2 (_, Nothing) = "" + checkChar2 (n, Just x) = + concat [ "Invalid character(s) (Line: ", show n, ", Position(s): ", x, ")." ] + +{- | +Returns @True@ for valid characters. Valid characters have ASCII value 32 - 127 +or newline (10). +-} +validChar :: Char -> Bool +validChar c = let ordc = ord c in ordc >= 32 && ordc < 127 || ordc == 10 + +-- * Miscellaneous + +-- | Returns @Just b@ if the list is not empty, else @Nothing@. +checkToMaybe :: [a] -> b -> Maybe b +checkToMaybe xs = checkToMaybe' (null xs) + +-- | Returns @Just a@ if @False@, else @Nothing@. +checkToMaybe' :: Bool -> a -> Maybe a +checkToMaybe' True _ = Nothing +checkToMaybe' False j = Just j + +-- | Turns right. +turnRight :: ArghDirection -> ArghDirection +turnRight ArghUp = ArghRight +turnRight ArghRight = ArghDown +turnRight ArghDown = ArghLeft +turnRight ArghLeft = ArghUp + +-- | Turns left. +turnLeft :: ArghDirection -> ArghDirection +turnLeft = turnRight.turnRight.turnRight + +-- * User interface + +{- | +Restores the settings (font, wrapping) of the @TextCtrl@. +-} +restoreSettings :: TextCtrl () -> IO () +restoreSettings code = set code [ text := "", font := fontFixed, wrap := WrapNone ] + +{- | +Used for the /Validate/ button (outputs if the Argh! program is valid or not). +-} +buttonCheckCode :: Frame () + -> TextCtrl () -- ^ @TextCtrl@ containing the Argh! source code + -> TextCtrl () -- ^ @TextCtrl@ containing the output. + -> IO () +buttonCheckCode f code console = do + txt <- get code text + case arghCompliant (lines txt) of + Nothing -> set console [ text := "Argh! OK!" ] + Just msg -> set console [ text := "Argh! invalid:\n" ++ msg ] + +{- | +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). +-} +arghError :: Bool -> TextCtrl () -> Coordinate -> Coordinate -> IO () +arghError bShowLocation console x y = + case bShowLocation of + False -> set console [ text :~ (++ "Argh!") ] + True -> + let z = concat [ "Argh! (", show x, ",", show y, ")" ] + in set console [ text :~ (++ z) ] + +-- | Creates the File menu. +makeFileMenu :: Frame () -> Var String -> Var String + -> TextCtrl () -> TextCtrl () -> IO (Menu ()) +makeFileMenu f filepath filepath' code console = do + mfile <- menuPane [ text := "&File" ] + mnew <- menuItem mfile [ text := "&New\tCtrl+N" + , on command := onFileNew f filepath code + , help := "Create a new Argh! program" ] + mopen <- menuItem mfile [ text := "&Open...\tCtrl+O" + , on command := onFileOpen f filepath code + , help := "Open an existing Argh! program" ] + msave <- menuItem mfile [ text := "&Save\tCtrl+S" + , on command := onFileSave f filepath code + , help := "Save the current Argh! program" ] + msaveas <- menuItem mfile [ text := "Save &as..." + , on command := onFileSaveAs f filepath code + , help := "Save the current Argh! program with a new name" ] + menuLine mfile + msaveoutput <- menuItem mfile [ text := "Save output" + , on command := onFileSaveOutput f filepath' console + , help := "Save the output" ] + msaveoutputas <- menuItem mfile [ text := "Save output as..." + , on command := onFileSaveOutputAs f filepath' console + , help := "Save the output with a new name" ] + menuLine mfile + mquit <- menuQuit mfile [ on command := close f + , help := "Exit the program" ] + return mfile + +-- | Creates the Help menu. +makeHelpMenu :: Frame () -> IO (Menu ()) +makeHelpMenu f = do + mhelp <- menuPane [ text := "&Help" ] + mabout <- menuAbout mhelp [ help := "About this Argh! interpreter" + , on command := onHelpAbout f ] + return mhelp + +-- | Creates the Edit menu. +makeEditMenu :: Frame () -> TextCtrl () -> IO (Menu ()) +makeEditMenu f code = do + medit <- menuPane [ text := "&Edit" ] + mappend <- menuItem medit [ text := "&Append file..." + , on command := onEditAppend f code + , help := "Append the contents of a file" ] + return medit + +-- | Handles the New option in the File menu. +onFileNew :: Frame () -> Var String -> TextCtrl () -> IO () +onFileNew f filepath code = do + txt <- get code text + case null txt of + True -> return () + False -> do + result <- confirmDialog f "Argh!" "The current Argh! program will be lost. Want to save?" True + case result of + False -> restoreSettings code + True -> do + filepath' <- get filepath value + result <- fileSaveDialog f True True "Save Argh! program" saveFiles filepath' "" + case result of + Nothing -> return () + Just path -> do + set filepath [ value := path ] + writeFile path txt + restoreSettings code + +-- | Handles the Open option in the File menu. +onFileOpen :: Frame () -> Var String -> TextCtrl () -> IO () +onFileOpen f filepath code = do + result <- fileOpenDialog f True True "Open Argh! program" openFiles "" "" + case result of + Nothing -> return () + Just path -> do + exists <- doesFileExist path + case exists of + False -> return () + True -> do + contents <- readFile path + restoreSettings code + set code [ text := contents ] + set filepath [ value := path ] + +-- | Handles the Save option in the File menu. +onFileSave :: Frame () -> Var String -> TextCtrl () -> IO () +onFileSave f filepath code = do + txt <- get code text + filepath' <- get filepath value + writeFile filepath' txt + +-- | Handles the Save as option in the File menu. +onFileSaveAs :: Frame () -> Var String -> TextCtrl () -> IO () +onFileSaveAs f filepath code = do + txt <- get code text + filepath' <- get filepath value + result <- fileSaveDialog f True True "Save Argh! program" saveFiles filepath' "" + case result of + Nothing -> return () + Just path -> do + set filepath [ value := path ] + writeFile path txt + +-- | Handles the Save output option in the File menu. +onFileSaveOutput :: Frame () -> Var String -> TextCtrl () -> IO () +onFileSaveOutput f filepath console = do + output <- get console text + filepath' <- get filepath value + writeFile filepath' output + +-- | Handles the Save output as option in the File menu. +onFileSaveOutputAs :: Frame () -> Var String -> TextCtrl () -> IO () +onFileSaveOutputAs f filepath console = do + output <- get console text + filepath' <- get filepath value + result <- fileSaveDialog f True True "Save output" outputFiles filepath' "" + case result of + Nothing -> return () + Just path -> do + set filepath [ value := path ] + writeFile path output + +-- | Handles the Append output option in the Edit menu. +onEditAppend :: Frame () -> TextCtrl () -> IO () +onEditAppend f code = do + result <- fileOpenDialog f True True "Append file" openFiles "" "" + case result of + Nothing -> return () + Just path -> do + exists <- doesFileExist path + case exists of + False -> return () + True -> do + currentCode <- get code text + contents <- readFile path + restoreSettings code + set code [ text := (currentCode ++ contents) ] + +-- | Handles the About option in the Help menu. +onHelpAbout :: Frame () -> IO () +onHelpAbout f = do + let string = unlines [ "Version " ++ show version ++ " - Created by Simeon Visser, February 2007." + , "" + , "For more information, see included readme and documentation." + , "" + , "Available under the GNU General Public License." ] + infoDialog f "About this Argh! interpreter" string
+ GPL.txt view
@@ -0,0 +1,339 @@+ GNU GENERAL PUBLIC LICENSE+ Version 2, June 1991++ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++ Preamble++ The licenses for most software are designed to take away your+freedom to share and change it. By contrast, the GNU General Public+License is intended to guarantee your freedom to share and change free+software--to make sure the software is free for all its users. This+General Public License applies to most of the Free Software+Foundation's software and to any other program whose authors commit to+using it. (Some other Free Software Foundation software is covered by+the GNU Lesser General Public License instead.) You can apply it to+your programs, too.++ When we speak of free software, we are referring to freedom, not+price. Our General Public Licenses are designed to make sure that you+have the freedom to distribute copies of free software (and charge for+this service if you wish), that you receive source code or can get it+if you want it, that you can change the software or use pieces of it+in new free programs; and that you know you can do these things.++ To protect your rights, we need to make restrictions that forbid+anyone to deny you these rights or to ask you to surrender the rights.+These restrictions translate to certain responsibilities for you if you+distribute copies of the software, or if you modify it.++ For example, if you distribute copies of such a program, whether+gratis or for a fee, you must give the recipients all the rights that+you have. You must make sure that they, too, receive or can get the+source code. And you must show them these terms so they know their+rights.++ We protect your rights with two steps: (1) copyright the software, and+(2) offer you this license which gives you legal permission to copy,+distribute and/or modify the software.++ Also, for each author's protection and ours, we want to make certain+that everyone understands that there is no warranty for this free+software. If the software is modified by someone else and passed on, we+want its recipients to know that what they have is not the original, so+that any problems introduced by others will not reflect on the original+authors' reputations.++ Finally, any free program is threatened constantly by software+patents. We wish to avoid the danger that redistributors of a free+program will individually obtain patent licenses, in effect making the+program proprietary. To prevent this, we have made it clear that any+patent must be licensed for everyone's free use or not licensed at all.++ The precise terms and conditions for copying, distribution and+modification follow.++ GNU GENERAL PUBLIC LICENSE+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION++ 0. This License applies to any program or other work which contains+a notice placed by the copyright holder saying it may be distributed+under the terms of this General Public License. The "Program", below,+refers to any such program or work, and a "work based on the Program"+means either the Program or any derivative work under copyright law:+that is to say, a work containing the Program or a portion of it,+either verbatim or with modifications and/or translated into another+language. (Hereinafter, translation is included without limitation in+the term "modification".) Each licensee is addressed as "you".++Activities other than copying, distribution and modification are not+covered by this License; they are outside its scope. The act of+running the Program is not restricted, and the output from the Program+is covered only if its contents constitute a work based on the+Program (independent of having been made by running the Program).+Whether that is true depends on what the Program does.++ 1. You may copy and distribute verbatim copies of the Program's+source code as you receive it, in any medium, provided that you+conspicuously and appropriately publish on each copy an appropriate+copyright notice and disclaimer of warranty; keep intact all the+notices that refer to this License and to the absence of any warranty;+and give any other recipients of the Program a copy of this License+along with the Program.++You may charge a fee for the physical act of transferring a copy, and+you may at your option offer warranty protection in exchange for a fee.++ 2. You may modify your copy or copies of the Program or any portion+of it, thus forming a work based on the Program, and copy and+distribute such modifications or work under the terms of Section 1+above, provided that you also meet all of these conditions:++ a) You must cause the modified files to carry prominent notices+ stating that you changed the files and the date of any change.++ b) You must cause any work that you distribute or publish, that in+ whole or in part contains or is derived from the Program or any+ part thereof, to be licensed as a whole at no charge to all third+ parties under the terms of this License.++ c) If the modified program normally reads commands interactively+ when run, you must cause it, when started running for such+ interactive use in the most ordinary way, to print or display an+ announcement including an appropriate copyright notice and a+ notice that there is no warranty (or else, saying that you provide+ a warranty) and that users may redistribute the program under+ these conditions, and telling the user how to view a copy of this+ License. (Exception: if the Program itself is interactive but+ does not normally print such an announcement, your work based on+ the Program is not required to print an announcement.)++These requirements apply to the modified work as a whole. If+identifiable sections of that work are not derived from the Program,+and can be reasonably considered independent and separate works in+themselves, then this License, and its terms, do not apply to those+sections when you distribute them as separate works. But when you+distribute the same sections as part of a whole which is a work based+on the Program, the distribution of the whole must be on the terms of+this License, whose permissions for other licensees extend to the+entire whole, and thus to each and every part regardless of who wrote it.++Thus, it is not the intent of this section to claim rights or contest+your rights to work written entirely by you; rather, the intent is to+exercise the right to control the distribution of derivative or+collective works based on the Program.++In addition, mere aggregation of another work not based on the Program+with the Program (or with a work based on the Program) on a volume of+a storage or distribution medium does not bring the other work under+the scope of this License.++ 3. You may copy and distribute the Program (or a work based on it,+under Section 2) in object code or executable form under the terms of+Sections 1 and 2 above provided that you also do one of the following:++ a) Accompany it with the complete corresponding machine-readable+ source code, which must be distributed under the terms of Sections+ 1 and 2 above on a medium customarily used for software interchange; or,++ b) Accompany it with a written offer, valid for at least three+ years, to give any third party, for a charge no more than your+ cost of physically performing source distribution, a complete+ machine-readable copy of the corresponding source code, to be+ distributed under the terms of Sections 1 and 2 above on a medium+ customarily used for software interchange; or,++ c) Accompany it with the information you received as to the offer+ to distribute corresponding source code. (This alternative is+ allowed only for noncommercial distribution and only if you+ received the program in object code or executable form with such+ an offer, in accord with Subsection b above.)++The source code for a work means the preferred form of the work for+making modifications to it. For an executable work, complete source+code means all the source code for all modules it contains, plus any+associated interface definition files, plus the scripts used to+control compilation and installation of the executable. However, as a+special exception, the source code distributed need not include+anything that is normally distributed (in either source or binary+form) with the major components (compiler, kernel, and so on) of the+operating system on which the executable runs, unless that component+itself accompanies the executable.++If distribution of executable or object code is made by offering+access to copy from a designated place, then offering equivalent+access to copy the source code from the same place counts as+distribution of the source code, even though third parties are not+compelled to copy the source along with the object code.++ 4. You may not copy, modify, sublicense, or distribute the Program+except as expressly provided under this License. Any attempt+otherwise to copy, modify, sublicense or distribute the Program is+void, and will automatically terminate your rights under this License.+However, parties who have received copies, or rights, from you under+this License will not have their licenses terminated so long as such+parties remain in full compliance.++ 5. You are not required to accept this License, since you have not+signed it. However, nothing else grants you permission to modify or+distribute the Program or its derivative works. These actions are+prohibited by law if you do not accept this License. Therefore, by+modifying or distributing the Program (or any work based on the+Program), you indicate your acceptance of this License to do so, and+all its terms and conditions for copying, distributing or modifying+the Program or works based on it.++ 6. Each time you redistribute the Program (or any work based on the+Program), the recipient automatically receives a license from the+original licensor to copy, distribute or modify the Program subject to+these terms and conditions. You may not impose any further+restrictions on the recipients' exercise of the rights granted herein.+You are not responsible for enforcing compliance by third parties to+this License.++ 7. If, as a consequence of a court judgment or allegation of patent+infringement or for any other reason (not limited to patent issues),+conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License. If you cannot+distribute so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you+may not distribute the Program at all. For example, if a patent+license would not permit royalty-free redistribution of the Program by+all those who receive copies directly or indirectly through you, then+the only way you could satisfy both it and this License would be to+refrain entirely from distribution of the Program.++If any portion of this section is held invalid or unenforceable under+any particular circumstance, the balance of the section is intended to+apply and the section as a whole is intended to apply in other+circumstances.++It is not the purpose of this section to induce you to infringe any+patents or other property right claims or to contest validity of any+such claims; this section has the sole purpose of protecting the+integrity of the free software distribution system, which is+implemented by public license practices. Many people have made+generous contributions to the wide range of software distributed+through that system in reliance on consistent application of that+system; it is up to the author/donor to decide if he or she is willing+to distribute software through any other system and a licensee cannot+impose that choice.++This section is intended to make thoroughly clear what is believed to+be a consequence of the rest of this License.++ 8. If the distribution and/or use of the Program is restricted in+certain countries either by patents or by copyrighted interfaces, the+original copyright holder who places the Program under this License+may add an explicit geographical distribution limitation excluding+those countries, so that distribution is permitted only in or among+countries not thus excluded. In such case, this License incorporates+the limitation as if written in the body of this License.++ 9. The Free Software Foundation may publish revised and/or new versions+of the General Public License from time to time. Such new versions will+be similar in spirit to the present version, but may differ in detail to+address new problems or concerns.++Each version is given a distinguishing version number. If the Program+specifies a version number of this License which applies to it and "any+later version", you have the option of following the terms and conditions+either of that version or of any later version published by the Free+Software Foundation. If the Program does not specify a version number of+this License, you may choose any version ever published by the Free Software+Foundation.++ 10. If you wish to incorporate parts of the Program into other free+programs whose distribution conditions are different, write to the author+to ask for permission. For software which is copyrighted by the Free+Software Foundation, write to the Free Software Foundation; we sometimes+make exceptions for this. Our decision will be guided by the two goals+of preserving the free status of all derivatives of our free software and+of promoting the sharing and reuse of software generally.++ NO WARRANTY++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,+REPAIR OR CORRECTION.++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE+POSSIBILITY OF SUCH DAMAGES.++ END OF TERMS AND CONDITIONS++ How to Apply These Terms to Your New Programs++ If you develop a new program, and you want it to be of the greatest+possible use to the public, the best way to achieve this is to make it+free software which everyone can redistribute and change under these terms.++ To do so, attach the following notices to the program. It is safest+to attach them to the start of each source file to most effectively+convey the exclusion of warranty; and each file should have at least+the "copyright" line and a pointer to where the full notice is found.++ <one line to give the program's name and a brief idea of what it does.>+ Copyright (C) <year> <name of author>++ This program is free software; you can redistribute it and/or modify+ it under the terms of the GNU General Public License as published by+ the Free Software Foundation; either version 2 of the License, or+ (at your option) any later version.++ This program is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ GNU General Public License for more details.++ You should have received a copy of the GNU General Public License along+ with this program; if not, write to the Free Software Foundation, Inc.,+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.++Also add information on how to contact you by electronic and paper mail.++If the program is interactive, make it output a short notice like this+when it starts in an interactive mode:++ Gnomovision version 69, Copyright (C) year name of author+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.+ This is free software, and you are welcome to redistribute it+ under certain conditions; type `show c' for details.++The hypothetical commands `show w' and `show c' should show the appropriate+parts of the General Public License. Of course, the commands you use may+be called something other than `show w' and `show c'; they could even be+mouse-clicks or menu items--whatever suits your program.++You should also get your employer (if you work as a programmer) or your+school, if any, to sign a "copyright disclaimer" for the program, if+necessary. Here is a sample; alter the names:++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program+ `Gnomovision' (which makes passes at compilers) written by James Hacker.++ <signature of Ty Coon>, 1 April 1989+ Ty Coon, President of Vice++This General Public License does not permit incorporating your program into+proprietary programs. If your program is a subroutine library, you may+consider it more useful to permit linking proprietary applications with the+library. If this is what you want to do, use the GNU Lesser General+Public License instead of this License.
+ Readme.txt view
@@ -0,0 +1,22 @@+An interpreter (v0.8) for the Argh! programming language + +-- Contents of this package -- + +The following files are included: + +- Readme.txt (this file) +- Argh.hs (the source) +- GPL.txt (the GNU General Public License text) +- /doc (Haddock documentation) + +-- Information -- + +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). + +The source code has been documented using Haddock. Just view that for more information about a function and the interpreter in general. + +To start the interpreter, use the "main" function. + +Simeon Visser +February 2007 +<svisser@cs.uu.nl>
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple +main = defaultMain
+ arghwxhaskell.cabal view
@@ -0,0 +1,28 @@+-- Initial arghwxhaskell.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/ + +name: arghwxhaskell +version: 0.8.1.0 +synopsis: An interpreter for the Argh! programming language in wxHaskell. +description: An interpreter for the Argh! esoteric programming language in + wxHaskell. The program allows one to load, edit, save, validate + and run Argh! programs. It currently supports all commands + except 'e' and 'E'. +homepage: https://wiki.haskell.org/Argh! +license: GPL-2 +license-file: GPL.txt +author: Simeon Visser +maintainer: - +-- copyright: +category: Language +build-type: Simple +extra-source-files: Readme.txt +cabal-version: >=1.10 + +executable arghwxhaskell + main-is: Argh.hs + -- other-modules: + -- other-extensions: + build-depends: base >=4.8 && <4.9, directory >=1.2 && <1.3, wx >=0.92 && <0.93 + -- hs-source-dirs: + default-language: Haskell98