├── Examples.agda ├── QuasiQuoting.agda ├── Quotable.agda ├── README.md ├── ReflectionHelpers.agda └── quasi-quoting.agda-lib /Examples.agda: -------------------------------------------------------------------------------- 1 | {-# OPTIONS --safe #-} 2 | 3 | module Examples where 4 | 5 | open import Level using (Level) 6 | open import Data.List 7 | open import Data.Bool 8 | open import Data.Nat 9 | open import Data.Unit 10 | open import Data.Empty 11 | open import Data.Product 12 | open import Data.String 13 | open import Relation.Binary.PropositionalEquality 14 | open import Effect.Monad 15 | open import Function 16 | 17 | open import Reflection hiding (_>>=_; _>>_) renaming (agda-sort to sort) 18 | open import Reflection.TCM.Effectful using (monad) 19 | open import Reflection.AST.Universe 20 | 21 | open Pattern 22 | open Sort 23 | open Clause 24 | 25 | open import Quotable 26 | open import QuasiQuoting 27 | open import ReflectionHelpers 28 | 29 | open import Agda.Builtin.Reflection using (withReduceDefs) 30 | 31 | private 32 | open module MonadTC {ℓ} = RawMonad {ℓ} monad 33 | 34 | private 35 | variable 36 | ℓ : Level 37 | A B : Set ℓ 38 | u : Univ 39 | 40 | data WTerm : Set where 41 | ⟨_⟩ : Term → WTerm 42 | 43 | macro unquoteTerm : WTerm → Term → TC ⊤ 44 | unquoteTerm ⟨ t ⟩ = unify t 45 | 46 | -- Example: simple 47 | 48 | test₁ : Term → Term 49 | test₁ t = ` λ n → n + ! t 50 | 51 | check₁ : test₁ (var 0 []) ≡ lam visible (abs "n" (def₂ (quote _+_) (var 0 []) (var 1 []))) 52 | check₁ = refl -- Lifted automatically ^^^^^^^^ 53 | 54 | -- Example: building terms with quasi-quoting 55 | 56 | test : Term → Term 57 | test B = ` ((A : Set) (x : !⟨ B ∶ Set ⟩) → !⟨ B ∶ Set ⟩) 58 | 59 | pattern [_∶_]→_ x a b = pi (vArg a) (abs x b) 60 | infixr 5 [_∶_]→_ 61 | 62 | check : test (var 0 []) ≡ [ "A" ∶ sort (lit 0) ]→ 63 | [ "x" ∶ var 1 [] ]→ 64 | var 2 [] 65 | check = refl 66 | 67 | nAry : ℕ → Term → Term → Term 68 | nAry zero A B = B 69 | nAry (suc n) A B = `⟨ (! A → ! nAry n A B) ∶ Set ⟩ 70 | 71 | -- Example: nested quotes 72 | 73 | plus1 : Term → Term 74 | plus1 t = ` ! t + 1 75 | 76 | nested : Term → Term 77 | nested t = ` ! plus1 (` 2 * ! t) + 5 78 | 79 | check-nested : ∀ t → nested t ≡ (` 2 * ! t + 1 + 5) 80 | check-nested t = refl 81 | 82 | fail-nest : Term 83 | fail-nest = ` λ (n : ℕ) → ! nested (` n) 84 | -- quoted variable used in splice 85 | -- Should be ok since the quoted variable appears under a quote 86 | 87 | -- Example: pattern lambda 88 | 89 | plam : (A : Set) → Term → Term → Term 90 | plam A b c = 91 | `⟨ (λ where 92 | true → ! b 93 | false → ! c) 94 | ∶ (Bool → A) ⟩ 95 | 96 | check-plam : plam ℕ (` 1) (` 2) ≡ 97 | pat-lam ( clause [] (vArg (con (quote true) []) ∷ []) (lit (nat 1)) 98 | ∷ clause [] (vArg (con (quote false) []) ∷ []) (lit (nat 2)) ∷ []) 99 | [] 100 | check-plam = refl 101 | 102 | _$'_ : (A → B) → A → B 103 | f $' x = f x 104 | 105 | plam' : (A B : Set) → Term → Term → Term 106 | plam' A B hd tl = `_ {A = List A → B} λ where 107 | [] → ! hd 108 | (x ∷ xs) → (!⟨ tl ∶ (A → List A → B) ⟩ $' x) xs 109 | 110 | check-plam' : plam' ℕ ℕ (var 0 []) (var 0 []) ≡ 111 | pat-lam ( clause [] (vArg (con (quote List.[]) []) ∷ []) (var 0 []) 112 | ∷ clause ( ("x" , vArg unknown) 113 | ∷ ("xs" , vArg (def (quote List) ( hArg (def (quote Level.zero) []) 114 | ∷ vArg unknown ∷ []))) 115 | ∷ []) 116 | (vArg (con (quote _∷_) (vArg (var 1) ∷ vArg (var 0) ∷ [])) ∷ []) 117 | (def (quote _$'_) (hArg _ ∷ hArg _ ∷ hArg _ ∷ hArg _ ∷ 118 | vArg (var 2 []) ∷ vArg (var 1 []) ∷ vArg (var 0 []) ∷ [])) 119 | ∷ []) 120 | [] 121 | check-plam' = refl 122 | 123 | test-plam' : (ℕ → List ℕ → Bool) → Bool → List ℕ → Bool 124 | test-plam' f x = unquoteTerm ⟨ plam' ℕ Bool (var 0 []) (var 1 []) ⟩ 125 | 126 | -- Example: trying to break things 127 | 128 | -- bad : Term 129 | -- bad = ` λ t → !⟨ t ∶ Term ⟩ -- Phase violation: quoted variable used in splice 130 | 131 | -- boom : ⊥ 132 | -- boom = ! lit (nat 4) -- Phase violation: splice used outside quote 133 | 134 | -- escape : Term 135 | -- escape = `_ λ {i} → i -- Phase violation: InsideQuote token escaping the quote 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | --- === 149 | 150 | -- Example: Quotable instances 151 | 152 | instance 153 | qList : ⦃ Quotable A ⦄ → Quotable (List A) 154 | qList {A = A} .quoteVal [] = `⟨ [] ∶ List A ⟩ 155 | qList {A = A} .quoteVal (x ∷ xs) = ` x ∷ xs 156 | 157 | qRefl : ⟦ u ⟧ → Term 158 | qRefl {⟨term⟩} (var x args) = ` Term.var x (! qRefl args) 159 | qRefl {⟨term⟩} (con c args) = ` Term.con c (! qRefl args) 160 | qRefl {⟨term⟩} (def f args) = ` def f (! qRefl args) 161 | qRefl {⟨term⟩} (lam v t) = ` lam v (! qRefl t) 162 | qRefl {⟨term⟩} (pat-lam cs args) = ` pat-lam (! qRefl cs) (! qRefl args) 163 | qRefl {⟨term⟩} (pi a b) = ` pi (! qRefl a) (! qRefl b) 164 | qRefl {⟨term⟩} (sort s) = ` sort (! qRefl s) 165 | qRefl {⟨term⟩} (lit l) = ` Term.lit l 166 | qRefl {⟨term⟩} (meta x args) = ` Term.meta x (! qRefl args) 167 | qRefl {⟨term⟩} unknown = ` Term.unknown 168 | qRefl {⟨pat⟩} (con c ps) = ` Pattern.con c (! qRefl ps) 169 | qRefl {⟨pat⟩} (dot t) = ` dot (! qRefl t) 170 | qRefl {⟨pat⟩} (var x) = ` Pattern.var x 171 | qRefl {⟨pat⟩} (lit l) = ` Pattern.lit l 172 | qRefl {⟨pat⟩} (proj f) = ` proj f 173 | qRefl {⟨pat⟩} (absurd t) = ` absurd t 174 | qRefl {⟨sort⟩} (set t) = ` set (! qRefl t) 175 | qRefl {⟨sort⟩} (prop t) = ` Sort.prop (! qRefl t) 176 | qRefl {⟨sort⟩} (lit n) = ` Sort.lit n 177 | qRefl {⟨sort⟩} (propLit n) = ` Sort.propLit n 178 | qRefl {⟨sort⟩} (inf n) = ` Sort.inf n 179 | qRefl {⟨sort⟩} unknown = ` Sort.unknown 180 | qRefl {⟨clause⟩} (clause tel ps t) = ` clause (! qRefl tel) (! qRefl ps) (! qRefl t) 181 | qRefl {⟨clause⟩} (absurd-clause tel ps) = ` absurd-clause (! qRefl tel) (! qRefl ps) 182 | qRefl {⟨list⟩ u} [] = `⟨ [] ∶ List ⟦ u ⟧ ⟩ 183 | qRefl {⟨list⟩ u} (x ∷ xs) = `⟨ ! qRefl x ∷ ! qRefl xs ∶ List ⟦ u ⟧ ⟩ 184 | qRefl {⟨arg⟩ u} (arg i x) = `⟨ arg i (! qRefl x) ∶ Arg ⟦ u ⟧ ⟩ 185 | qRefl {⟨abs⟩ u} (abs s x) = `⟨ abs s (! qRefl x) ∶ Abs ⟦ u ⟧ ⟩ 186 | qRefl {⟨named⟩ u} (x , t) = `⟨ x , (! qRefl t) ∶ String × ⟦ u ⟧ ⟩ 187 | 188 | instance 189 | qTerm : Quotable Term 190 | qTerm .quoteVal = qRefl 191 | 192 | -- Example: function application on reflected syntax 193 | -- Awkward since β-redexes are not representable in the reflected syntax. 194 | 195 | -- Hard to get this to work with the unsolved metas! 196 | 197 | private 198 | app : ∀ {a b} {A : Set a} {B : A → Set b} → (∀ x → B x) → ∀ x → B x 199 | app f = f 200 | 201 | tcApply : Term → Term → TC Term 202 | tcApply f x = withReduceDefs (true , quote app ∷ []) (reduce (def (quote app) (vArg f ∷ vArg x ∷ []))) 203 | -- tcApply f x = onlyReduceDefs (quote app ∷ []) (reduce (def₂ (quote app) f x)) 204 | -- ^^ this doesn't work because onlyReduceDefs kicks in and refuses to reduce def₂ 205 | -- tcApply f x = onlyReduceDefs (quote app ∷ []) (` app (! f) (! x)) 206 | -- ^^ this doesn't work because ! is typed and we don't know the types 207 | 208 | macro 209 | testApply : (A → B) → A → Term → TC ⊤ 210 | testApply f x hole = do 211 | `f ← quoteTC f 212 | `x ← quoteTC x 213 | `fx ← tcApply `f `x 214 | unify hole =<< quoteTC `fx 215 | 216 | _ : testApply (λ n → n + 1) 5 ≡ (` 5 + 1) 217 | _ = refl 218 | -------------------------------------------------------------------------------- /QuasiQuoting.agda: -------------------------------------------------------------------------------- 1 | {-# OPTIONS --safe #-} 2 | 3 | module QuasiQuoting where 4 | 5 | open import Level using (Level) 6 | open import Data.Unit using (⊤) 7 | open import Data.Bool 8 | open import Data.Nat 9 | open import Data.List 10 | open import Data.Empty using (⊥) 11 | open import Data.Maybe hiding (_>>=_; map) 12 | open import Data.Word64 using (Word64) 13 | open import Data.String using (String) 14 | open import Data.Char using (Char) 15 | open import Data.Float using (Float) 16 | open import Data.Product using (_×_; _,_) 17 | open import Effect.Monad using (RawMonad) 18 | open import Function 19 | open import Relation.Binary.PropositionalEquality 20 | 21 | open import Reflection hiding (_>>=_; _>>_; pure) renaming (agda-sort to sort) 22 | open import Reflection.AST.Universe 23 | open import Reflection.AST.DeBruijn 24 | open import Reflection.TCM.Effectful using (monad) 25 | open import Reflection.AST.Argument.Visibility 26 | open import Reflection.AST.Argument.Relevance 27 | open import Reflection.AST.Argument.Information 28 | open import Agda.Builtin.Reflection using (onlyReduceDefs) renaming (primMetaLess to _<ᵐ_) 29 | 30 | open import Quotable 31 | open import ReflectionHelpers hiding (strengthenBy) 32 | 33 | private 34 | variable 35 | ℓ : Level 36 | A B : Set ℓ 37 | u : Univ 38 | 39 | private 40 | open module MonadTC {ℓ} = RawMonad {ℓ} monad 41 | 42 | open Pattern 43 | open Sort 44 | open Clause 45 | 46 | pattern ⟨tel⟩ = ⟨list⟩ (⟨named⟩ (⟨arg⟩ ⟨term⟩)) 47 | 48 | -- Splicing 49 | 50 | data InsideQuote : Set where 51 | 52 | ensureInsideQuote : Term → TC ⊤ 53 | ensureInsideQuote hole = do 54 | n ← length <$> getContext 55 | foldr catchTC (typeErrorFmt "Phase violation: splice used outside quote") 56 | (map (λ i → unify hole (var i [])) (downFrom n)) 57 | 58 | -- The (empty) InsideQuote argument guarantees that splice can only be 59 | -- used inside a quote. Use a tactic argument instead of an instance 60 | -- argument to make it possible to nest quotes. 61 | !_ : {@(tactic ensureInsideQuote) i : InsideQuote} → Term → A 62 | !_ {i = ()} 63 | 64 | !⟨_∶_⟩ : {@(tactic ensureInsideQuote) _ : InsideQuote} → Term → (A : Set ℓ) → A 65 | !⟨ t ∶ _ ⟩ = ! t 66 | 67 | -- Quoting 68 | 69 | splice : ℕ → Term → TC Term 70 | splice 0 `t = pure `t 71 | splice n `t = do 72 | just `t ← pure $ strengthenBy n `t 73 | where nothing → typeErrorFmt "Phase violation: quoted variable used in splice" 74 | return (def₂ (quote weaken) (lit (nat n)) `t) 75 | 76 | qquote : ℕ → ⟦ u ⟧ → TC Term 77 | qquote {⟨term⟩} n (def (quote !_) (hArg _ ∷ hArg _ ∷ hArg _ ∷ vArg `t ∷ [])) = splice n `t 78 | qquote {⟨term⟩} n (def (quote !⟨_∶_⟩) (hArg _ ∷ hArg _ ∷ vArg `t ∷ vArg _ ∷ [])) = splice n `t 79 | qquote {⟨term⟩} n t@(var x args) = 80 | if x <ᵇ n then con₂ (quote Term.var) (quoteVal x) <$> qquote n args 81 | else splice n (def₁ (quote quoteVal) t) 82 | -- Here we have a variable from the outer context. For instance 83 | -- foo : ℕ → Term 84 | -- foo n = ` n + 1 85 | -- In this case we need to defer the quoting to when `foo` is evaluated and 86 | -- we know the value 87 | -- of n. This is achieved by replacing the variable by a splice: 88 | -- foo n = ` !(quoteVal n) + 1 89 | -- and requires a Quotable instance for the type in question. 90 | qquote {⟨term⟩} n (con c args) = con₂ (quote Term.con) (quoteVal c) <$> qquote n args 91 | qquote {⟨term⟩} n (def f args) = con₂ (quote def) (quoteVal f) <$> qquote n args 92 | qquote {⟨term⟩} n (lam v b) = con₂ (quote lam) (quoteVal v) <$> qquote n b 93 | qquote {⟨term⟩} n (pat-lam cs args) = con₂ (quote pat-lam) <$> qquote n cs <*> qquote n args 94 | qquote {⟨term⟩} n (pi a b) = con₂ (quote pi) <$> qquote n a <*> qquote n b 95 | qquote {⟨term⟩} n (sort s) = con₁ (quote sort) <$> qquote n s 96 | qquote {⟨term⟩} n (lit l) = pure $ con₁ (quote Term.lit) (quoteVal l) 97 | qquote {⟨term⟩} n t@(meta x args) = blockOnMeta x 98 | qquote {⟨term⟩} n unknown = pure $ con (quote Term.unknown) [] 99 | qquote {⟨pat⟩} n (con c ps) = con₂ (quote Pattern.con) (quoteVal c) <$> qquote n ps 100 | qquote {⟨pat⟩} n (dot t) = con₁ (quote dot) <$> qquote n t 101 | qquote {⟨pat⟩} n (var x) = pure $ con₁ (quote Pattern.var) (quoteVal x) 102 | qquote {⟨pat⟩} n (lit l) = pure $ con₁ (quote Pattern.lit) (quoteVal l) 103 | qquote {⟨pat⟩} n (proj f) = pure $ con₁ (quote proj) (quoteVal f) 104 | qquote {⟨pat⟩} n (absurd x) = pure $ con₁ (quote absurd) (quoteVal x) 105 | qquote {⟨sort⟩} n (set t) = con₁ (quote Sort.set) <$> qquote n t 106 | qquote {⟨sort⟩} n (lit l) = pure $ con₁ (quote Sort.lit) (quoteVal l) 107 | qquote {⟨sort⟩} n (prop t) = con₁ (quote Sort.prop) <$> qquote n t 108 | qquote {⟨sort⟩} n (propLit t) = pure $ con₁ (quote Sort.propLit) (quoteVal t) 109 | qquote {⟨sort⟩} n (inf t) = pure $ con₁ (quote Sort.inf) (quoteVal t) 110 | qquote {⟨sort⟩} n unknown = pure $ con (quote Sort.unknown) [] 111 | qquote {⟨clause⟩} n (clause tel ps t) = con₃ (quote clause) <$> qquote n tel <*> qquote n′ ps <*> qquote n′ t 112 | where n′ = n + length tel 113 | qquote {⟨clause⟩} n (absurd-clause tel ps) = con₂ (quote absurd-clause) <$> qquote n tel <*> qquote n′ ps 114 | where n′ = n + length tel 115 | qquote {⟨list⟩ u} n [] = pure (con (quote List.[]) []) 116 | qquote {⟨tel⟩} n (dom ∷ Γ) = con₂ (quote List._∷_) <$> qquote n dom <*> qquote (suc n) Γ 117 | qquote {⟨list⟩ u} n (x ∷ xs) = con₂ (quote List._∷_) <$> qquote n x <*> qquote n xs 118 | qquote {⟨arg⟩ u} n (arg i x) = con₂ (quote arg) (quoteVal i) <$> qquote n x 119 | qquote {⟨abs⟩ u} n (abs x t) = con₂ (quote abs) (quoteVal x) <$> qquote (suc n) t 120 | qquote {⟨named⟩ u} n (x , t) = con₂ (quote _,_) (quoteVal x) <$> qquote n t 121 | 122 | blockIfMeta : Term → TC Term 123 | blockIfMeta (meta x _) = blockOnMeta x 124 | blockIfMeta t = pure t 125 | 126 | quasiQuote : ({InsideQuote} → A) → Term → TC ⊤ 127 | quasiQuote x hole = do 128 | lam _ (abs _ t) ← quoteTC (λ i → x {i}) 129 | where t → typeErrorFmt "Impossible: %t" t 130 | q ← qquote 0 t 131 | t ← extendContext "i" (hArg (def (quote InsideQuote) [])) $ do 132 | just t ← pure (strengthen q) 133 | where nothing → typeErrorFmt "Phase violation: InsideQuote token escaping the quote" 134 | pure t 135 | unify hole t 136 | 137 | macro 138 | typedQuasiQuote = quasiQuote 139 | syntax typedQuasiQuote {A = A} x = `⟨ x ∶ A ⟩ 140 | 141 | infix 0 `_ 142 | `_ = quasiQuote 143 | -------------------------------------------------------------------------------- /Quotable.agda: -------------------------------------------------------------------------------- 1 | {-# OPTIONS --safe #-} 2 | 3 | module Quotable where 4 | 5 | open import Level using (Level) 6 | open import Data.Nat using (ℕ) 7 | open import Data.Word64 using (Word64) 8 | open import Data.String using (String) 9 | open import Data.Char using (Char) 10 | open import Data.Float using (Float) 11 | 12 | open import Reflection 13 | open import Reflection.AST.Argument.Visibility 14 | open import Reflection.AST.Argument.Relevance 15 | open import Reflection.AST.Argument.Modality 16 | open import Reflection.AST.Argument.Quantity 17 | open import Reflection.AST.Argument.Information 18 | 19 | open import ReflectionHelpers 20 | 21 | private 22 | variable 23 | ℓ : Level 24 | A : Set ℓ 25 | 26 | record Quotable (A : Set ℓ) : Set ℓ where 27 | field quoteVal : A → Term 28 | 29 | open Quotable ⦃ ... ⦄ public 30 | 31 | instance 32 | qSet : Quotable (Set ℓ) 33 | qSet .quoteVal _ = unknown -- Cheating, hoping that these will be solved by unification! 34 | 35 | qℕ : Quotable ℕ 36 | qℕ .quoteVal n = lit (nat n) 37 | 38 | qWord : Quotable Word64 39 | qWord .quoteVal w = lit (word64 w) 40 | 41 | qChar : Quotable Char 42 | qChar .quoteVal s = lit (char s) 43 | 44 | qString : Quotable String 45 | qString .quoteVal s = lit (string s) 46 | 47 | qFloat : Quotable Float 48 | qFloat .quoteVal s = lit (float s) 49 | 50 | qName : Quotable Name 51 | qName .quoteVal x = lit (name x) 52 | 53 | qMeta : Quotable Meta 54 | qMeta .quoteVal x = lit (meta x) 55 | 56 | qVis : Quotable Visibility 57 | qVis .quoteVal visible = con₀ (quote visible) 58 | qVis .quoteVal hidden = con₀ (quote hidden) 59 | qVis .quoteVal instance′ = con₀ (quote instance′) 60 | 61 | qRel : Quotable Relevance 62 | qRel .quoteVal relevant = con₀ (quote relevant) 63 | qRel .quoteVal irrelevant = con₀ (quote irrelevant) 64 | 65 | qQua : Quotable Quantity 66 | qQua .quoteVal quantity-0 = con₀ (quote quantity-0) 67 | qQua .quoteVal quantity-ω = con₀ (quote quantity-ω) 68 | 69 | qMod : Quotable Modality 70 | qMod .quoteVal (modality r q) = con₂ (quote Reflection.modality) (quoteVal r) (quoteVal q) 71 | 72 | qInfo : Quotable ArgInfo 73 | qInfo .quoteVal (arg-info v r) = con₂ (quote arg-info) (quoteVal v) (quoteVal r) 74 | 75 | qLit : Quotable Literal 76 | qLit .quoteVal (nat n) = con₁ (quote nat) (quoteVal n) 77 | qLit .quoteVal (word64 n) = con₁ (quote word64) (quoteVal n) 78 | qLit .quoteVal (string n) = con₁ (quote string) (quoteVal n) 79 | qLit .quoteVal (char n) = con₁ (quote char) (quoteVal n) 80 | qLit .quoteVal (float n) = con₁ (quote float) (quoteVal n) 81 | qLit .quoteVal (name n) = con₁ (quote name) (quoteVal n) 82 | qLit .quoteVal (meta n) = con₁ (quote Literal.meta) (quoteVal n) 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # quasi-quote 2 | A quasi-quoting library for Agda, supporting automatic de Bruijn management. Very much work-in-progress. 3 | Requires the `experimental` branch of the standard library at [commit bee4f912f](https://github.com/agda/agda-stdlib/tree/bee4f912f4ef610deecf0b8dd16fa11b43065358) or later. 4 | 5 | ## Example 6 | ```agda 7 | test₁ : Term → Term 8 | test₁ t = `(λ n → n + ! t) 9 | -- quote ^ splice ^ 10 | 11 | check₁ : test₁ (var 0 []) ≡ lam visible (abs "n" (def₂ (quote _+_) (var 0 []) (var 1 []))) 12 | check₁ = refl -- Lifted automatically ^^^^^^^^ 13 | ``` 14 | -------------------------------------------------------------------------------- /ReflectionHelpers.agda: -------------------------------------------------------------------------------- 1 | {-# OPTIONS --safe #-} 2 | 3 | module ReflectionHelpers where 4 | 5 | open import Level using (Level) 6 | open import Data.Bool 7 | open import Data.List 8 | open import Data.Nat 9 | open import Data.Maybe 10 | import Data.Maybe.Effectful as Maybe using (applicative) 11 | open import Effect.Monad 12 | open import Reflection 13 | open import Reflection.TCM 14 | import Reflection.AST.Traversal as Traverse 15 | 16 | private 17 | variable 18 | ℓ : Level 19 | A : Set ℓ 20 | 21 | ------------------------------------------------------------------------ 22 | -- Strengthening 23 | 24 | module _ where 25 | 26 | open Traverse Maybe.applicative 27 | 28 | private 29 | strVar : ℕ → Cxt → ℕ → Maybe ℕ 30 | strVar by (from , Γ) i with i <ᵇ from | i <ᵇ from + by 31 | ... | true | _ = just i 32 | ... | _ | true = nothing 33 | ... | _ | _ = just (i ∸ by) 34 | 35 | actions : ℕ → Actions 36 | actions by = record defaultActions { onVar = strVar by } 37 | 38 | strengthenFromBy′ : (Actions → Cxt → A → Maybe A) → (from by : ℕ) → A → Maybe A 39 | strengthenFromBy′ trav from by = trav (actions by) (from , []) -- not using the context part 40 | 41 | strengthenFromBy : (from by : ℕ) → Term → Maybe Term 42 | strengthenFromBy = strengthenFromBy′ traverseTerm 43 | 44 | strengthenBy : ℕ → Term → Maybe Term 45 | strengthenBy = strengthenFromBy 0 46 | 47 | con₀ : Name → Term 48 | con₀ f = con f [] 49 | 50 | con₁ : Name → Term → Term 51 | con₁ f a = con f (vArg a ∷ []) 52 | 53 | con₂ : Name → Term → Term → Term 54 | con₂ f a b = con f (vArg a ∷ vArg b ∷ []) 55 | 56 | con₃ : Name → Term → Term → Term → Term 57 | con₃ f a b c = con f (vArg a ∷ vArg b ∷ vArg c ∷ []) 58 | 59 | def₁ : Name → Term → Term 60 | def₁ f a = def f (vArg a ∷ []) 61 | 62 | def₂ : Name → Term → Term → Term 63 | def₂ f a b = def f (vArg a ∷ vArg b ∷ []) 64 | -------------------------------------------------------------------------------- /quasi-quoting.agda-lib: -------------------------------------------------------------------------------- 1 | name: quasi-quoting 2 | include: . 3 | depend: standard-library 4 | --------------------------------------------------------------------------------