{-# OPTIONS --without-K --safe #-} module Fragment.Tactic.Fragment where open import Reflection hiding (name; Type; _≟_) open import Reflection.Term using (_≟_) open import Level using (_⊔_) open import Relation.Binary using (Setoid) open import Data.Bool using (Bool; _∨_; true; false; if_then_else_) open import Data.Nat using (ℕ) open import Data.List using (List; []; _∷_; map; sum; length) open import Data.Vec using (fromList) open import Data.Product using (_×_; _,_) open import Data.Unit using (⊤; tt) open import Data.String using (String; _++_) open import Data.Maybe using (Maybe; just; nothing) open import Fragment.Tactic.Utils open import Fragment.Equational.Theory open import Fragment.Equational.Model open import Fragment.Equational.FreeExtension hiding (reduce) open import Fragment.Algebra.Signature import Fragment.Algebra.Free as Free read-goal : List (Arg Term) → TC (Term × List (Arg Term)) read-goal (vArg x ∷ xs) = return (x , xs) read-goal (_ ∷ xs) = read-goal xs read-goal [] = typeError (strErr "failed to read goal" ∷ []) read-goals : List (Arg Term) → TC (Term × Term) read-goals xs = do (fst , xs) ← read-goal xs (snd , _) ← read-goal xs return (fst , snd) extract-goals : Term → TC (Term × Term) extract-goals (var _ args) = read-goals args extract-goals (con _ args) = read-goals args extract-goals (def _ args) = read-goals args extract-goals (meta _ args) = read-goals args extract-goals t = typeError (strErr "can't read goals from" ∷ termErr t ∷ []) record Operator : Set where constructor operator field name : Name normalised : Term arity : ℕ open Operator record CoreCtx : Set where field signature : Term theory : Term model : Term carrier : Term frex : Term record GlobalCtx : Set where field core : CoreCtx operators : List Operator telescope : List (Arg String) lhs : Term rhs : Term open CoreCtx core public pattern modelType Θ a ℓ = def (quote Model) (vArg Θ ∷ hArg a ∷ hArg ℓ ∷ []) ctx : Name → Term → Term → TC GlobalCtx ctx frex model goal = do τ ← inferType model γ ← inferType goal signature ← extract-Σ τ theory ← extract-Θ τ carrier ← normalise (def (quote ∥_∥) (vra theory ∷ vra model ∷ [])) let core = record { signature = signature ; theory = theory ; model = model ; carrier = carrier ; frex = def frex [] } operators ← extract-ops core (inner , telescope) ← strip-telescope γ (lhs , rhs) ← extract-goals inner return (record { core = core ; operators = operators ; telescope = telescope ; lhs = lhs ; rhs = rhs }) where modelErr : ∀ {a} {A : Set a} → Term → String → TC A modelErr t err = typeError ( termErr t ∷ strErr "isn't a" ∷ nameErr (quote Model) ∷ strErr ("(" ++ err ++ ")") ∷ [] ) extract-Σ : Term → TC Term extract-Σ (modelType Θ _ _) = normalise (def (quote Theory.Σ) (vra Θ ∷ [])) extract-Σ t = modelErr t "when extracting the signature" extract-Θ : Term → TC Term extract-Θ (modelType Θ _ _) = normalise Θ extract-Θ t = modelErr t "when extracting the theory" extract-arity : CoreCtx → Name → TC ℕ extract-arity ctx op = do τ ← inferType (def (quote _⟦_⟧_) ( vra (CoreCtx.theory ctx) ∷ vra (CoreCtx.model ctx) ∷ vra (con op []) ∷ [] )) α ← extract-type-arg τ vec-len α extract-interp : CoreCtx → Name → ℕ → TC Term extract-interp ctx op arity = do let t = def (quote _⟦_⟧_) ( vra (CoreCtx.theory ctx) ∷ vra (CoreCtx.model ctx) ∷ vra (con op []) ∷ [] ) normalise (n-ary arity (apply t (vra (vec (debrujin arity)) ∷ []))) extract-ops : CoreCtx → TC (List Operator) extract-ops ctx = do ops ← normalise (def (quote ops) (vra (CoreCtx.signature ctx) ∷ [])) symbols ← extract-constructors ops arities ← listTC (map (extract-arity ctx) symbols) interps ← listTC (mapList (map (extract-interp ctx) symbols) arities) return (mapList (mapList (map operator symbols) interps) arities) record FoldCtx {a b} (A : Set a) (B : Set b) : Set (a ⊔ b) where constructor foldCtx field global : GlobalCtx f : Term → B → A × B g : Operator → List A → A ε : B open GlobalCtx global public mutual map-fold : ∀ {a b} {A : Set a} {B : Set b} → FoldCtx A B → List (Arg Term) → B → TC (List A × B) map-fold ctx [] acc = return ([] , acc) map-fold ctx (vArg x ∷ xs) acc = do (x , acc) ← fold-acc ctx x acc (xs , acc) ← map-fold ctx xs acc return (x ∷ xs , acc) map-fold ctx (_ ∷ xs) acc = map-fold ctx xs acc fold-inner : ∀ {a b} {A : Set a} {B : Set b} → FoldCtx A B → Operator → Term → B → TC (List A × B) fold-inner ctx op (var _ args) acc = map-fold ctx (ekat (arity op) args) acc fold-inner ctx op (con _ args) acc = map-fold ctx (ekat (arity op) args) acc fold-inner ctx op (def _ args) acc = map-fold ctx (ekat (arity op) args) acc fold-inner ctx op (meta _ args) acc = map-fold ctx (ekat (arity op) args) acc fold-inner ctx op (pat-lam _ args) acc = map-fold ctx (ekat (arity op) args) acc fold-inner _ _ t _ = typeError (termErr t ∷ strErr "has no arguments" ∷ []) fold-acc : ∀ {a b} {A : Set a} {B : Set b} → FoldCtx A B → Term → B → TC (A × B) fold-acc ctx t acc = do op? ← find (λ x → prefix (arity x) (normalised x) t) (FoldCtx.operators ctx) resolve op? where resolve : Maybe Operator → TC _ resolve (just op) = do (args , acc) ← fold-inner ctx op t acc return ((FoldCtx.g ctx) op args , acc) resolve nothing = return ((FoldCtx.f ctx) t acc) fold : ∀ {a b} {A : Set a} {B : Set b} → FoldCtx A B → Term → TC (A × B) fold ctx t = fold-acc ctx t (FoldCtx.ε ctx) fold-⊤ : ∀ {a} {A : Set a} → GlobalCtx → (Term → A) → (Operator → List A → A) → Term → TC A fold-⊤ ctx f g t = do (x , _) ← fold (foldCtx ctx (λ x _ → (f x , tt)) g tt) t return x accumulate : ∀ {a} {A : Set a} → GlobalCtx → (Term → A → A) → A → Term → TC A accumulate ctx f ε t = do (_ , acc) ← fold (foldCtx ctx (λ x acc → (tt , f x acc)) (λ _ _ → tt) ε) t return acc leaves : GlobalCtx → Term → TC ℕ leaves ctx = fold-⊤ ctx (λ _ → 1) (λ _ → sum) mutual argsOpen : Term → List (Arg Term) → TC Bool argsOpen τ [] = return false argsOpen τ (vArg x ∷ xs) = do head ← isOpen τ x tail ← argsOpen τ xs return (head ∨ tail) argsOpen τ (_ ∷ xs) = argsOpen τ xs isOpen : Term → Term → TC Bool isOpen τ t@(var _ _) = hasType τ t isOpen τ t@(meta _ _) = hasType τ t isOpen τ (con c args) = argsOpen τ args isOpen τ (def f args) = argsOpen τ args isOpen τ unknown = return true isOpen τ _ = return false findOpen : GlobalCtx → List Term → Term → TC (List Term) findOpen ctx ε t = flatten (accumulate ctx binding (return ε) t) where binding : Term → TC (List Term) → TC (List Term) binding t env = do env ← env let τ = CoreCtx.carrier (GlobalCtx.core ctx) open? ← isOpen τ t if open? then return (insert env t) else return env buildSyntax : GlobalCtx → List Term → Term → TC Term buildSyntax ctx env t = fold-⊤ ctx buildInj buildTerm t where bt : Term bt = def (quote Free.BT) ( vra (GlobalCtx.signature ctx) ∷ vra (GlobalCtx.carrier ctx) ∷ vra (lit (nat (length env))) ∷ [] ) buildAtom : Term → Term buildAtom t = con (quote Free.Term.atom) ( hra (GlobalCtx.signature ctx) ∷ hra unknown ∷ hra bt ∷ vra t ∷ [] ) buildDyn : ℕ → Term buildDyn n = con (quote Free.BT.dyn) ( hra (GlobalCtx.signature ctx) ∷ hra unknown ∷ hra (GlobalCtx.carrier ctx) ∷ hra (lit (nat (length env))) ∷ vra (fin n) ∷ [] ) buildSta : Term → Term buildSta t = con (quote Free.BT.sta) ( hra (GlobalCtx.signature ctx) ∷ hra unknown ∷ hra (GlobalCtx.carrier ctx) ∷ hra (lit (nat (length env))) ∷ vra t ∷ [] ) buildInj : Term → Term buildInj t with indexOf env t ... | just n = buildAtom (buildDyn n) ... | nothing = buildAtom (buildSta t) buildTerm : Operator → List Term → Term buildTerm op xs = con (quote Free.Term.term) ( hra (GlobalCtx.signature ctx) ∷ hra unknown ∷ hra bt ∷ hra (lit (nat (arity op))) ∷ vra (con (name op) []) ∷ vra (vec (fromList xs)) ∷ [] ) environment : List Term → Term environment env = vec (fromList env) macro fragment : Name → Term → Term → TC ⊤ fragment frex model goal = do ctx ← ctx frex model goal env ← findOpen ctx [] (GlobalCtx.lhs ctx) env ← findOpen ctx env (GlobalCtx.rhs ctx) lhs ← buildSyntax ctx env (GlobalCtx.lhs ctx) rhs ← buildSyntax ctx env (GlobalCtx.rhs ctx) let n = length env let frex = def (quote FreeExtension._[_]) ( hra (GlobalCtx.theory ctx) ∷ vra (GlobalCtx.frex ctx) ∷ vra (GlobalCtx.model ctx) ∷ vra (lit (nat n)) ∷ [] ) let setoid = def (quote ∥_∥/≈) ( hra (GlobalCtx.theory ctx) ∷ vra frex ∷ [] ) let p = def (quote Setoid.refl) (vra setoid ∷ []) let frexify = def (quote frexify) ( vra (GlobalCtx.theory ctx) ∷ vra (GlobalCtx.frex ctx) ∷ vra (GlobalCtx.model ctx) ∷ vra (vec (fromList env)) ∷ hra lhs ∷ hra rhs ∷ vra p ∷ [] ) frexify ← restore-telescope (GlobalCtx.telescope ctx) frexify unify frexify goal