1{-# LANGUAGE GeneralizedNewtypeDeriving, ConstraintKinds, PatternGuards #-}
2module Idris.ParseData where
4import Prelude hiding (pi)
6import Text.Trifecta.Delta
7import Text.Trifecta hiding (span, stringLiteral, charLiteral, natural, symbol, char, string, whiteSpace, Err)
8import Text.Parser.LookAhead
9import Text.Parser.Expression
10import qualified Text.Parser.Token as Tok
11import qualified Text.Parser.Char as Chr
12import qualified Text.Parser.Token.Highlight as Hi
15import Idris.ParseHelpers
21import Idris.Core.Evaluate
23import Idris.Docstrings
25import Control.Applicative
27import Control.Monad.State.Strict
30import qualified Data.List.Split as Spl
34import qualified Data.HashSet as HS
35import qualified Data.Text as T
36import qualified Data.ByteString.UTF8 as UTF8
40{- |Parses a record type declaration
42 DocComment Accessibility? 'record' FnName TypeSig 'where' OpenBlock Constructor KeepTerminator CloseBlock;
44record :: SyntaxInfo -> IdrisParser PDecl
45record syn = do (doc, argDocs, acc, opts) <- try (do
46 (doc, argDocs) <- option noDocs docComment
48 let doc' = annotCode (tryFullExpr syn ist) doc
49 argDocs' = [ (n, annotCode (tryFullExpr syn ist) d)
51 acc <- optional accessibility
54 return (doc', argDocs', acc, opts))
58 ty <- typeExpr (allowImp syn)
59 let tyn = expandNS syn tyn_in
61 (cdoc, cargDocs, cn, cty, _, _) <- indentedBlockS (constructor syn)
63 let rsyn = syn { syn_namespace = show (nsroot tyn) :
65 let fns = getRecNames rsyn cty
66 mapM_ (\n -> addAcc n acc) fns
67 return $ PRecord doc rsyn fc tyn ty opts cdoc cn cty
68 <?> "record type declaration"
70 getRecNames :: SyntaxInfo -> PTerm -> [Name]
71 getRecNames syn (PPi _ n _ sc) = [expandNS syn n, expandNS syn (mkType n)]
75 toFreeze :: Maybe Accessibility -> Maybe Accessibility
76 toFreeze (Just Frozen) = Just Hidden
79{- | Parses data declaration type (normal or codata)
80DataI ::= 'data' | 'codata';
82dataI :: IdrisParser DataOpts
83dataI = do reserved "data"; return []
84 <|> do reserved "codata"; return [Codata]
86{- | Parses if a data should not have a default eliminator
87DefaultEliminator ::= 'noelim'?
89dataOpts :: DataOpts -> IdrisParser DataOpts
91 = do reserved "%elim"; dataOpts (DefaultEliminator : DefaultCaseFun : opts)
92 <|> do reserved "%case"; dataOpts (DefaultCaseFun : opts)
93 <|> do reserved "%error_reverse"; dataOpts (DataErrRev : opts)
97{- | Parses a data type declaration
98Data ::= DocComment? Accessibility? DataI DefaultEliminator FnName TypeSig ExplicitTypeDataRest?
99 | DocComment? Accessibility? DataI DefaultEliminator FnName Name* DataRest?
101Constructor' ::= Constructor KeepTerminator;
102ExplicitTypeDataRest ::= 'where' OpenBlock Constructor'* CloseBlock;
104DataRest ::= '=' SimpleConstructorList Terminator
107SimpleConstructorList ::=
109 | SimpleConstructor '|' SimpleConstructorList
112data_ :: SyntaxInfo -> IdrisParser PDecl
113data_ syn = do (doc, argDocs, acc, dataOpts) <- try (do
114 (doc, argDocs) <- option noDocs docComment
116 acc <- optional accessibility
120 let dataOpts = combineDataOpts (elim ++ co)
121 doc' = annotCode (tryFullExpr syn ist) doc
122 argDocs' = [ (n, annotCode (tryFullExpr syn ist) d)
123 | (n, d) <- argDocs ]
124 return (doc', argDocs', acc, dataOpts))
129 ty <- typeExpr (allowImp syn)
130 let tyn = expandNS syn tyn_in
131 option (PData doc argDocs syn fc dataOpts (PLaterdecl tyn ty)) (do
133 cons <- indentedBlock (constructor syn)
134 accData acc tyn (map (\ (_, _, n, _, _, _) -> n) cons)
135 return $ PData doc argDocs syn fc dataOpts (PDatadecl tyn ty cons))) <|> (do
137 let ty = bindArgs (map (const PType) args) PType
138 let tyn = expandNS syn tyn_in
139 option (PData doc argDocs syn fc dataOpts (PLaterdecl tyn ty)) (do
140 try (lchar '=') <|> do reserved "where"
141 let kw = (if DefaultEliminator `elem` dataOpts then "%elim" else "") ++ (if Codata `elem` dataOpts then "co" else "") ++ "data "
142 let n = show tyn_in ++ " "
144 let as = concat (intersperse " " $ map show args) ++ " "
145 let ns = concat (intersperse " -> " $ map ((\x -> "(" ++ x ++ " : Type)") . show) args)
146 let ss = concat (intersperse " -> " $ map (const "Type") args)
147 let fix1 = s ++ as ++ " = ..."
148 let fix2 = s ++ ": " ++ ns ++ " -> Type where\n ..."
149 let fix3 = s ++ ": " ++ ss ++ " -> Type where\n ..."
150 fail $ fixErrorMsg "unexpected \"where\"" [fix1, fix2, fix3]
151 cons <- sepBy1 (simpleConstructor syn) (reservedOp "|")
153 let conty = mkPApp fc (PRef fc tyn) (map (PRef fc) args)
154 cons' <- mapM (\ (doc, argDocs, x, cargs, cfc, fs) ->
155 do let cty = bindArgs cargs conty
156 return (doc, argDocs, x, cty, cfc, fs)) cons
157 accData acc tyn (map (\ (_, _, n, _, _, _) -> n) cons')
158 return $ PData doc argDocs syn fc dataOpts (PDatadecl tyn ty cons')))
159 <?> "data type declaration"
161 mkPApp :: FC -> PTerm -> [PTerm] -> PTerm
163 mkPApp fc t xs = PApp fc t (map pexp xs)
164 bindArgs :: [PTerm] -> PTerm -> PTerm
165 bindArgs xs t = foldr (PPi expl (sMN 0 "_t")) t xs
166 combineDataOpts :: DataOpts -> DataOpts
167 combineDataOpts opts = if Codata `elem` opts
168 then delete DefaultEliminator opts
172{- | Parses a type constructor declaration
173 Constructor ::= DocComment? FnName TypeSig;
175constructor :: SyntaxInfo -> IdrisParser (Docstring (Either Err PTerm), [(Name, Docstring (Either Err PTerm))], Name, PTerm, FC, [Name])
177 = do (doc, argDocs) <- option noDocs docComment
178 cn_in <- fnName; fc <- getFC
179 let cn = expandNS syn cn_in
181 fs <- option [] (do lchar '%'; reserved "erase"
182 sepBy1 name (lchar ','))
183 ty <- typeExpr (allowImp syn)
185 let doc' = annotCode (tryFullExpr syn ist) doc
186 argDocs' = [ (n, annotCode (tryFullExpr syn ist) d)
187 | (n, d) <- argDocs ]
188 return (doc', argDocs', cn, ty, fc, fs)
191{- | Parses a constructor for simple discriminated union data types
192 SimpleConstructor ::= FnName SimpleExpr* DocComment?
194simpleConstructor :: SyntaxInfo -> IdrisParser (Docstring (Either Err PTerm), [(Name, Docstring (Either Err PTerm))], Name, [PTerm], FC, [Name])
196 = do (doc, _) <- option noDocs (try docComment)
198 let doc' = annotCode (tryFullExpr syn ist) doc
200 let cn = expandNS syn cn_in
202 args <- many (do notEndApp
204 return (doc', [], cn, args, fc, [])
207{- | Parses a dsl block declaration
208DSL ::= 'dsl' FnName OpenBlock Overload'+ CloseBlock;
210dsl :: SyntaxInfo -> IdrisParser PDecl
211dsl syn = do reserved "dsl"
213 bs <- indentedBlock (overload syn)
214 let dsl = mkDSL bs (dsl_info syn)
217 put (i { idris_dsls = addDef n dsl (idris_dsls i) })
219 <?> "dsl block declaration"
220 where mkDSL :: [(String, PTerm)] -> DSL -> DSL
221 mkDSL bs dsl = let var = lookup "variable" bs
222 first = lookup "index_first" bs
223 next = lookup "index_next" bs
224 leto = lookup "let" bs
225 lambda = lookup "lambda" bs
226 pi = lookup "pi" bs in
227 initDSL { dsl_var = var,
234{- | Checks DSL for errors -}
235-- FIXME: currently does nothing, check if DSL is really sane
237-- Issue #1595 on the Issue Tracker
239-- https://github.com/idris-lang/Idris-dev/issues/1595
241checkDSL :: DSL -> IdrisParser ()
242checkDSL dsl = return ()
244{- | Parses a DSL overload declaration
245OverloadIdentifier ::= 'let' | Identifier;
246Overload ::= OverloadIdentifier '=' Expr;
248overload :: SyntaxInfo -> IdrisParser (String, PTerm)
249overload syn = do o <- identifier <|> do reserved "let"
251 if o `notElem` overloadable
252 then fail $ show o ++ " is not an overloading"
257 <?> "dsl overload declaratioN"
258 where overloadable = ["let","lambda","pi","index_first","index_next","variable"]
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