-
Notifications
You must be signed in to change notification settings - Fork 172
/
Copy pathUtil.hs
139 lines (111 loc) · 3.86 KB
/
Util.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
module Util where
import Data.Bifunctor
import Data.List
import Data.Maybe (fromMaybe)
import qualified Map
import qualified Set
import System.Info (os)
joinWith :: String -> [String] -> String
joinWith = intercalate
joinLines :: [String] -> String
joinLines = joinWith "\n"
joinWithSpace :: [String] -> String
joinWithSpace = unwords
joinWithComma :: [String] -> String
joinWithComma = intercalate ", "
joinWithUnderscore :: [String] -> String
joinWithUnderscore = intercalate "_"
joinWithPeriod :: [String] -> String
joinWithPeriod = intercalate "."
pairwise :: Show a => [a] -> [(a, a)]
pairwise [] = []
pairwise (x : y : xs) = (x, y) : pairwise xs
pairwise leftover = error ("An uneven number of forms sent to pairwise: " ++ show leftover)
compilerError :: String -> a
compilerError msg = error ("Internal compiler error: " ++ msg)
-- | Unwraps a Maybe value a to Right a, or returns a default value (Left b) if it was Nothing.
toEither :: Maybe a -> b -> Either b a
toEither a b = case a of
Just ok -> Right ok
Nothing -> Left b
replaceChars :: Map.Map Char String -> String -> String
replaceChars dict = concatMap replacer
where
replacer c = fromMaybe [c] (Map.lookup c dict)
replaceStrings :: Map.Map String String -> String -> String
replaceStrings dict s = fromMaybe s (Map.lookup s dict)
addIfNotPresent :: Eq a => a -> [a] -> [a]
addIfNotPresent x xs =
if x `elem` xs
then xs
else xs ++ [x]
remove :: (a -> Bool) -> [a] -> [a]
remove f = filter (not . f)
enumerate :: Int -> String
enumerate 0 = "first"
enumerate 1 = "second"
enumerate 2 = "third"
enumerate 3 = "fourth"
enumerate 4 = "fifth"
enumerate 5 = "sixth"
enumerate 6 = "seventh"
enumerate n = show n ++ ":th"
data Platform = Linux | MacOS | Windows | FreeBSD | NetBSD deriving (Show, Eq)
platform :: Platform
platform =
case os of
"linux" -> Linux
"darwin" -> MacOS
"mingw32" -> Windows
"freebsd" -> FreeBSD
"netbsd" -> NetBSD
p -> error ("Unknown platform: " ++ p)
unionOfSetsInList :: Ord a => [Set.Set a] -> Set.Set a
unionOfSetsInList (x : xs) =
foldl' Set.union x xs
unionOfSetsInList [] =
Set.empty
intersectionOfSetsInList :: Ord a => [Set.Set a] -> Set.Set a
intersectionOfSetsInList (x : xs) =
foldl' Set.intersection x xs
intersectionOfSetsInList [] =
Set.empty
evenIndices :: [a] -> [a]
evenIndices = map snd . filter (even . fst) . zip ([0 ..] :: [Int])
-- 'Naked' Lmabdas declared at the top level have their own s-expression forms
-- as names, e.g. (fn <> [] ()). This can result in invalid c code. This
-- function checks a lambda's nesting level. If the lambda is declared at the
-- top level it returns a constant string, otherwise it returns the provided
-- name (usually the name of the function in which the lambda is defined).
lambdaToCName :: String -> Int -> String
lambdaToCName name nestLevel =
if nestLevel > 0
then name
else "NAKED_LAMBDA"
-- Given an integer, create a dummy argument name for it.
-- Called by XObj producing functions such as addCommand.
intToArgName :: Int -> String
intToArgName 1 = "x"
intToArgName 2 = "y"
intToArgName 3 = "z"
intToArgName 4 = "w"
intToArgName 5 = "v"
intToArgName 6 = "u"
intToArgName 7 = "t"
intToArgName 8 = "s"
intToArgName 9 = "r"
intToArgName n = intToArgName 1 ++ intToArgName (n `div` 10)
replaceLeft :: b -> Either a c -> Either b c
replaceLeft x e = first (const x) e
unwrapErr :: Show e => Either e a -> Either String a
unwrapErr = first show
toMaybe :: (b -> c) -> Either a b -> Maybe c
toMaybe f e = either (const Nothing) (Just . f) e
maybeId :: Either a b -> Maybe b
maybeId = toMaybe id
whenRight :: Applicative f => Either a b -> f (Either a c) -> f (Either a c)
whenRight (Right _) cont = cont
whenRight (Left err) _ = pure (Left err)
whenRightReturn :: Applicative f => Either a b -> Either a c -> f (Either a c)
whenRightReturn (Right _) cont = pure cont
whenRightReturn (Left err) _ = pure (Left err)