Add reflection operation for adding declarations

Declarations can be quoted with `[ decl ]. See reflection004 for an
example.
This commit is contained in:
Edwin Brady 2020-06-01 15:01:52 +01:00
parent e6f6c105d1
commit 02d371a94b
15 changed files with 87 additions and 17 deletions

View File

@ -23,9 +23,12 @@ data Elab : Type -> Type where
-- and their types. If there's no results, the name is undefined. -- and their types. If there's no results, the name is undefined.
GetType : Name -> Elab (List (Name, TTImp)) GetType : Name -> Elab (List (Name, TTImp))
-- Get the constructors of a data type -- Get the constructors of a data type. The name must be fully resolved.
GetCons : Name -> Elab (List Name) GetCons : Name -> Elab (List Name)
-- Check a group of top level declarations
Declare : List Decl -> Elab ()
mutual mutual
export export
Functor Elab where Functor Elab where
@ -79,3 +82,7 @@ getType = GetType
export export
getCons : Name -> Elab (List Name) getCons : Name -> Elab (List Name)
getCons = GetCons getCons = GetCons
export
declare : List Decl -> Elab ()
declare = Declare

View File

@ -251,9 +251,8 @@ mutual
desugarB side ps (PQuoteName fc n) desugarB side ps (PQuoteName fc n)
= pure $ IQuoteName fc n = pure $ IQuoteName fc n
desugarB side ps (PQuoteDecl fc x) desugarB side ps (PQuoteDecl fc x)
= do [x'] <- desugarDecl ps x = do xs <- traverse (desugarDecl ps) x
| _ => throw (GenericMsg fc "Can't quote this declaration") pure $ IQuoteDecl fc (concat xs)
pure $ IQuoteDecl fc x'
desugarB side ps (PUnquote fc tm) desugarB side ps (PUnquote fc tm)
= pure $ IUnquote fc !(desugarB side ps tm) = pure $ IUnquote fc !(desugarB side ps tm)
desugarB side ps (PRunElab fc tm) desugarB side ps (PRunElab fc tm)

View File

@ -385,6 +385,12 @@ mutual
symbol "}}" symbol "}}"
end <- location end <- location
pure (PQuoteName (MkFC fname start end) n) pure (PQuoteName (MkFC fname start end) n)
<|> do start <- location
symbol "`["
ns <- nonEmptyBlock (topDecl fname)
symbol "]"
end <- location
pure (PQuoteDecl (MkFC fname start end) (collectDefs (concat ns)))
<|> do start <- location <|> do start <- location
symbol "~" symbol "~"
e <- simpleExpr fname indents e <- simpleExpr fname indents

View File

@ -241,11 +241,9 @@ mutual
toPTerm p (IForce fc tm) = pure (PForce fc !(toPTerm argPrec tm)) toPTerm p (IForce fc tm) = pure (PForce fc !(toPTerm argPrec tm))
toPTerm p (IQuote fc tm) = pure (PQuote fc !(toPTerm argPrec tm)) toPTerm p (IQuote fc tm) = pure (PQuote fc !(toPTerm argPrec tm))
toPTerm p (IQuoteName fc n) = pure (PQuoteName fc n) toPTerm p (IQuoteName fc n) = pure (PQuoteName fc n)
toPTerm p (IQuoteDecl fc d) toPTerm p (IQuoteDecl fc ds)
= do md <- toPDecl d = do ds' <- traverse toPDecl ds
case md of pure $ PQuoteDecl fc (mapMaybe id ds')
Nothing => throw (InternalError "Can't resugar log or pragma")
Just d' => pure (PQuoteDecl fc d')
toPTerm p (IUnquote fc tm) = pure (PUnquote fc !(toPTerm argPrec tm)) toPTerm p (IUnquote fc tm) = pure (PUnquote fc !(toPTerm argPrec tm))
toPTerm p (IRunElab fc tm) = pure (PRunElab fc !(toPTerm argPrec tm)) toPTerm p (IRunElab fc tm) = pure (PRunElab fc !(toPTerm argPrec tm))

View File

@ -54,7 +54,7 @@ mutual
PPrimVal : FC -> Constant -> PTerm PPrimVal : FC -> Constant -> PTerm
PQuote : FC -> PTerm -> PTerm PQuote : FC -> PTerm -> PTerm
PQuoteName : FC -> Name -> PTerm PQuoteName : FC -> Name -> PTerm
PQuoteDecl : FC -> PDecl -> PTerm PQuoteDecl : FC -> List PDecl -> PTerm
PUnquote : FC -> PTerm -> PTerm PUnquote : FC -> PTerm -> PTerm
PRunElab : FC -> PTerm -> PTerm PRunElab : FC -> PTerm -> PTerm
PHole : FC -> (bracket : Bool) -> (holename : String) -> PTerm PHole : FC -> (bracket : Bool) -> (holename : String) -> PTerm
@ -441,7 +441,7 @@ mutual
showPrec _ (PSearch _ _) = "%search" showPrec _ (PSearch _ _) = "%search"
showPrec d (PQuote _ tm) = "`(" ++ showPrec d tm ++ ")" showPrec d (PQuote _ tm) = "`(" ++ showPrec d tm ++ ")"
showPrec d (PQuoteName _ n) = "`{{" ++ showPrec d n ++ "}}" showPrec d (PQuoteName _ n) = "`{{" ++ showPrec d n ++ "}}"
showPrec d (PQuoteDecl _ tm) = "`( <<declaration>> )" showPrec d (PQuoteDecl _ tm) = "`[ <<declaration>> ]"
showPrec d (PUnquote _ tm) = "~(" ++ showPrec d tm ++ ")" showPrec d (PUnquote _ tm) = "~(" ++ showPrec d tm ++ ")"
showPrec d (PRunElab _ tm) = "%runElab " ++ showPrec d tm showPrec d (PRunElab _ tm) = "%runElab " ++ showPrec d tm
showPrec d (PPrimVal _ c) = showPrec d c showPrec d (PPrimVal _ c) = showPrec d c
@ -693,7 +693,7 @@ mapPTermM f = goPTerm where
>>= f >>= f
goPTerm t@(PQuoteName _ _) = f t goPTerm t@(PQuoteName _ _) = f t
goPTerm (PQuoteDecl fc x) = goPTerm (PQuoteDecl fc x) =
PQuoteDecl fc <$> goPDecl x PQuoteDecl fc <$> traverse goPDecl x
>>= f >>= f
goPTerm (PUnquote fc x) = goPTerm (PUnquote fc x) =
PUnquote fc <$> goPTerm x PUnquote fc <$> goPTerm x

View File

@ -159,7 +159,7 @@ symbols
"@{", "@{",
"[|", "|]", "[|", "|]",
"(", ")", "{", "}}", "}", "[", "]", ",", ";", "_", "(", ")", "{", "}}", "}", "[", "]", ",", ";", "_",
"`(", "`{{", "`"] "`(", "`{{", "`[", "`"]
export export
isOpChar : Char -> Bool isOpChar : Char -> Bool

View File

@ -215,3 +215,25 @@ checkQuoteName rig elabinfo nest env fc n exp
qnm <- reflect fc defs env n qnm <- reflect fc defs env n
qty <- getCon fc defs (reflectiontt "Name") qty <- getCon fc defs (reflectiontt "Name")
checkExp rig elabinfo env fc qnm (gnf env qty) exp checkExp rig elabinfo env fc qnm (gnf env qty) exp
export
checkQuoteDecl : {vars : _} ->
{auto c : Ref Ctxt Defs} ->
{auto m : Ref MD Metadata} ->
{auto u : Ref UST UState} ->
{auto e : Ref EST (EState vars)} ->
RigCount -> ElabInfo ->
NestedNames vars -> Env Term vars ->
FC -> List ImpDecl -> Maybe (Glued vars) ->
Core (Term vars, Glued vars)
checkQuoteDecl rig elabinfo nest env fc ds exp
= do defs <- get Ctxt
q <- newRef Unq (the (List (Name, FC, RawImp)) [])
ds' <- traverse getUnquoteDecl ds
qds <- reflect fc defs env ds'
unqs <- get Unq
qd <- getCon fc defs (reflectionttimp "Decl")
qty <- appCon fc defs (prelude "List") [qd]
checkExp rig elabinfo env fc
!(bindUnqs unqs rig elabinfo nest env qds)
(gnf env qty) exp

View File

@ -96,6 +96,11 @@ elabScript fc elabinfo nest env (NDCon nfc nm t ar args) exp
lookupDefExact cn (gamma defs) lookupDefExact cn (gamma defs)
| _ => throw (GenericMsg fc (show cn ++ " is not a type")) | _ => throw (GenericMsg fc (show cn ++ " is not a type"))
scriptRet cons scriptRet cons
elabCon defs "Declare" [d]
= do d' <- evalClosure defs d
decls <- reify defs d'
traverse_ (processDecl [] (MkNested []) []) decls
scriptRet ()
elabCon defs n args = failWith defs elabCon defs n args = failWith defs
elabScript fc elabinfo nest env script exp elabScript fc elabinfo nest env script exp
= do defs <- get Ctxt = do defs <- get Ctxt

View File

@ -180,8 +180,8 @@ checkTerm rig elabinfo nest env (IQuote fc tm) exp
= checkQuote rig elabinfo nest env fc tm exp = checkQuote rig elabinfo nest env fc tm exp
checkTerm rig elabinfo nest env (IQuoteName fc n) exp checkTerm rig elabinfo nest env (IQuoteName fc n) exp
= checkQuoteName rig elabinfo nest env fc n exp = checkQuoteName rig elabinfo nest env fc n exp
checkTerm rig elabinfo nest env (IQuoteDecl fc tm) exp checkTerm rig elabinfo nest env (IQuoteDecl fc ds) exp
= throw (GenericMsg fc "Declaration reflection not implemented yet") = checkQuoteDecl rig elabinfo nest env fc ds exp
checkTerm rig elabinfo nest env (IUnquote fc tm) exp checkTerm rig elabinfo nest env (IUnquote fc tm) exp
= throw (GenericMsg fc "Can't escape outside a quoted term") = throw (GenericMsg fc "Can't escape outside a quoted term")
checkTerm rig elabinfo nest env (IRunElab fc tm) exp checkTerm rig elabinfo nest env (IRunElab fc tm) exp

View File

@ -92,7 +92,7 @@ mutual
-- Quasiquoting -- Quasiquoting
IQuote : FC -> RawImp -> RawImp IQuote : FC -> RawImp -> RawImp
IQuoteName : FC -> Name -> RawImp IQuoteName : FC -> Name -> RawImp
IQuoteDecl : FC -> ImpDecl -> RawImp IQuoteDecl : FC -> List ImpDecl -> RawImp
IUnquote : FC -> RawImp -> RawImp IUnquote : FC -> RawImp -> RawImp
IRunElab : FC -> RawImp -> RawImp IRunElab : FC -> RawImp -> RawImp

View File

@ -86,7 +86,7 @@ idrisTests
-- Records, access and dependent update -- Records, access and dependent update
"record001", "record002", "record003", "record004", "record001", "record002", "record003", "record004",
-- Quotation and reflection -- Quotation and reflection
"reflection001", "reflection002", "reflection003", "reflection001", "reflection002", "reflection003", "reflection004",
-- Miscellaneous regressions -- Miscellaneous regressions
"reg001", "reg002", "reg003", "reg004", "reg005", "reg006", "reg007", "reg001", "reg002", "reg003", "reg004", "reg005", "reg006", "reg007",
"reg008", "reg009", "reg010", "reg011", "reg012", "reg013", "reg014", "reg008", "reg009", "reg010", "reg011", "reg012", "reg013", "reg014",

View File

@ -0,0 +1,5 @@
1/1: Building refdecl (refdecl.idr)
Main> 9
Main> 12
Main> 5
Main> Bye for now!

View File

@ -0,0 +1,4 @@
foo 4 5
mkMult 3
myplus 2 3
:q

View File

@ -0,0 +1,21 @@
import Language.Reflection
%language ElabReflection
logDecls : TTImp -> Elab TT
logDecls v
= do declare [IClaim EmptyFC MW Public []
(MkTy EmptyFC `{{ Main.foo }}
`(Int -> Int -> Int) )]
declare `[ foo x y = x + y ]
declare `[ multBy : Int -> Int
multBy x = x * ~(v) ]
declare `[ myplus : Nat -> Nat -> Nat
myplus Z y = y
myplus (S k) y = S (myplus k y) ]
check `( multBy )
mkMult : Int -> Int
mkMult = %runElab logDecls `(4)

3
tests/idris2/reflection004/run Executable file
View File

@ -0,0 +1,3 @@
$1 --no-banner refdecl.idr < input
rm -rf build