mirror of
https://github.com/idris-lang/Idris2.git
synced 2024-12-24 12:14:26 +03:00
2f6ec76223
* Only normalise a search goal if it's fast While we do end up normalising it anyway on success, there might be things blocking it that make the intermediate terms very big, so only do it speculatively to see if it's quick. * Get information about names in reflection Currently this is only whether it's a function, or data or type constructor. I expect more may be useful/possible.
204 lines
6.1 KiB
Idris
204 lines
6.1 KiB
Idris
module Language.Reflection
|
|
|
|
import public Language.Reflection.TT
|
|
import public Language.Reflection.TTImp
|
|
|
|
import public Control.Monad.Trans
|
|
|
|
%default total
|
|
|
|
----------------------------------
|
|
--- Elaboration data structure ---
|
|
----------------------------------
|
|
|
|
||| Elaboration scripts
|
|
||| Where types/terms are returned, binders will have unique, if not
|
|
||| necessarily human readabe, names
|
|
export
|
|
data Elab : Type -> Type where
|
|
Pure : a -> Elab a
|
|
Bind : Elab a -> (a -> Elab b) -> Elab b
|
|
Fail : FC -> String -> Elab a
|
|
|
|
Try : Elab a -> Elab a -> Elab a
|
|
|
|
||| Log a message. Takes a
|
|
||| * topic
|
|
||| * level
|
|
||| * message
|
|
LogMsg : String -> Nat -> String -> Elab ()
|
|
||| Print and log a term. Takes a
|
|
||| * topic
|
|
||| * level
|
|
||| * message
|
|
||| * term
|
|
LogTerm : String -> Nat -> String -> TTImp -> Elab ()
|
|
||| Resugar, print and log a term. Takes a
|
|
||| * topic
|
|
||| * level
|
|
||| * message
|
|
||| * term
|
|
LogSugaredTerm : String -> Nat -> String -> TTImp -> Elab ()
|
|
|
|
-- Elaborate a TTImp term to a concrete value
|
|
Check : TTImp -> Elab expected
|
|
-- Quote a concrete expression back to a TTImp
|
|
Quote : (0 _ : val) -> Elab TTImp
|
|
|
|
-- Elaborate under a lambda
|
|
Lambda : (0 x : Type) ->
|
|
{0 ty : x -> Type} ->
|
|
((val : x) -> Elab (ty val)) -> Elab ((val : x) -> (ty val))
|
|
|
|
-- Get the current goal type, if known
|
|
-- (it might need to be inferred from the solution)
|
|
Goal : Elab (Maybe TTImp)
|
|
-- Get the names of local variables in scope
|
|
LocalVars : Elab (List Name)
|
|
-- Generate a new unique name, based on the given string
|
|
GenSym : String -> Elab Name
|
|
-- Put a name in the current namespace
|
|
InCurrentNS : Name -> Elab Name
|
|
-- Get the types of every name which matches.
|
|
-- There may be ambiguities - returns a list of fully explicit names
|
|
-- and their types. If there's no results, the name is undefined.
|
|
GetType : Name -> Elab (List (Name, TTImp))
|
|
-- Get the metadata associated with a name
|
|
GetInfo : Name -> Elab (List (Name, NameInfo))
|
|
-- Get the type of a local variable
|
|
GetLocalType : Name -> Elab TTImp
|
|
-- Get the constructors of a data type. The name must be fully resolved.
|
|
GetCons : Name -> Elab (List Name)
|
|
-- Check a group of top level declarations
|
|
Declare : List Decl -> Elab ()
|
|
|
|
export
|
|
Functor Elab where
|
|
map f e = Bind e $ Pure . f
|
|
|
|
export
|
|
Applicative Elab where
|
|
pure = Pure
|
|
f <*> a = Bind f (<$> a)
|
|
|
|
export
|
|
Alternative Elab where
|
|
empty = Fail EmptyFC ""
|
|
l <|> r = Try l r
|
|
|
|
export
|
|
Monad Elab where
|
|
(>>=) = Bind
|
|
|
|
-----------------------------
|
|
--- Elaboration interface ---
|
|
-----------------------------
|
|
|
|
public export
|
|
interface Monad m => Elaboration m where
|
|
|
|
||| Report an error in elaboration at some location
|
|
failAt : FC -> String -> m a
|
|
|
|
||| Try the first elaborator. If it fails, reset the elaborator state and
|
|
||| run the second
|
|
try : Elab a -> Elab a -> m a
|
|
|
|
||| Write a log message, if the log level is >= the given level
|
|
logMsg : String -> Nat -> String -> m ()
|
|
|
|
||| Write a log message and a rendered term, if the log level is >= the given level
|
|
logTerm : String -> Nat -> String -> TTImp -> m ()
|
|
|
|
||| Write a log message and a resugared & rendered term, if the log level is >= the given level
|
|
logSugaredTerm : String -> Nat -> String -> TTImp -> m ()
|
|
|
|
||| Check that some TTImp syntax has the expected type
|
|
||| Returns the type checked value
|
|
check : TTImp -> m expected
|
|
|
|
||| Return TTImp syntax of a given value
|
|
quote : (0 _ : val) -> m TTImp
|
|
|
|
||| Build a lambda expression
|
|
lambda : (0 x : Type) ->
|
|
{0 ty : x -> Type} ->
|
|
((val : x) -> Elab (ty val)) -> m ((val : x) -> (ty val))
|
|
|
|
||| Get the goal type of the current elaboration
|
|
goal : m (Maybe TTImp)
|
|
|
|
||| Get the names of the local variables in scope
|
|
localVars : m (List Name)
|
|
|
|
||| Generate a new unique name
|
|
genSym : String -> m Name
|
|
|
|
||| Given a name, return the name decorated with the current namespace
|
|
inCurrentNS : Name -> m Name
|
|
|
|
||| Given a possibly ambiguous name, get all the matching names and their types
|
|
getType : Name -> m (List (Name, TTImp))
|
|
|
|
||| Get the metadata associated with a name. Returns all matching namea and their types
|
|
getInfo : Name -> m (List (Name, NameInfo))
|
|
|
|
||| Get the type of a local variable
|
|
getLocalType : Name -> m TTImp
|
|
|
|
||| Get the constructors of a fully qualified data type name
|
|
getCons : Name -> m (List Name)
|
|
|
|
||| Make some top level declarations
|
|
declare : List Decl -> m ()
|
|
|
|
export %inline
|
|
||| Report an error in elaboration
|
|
fail : Elaboration m => String -> m a
|
|
fail = failAt EmptyFC
|
|
|
|
||| Log the current goal type, if the log level is >= the given level
|
|
export %inline
|
|
logGoal : Elaboration m => String -> Nat -> String -> m ()
|
|
logGoal str n msg = whenJust !goal $ logTerm str n msg
|
|
|
|
export
|
|
Elaboration Elab where
|
|
failAt = Fail
|
|
try = Try
|
|
logMsg = LogMsg
|
|
logTerm = LogTerm
|
|
logSugaredTerm = LogSugaredTerm
|
|
check = Check
|
|
quote = Quote
|
|
lambda = Lambda
|
|
goal = Goal
|
|
localVars = LocalVars
|
|
genSym = GenSym
|
|
inCurrentNS = InCurrentNS
|
|
getType = GetType
|
|
getInfo = GetInfo
|
|
getLocalType = GetLocalType
|
|
getCons = GetCons
|
|
declare = Declare
|
|
|
|
public export
|
|
Elaboration m => MonadTrans t => Monad (t m) => Elaboration (t m) where
|
|
failAt = lift .: failAt
|
|
try = lift .: try
|
|
logMsg s = lift .: logMsg s
|
|
logTerm s n = lift .: logTerm s n
|
|
logSugaredTerm s n = lift .: logSugaredTerm s n
|
|
check = lift . check
|
|
quote v = lift $ quote v
|
|
lambda x = lift . lambda x
|
|
goal = lift goal
|
|
localVars = lift localVars
|
|
genSym = lift . genSym
|
|
inCurrentNS = lift . inCurrentNS
|
|
getType = lift . getType
|
|
getInfo = lift . getInfo
|
|
getLocalType = lift . getLocalType
|
|
getCons = lift . getCons
|
|
declare = lift . declare
|