packages feed

idris-0.9.9.1: src/Idris/REPLParser.hs

module Idris.REPLParser(parseCmd) where

import System.FilePath ((</>))
import System.Console.ANSI (Color(..))

import Idris.Colours
import Idris.Parser
import Idris.AbsSyntax
import Core.TT

import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Expr
import Text.ParserCombinators.Parsec.Language
import qualified Text.ParserCombinators.Parsec.Token as PTok

import Debug.Trace
import Data.List
import Data.List.Split(splitOn)
import Data.Char(toLower)

parseCmd :: IState -> String -> String -> Either ParseError Command
parseCmd i inputname = runParser pCmd i inputname

cmd :: [String] -> IParser ()
cmd xs = do lchar ':'; docmd (sortBy (\x y -> compare (length y) (length x)) xs)
    where docmd [] = fail "No such command"
          docmd (x:xs) = try (discard (symbol x)) <|> docmd xs

pCmd :: IParser Command
pCmd = do spaces; try (do cmd ["q", "quit"]; eof; return Quit)
              <|> try (do cmd ["h", "?", "help"]; eof; return Help)
              <|> try (do cmd ["r", "reload"]; eof; return Reload)
              <|> try (do cmd ["m", "module"]; f <- identifier; eof;
                          return (ModImport (toPath f)))
              <|> try (do cmd ["e", "edit"]; eof; return Edit)
              <|> try (do cmd ["exec", "execute"]; eof; return Execute)
              <|> try (do cmd ["ttshell"]; eof; return TTShell)
              <|> try (do cmd ["c", "compile"]; f <- identifier; eof; return (Compile ViaC f))
              <|> try (do cmd ["jc", "newcompile"]; f <- identifier; eof; return (Compile ViaJava f))
              <|> try (do cmd ["js", "javascript"]; f <- identifier; eof; return (Compile ViaJavaScript f))
              <|> try (do cmd ["m", "metavars"]; eof; return Metavars)
              <|> try (do cmd ["proofs"]; eof; return Proofs)
              <|> try (do cmd ["p", "prove"]; n <- pName; eof; return (Prove n))
              <|> try (do cmd ["a", "addproof"]; do n <- option Nothing (do x <- pName;
                                                                            return (Just x))
                                                    eof; return (AddProof n))
              <|> try (do cmd ["rmproof"]; n <- pName; eof; return (RmProof n))
              <|> try (do cmd ["showproof"]; n <- pName; eof; return (ShowProof n))
              <|> try (do cmd ["log"]; i <- natural; eof; return (LogLvl (fromIntegral i)))
              <|> try (do cmd ["l", "load"]; f <- getInput; return (Load f))
              <|> try (do cmd ["cd"]; f <- getInput; return (ChangeDirectory f))
              <|> try (do cmd ["spec"]; whiteSpace; t <- pFullExpr defaultSyntax; return (Spec t))
              <|> try (do cmd ["hnf"]; whiteSpace; t <- pFullExpr defaultSyntax; return (HNF t))
              <|> try (do cmd ["doc"]; n <- pfName; eof; return (DocStr n))
              <|> try (do cmd ["d", "def"]; many1 (char ' ') ; n <- pfName; eof; return (Defn n))
              <|> try (do cmd ["total"]; do n <- pfName; eof; return (TotCheck n))
              <|> try (do cmd ["t", "type"]; do whiteSpace; t <- pFullExpr defaultSyntax; return (Check t))
              <|> try (do cmd ["u", "universes"]; eof; return Universes)
              <|> try (do cmd ["di", "dbginfo"]; n <- pfName; eof; return (DebugInfo n))
              <|> try (do cmd ["i", "info"]; n <- pfName; eof; return (Info n))
              <|> try (do cmd ["miss", "missing"]; n <- pfName; eof; return (Missing n))
              <|> try (do cmd ["dynamic"]; eof; return ListDynamic)
              <|> try (do cmd ["dynamic"]; l <- getInput; return (DynamicLink l))
              <|> try (do cmd ["color", "colour"]; pSetColourCmd)
              <|> try (do cmd ["set"]; o <-pOption; return (SetOpt o))
              <|> try (do cmd ["unset"]; o <-pOption; return (UnsetOpt o))
              <|> try (do cmd ["s", "search"]; whiteSpace; t <- pFullExpr defaultSyntax; return (Search t))
              <|> try (do cmd ["x"]; whiteSpace; t <- pFullExpr defaultSyntax; return (ExecVal t))
              <|> try (do cmd ["patt"]; whiteSpace; t <- pFullExpr defaultSyntax; return (Pattelab t))
              <|> do whiteSpace; do eof; return NOP
                             <|> do t <- pFullExpr defaultSyntax; return (Eval t)

 where toPath n = foldl1' (</>) $ splitOn "." n

pOption :: IParser Opt
pOption = do discard (symbol "errorcontext"); return ErrContext
      <|> do discard (symbol "showimplicits"); return ShowImpl


colours :: [(String, Color)]
colours = [ ("black", Black)
          , ("red", Red)
          , ("green", Green)
          , ("yellow", Yellow)
          , ("blue", Blue)
          , ("magenta", Magenta)
          , ("cyan", Cyan)
          , ("white", White)
          ]

pColour :: IParser Color
pColour = doColour colours
    where doColour [] = fail "Unknown colour"
          doColour ((s, c):cs) = (try (symbol s) >> return c) <|> doColour cs

pColourMod :: IParser (IdrisColour -> IdrisColour)
pColourMod = try (symbol "vivid" >> return doVivid)
         <|> try (symbol "dull" >> return doDull)
         <|> try (symbol "underline" >> return doUnderline)
         <|> try (symbol "nounderline" >> return doNoUnderline)
         <|> try (symbol "bold" >> return doBold)
         <|> try (symbol "nobold" >> return doNoBold)
         <|> try (pColour >>= return . doSetColour)
    where doVivid i       = i { vivid = True }
          doDull i        = i { vivid = False }
          doUnderline i   = i { underline = True }
          doNoUnderline i = i { underline = False }
          doBold i        = i { bold = True }
          doNoBold i      = i { bold = False }
          doSetColour c i = i { colour = c }


colourTypes :: [(String, ColourType)]
colourTypes = map (\x -> ((map toLower . reverse . drop 6 . reverse . show) x, x)) $
              enumFromTo minBound maxBound

pColourType :: IParser ColourType
pColourType = doColourType colourTypes
    where doColourType [] = fail $ "Unknown colour category. Options: " ++
                                   (concat . intersperse ", " . map fst) colourTypes
          doColourType ((s,ct):cts) = (try (symbol s) >> return ct) <|> doColourType cts

pSetColourCmd :: IParser Command
pSetColourCmd = (do c <- pColourType
                    let defaultColour = IdrisColour Black True False False
                    opts <- sepBy pColourMod spaces
                    let colour = foldr ($) defaultColour $ reverse opts
                    return $ SetColour c colour)
            <|> try (symbol "on" >> return ColourOn)
            <|> try (symbol "off" >> return ColourOff)