-- a any version of function that supports IO
anyIO :: (a -> IO Bool) -> [a] -> IO Bool
if result then return True else anyIO fn l
-- checks if provers in the prover list are availabe on
checkPresenceProvers :: [String] -> IO [String]
checkPresenceProvers ls = case ls of
path <- getEnvDef "PATH" ""
let lsPaths = map trim $ splitOn ':' path
completePath x = case x of
result <- anyIO (doesFileExist . completePath)
contd <- checkPresenceProvers l
else checkPresenceProvers l
contd <- checkPresenceProvers l
-- removes the extension of the file find in the
-- name of the prompter ( it delets everything
-- after the last . and assumes a prompter length of 2 )
delExtension :: String -> String
delExtension str = let rstr = reverse str in
reverse $ safeTail $ case dropWhile (/= '.') rstr of
-- | Checks if a string represents a int or not
checkIntString :: String -> Bool
checkIntString = not . any (not . isDigit)
padBlanks :: String -> String
padBlanks s = ' ' : s ++ " "
-- | Generates a string representing the type of link
arrowLink :: DGLinkLab -> String
arrowLink edgLab = padBlanks $ if isLocalEdge $ dgl_type edgLab
-- | Checks if the string starts with an arrow
checkArrowLink :: String -> (Bool, String, String)
checkArrowLink str = case find snd
$ map (\ s -> (s, isPrefixOf s str)) [localArr, globalArr] of
Nothing -> (False, [], str)
Just (a, _) -> (True, padBlanks a, drop (length a) str)
-- | Given a string inserts spaces before and after an
spacesAroundArrows :: String -> String -> String
spacesAroundArrows s output = case s of
case checkArrowLink $ trimLeft s of
(True, arr, rs) -> spacesAroundArrows rs
(False, _, _) -> spacesAroundArrows tl
-- | Given a string the function decomposes it into 4 lists,
-- one for node goals, the other for edges, the third for
-- numbered edges and the last for names that could not be
-- processed due to errors
decomposeIntoGoals :: String -> ([String], [String], [String], [String])
decomposeIntoGoals input = let
-- the new input where words and arrows are separated
nwInput = words $ spacesAroundArrows input []
-- funtion to parse the input and decompose it into
parse info nbOfArrows word sw listNode listEdge listNbEdge listError =
[] -> case nbOfArrows :: Integer of
0 -> (word : listNode, listEdge, listNbEdge, listError)
1 -> (listNode, word : listEdge, listNbEdge, listError)
2 -> (listNode, listEdge, word : listNbEdge, listError)
_ -> (listNode, listEdge, listNbEdge, word : listError)
x : l -> case checkArrowLink x of
[] -> (listNode, listEdge, listNbEdge, word : listError)
_ -> parse l (nbOfArrows + 1) (word ++ arr) True
listNode listEdge listNbEdge listError
then parse l nbOfArrows (word ++ x) False
listNode listEdge listNbEdge listError
(word : listNode) listEdge listNbEdge listError
listNode (word : listEdge) listNbEdge listError
listNode listEdge (word : listNbEdge) listError
listNode listEdge listNbEdge (word : listError)
in parse nwInput 0 [] True [] [] [] []
-- | mapAndSplit maps a function to a list. If the function can not
-- be applied to an element it is stored in a different list for
-- producing error message later on
mapAndSplit :: (a -> Maybe b) -> [a] -> ([a], [b])
let ps = map (\ x -> (x, fn x)) ls
(oks, errs) = partition (isJust . snd) ps
in (map fst errs, mapMaybe snd oks)
-- | concatMapAndSplit is similar to mapAndSplit, just that it behaves
-- in a similar manner to concatMap (
i.e. sums up lists produced by
concatMapAndSplit :: (a -> [b]) -> [a] -> ([a],[b])
concatMapAndSplit fn ls =
let ps = map (\ x -> (x, fn x)) ls
(errs, oks) = partition (null . snd) ps
in (map fst errs, concatMap snd oks)
-- | Given a list of node names and the list of all nodes
-- the function returns all the nodes that have their name
obtainNodeList :: [String] -> [LNode DGNodeLab] ->([String], [LNode DGNodeLab])
obtainNodeList lN allNodes = mapAndSplit
(\ x -> find (\ (_, label) -> getDGNodeName label == x) allNodes) lN
-- | Given a node decides if it contains goals or not
nodeContainsGoals:: LNode DGNodeLab -> G_theory -> Bool
nodeContainsGoals (_, l) th =
(\ s -> not (isAxiom s) && not (isProvenSenStatus s)) sens) ||
hasOpenNodeConsStatus False l
-- | Given an edge decides if it contains goals or not
edgeContainsGoals:: LEdge DGLinkLab -> Bool
edgeContainsGoals (_, _, l) = case thmLinkStatus $ dgl_type l of
-- | Given a list of edges and the complete list of all
-- edges computes not only the names of edges but also the
-- numbered name of edges
createEdgeNames:: [LNode DGNodeLab] -> [LEdge DGLinkLab] -> [String]
createEdgeNames lsN lsE = let
-- function that returns the name of a node given its number
nameOf x ls = case lookup x ls of
Nothing -> "Unknown node"
Just nlab -> showName $ dgn_name nlab
ordFn (x1, x2, _) (y1, y2, _) = compare (x1, x2) (y1, y2)
-- sorted and grouped list of edges
edgs = groupBy ( \ x y -> ordFn x y == EQ) $ sortBy ordFn lsE
allEds = concatMap (\ l -> case l of
[(x, y, edgLab)] ->[(nameOf x lsN ++
_ -> map (\ (x, y, edgLab) ->
showEdgeId (dgl_id edgLab)
-- | Given a list of edge names and numbered edge names
-- and the list of all nodes and edges the function
-- identifies the edges that appear in the name lists
obtainEdgeList :: [String] ->[String] ->[LNode DGNodeLab]
-> [LEdge DGLinkLab]-> ([String],[LEdge DGLinkLab])
obtainEdgeList lsEdge lsNbEdge allNodes allEdges = let
-- function that searches through a list of nodes to
-- find the node number for a given name.
case find ( \ (_, label) ->
getDGNodeName label == s) ls of
-- converts a string to a number (for some reason I
-- could not find such a function already implemented
node1 = getNodeNb (head allx) allNodes
node2 = getNodeNb (allx !! 2) allNodes
filter (\ (x1, y1, _) -> x == x1 && y == y1) allEdges
-- compute the list of all numbered edges
node1 = getNodeNb (head allx) allNodes
node2 = getNodeNb (allx !! 5) allNodes
let ls = filter(\ (x1, y1, elab) -> x == x1 && y == y1 &&
dgl_id elab == EdgeId nb) allEdges
els : _ -> Just els) lsNbEdge
in (fst l1 ++ fst l2, snd l1 ++ snd l2)
-- | Giben a listof edgenamesand numbered edge names and
-- the list of all nodes and edges the function identifies
-- the edges that appearin the name list and are also goals
obtainGoalEdgeList :: [String] -> [String] -> [LNode DGNodeLab]
-> [LEdge DGLinkLab] -> ([String], [LEdge DGLinkLab])
obtainGoalEdgeList ls1 ls2 ls3 ls4 =
let (l1, l2) = obtainEdgeList ls1 ls2 ls3 ls4
in (l1, filter edgeContainsGoals l2)
-- | Function that given a string removes comments contained
stripComments :: String -> String
-- | The function obtain the unfinished edge name from the
-- last position of the input or list of possible unfinished
unfinishedEdgeName :: String -> String
unfinishedEdgeName input = let
lastButN nb = lastString . reverse . drop nb . reverse
-- we need a penultimum (the one before the last) function
-- and the one before the penultimum
prevPrevLast = lastButN 2
prev2PrevLast = lastButN 3
prev3PrevLast = lastButN 4
in if isSpace $ lastChar input
-- if so, then either the last word is an arrow, and
-- then we have the consider last two words, or it
-- is not an arrow and then we need to consider just
case checkArrowLink $ lastString wrds of
case checkArrowLink $ prevPrevLast wrds of
(True, arr2, _) -> prev2PrevLast wrds
++ arr2 ++ prevLast wrds ++ arr1
_ -> prevLast wrds ++ arr1
_ -> case checkArrowLink $ prevLast wrds of
-- an entire edge name was just inserted
-- before and now we need a fresh new start
-- if just the first word of an edge was
-- inserted then return that
_ -> case lastString wrds of
_ -> lastString wrds ++ " "
-- then we could be in the middle of the first node
-- name, arrow or the second node name
case checkArrowLink $ prevLast wrds of
-- in the middle of the last word
(True, arr1, _) -> case checkArrowLink $ prev2PrevLast wrds of
(True, arr2, _) -> prev3PrevLast wrds ++
arr2 ++ prevPrevLast wrds ++
_ -> prevPrevLast wrds ++ arr1 ++ lastString wrds
_ -> case checkArrowLink $ prevPrevLast wrds of
-- in the middle of the first word
(True, _, _) -> lastString wrds
-- in the middle of the arrow
_ -> case prevLast wrds of
_ -> prevLast wrds ++ " " ++ lastString wrds
-- | Given a list of files and folders the function filters
-- only directory names and files ending in extenstion
fileFilter :: String -> [String] -> [String] -> IO [String]
fileFilter lPath ls cons = case ls of
-- check if current element is a directory
b <- doesDirectoryExist (lPath ++ x)
-- if it is,then add "/" to indicate is a folder
then fileFilter lPath l ((x ++ "/") : cons)
-- if it is not a folder then it must be a file
-- so check the extension
else if isSuffixOf ".casl" x
then fileFilter lPath l (x : cons)
else fileFilter lPath l cons
-- | Given a list of files and folders the function expands
-- the list adding the content of all folders in the list
fileExtend :: String -> [String] -> [String] -> IO [String]
fileExtend lPath ls cons = case ls of
-- check if current element is a directory
b <- doesDirectoryExist lPathx
-- if it is a folder add its content
do ll <- getDirectoryContents lPathx
nll<- fileFilter lPathx ll []
fileExtend lPath l (nll' ++ cons)
-- if it is not then leave the file alone
else fileExtend lPath l (x : cons)
-- | The function behaves exactly as tail just that
-- in the case of empty list returns an empty list
safeLast :: a -> [a] -> a
safeLast d l = if null l then d else last l
-- | The function behaves exactly like last just that
-- in case of an empty list returns the space
-- character (it works only for lists of chars)
lastChar :: String -> Char
-- | The function behaves exactly like last just that
-- in case of an empty list returns the empty string
-- (it is meant only for list of strings)
lastString::[String]->String
-- | The function nicely outputs a list of errors
prettyPrintErrList :: [String] -> String
prettyPrintErrList = (intercalate "\n")
. map (\ x -> "Input " ++ x ++ " could not be processed")