Mercurial > hg > Members > kono > Proof > agda-reflection
view reflection-ex.agda @ 0:776f851a03a3
reflection and tactics
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 15 Mar 2019 17:35:46 +0900 |
parents | |
children | 6f01428aaf2d |
line wrap: on
line source
module reflection-ex where open import Data.Bool open import Data.String open import Data.Nat postulate Name : Set {-# BUILTIN QNAME Name #-} primitive primQNameEquality : Name → Name → Bool primQNameLess : Name → Name → Bool primShowQName : Name → String nameOfNat : Name nameOfNat = quote ℕ isNat : Name → Bool isNat (quote ℕ) = true isNat _ = false postulate Meta : Set {-# BUILTIN AGDAMETA Meta #-} primitive primMetaEquality : Meta → Meta → Bool primMetaLess : Meta → Meta → Bool primShowMeta : Meta → String open import Data.Word open import Data.Float open import Data.Char data Literal : Set where nat : (n : ℕ) → Literal word64 : (n : Word64) → Literal float : (x : Float) → Literal char : (c : Char) → Literal string : (s : String) → Literal name : (x : Name) → Literal meta : (x : Meta) → Literal {-# BUILTIN AGDALITERAL Literal #-} {-# BUILTIN AGDALITNAT nat #-} {-# BUILTIN AGDALITWORD64 word64 #-} {-# BUILTIN AGDALITFLOAT float #-} {-# BUILTIN AGDALITCHAR char #-} {-# BUILTIN AGDALITSTRING string #-} {-# BUILTIN AGDALITQNAME name #-} {-# BUILTIN AGDALITMETA meta #-} data Visibility : Set where visible hidden instance′ : Visibility {-# BUILTIN HIDING Visibility #-} {-# BUILTIN VISIBLE visible #-} {-# BUILTIN HIDDEN hidden #-} {-# BUILTIN INSTANCE instance′ #-} data Relevance : Set where relevant irrelevant : Relevance {-# BUILTIN RELEVANCE Relevance #-} {-# BUILTIN RELEVANT relevant #-} {-# BUILTIN IRRELEVANT irrelevant #-} data ArgInfo : Set where arg-info : (v : Visibility) (r : Relevance) → ArgInfo data Arg (A : Set) : Set where arg : (i : ArgInfo) (x : A) → Arg A {-# BUILTIN ARGINFO ArgInfo #-} {-# BUILTIN ARGARGINFO arg-info #-} {-# BUILTIN ARG Arg #-} {-# BUILTIN ARGARG arg #-} open import Data.List data Pattern : Set where con : (c : Name) (ps : List (Arg Pattern)) → Pattern dot : Pattern var : (s : String) → Pattern lit : (l : Literal) → Pattern proj : (f : Name) → Pattern absurd : Pattern {-# BUILTIN AGDAPATTERN Pattern #-} {-# BUILTIN AGDAPATCON con #-} {-# BUILTIN AGDAPATDOT dot #-} {-# BUILTIN AGDAPATVAR var #-} {-# BUILTIN AGDAPATLIT lit #-} {-# BUILTIN AGDAPATPROJ proj #-} {-# BUILTIN AGDAPATABSURD absurd #-} data Abs (A : Set) : Set where abs : (s : String) (x : A) → Abs A {-# BUILTIN ABS Abs #-} {-# BUILTIN ABSABS abs #-} data Term : Set data Sort : Set data Clause : Set Type = Term data Term where var : (x : ℕ) (args : List (Arg Term)) → Term con : (c : Name) (args : List (Arg Term)) → Term def : (f : Name) (args : List (Arg Term)) → Term lam : (v : Visibility) (t : Abs Term) → Term pat-lam : (cs : List Clause) (args : List (Arg Term)) → Term pi : (a : Arg Type) (b : Abs Type) → Term agda-sort : (s : Sort) → Term lit : (l : Literal) → Term meta : (x : Meta) → List (Arg Term) → Term unknown : Term -- Treated as '_' when unquoting. data Sort where set : (t : Term) → Sort -- A Set of a given (possibly neutral) level. lit : (n : ℕ) → Sort -- A Set of a given concrete level. unknown : Sort data Clause where clause : (ps : List (Arg Pattern)) (t : Term) → Clause absurd-clause : (ps : List (Arg Pattern)) → Clause {-# BUILTIN AGDASORT Sort #-} {-# BUILTIN AGDATERM Term #-} {-# BUILTIN AGDACLAUSE Clause #-} {-# BUILTIN AGDATERMVAR var #-} {-# BUILTIN AGDATERMCON con #-} {-# BUILTIN AGDATERMDEF def #-} {-# BUILTIN AGDATERMMETA meta #-} {-# BUILTIN AGDATERMLAM lam #-} {-# BUILTIN AGDATERMEXTLAM pat-lam #-} {-# BUILTIN AGDATERMPI pi #-} {-# BUILTIN AGDATERMSORT agda-sort #-} {-# BUILTIN AGDATERMLIT lit #-} {-# BUILTIN AGDATERMUNSUPPORTED unknown #-} {-# BUILTIN AGDASORTSET set #-} {-# BUILTIN AGDASORTLIT lit #-} {-# BUILTIN AGDASORTUNSUPPORTED unknown #-} {-# BUILTIN AGDACLAUSECLAUSE clause #-} {-# BUILTIN AGDACLAUSEABSURD absurd-clause #-} data Definition : Set where function : (cs : List Clause) → Definition data-type : (pars : ℕ) (cs : List Name) → Definition -- parameters and constructors record-type : (c : Name) (fs : List (Arg Name)) → -- c: name of record constructor Definition -- fs: fields data-cons : (d : Name) → Definition -- d: name of data type axiom : Definition prim-fun : Definition {-# BUILTIN AGDADEFINITION Definition #-} {-# BUILTIN AGDADEFINITIONFUNDEF function #-} {-# BUILTIN AGDADEFINITIONDATADEF data-type #-} {-# BUILTIN AGDADEFINITIONRECORDDEF record-type #-} {-# BUILTIN AGDADEFINITIONDATACONSTRUCTOR data-cons #-} {-# BUILTIN AGDADEFINITIONPOSTULATE axiom #-} {-# BUILTIN AGDADEFINITIONPRIMITIVE prim-fun #-} -- Error messages can contain embedded names and terms. data ErrorPart : Set where strErr : String → ErrorPart termErr : Term → ErrorPart nameErr : Name → ErrorPart {-# BUILTIN AGDAERRORPART ErrorPart #-} {-# BUILTIN AGDAERRORPARTSTRING strErr #-} {-# BUILTIN AGDAERRORPARTTERM termErr #-} {-# BUILTIN AGDAERRORPARTNAME nameErr #-} postulate TC : ∀ {a} → Set a → Set a returnTC : ∀ {a} {A : Set a} → A → TC A bindTC : ∀ {a b} {A : Set a} {B : Set b} → TC A → (A → TC B) → TC B {-# BUILTIN AGDATCM TC #-} {-# BUILTIN AGDATCMRETURN returnTC #-} {-# BUILTIN AGDATCMBIND bindTC #-} open import Data.Unit open import Data.Product postulate -- Unify two terms, potentially solving metavariables in the process. unify : Term → Term → TC ⊤ -- Throw a type error. Can be caught by catchTC. typeError : ∀ {a} {A : Set a} → List ErrorPart → TC A -- Block a type checking computation on a metavariable. This will abort -- the computation and restart it (from the beginning) when the -- metavariable is solved. blockOnMeta : ∀ {a} {A : Set a} → Meta → TC A -- Prevent current solutions of metavariables from being rolled back in -- case 'blockOnMeta' is called. commitTC : TC ⊤ -- Backtrack and try the second argument if the first argument throws a -- type error. catchTC : ∀ {a} {A : Set a} → TC A → TC A → TC A -- Infer the type of a given term inferType : Term → TC Type -- Check a term against a given type. This may resolve implicit arguments -- in the term, so a new refined term is returned. Can be used to create -- new metavariables: newMeta t = checkType unknown t checkType : Term → Type → TC Term -- Compute the normal form of a term. normalise : Term → TC Term -- Compute the weak head normal form of a term. reduce : Term → TC Term -- Get the current context. Returns the context in reverse order, so that -- it is indexable by deBruijn index. Note that the types in the context are -- valid in the rest of the context. To use in the current context they need -- to be weakened by 1 + their position in the list. getContext : TC (List (Arg Type)) -- Extend the current context with a variable of the given type. extendContext : ∀ {a} {A : Set a} → Arg Type → TC A → TC A -- Set the current context. Takes a context telescope with the outer-most -- entry first, in contrast to 'getContext'. Each type should be valid in the -- context formed by the preceding elements in the list. inContext : ∀ {a} {A : Set a} → List (Arg Type) → TC A → TC A -- Quote a value, returning the corresponding Term. quoteTC : ∀ {a} {A : Set a} → A → TC Term -- Unquote a Term, returning the corresponding value. unquoteTC : ∀ {a} {A : Set a} → Term → TC A -- Create a fresh name. freshName : String → TC Name -- Declare a new function of the given type. The function must be defined -- later using 'defineFun'. Takes an Arg Name to allow declaring instances -- and irrelevant functions. The Visibility of the Arg must not be hidden. declareDef : Arg Name → Type → TC ⊤ -- Declare a new postulate of the given type. The Visibility of the Arg -- must not be hidden. It fails when executed from command-line with --safe -- option. declarePostulate : Arg Name → Type → TC ⊤ -- Define a declared function. The function may have been declared using -- 'declareDef' or with an explicit type signature in the program. defineFun : Name → List Clause → TC ⊤ -- Get the type of a defined name. Replaces 'primNameType'. getType : Name → TC Type -- Get the definition of a defined name. Replaces 'primNameDefinition'. getDefinition : Name → TC Definition -- Check if a name refers to a macro isMacro : Name → TC Bool -- Change the behaviour of inferType, checkType, quoteTC, getContext -- to normalise (or not) their results. The default behaviour is no -- normalisation. withNormalisation : ∀ {a} {A : Set a} → Bool → TC A → TC A -- Prints the third argument if the corresponding verbosity level is turned -- on (with the -v flag to Agda). debugPrint : String → ℕ → List ErrorPart → TC ⊤ -- Fail if the given computation gives rise to new, unsolved -- "blocking" constraints. noConstraints : ∀ {a} {A : Set a} → TC A → TC A -- Run the given TC action and return the first component. Resets to -- the old TC state if the second component is 'false', or keep the -- new TC state if it is 'true'. runSpeculative : ∀ {a} {A : Set a} → TC (Σ A λ _ → Bool) → TC A {-# BUILTIN AGDATCMUNIFY unify #-} {-# BUILTIN AGDATCMTYPEERROR typeError #-} {-# BUILTIN AGDATCMBLOCKONMETA blockOnMeta #-} {-# BUILTIN AGDATCMCATCHERROR catchTC #-} {-# BUILTIN AGDATCMINFERTYPE inferType #-} {-# BUILTIN AGDATCMCHECKTYPE checkType #-} {-# BUILTIN AGDATCMNORMALISE normalise #-} {-# BUILTIN AGDATCMREDUCE reduce #-} {-# BUILTIN AGDATCMGETCONTEXT getContext #-} {-# BUILTIN AGDATCMEXTENDCONTEXT extendContext #-} {-# BUILTIN AGDATCMINCONTEXT inContext #-} {-# BUILTIN AGDATCMQUOTETERM quoteTC #-} {-# BUILTIN AGDATCMUNQUOTETERM unquoteTC #-} {-# BUILTIN AGDATCMFRESHNAME freshName #-} {-# BUILTIN AGDATCMDECLAREDEF declareDef #-} {-# BUILTIN AGDATCMDECLAREPOSTULATE declarePostulate #-} {-# BUILTIN AGDATCMDEFINEFUN defineFun #-} {-# BUILTIN AGDATCMGETTYPE getType #-} {-# BUILTIN AGDATCMGETDEFINITION getDefinition #-} {-# BUILTIN AGDATCMCOMMIT commitTC #-} {-# BUILTIN AGDATCMISMACRO isMacro #-} {-# BUILTIN AGDATCMWITHNORMALISATION withNormalisation #-} {-# BUILTIN AGDATCMDEBUGPRINT debugPrint #-} {-# BUILTIN AGDATCMNOCONSTRAINTS noConstraints #-} {-# BUILTIN AGDATCMRUNSPECULATIVE runSpeculative #-} macro plus-to-times : Term → Term → TC ⊤ plus-to-times (def (quote _+_) (a ∷ b ∷ [])) hole = unify hole (def (quote _*_) (a ∷ b ∷ [])) plus-to-times v hole = unify hole v open import Relation.Binary.PropositionalEquality hiding ( [_] ; sym ) thm : (a b : ℕ) → plus-to-times (a + b) ≡ a * b thm a b = refl postulate magic : Type → Term macro by-magic : Term → TC ⊤ by-magic hole = bindTC (inferType hole) λ goal → unify hole (magic goal) open import Relation.Nullary -- thm1 : {P NP : Set} → ¬ P ≡ NP -- thm1 = ? by-magic --unquoteDecl x₁ .. x ₙ = m --unquoteDef x₁ .. x ₙ = m -- Defining: id-name {A} x = x defId : (id-name : Name) → TC ⊤ defId id-name = do defineFun id-name [ clause ( arg (arg-info hidden relevant) (var "A") ∷ arg (arg-info visible relevant) (var "x") ∷ [] ) (var 0 []) ] id : {A : Set} (x : A) → A unquoteDef id = defId id open import Level renaming ( suc to succ ; zero to Zero ) mkId : (id-name : Name) → TC ⊤ mkId id-name = do ty ← quoteTC ({A : Set} (x : A) → A) declareDef (arg (arg-info visible relevant) id-name) ty defId id-name where _>>=_ : {a : Level} {B A : Set a} (m : TC B) (f : (x : B) → TC A) → TC A _>>=_ = bindTC _>>_ : {a : Level} {B A : Set a} (m : TC B) (m' : TC A) → TC A _>>_ x y = bindTC x ( λ _ → y ) mkId' : (id-name : Name) → TC ⊤ mkId' id-name = bindTC ( quoteTC ({A : Set} (x : A) → A) ) ( λ ty → bindTC (declareDef (arg (arg-info visible relevant) id-name) ty ) ( λ _ → defId id-name) ) lemma1 : ( x : Name ) → mkId x ≡ mkId' x lemma1 x = refl unquoteDecl id′ = mkId id′