1{-# LANGUAGE PatternGuards #-}
2module Idris.Elab.Provider(elabProvider) where
14import Idris.Primitives
16import Idris.PartialEval
18import Idris.Output (iputStrLn, pshow, iWarn)
22import Idris.Elab.Clause
23import Idris.Elab.Value
24import Idris.Elab.Utils
27import Idris.Core.Elaborate hiding (Tactic(..))
28import Idris.Core.Evaluate
29import Idris.Core.Execute
30import Idris.Core.Typecheck
31import Idris.Core.CaseTree
33import Idris.Docstrings
35import Prelude hiding (id, (.))
36import Control.Category
38import Control.Applicative hiding (Const)
41import Control.Monad.State.Strict as State
46import qualified Data.Map as Map
47import qualified Data.Set as S
48import qualified Data.Text as T
49import Data.Char(isLetter, toLower)
50import Data.List.Split (splitOn)
52import Util.Pretty(pretty, text)
54-- | Elaborate a type provider
55elabProvider :: Docstring (Either Err PTerm) -> ElabInfo -> SyntaxInfo -> FC -> ProvideWhat -> Name -> Idris ()
56elabProvider doc info syn fc what n
58 -- Ensure that the experimental extension is enabled
59 unless (TypeProviders `elem` idris_language_extensions i) $
60 ifail $ "Failed to define type provider \"" ++ show n ++
61 "\".\nYou must turn on the TypeProviders extension."
65 -- First elaborate the expected type (and check that it's a type)
66 -- The goal type for a postulate is always Type.
67 (ty', typ) <- case what of
68 ProvTerm ty p -> elabVal info ERHS ty
69 ProvPostulate _ -> elabVal info ERHS PType
70 unless (isTType typ) $
71 ifail ("Expected a type, got " ++ show ty' ++ " : " ++ show typ)
73 -- Elaborate the provider term to TT and check that the type matches
74 (e, et) <- case what of
75 ProvTerm _ tm -> elabVal info ERHS tm
76 ProvPostulate tm -> elabVal info ERHS tm
77 unless (isProviderOf ctxt ty' et) $
78 ifail $ "Expected provider type " ++ show (providerOf ty') ++
79 ", got " ++ show et ++ " instead."
81 -- Execute the type provider and normalise the result
82 -- use 'run__provider' to convert to a primitive IO action
84 rhs <- execute (mkApp (P Ref (sUN "run__provider") Erased)
86 let rhs' = normalise ctxt [] rhs
87 logLvl 3 $ "Normalised " ++ show n ++ "'s RHS to " ++ show rhs
89 -- Extract the provided term or postulate from the type provider
90 provided <- getProvided fc rhs'
94 | ProvTerm ty _ <- what ->
95 do -- Finally add a top-level definition of the provided term
96 elabType info syn doc [] fc [] n ty
97 elabClauses info fc [] n [PClause fc n (PApp fc (PRef fc n) []) [] (delab i tm) []]
98 logLvl 3 $ "Elaborated provider " ++ show n ++ " as: " ++ show tm
99 | ProvPostulate _ <- what ->
100 do -- Add the postulate
101 elabPostulate info syn doc fc [] n (delab i tm)
102 logLvl 3 $ "Elaborated provided postulate " ++ show n
104 ierror . Msg $ "Attempted to provide a postulate where a term was expected."
106 where isTType :: TT Name -> Bool
107 isTType (TType _) = True
110 -- Note: IO (Providers.Provider ty) is used instead of IO'
111 -- (MkFFI C_FFI) (Providers.Provider ty) in hopes of better
112 -- error messages with less normalisation
113 providerOf :: Type -> Type
114 providerOf ty = App (P Ref (sUN "IO") Erased) $
115 App (P Ref (sNS (sUN "Provider") ["Providers", "Prelude"]) Erased)
118 isProviderOf :: Context -> TT Name -> TT Name -> Bool
119 isProviderOf ctxt tp prov =
120 case converts ctxt [] (providerOf tp) prov of
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