|
| 1 | +{-# OPTIONS --without-K --safe #-} |
| 2 | + |
| 3 | +open import Data.Nat |
| 4 | + |
| 5 | +module Reflection.Apply (limit : ℕ) where |
| 6 | + |
| 7 | +open import Level renaming (suc to lsuc; _⊔_ to lmax) |
| 8 | +open import Data.List |
| 9 | +open import Data.Sum.Base |
| 10 | +open import Data.Product |
| 11 | +open import Function.Base |
| 12 | +open import Data.Nat.Base |
| 13 | +open import Relation.Nullary |
| 14 | +open import Data.Bool.Base |
| 15 | +open import Reflection hiding (map-Args ; returnTC ; _≟_ ; _>>=_) renaming (return to returnTC) |
| 16 | +open import Reflection.Argument |
| 17 | +open import Reflection.Argument.Visibility using () renaming (_≟_ to _≟ᵥ_) |
| 18 | +open import Reflection.Pattern hiding (_≟_) |
| 19 | +open import Reflection.Term |
| 20 | +open import Data.Maybe.Base hiding (_>>=_) |
| 21 | + |
| 22 | +Result : Set 0ℓ → Set 0ℓ |
| 23 | +Result A = List ErrorPart ⊎ A |
| 24 | + |
| 25 | +pattern ok v = inj₂ v |
| 26 | +pattern err e = inj₁ e |
| 27 | + |
| 28 | +module _ where |
| 29 | + import Data.Sum.Categorical.Left (List ErrorPart) 0ℓ as S |
| 30 | + open import Category.Monad |
| 31 | + open RawMonad S.monad |
| 32 | + |
| 33 | + failed-app : Term → Arg Term → Result Term |
| 34 | + failed-app t (arg _ a) = err (strErr "attempted to apply" ∷ termErr a ∷ strErr "to" ∷ termErr t ∷ []) |
| 35 | + |
| 36 | + data Fuel : Set 0ℓ where |
| 37 | + fuel : ℕ → Fuel |
| 38 | + |
| 39 | + shift-index : ℕ → ℕ → Term → Term |
| 40 | + shift-index-args : ℕ → ℕ → Args Term → Args Term |
| 41 | + shift-index-clauses : ℕ → ℕ → List Clause → List Clause |
| 42 | + |
| 43 | + shift-index i j (var k args) with does (j ≤? k) |
| 44 | + ... | true = var (i + k) $ shift-index-args i j args |
| 45 | + ... | false = var k $ shift-index-args i j args |
| 46 | + shift-index i j (con c args) = con c $ shift-index-args i j args |
| 47 | + shift-index i j (def f args) = def f $ shift-index-args i j args |
| 48 | + shift-index i j (meta x args) = meta x $ shift-index-args i j args |
| 49 | + shift-index i j (lam v (abs s t)) = lam v $ abs s $ shift-index i (suc j) t |
| 50 | + shift-index i j (pat-lam cs args) = let |
| 51 | + cs = shift-index-clauses i j cs |
| 52 | + args = shift-index-args i j args |
| 53 | + in pat-lam cs args |
| 54 | + shift-index i j (Π[ s ∶ arg v A ] t) = let |
| 55 | + A = shift-index i j A |
| 56 | + t = shift-index i (suc j) t |
| 57 | + in Π[ s ∶ arg v A ] t |
| 58 | + shift-index i j (sort s) = sort s |
| 59 | + shift-index i j (lit l) = lit l |
| 60 | + shift-index i j unknown = unknown |
| 61 | + |
| 62 | + shift-index-args i j [] = [] |
| 63 | + shift-index-args i j (arg info a ∷ as) = let |
| 64 | + a = shift-index i j a |
| 65 | + as = shift-index-args i j as |
| 66 | + in arg info a ∷ as |
| 67 | + |
| 68 | + shift-index-clauses i j [] = [] |
| 69 | + shift-index-clauses i j (clause ps t ∷ cs) = let |
| 70 | + t = shift-index i (j + pattern-args-size ps) t |
| 71 | + cs = shift-index-clauses i j cs |
| 72 | + in clause ps t ∷ cs |
| 73 | + shift-index-clauses i j (absurd-clause ps ∷ cs) = |
| 74 | + absurd-clause ps ∷ shift-index-clauses i j cs |
| 75 | + |
| 76 | + app : ⦃ Fuel ⦄ → Arg Term → Term → Result Term |
| 77 | + app-many : ⦃ Fuel ⦄ → Args Term → Term → Result Term |
| 78 | + subst : ⦃ Fuel ⦄ → ℕ → Term → Term → Result Term |
| 79 | + subst-args : ⦃ Fuel ⦄ → ℕ → Term → Args Term → Result (Args Term) |
| 80 | + subst-clauses : ⦃ Fuel ⦄ → ℕ → Term → List (Clause) → Result (List Clause) |
| 81 | + |
| 82 | + app a (var x args) = return $ var x (args ∷ʳ a) |
| 83 | + app a (con c args) = return $ con c (args ∷ʳ a) |
| 84 | + app a (def f args) = return $ def f (args ∷ʳ a) |
| 85 | + app a (meta x args) = return $ meta x (args ∷ʳ a) |
| 86 | + app a (pat-lam cs args) = return $ pat-lam cs (args ∷ʳ a) |
| 87 | + app a @ (arg (arg-info v₁ _) x) |
| 88 | + b @ (lam v₂ (abs _ t)) |
| 89 | + with does (v₁ ≟ᵥ v₂) |
| 90 | + ... | true = subst 0 x t |
| 91 | + ... | false = failed-app b a |
| 92 | + app a @ (arg (arg-info v₁ _) x) |
| 93 | + b @ (Π[ _ ∶ arg (arg-info v₂ _) _ ] t) |
| 94 | + with does (v₁ ≟ᵥ v₂) |
| 95 | + ... | true = subst 0 x t |
| 96 | + ... | false = failed-app b a |
| 97 | + -- catch all |
| 98 | + app a t = failed-app t a |
| 99 | + |
| 100 | + app-many [] t = return t |
| 101 | + app-many (a ∷ as) t = do |
| 102 | + ta ← app a t |
| 103 | + app-many as ta |
| 104 | + |
| 105 | + subst i x (var j args) with compare i j |
| 106 | + ... | less m k = do |
| 107 | + args ← subst-args i x args |
| 108 | + -- decrement j by one since λ was eliminated |
| 109 | + return $ var (m + k) args -- j ≡ suc (m + k) |
| 110 | + ... | greater _ _ = do |
| 111 | + args ← subst-args i x args |
| 112 | + -- j refers to variable named inside eliminated λ |
| 113 | + return $ var j args |
| 114 | + subst ⦃ fuel (suc n) ⦄ |
| 115 | + i x (var j args) | equal _ = do |
| 116 | + args ← subst-args ⦃ fuel (suc n) ⦄ i x args |
| 117 | + app-many ⦃ fuel n ⦄ args (shift-index i 0 x) |
| 118 | + subst ⦃ fuel zero ⦄ |
| 119 | + i x (var j []) | equal _ = return x |
| 120 | + subst ⦃ fuel zero ⦄ |
| 121 | + _ _ (var j (_ ∷ _)) | equal _ = err (strErr "evaluation limit reached" ∷ []) |
| 122 | + subst i x (con c args) = do |
| 123 | + args ← subst-args i x args |
| 124 | + return $ con c args |
| 125 | + subst i x (def f args) = do |
| 126 | + args ← subst-args i x args |
| 127 | + return $ def f args |
| 128 | + subst i x (lam v (abs s t)) = do |
| 129 | + t ← subst (suc i) x t |
| 130 | + return $ lam v (abs s t) |
| 131 | + subst i x (meta m args) = do |
| 132 | + args ← subst-args i x args |
| 133 | + return $ meta m args |
| 134 | + subst i x (sort s) = return $ sort s |
| 135 | + subst i x (lit l) = return $ lit l |
| 136 | + subst i x unknown = return unknown |
| 137 | + subst i x (pat-lam cs args) = do |
| 138 | + cs ← subst-clauses i x cs |
| 139 | + args ← subst-args i x args |
| 140 | + return $ pat-lam cs args |
| 141 | + subst i x (Π[ s ∶ arg v A ] t) = do |
| 142 | + A ← subst i x A |
| 143 | + t ← subst (suc i) x t |
| 144 | + return $ Π[ s ∶ arg v A ] t |
| 145 | + |
| 146 | + subst-args i x [] = return [] |
| 147 | + subst-args i x (arg v a ∷ as) = do |
| 148 | + a ← subst i x a |
| 149 | + as ← subst-args i x as |
| 150 | + return $ arg v a ∷ as |
| 151 | + |
| 152 | + subst-clauses i x [] = return [] |
| 153 | + subst-clauses i x (clause ps t ∷ cs) = do |
| 154 | + t ← subst (i + pattern-args-size ps) x t |
| 155 | + cs ← subst-clauses i x cs |
| 156 | + return $ clause ps t ∷ cs |
| 157 | + subst-clauses i x (absurd-clause ps ∷ cs) = do |
| 158 | + cs ← subst-clauses i x cs |
| 159 | + return $ absurd-clause ps ∷ cs |
| 160 | + |
| 161 | +{- Apply an argument to a term. Fails if the recusion limit is reached or an |
| 162 | + attempt is made to apply an argument to non-function-like term. |
| 163 | +-} |
| 164 | +apply : Term → Arg Term → Result Term |
| 165 | +apply f x = app ⦃ fuel limit ⦄ x f |
| 166 | + |
| 167 | +open import Relation.Binary.PropositionalEquality |
| 168 | + |
| 169 | +open import Relation.Unary |
| 170 | + |
| 171 | +{- Retrieve any trailing arguments in a term -} |
| 172 | +term-args : Term → Maybe (Args Term) |
| 173 | +term-args (var _ args) = just args |
| 174 | +term-args (con _ args) = just args |
| 175 | +term-args (def _ args) = just args |
| 176 | +term-args (pat-lam _ args) = just args |
| 177 | +term-args (meta _ args) = just args |
| 178 | +term-args other = nothing |
| 179 | + |
| 180 | +{- Like term-args, but contains only the visible arguments -} |
| 181 | +term-vis-args : Term → Maybe (List Term) |
| 182 | +term-vis-args t = do |
| 183 | + args ← term-args t |
| 184 | + just $ Data.List.map (λ {(arg _ t) → t}) $ filter is-vis args |
| 185 | + where |
| 186 | + open import Data.Maybe using (_>>=_) |
| 187 | + args = term-args t |
| 188 | + is-vis : Decidable ((λ {(arg (arg-info v _) _) → v}) ⊢ (_≡ visible)) |
| 189 | + is-vis (arg (arg-info v r) x) = v ≟ᵥ visible |
| 190 | + |
| 191 | +{- Conveniently convert a Result into a TC -} |
| 192 | +Result→TC : {A : Set 0ℓ} → Result A → TC A |
| 193 | +Result→TC (err e) = typeError e |
| 194 | +Result→TC (ok v) = returnTC v |
0 commit comments