on master help sign in
Merge branch 'feature/eliminators' of https://github.com/ahmadsalim/Idris-dev into ahmadsalim-feature/eliminators
commit7b8f3b41c8efb110188ab3087ef04fc4ea78c6fe authorEdwin Brady <ecb10@st-andrews.ac.uk> dateSat 30 Nov 2013, 13:40 (13 years ago) parent22fcec9725587f
11 files changed+328−28
libs/prelude/Prelude/List.idr+1−1 libs/prelude/Prelude/Nat.idr+1−1 libs/prelude/Prelude/Vect.idr+1−1 src/Core/TT.hs+2 src/Idris/AbsSyntax.hs+13−1 src/Idris/AbsSyntaxTree.hs+9−1 src/Idris/DeepSeq.hs+5 src/Idris/ElabDecls.hs+260−10 src/Idris/IBC.hs+13−1 src/Idris/ParseData.hs+22−12 src/Idris/ParseExpr.hs+1
libs/prelude/Prelude/List.idr+1−1
@@ -15,7 +15,7 @@ import Prelude.Nat
1515infixr 7 ::
1616infixl 8 ++
1717
18−data List a
18+%elim data List a
1919 = Nil
2020 | (::) a (List a)
2121
libs/prelude/Prelude/Nat.idr+1−1
@@ -10,7 +10,7 @@ import Prelude.Classes
1010%access public
1111%default total
1212
13−data Nat
13+%elim data Nat
1414 = Z
1515 | S Nat
1616
libs/prelude/Prelude/Vect.idr+1−1
@@ -11,7 +11,7 @@ import Prelude.Nat
1111
1212infixr 7 ::
1313
14−data Vect : Nat -> Type -> Type where
14+%elim data Vect : Nat -> Type -> Type where
1515 Nil : Vect Z a
1616 (::) : a -> Vect n a -> Vect (S n) a
1717
src/Core/TT.hs+2
@@ -237,6 +237,7 @@ data SpecialName = WhereN Int Name Name
237237 | ParentN Name String
238238 | MethodN Name
239239 | CaseN Name
240+ | ElimN Name
240241 deriving (Eq, Ord)
241242{-!
242243deriving instance Binary SpecialName
@@ -269,6 +270,7 @@ instance Show SpecialName where
269270 show (MethodN m) = "method " ++ show m
270271 show (ParentN p c) = show p ++ "#" ++ c
271272 show (CaseN n) = "case block in " ++ show n
273+ show (ElimN n) = "<<" ++ show n ++ " eliminator>>"
272274
273275-- Show a name in a way decorated for code generation, not human reading
274276showCG :: Name -> String
src/Idris/AbsSyntax.hs+13−1
@@ -634,6 +634,7 @@ inferDecl = PDatadecl inferTy
634634 [("", inferCon, PPi impl (MN 0 "A") PType (
635635 PPi expl (MN 0 "a") (PRef bi (MN 0 "A"))
636636 (PRef bi inferTy)), bi)]
637+inferOpts = []
637638
638639infTerm t = PApp bi (PRef bi inferCon) [pimp (MN 0 "A") Placeholder True, pexp t]
639640infP = P (TCon 6 0) inferTy (TType (UVal 0))
@@ -646,7 +647,7 @@ getInferTerm tm = tm -- error ("getInferTerm " ++ show tm)
646647getInferType (Bind n b sc) = Bind n b $ getInferType sc
647648getInferType (App (App _ ty) _) = ty
648649
649−-- Handy primitives: Unit, False, Pair, MkPair, =, mkForeign
650+-- Handy primitives: Unit, False, Pair, MkPair, =, mkForeign, Elim type class
650651
651652primNames = [unitTy, unitCon,
652653 falseTy, pairTy, pairCon,
@@ -656,9 +657,11 @@ unitTy = MN 0 "__Unit"
656657unitCon = MN 0 "__II"
657658unitDecl = PDatadecl unitTy PType
658659 [("", unitCon, PRef bi unitTy, bi)]
660+unitOpts = [DefaultEliminator]
659661
660662falseTy = MN 0 "__False"
661663falseDecl = PDatadecl falseTy PType []
664+falseOpts = []
662665
663666pairTy = MN 0 "__Pair"
664667pairCon = MN 0 "__MkPair"
@@ -670,6 +673,7 @@ pairDecl = PDatadecl pairTy (piBind [(n "A", PType), (n "B", PType)] PType)
670673 (PApp bi (PRef bi pairTy) [pexp (PRef bi (n "A")),
671674 pexp (PRef bi (n "B"))])))), bi)]
672675 where n a = MN 0 a
676+pairOpts = []
673677
674678eqTy = UN "="
675679eqCon = UN "refl"
@@ -683,6 +687,14 @@ eqDecl = PDatadecl eqTy (piBind [(n "a", PType), (n "b", PType),
683687 pexp (PRef bi (n "x")),
684688 pexp (PRef bi (n "x"))])), bi)]
685689 where n a = MN 0 a
690+eqOpts = []
691+
692+elimName = UN "__Elim"
693+elimMethElimTy = UN "__elimTy"
694+elimMethElim = UN "elim"
695+elimDecl = PClass "Type class for eliminators" defaultSyntax bi [] elimName [(UN "scrutineeType", PType)]
696+ [PTy "" defaultSyntax bi [TotalFn] elimMethElimTy PType,
697+ PTy "" defaultSyntax bi [TotalFn] elimMethElim (PRef bi elimMethElimTy)]
686698
687699-- Defined in builtins.idr
688700sigmaTy = UN "Exists"
src/Idris/AbsSyntaxTree.hs+9−1
@@ -392,6 +392,14 @@ inlinable = elem Inlinable
392392dictionary :: FnOpts -> Bool
393393dictionary = elem Dictionary
394394
395+
396+-- | Data declaration options
397+data DataOpt = Codata -- Set if the the data-type is coinductive
398+ | DefaultEliminator -- Set if an eliminator should be generated for data type
399+ deriving (Show, Eq)
400+
401+type DataOpts = [DataOpt]
402+
395403-- | Top-level declarations such as compiler directives, definitions,
396404-- datatypes and typeclasses.
397405data PDecl' t
@@ -400,7 +408,7 @@ data PDecl' t
400408 | PPostulate String SyntaxInfo FC FnOpts Name t -- ^ Postulate
401409 | PClauses FC FnOpts Name [PClause' t] -- ^ Pattern clause
402410 | PCAF FC Name t -- ^ Top level constant
403− | PData String SyntaxInfo FC Bool (PData' t) -- ^ Data declaration. The Bool argument is True for codata.
411+ | PData String SyntaxInfo FC DataOpts (PData' t) -- ^ Data declaration.
404412 | PParams FC [(Name, t)] [PDecl' t] -- ^ Params block
405413 | PNamespace String [PDecl' t] -- ^ New namespace
406414 | PRecord String SyntaxInfo FC Name t String Name t -- ^ Record declaration
src/Idris/DeepSeq.hs+5
@@ -31,6 +31,7 @@ instance NFData SpecialName where
3131 rnf (ParentN x1 x2) = rnf x1 `seq` rnf x2 `seq` ()
3232 rnf (MethodN x1) = rnf x1 `seq` ()
3333 rnf (CaseN x1) = rnf x1 `seq` ()
34+ rnf (ElimN x1) = rnf x1 `seq` ()
3435
3536instance NFData IntTy where
3637 rnf (ITFixed x1) = rnf x1 `seq` ()
@@ -164,6 +165,10 @@ instance NFData FnOpt where
164165 rnf Reflection = ()
165166 rnf (Specialise x1) = rnf x1 `seq` ()
166167
168+instance NFData DataOpt where
169+ rnf Codata = ()
170+ rnf DefaultEliminator = ()
171+
167172instance (NFData t) => NFData (PDecl' t) where
168173 rnf (PFix x1 x2 x3) = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` ()
169174 rnf (PTy x1 x2 x3 x4 x5 x6)
src/Idris/ElabDecls.hs+260−10
@@ -33,6 +33,12 @@ import Data.List
3333import Data.Maybe
3434import Debug.Trace
3535
36+import qualified Data.Map as Map
37+import Data.Char(isLetter, toLower)
38+import Data.List.Split (splitOn)
39+
40+import Util.Pretty(pretty)
41+
3642recheckC fc env t
3743 = do -- t' <- applyOpts (forget t) (doesn't work, or speed things up...)
3844 ctxt <- getContext
@@ -143,9 +149,10 @@ elabPostulate info syn doc fc opts n ty
143149 -- remove it from the deferred definitions list
144150 solveDeferred n
145151
146−elabData :: ElabInfo -> SyntaxInfo -> String -> FC -> Bool -> PData -> Idris ()
147−elabData info syn doc fc codata (PLaterdecl n t_in)
148− = do iLOG (show (fc, doc))
152+elabData :: ElabInfo -> SyntaxInfo -> String -> FC -> DataOpts -> PData -> Idris ()
153+elabData info syn doc fc opts (PLaterdecl n t_in)
154+ = do let codata = Codata `elem` opts
155+ iLOG (show (fc, doc))
149156 checkUndefined fc n
150157 ctxt <- getContext
151158 i <- getIState
@@ -161,8 +168,9 @@ elabData info syn doc fc codata (PLaterdecl n t_in)
161168 logLvl 2 $ "---> " ++ show cty
162169 updateContext (addTyDecl n (TCon 0 0) cty) -- temporary, to check cons
163170
164−elabData info syn doc fc codata (PDatadecl n t_in dcons)
165− = do iLOG (show fc)
171+elabData info syn doc fc opts (PDatadecl n t_in dcons)
172+ = do let codata = Codata `elem` opts
173+ iLOG (show fc)
166174 undef <- isUndefined fc n
167175 ctxt <- getContext
168176 i <- getIState
@@ -194,6 +202,8 @@ elabData info syn doc fc codata (PDatadecl n t_in dcons)
194202 collapseCons n cons
195203 updateContext (addDatatype (Data n ttag cty cons))
196204 mapM_ (checkPositive n) cons
205+ if DefaultEliminator `elem` opts then evalStateT (elabEliminator params n t dcons info) Map.empty
206+ else return ()
197207 where
198208 -- parameters are names which are unchanged across the structure,
199209 -- which appear exactly once in the return type of a constructor
@@ -245,12 +255,252 @@ elabData info syn doc fc codata (PDatadecl n t_in dcons)
245255 | otherwise = count n ts
246256 mParam args (_ : rest) = Nothing : mParam args rest
247257
258+type EliminatorState = StateT (Map.Map String Int) Idris
259+
260+-- TODO: Use uniqueName for generating names, rewrite everything to use idris_implicits instead of manual splitting, generally just rewrite
261+elabEliminator :: [Int] -> Name -> PTerm -> [(String, Name, PTerm, FC)] -> ElabInfo -> EliminatorState ()
262+elabEliminator paramPos n ty cons info = do
263+ elimLog $ "Elaborating eliminator"
264+ let (cnstrs, _) = splitPi ty
265+ let (splittedTy@(pms, idxs)) = splitPms cnstrs
266+ generalParams <- namePis False pms
267+ motiveIdxs <- namePis False idxs
268+ let motive = mkMotive n paramPos generalParams motiveIdxs
269+ consTerms <- mapM (\(c@(_,cnm,_,_)) -> do
270+ name <- freshName $ "elim_" ++ simpleName cnm
271+ consTerm <- extractConsTerm c generalParams
272+ return (name, expl, consTerm)) cons
273+ scrutineeIdxs <- namePis False idxs
274+ let motiveConstr = [(motiveName, expl, motive)]
275+ let scrutinee = (scrutineeName, expl, applyCons n (interlievePos paramPos generalParams scrutineeIdxs 0))
276+ let eliminatorTy = piConstr (generalParams ++ motiveConstr ++ consTerms ++ scrutineeIdxs ++ [scrutinee]) (applyMotive (map (\(n,_,_) -> PRef elimFC n) scrutineeIdxs) (PRef elimFC scrutineeName))
277+ let eliminatorTyDecl = PTy (show n) defaultSyntax elimFC [TotalFn] elimDeclName eliminatorTy
278+ let clauseConsElimArgs = map getPiName consTerms
279+ let clauseGeneralArgs' = map getPiName generalParams ++ [motiveName] ++ clauseConsElimArgs
280+ let clauseGeneralArgs = map (\arg -> pexp (PRef elimFC arg)) clauseGeneralArgs'
281+ let elimSig = "-- eliminator signature: " ++ showImp Nothing True True eliminatorTy
282+ eliminatorClauses <- mapM (\(cns, cnsElim) -> generateEliminatorClauses cns cnsElim clauseGeneralArgs generalParams) (zip cons clauseConsElimArgs)
283+ let eliminatorDef = PClauses emptyFC [TotalFn] elimDeclName eliminatorClauses
284+ elimLog $ "-- eliminator definition: " ++ showDeclImp True eliminatorDef
285+ Control.Monad.State.lift $ idrisCatch (elabDecl EAll info eliminatorTyDecl) (\err -> return ())
286+ -- Do not elaborate clauses if there aren't any
287+ case eliminatorClauses of
288+ [] -> return ()
289+ _ -> Control.Monad.State.lift $ idrisCatch (elabDecl EAll info eliminatorDef) (\err -> return ())
290+ where elimLog :: String -> EliminatorState ()
291+ elimLog s = Control.Monad.State.lift (logLvl 2 s)
292+
293+ elimFC :: FC
294+ elimFC = fileFC "(eliminator)"
295+
296+ elimDeclName :: Name
297+ elimDeclName = SN $ ElimN n
298+
299+ applyNS :: Name -> [String] -> Name
300+ applyNS n [] = n
301+ applyNS n ns = NS n ns
302+
303+ splitPi :: PTerm -> ([(Name, Plicity, PTerm)], PTerm)
304+ splitPi = splitPi' []
305+ where splitPi' :: [(Name, Plicity, PTerm)] -> PTerm -> ([(Name, Plicity, PTerm)], PTerm)
306+ splitPi' acc (PPi pl n tyl tyr) = splitPi' ((n, pl, tyl):acc) tyr
307+ splitPi' acc t = (reverse acc, t)
308+
309+ splitPms :: [(Name, Plicity, PTerm)] -> ([(Name, Plicity, PTerm)], [(Name, Plicity, PTerm)])
310+ splitPms cnstrs = (map fst pms, map fst idxs)
311+ where (pms, idxs) = partition (\c -> snd c `elem` paramPos) (zip cnstrs [0..])
312+
313+ isMachineGenerated :: Name -> Bool
314+ isMachineGenerated (MN _ _) = True
315+ isMachineGenerated _ = False
316+
317+ namePis :: Bool -> [(Name, Plicity, PTerm)] -> EliminatorState [(Name, Plicity, PTerm)]
318+ namePis keepOld pms = do names <- mapM (mkPiName keepOld) pms
319+ let oldNames = map fst names
320+ let params = map snd names
321+ return $ map (\(n, pl, ty) -> (n, pl, removeParamPis oldNames params ty)) params
322+
323+ mkPiName :: Bool -> (Name, Plicity, PTerm) -> EliminatorState (Name, (Name, Plicity, PTerm))
324+ mkPiName keepOld (n, pl, piarg) | not (isMachineGenerated n) && keepOld = do return (n, (n, pl, piarg))
325+ mkPiName _ (oldName, pl, piarg) = do name <- freshName $ keyOf piarg
326+ return (oldName, (name, pl, piarg))
327+ where keyOf :: PTerm -> String
328+ keyOf (PRef _ name) | isLetter (nameStart name) = (toLower $ nameStart name):"__"
329+ keyOf (PApp _ tyf _) = keyOf tyf
330+ keyOf PType = "ty__"
331+ keyOf _ = "carg__"
332+ nameStart :: Name -> Char
333+ nameStart n = nameStart' (simpleName n)
334+ where nameStart' :: String -> Char
335+ nameStart' "" = ' '
336+ nameStart' ns = head ns
337+
338+ simpleName :: Name -> String
339+ simpleName (NS n _) = simpleName n
340+ simpleName (MN i n) = n ++ show i
341+ simpleName n = show n
342+
343+ nameSpaces :: Name -> [String]
344+ nameSpaces (NS _ ns) = ns
345+ nameSpaces _ = []
346+
347+ freshName :: String -> EliminatorState Name
348+ freshName key = do
349+ nameMap <- get
350+ let i = fromMaybe 0 (Map.lookup key nameMap)
351+ let name = key ++ show i ++ "__"
352+ put $ Map.insert key (i+1) nameMap
353+ return (MN i name)
354+
355+ scrutineeName :: Name
356+ scrutineeName = MN 0 "scrutinee"
357+
358+ scrutineeArgName :: Name
359+ scrutineeArgName = MN 0 "scrutineeArg"
360+
361+ motiveName :: Name
362+ motiveName = MN 0 "prop"
363+
364+ mkMotive :: Name -> [Int] -> [(Name, Plicity, PTerm)] -> [(Name, Plicity, PTerm)] -> PTerm
365+ mkMotive n paramPos params indicies =
366+ let scrutineeTy = (scrutineeArgName, expl, applyCons n (interlievePos paramPos params indicies 0))
367+ in piConstr (indicies ++ [scrutineeTy]) PType
368+
369+ piConstr :: [(Name, Plicity, PTerm)] -> PTerm -> PTerm
370+ piConstr [] ty = ty
371+ piConstr ((n, pl, tyb):tyr) ty = PPi pl n tyb (piConstr tyr ty)
372+
373+ interlievePos :: [Int] -> [a] -> [a] -> Int -> [a]
374+ interlievePos idxs [] l2 i = l2
375+ interlievePos idxs l1 [] i = l1
376+ interlievePos idxs (x:xs) l2 i | i `elem` idxs = x:(interlievePos idxs xs l2 (i+1))
377+ interlievePos idxs l1 (y:ys) i = y:(interlievePos idxs l1 ys (i+1))
378+
379+ replaceParams :: [Int] -> [(Name, Plicity, PTerm)] -> PTerm -> PTerm
380+ replaceParams paramPos params cns =
381+ let (_, cnsResTy) = splitPi cns
382+ in case cnsResTy of
383+ PApp _ _ args ->
384+ let oldParams = paramNamesOf 0 paramPos args
385+ in removeParamPis oldParams params cns
386+ _ -> cns
387+
388+ removeParamPis :: [Name] -> [(Name, Plicity, PTerm)] -> PTerm -> PTerm
389+ removeParamPis oldParams params (PPi pl n tyb tyr) =
390+ case findIndex (== n) oldParams of
391+ Nothing -> (PPi pl n (removeParamPis oldParams params tyb) (removeParamPis oldParams params tyr))
392+ Just i -> (removeParamPis oldParams params tyr)
393+ removeParamPis oldParams params (PRef _ n) =
394+ case findIndex (== n) oldParams of
395+ Nothing -> (PRef elimFC n)
396+ Just i -> let (newname,_,_) = params !! i in (PRef elimFC (newname))
397+ removeParamPis oldParams params (PApp _ cns args) =
398+ PApp elimFC (removeParamPis oldParams params cns) $ replaceParamArgs args
399+ where replaceParamArgs :: [PArg] -> [PArg]
400+ replaceParamArgs [] = []
401+ replaceParamArgs (arg:args) =
402+ case extractName (getTm arg) of
403+ [] -> arg:replaceParamArgs args
404+ [n] ->
405+ case findIndex (== n) oldParams of
406+ Nothing -> arg:replaceParamArgs args
407+ Just i -> let (newname,_,_) = params !! i in arg {getTm = PRef elimFC newname}:replaceParamArgs args
408+ removeParamPis oldParams params t = t
409+
410+ paramNamesOf :: Int -> [Int] -> [PArg] -> [Name]
411+ paramNamesOf i paramPos [] = []
412+ paramNamesOf i paramPos (arg:args) = (if i `elem` paramPos then extractName (getTm arg) else []) ++ paramNamesOf (i+1) paramPos args
413+
414+ extractName :: PTerm -> [Name]
415+ extractName (PRef _ n) = [n]
416+ extractName _ = []
417+
418+ splitArgPms :: PTerm -> ([PTerm], [PTerm])
419+ splitArgPms (PApp _ f args) = splitArgPms' args
420+ where splitArgPms' :: [PArg] -> ([PTerm], [PTerm])
421+ splitArgPms' cnstrs = (map (getTm . fst) pms, map (getTm . fst) idxs)
422+ where (pms, idxs) = partition (\c -> snd c `elem` paramPos) (zip cnstrs [0..])
423+ splitArgPms _ = ([],[])
424+
425+
426+ implicitIndexes :: (String, Name, PTerm, FC) -> EliminatorState [(Name, Plicity, PTerm)]
427+ implicitIndexes (cns@(doc, cnm, ty, fc)) = do
428+ i <- Control.Monad.State.lift getIState
429+ implargs' <- case lookupCtxt cnm (idris_implicits i) of
430+ [] -> do fail $ "Error while showing implicits for " ++ show cnm
431+ [args] -> do return args
432+ _ -> do fail $ "Ambigous name for " ++ show cnm
433+ let implargs = mapMaybe convertImplPi implargs'
434+ let (_, cnsResTy) = splitPi ty
435+ case cnsResTy of
436+ PApp _ _ args ->
437+ let oldParams = paramNamesOf 0 paramPos args
438+ in return $ filter (\(n,_,_) -> not (n `elem` oldParams))implargs
439+ _ -> return implargs
440+
441+ extractConsTerm :: (String, Name, PTerm, FC) -> [(Name, Plicity, PTerm)] -> EliminatorState PTerm
442+ extractConsTerm (doc, cnm, ty, fc) generalParameters = do
443+ let cons' = replaceParams paramPos generalParameters ty
444+ let (args, resTy) = splitPi cons'
445+ implidxs <- implicitIndexes (doc, cnm, ty, fc)
446+ consArgs <- namePis True args
447+ let recArgs = findRecArgs consArgs
448+ let recMotives = map applyRecMotive recArgs
449+ let (_, consIdxs) = splitArgPms resTy
450+ return $ piConstr (implidxs ++ consArgs ++ recMotives) (applyMotive consIdxs (applyCons cnm consArgs))
451+ where applyRecMotive :: (Name, Plicity, PTerm) -> (Name, Plicity, PTerm)
452+ applyRecMotive (n,_,ty) = (MN 0 $ "ih" ++ simpleName n, expl, applyMotive idxs (PRef elimFC n))
453+ where (_, idxs) = splitArgPms ty
454+
455+ findRecArgs :: [(Name, Plicity, PTerm)] -> [(Name, Plicity, PTerm)]
456+ findRecArgs [] = []
457+ findRecArgs (ty@(_,_,PRef _ tn):rs) | simpleName tn == simpleName n = ty:findRecArgs rs
458+ findRecArgs (ty@(_,_,PApp _ (PRef _ tn) _):rs) | simpleName tn == simpleName n = ty:findRecArgs rs
459+ findRecArgs (ty:rs) = findRecArgs rs
460+
461+ applyCons :: Name -> [(Name, Plicity, PTerm)] -> PTerm
462+ applyCons tn targs = PApp elimFC (PRef elimFC tn) (map convertArg targs)
463+
464+ convertArg :: (Name, Plicity, PTerm) -> PArg
465+ convertArg (n, _, _) = pexp (PRef elimFC n)
466+
467+ applyMotive :: [PTerm] -> PTerm -> PTerm
468+ applyMotive idxs t = PApp elimFC (PRef elimFC motiveName) (map pexp idxs ++ [pexp t])
469+
470+ getPiName :: (Name, Plicity, PTerm) -> Name
471+ getPiName (name,_,_) = name
472+
473+ convertImplPi :: PArg -> Maybe (Name, Plicity, PTerm)
474+ convertImplPi (PImp {getTm = t, pname = n}) = Just (n, expl, t)
475+ convertImplPi _ = Nothing
476+
477+ generateEliminatorClauses :: (String, Name, PTerm, FC) -> Name -> [PArg] -> [(Name, Plicity, PTerm)] -> EliminatorState PClause
478+ generateEliminatorClauses (doc, cnm, ty, fc) cnsElim generalArgs generalParameters = do
479+ let cons' = replaceParams paramPos generalParameters ty
480+ let (args, resTy) = splitPi cons'
481+ i <- Control.Monad.State.lift getIState
482+ implidxs <- implicitIndexes (doc, cnm, ty, fc)
483+ let (_, generalIdxs') = splitArgPms resTy
484+ let generalIdxs = map pexp generalIdxs'
485+ consArgs <- namePis True args
486+ let lhsPattern = PApp elimFC (PRef elimFC elimDeclName) (generalArgs ++ generalIdxs ++ [pexp $ applyCons cnm consArgs])
487+ let recArgs = findRecArgs consArgs
488+ let recElims = map applyRecElim recArgs
489+ let rhsExpr = PApp elimFC (PRef elimFC cnsElim) (map convertArg implidxs ++ map convertArg consArgs ++ recElims)
490+ return $ PClause elimFC elimDeclName lhsPattern [] rhsExpr []
491+ where applyRecElim :: (Name, Plicity, PTerm) -> PArg
492+ applyRecElim (constr@(recCnm,_,recTy)) = pexp $ PApp elimFC (PRef elimFC elimDeclName) (generalArgs ++ map pexp idxs ++ [pexp $ PRef elimFC recCnm])
493+ where (_, idxs) = splitArgPms recTy
494+
248495-- | Elaborate primitives
249496
250497elabPrims :: Idris ()
251498elabPrims = do mapM_ (elabDecl EAll toplevel)
252− (map (PData "" defaultSyntax (fileFC "builtin") False)
253− [inferDecl, unitDecl, falseDecl, pairDecl, eqDecl])
499+ (map (\(opt, decl) -> PData "" defaultSyntax (fileFC "builtin") opt decl)
500+ (zip
501+ [inferOpts, unitOpts, falseOpts, pairOpts, eqOpts]
502+ [inferDecl, unitDecl, falseDecl, pairDecl, eqDecl]))
503+ elabDecl EAll toplevel elimDecl
254504 mapM_ elabPrim primitives
255505 -- Special case prim__believe_me because it doesn't work on just constants
256506 elabBelieveMe
@@ -400,7 +650,7 @@ elabTransform info fc safe lhs_in rhs_in
400650elabRecord :: ElabInfo -> SyntaxInfo -> String -> FC -> Name ->
401651 PTerm -> String -> Name -> PTerm -> Idris ()
402652elabRecord info syn doc fc tyn ty cdoc cn cty
403− = do elabData info syn doc fc False (PDatadecl tyn ty [(cdoc, cn, cty, fc)])
653+ = do elabData info syn doc fc [] (PDatadecl tyn ty [(cdoc, cn, cty, fc)])
404654 cty' <- implicit syn cn cty
405655 i <- getIState
406656 cty <- case lookupTy cn (tt_ctxt i) of
@@ -1286,7 +1536,7 @@ elabClass info syn doc fc constraints tn ps ds
12861536 let cons = [("", cn, cty, fc)]
12871537 let ddecl = PDatadecl tn tty cons
12881538 logLvl 5 $ "Class data " ++ showDImp True ddecl
1289− elabData info (syn { no_imp = no_imp syn ++ mnames }) doc fc False ddecl
1539+ elabData info (syn { no_imp = no_imp syn ++ mnames }) doc fc [] ddecl
12901540 -- for each constraint, build a top level function to chase it
12911541 logLvl 5 $ "Building functions"
12921542 let usyn = syn { using = map (\ (x,y) -> UImplicit x y) ps
@@ -1709,7 +1959,7 @@ elabDecl' what info (PRecord doc s f tyn ty cdoc cn cty)
17091959 elabRecord info s doc f tyn ty cdoc cn cty
17101960 | otherwise
17111961 = do iLOG $ "Elaborating [type of] " ++ show tyn
1712− elabData info s doc f False (PLaterdecl tyn ty)
1962+ elabData info s doc f [] (PLaterdecl tyn ty)
17131963elabDecl' _ info (PDSL n dsl)
17141964 = do i <- getIState
17151965 putIState (i { idris_dsls = addDef n dsl (idris_dsls i) })
src/Idris/IBC.hs+13−1
@@ -23,7 +23,7 @@ import Debug.Trace
2323import Paths_idris
2424
2525ibcVersion :: Word8
26−ibcVersion = 44
26+ibcVersion = 45
2727
2828data IBCFile = IBCFile { ver :: Word8,
2929 sourcefile :: FilePath,
@@ -410,6 +410,7 @@ instance Binary SpecialName where
410410 MethodN x1 -> do putWord8 3
411411 put x1
412412 CaseN x1 -> do putWord8 4; put x1
413+ ElimN x1 -> do putWord8 5; put x1
413414 get
414415 = do i <- getWord8
415416 case i of
@@ -427,6 +428,8 @@ instance Binary SpecialName where
427428 return (MethodN x1)
428429 4 -> do x1 <- get
429430 return (CaseN x1)
431+ 5 -> do x1 <- get
432+ return (ElimN x1)
430433 _ -> error "Corrupted binary data for SpecialName"
431434
432435
@@ -931,6 +934,15 @@ instance Binary IBCFile where
931934 return (IBCFile x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27)
932935 else return (initIBC { ver = x1 })
933936
937+instance Binary DataOpt where
938+ put x = case x of
939+ Codata -> putWord8 0
940+ DefaultEliminator -> putWord8 1
941+ get = do i <- getWord8
942+ case i of
943+ 0 -> return Codata
944+ 1 -> return DefaultEliminator
945+
934946instance Binary FnOpt where
935947 put x
936948 = case x of
src/Idris/ParseData.hs+22−12
@@ -70,13 +70,19 @@ record syn = do (doc, acc) <- try (do
7070{- | Parses data declaration type (normal or codata)
7171DataI ::= 'data' | 'codata';
7272-}
73−dataI :: IdrisParser Bool
74−dataI = do reserved "data"; return False
75− <|> do reserved "codata"; return True
73+dataI :: IdrisParser DataOpts
74+dataI = do reserved "data"; return []
75+ <|> do reserved "codata"; return [Codata]
76+
77+{- | Parses if a data should not have a default eliminator
78+DefaultEliminator ::= 'noelim'?
79+ -}
80+defaultEliminator :: IdrisParser DataOpts
81+defaultEliminator = do option [] (do reserved "%elim"; return [DefaultEliminator])
7682
7783{- | Parses a data type declaration
78−Data ::= DocComment? Accessibility? DataI FnName TypeSig ExplicitTypeDataRest?
79− | DocComment? Accessibility? DataI FnName Name* DataRest?
84+Data ::= DocComment? Accessibility? DataI DefaultEliminator FnName TypeSig ExplicitTypeDataRest?
85+ | DocComment? Accessibility? DataI DefaultEliminator FnName Name* DataRest?
8086 ;
8187Constructor' ::= Constructor KeepTerminator;
8288ExplicitTypeDataRest ::= 'where' OpenBlock Constructor'* CloseBlock;
@@ -90,29 +96,31 @@ SimpleConstructorList ::=
9096 ;
9197-}
9298data_ :: SyntaxInfo -> IdrisParser PDecl
93−data_ syn = do (doc, acc, co) <- try (do
99+data_ syn = do (doc, acc, dataOpts) <- try (do
94100 doc <- option "" (docComment '|')
95101 pushIndent
96102 acc <- optional accessibility
103+ elim <- defaultEliminator
97104 co <- dataI
98− return (doc, acc, co))
105+ let dataOpts = combineDataOpts(elim ++ co)
106+ return (doc, acc, dataOpts))
99107 fc <- getFC
100108 tyn_in <- fnName
101109 (do try (lchar ':')
102110 popIndent
103111 ty <- typeExpr (allowImp syn)
104112 let tyn = expandNS syn tyn_in
105− option (PData doc syn fc co (PLaterdecl tyn ty)) (do
113+ option (PData doc syn fc dataOpts (PLaterdecl tyn ty)) (do
106114 reserved "where"
107115 cons <- indentedBlock (constructor syn)
108116 accData acc tyn (map (\ (_, n, _, _) -> n) cons)
109− return $ PData doc syn fc co (PDatadecl tyn ty cons))) <|> (do
117+ return $ PData doc syn fc dataOpts (PDatadecl tyn ty cons))) <|> (do
110118 args <- many name
111119 let ty = bindArgs (map (const PType) args) PType
112120 let tyn = expandNS syn tyn_in
113− option (PData doc syn fc co (PLaterdecl tyn ty)) (do
121+ option (PData doc syn fc dataOpts (PLaterdecl tyn ty)) (do
114122 try (lchar '=') <|> do reserved "where"
115− let kw = (if co then "co" else "") ++ "data "
123+ let kw = (if DefaultEliminator `elem` dataOpts then "" else "%noelim ") ++ (if Codata `elem` dataOpts then "co" else "") ++ "data "
116124 let n = show tyn_in ++ " "
117125 let s = kw ++ n
118126 let as = concat (intersperse " " $ map show args) ++ " "
@@ -129,7 +137,7 @@ data_ syn = do (doc, acc, co) <- try (do
129137 do let cty = bindArgs cargs conty
130138 return (doc, x, cty, cfc)) cons
131139 accData acc tyn (map (\ (_, n, _, _) -> n) cons')
132− return $ PData doc syn fc co (PDatadecl tyn ty cons')))
140+ return $ PData doc syn fc dataOpts (PDatadecl tyn ty cons')))
133141 <?> "data type declaration"
134142 where
135143 mkPApp :: FC -> PTerm -> [PTerm] -> PTerm
@@ -137,6 +145,8 @@ data_ syn = do (doc, acc, co) <- try (do
137145 mkPApp fc t xs = PApp fc t (map pexp xs)
138146 bindArgs :: [PTerm] -> PTerm -> PTerm
139147 bindArgs xs t = foldr (PPi expl (MN 0 "t")) t xs
148+ combineDataOpts :: DataOpts -> DataOpts
149+ combineDataOpts opts = if Codata `elem` opts then delete DefaultEliminator opts else opts
140150
141151
142152{- | Parses a type constructor declaration
src/Idris/ParseExpr.hs+1
@@ -267,6 +267,7 @@ simpleExpr syn =
267267 tm <- option Placeholder (do lchar '{'; t <- expr syn; lchar '}';
268268 return t)
269269 return (PRefl fc tm)
270+ <|> do reserved "elim_for"; fc <- getFC; t <- fnName; return (PRef fc (SN $ ElimN t))
270271 <|> proofExpr syn
271272 <|> tacticsExpr syn
272273 <|> caseExpr syn