1{-# LANGUAGE FlexibleInstances, IncoherentInstances, PatternGuards #-}
3module Idris.IdeSlave(parseMessage, convSExp, IdeSlaveCommand(..), sexpToCommand, toSExp, SExp(..), SExpable) where
8import qualified Data.ByteString.UTF8 as UTF8
9-- import qualified Data.Text as T
10import Text.Trifecta hiding (Err)
11import Text.Trifecta.Delta
15import Control.Applicative
17data SExp = SexpList [SExp]
24sExpToString :: SExp -> String
25sExpToString (StringAtom s) = "\"" ++ escape s ++ "\""
26sExpToString (BoolAtom True) = ":True"
27sExpToString (BoolAtom False) = ":False"
28sExpToString (IntegerAtom i) = printf "%d" i
29sExpToString (SymbolAtom s) = ":" ++ s
30sExpToString (SexpList l) = "(" ++ intercalate " " (map sExpToString l) ++ ")"
35instance SExpable SExp where
38instance SExpable Bool where
39 toSExp True = BoolAtom True
40 toSExp False = BoolAtom False
42instance SExpable String where
43 toSExp s = StringAtom s
45instance SExpable Integer where
46 toSExp n = IntegerAtom n
48instance SExpable Int where
49 toSExp n = IntegerAtom (toInteger n)
52instance SExpable Name where
53 toSExp s = StringAtom (show s)
56instance (SExpable a) => SExpable (Maybe a) where
57 toSExp Nothing = SexpList [SymbolAtom "Nothing"]
58 toSExp (Just a) = SexpList [SymbolAtom "Just", toSExp a]
60instance (SExpable a) => SExpable [a] where
61 toSExp l = SexpList (map toSExp l)
63instance (SExpable a, SExpable b) => SExpable (a, b) where
64 toSExp (l, r) = SexpList [toSExp l, toSExp r]
66instance (SExpable a, SExpable b, SExpable c) => SExpable (a, b, c) where
67 toSExp (l, m, n) = SexpList [toSExp l, toSExp m, toSExp n]
69instance (SExpable a, SExpable b, SExpable c, SExpable d) => SExpable (a, b, c, d) where
70 toSExp (l, m, n, o) = SexpList [toSExp l, toSExp m, toSExp n, toSExp o]
72escape :: String -> String
73escape = concatMap escapeChar
75 escapeChar '\\' = "\\\\"
76 escapeChar '"' = "\\\""
79pSExp = do xs <- between (char '(') (char ')') (pSExp `sepBy` (char ' '))
83atom = do string "nil"; return (SexpList [])
84 <|> do char ':'; x <- atomC; return x
85 <|> do char '"'; xs <- many quotedChar; char '"'; return (StringAtom xs)
86 <|> do ints <- some digit
88 ((num, ""):_) -> return (IntegerAtom (toInteger num))
89 _ -> return (StringAtom ints)
91atomC = do string "True"; return (BoolAtom True)
92 <|> do string "False"; return (BoolAtom False)
93 <|> do xs <- many (noneOf " \n\t\r\"()"); return (SymbolAtom xs)
95quotedChar = try (string "\\\\" >> return '\\')
96 <|> try (string "\\\"" >> return '"')
99parseSExp :: String -> Result SExp
100parseSExp = parseString pSExp (Directed (UTF8.fromString "(unknown)") 0 0 0 0)
102data IdeSlaveCommand = REPLCompletions String
105 | CaseSplit Int String
106 | AddClause Int String
107 | AddProofClause Int String
108 | AddMissing Int String
109 | MakeWithBlock Int String
110 | ProofSearch Int String [String]
114sexpToCommand :: SExp -> Maybe IdeSlaveCommand
115sexpToCommand (SexpList (x:[])) = sexpToCommand x
116sexpToCommand (SexpList [SymbolAtom "interpret", StringAtom cmd]) = Just (Interpret cmd)
117sexpToCommand (SexpList [SymbolAtom "repl-completions", StringAtom prefix]) = Just (REPLCompletions prefix)
118sexpToCommand (SexpList [SymbolAtom "load-file", StringAtom filename]) = Just (LoadFile filename)
119sexpToCommand (SexpList [SymbolAtom "type-of", StringAtom name]) = Just (TypeOf name)
120sexpToCommand (SexpList [SymbolAtom "case-split", IntegerAtom line, StringAtom name]) = Just (CaseSplit (fromInteger line) name)
121sexpToCommand (SexpList [SymbolAtom "add-clause", IntegerAtom line, StringAtom name]) = Just (AddClause (fromInteger line) name)
122sexpToCommand (SexpList [SymbolAtom "add-proof-clause", IntegerAtom line, StringAtom name]) = Just (AddProofClause (fromInteger line) name)
123sexpToCommand (SexpList [SymbolAtom "add-missing", IntegerAtom line, StringAtom name]) = Just (AddMissing (fromInteger line) name)
124sexpToCommand (SexpList [SymbolAtom "make-with", IntegerAtom line, StringAtom name]) = Just (MakeWithBlock (fromInteger line) name)
125sexpToCommand (SexpList [SymbolAtom "proof-search", IntegerAtom line, StringAtom name, SexpList hintexp]) | Just hints <- getHints hintexp = Just (ProofSearch (fromInteger line) name hints)
126 where getHints = mapM (\h -> case h of
127 StringAtom s -> Just s
129sexpToCommand _ = Nothing
131parseMessage :: String -> Either Err (SExp, Integer)
132parseMessage x = case receiveString x of
133 Right (SexpList [cmd, (IntegerAtom id)]) -> Right (cmd, id)
136receiveString :: String -> Either Err SExp
138 case readHex (take 6 x) of
140 let msg = drop 6 x in
141 if (length msg) /= (num - 1)
142 then Left . Msg $ "bad input length"
143 else (case parseSExp msg of
144 Failure _ -> Left . Msg $ "parse failure"
145 Success r -> Right r)
146 _ -> Left . Msg $ "readHex failed"
148convSExp :: SExpable a => String -> a -> Integer -> String
150 let sex = SexpList [SymbolAtom pre, toSExp s, IntegerAtom id] in
151 let str = sExpToString sex in
152 (getHexLength str) ++ str
154getHexLength :: String -> String
155getHexLength s = printf "%06x" (1 + (length s))
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list