12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152-------------------------------------------------------------------------- A store mapping "atoms" — subterms a macro abstracts over — to-- variable indices.---- An atom is stored as a pair of its *original spelling* — what the-- macro should splice into emitted terms, so nothing the user wrote-- ever appears unfolded — and its weak-head normal form, which acts-- as a second identity key: two spellings of the same value (two-- definitions unfolding to the same constructor form) count as one-- atom. Whnf-equality implies definitional equality, so emitting the-- first-seen spelling for both stays type-correct.---- PERFORMANCE WARNING: keep the store operations as separate,-- first-order list traversals whose results the caller forces-- promptly (e.g. a `just i ← pure (atomStoreIndex …)` pattern). A-- fused insert-and-index traversal returning a pair looks equivalent-- but builds thunk chains that Agda's reflection evaluator-- re-evaluates without sharing — on an 8-atom goal this blew up from-- milliseconds to an out-of-memory kill-- (see `Tactic.Solver.Ring.Tests.EdgeCases` / big8). {-# OPTIONS --safe --without-K #-}module Reflection.Utils.AtomStore where open import Meta.Prelude import Data.Maybe as Maybeopen import Data.List using (map)open import Reflectionopen import Reflection.AST.AlphaEquality using (_=α=_) Atom : SetAtom = Term × Term -- (original spelling , whnf key) AtomStore : SetAtomStore = List Atom atomMatches : Atom → Atom → BoolatomMatches (orig , whnf) (o , w) = (orig =α= o) ∨ (whnf =α= w) insertAtomStore : Atom → AtomStore → AtomStoreinsertAtomStore a [] = a ∷ []insertAtomStore a (b ∷ rest) = if atomMatches a b then b ∷ rest else b ∷ insertAtomStore a rest atomStoreIndex : Atom → AtomStore → Maybe ℕatomStoreIndex a [] = nothingatomStoreIndex a (b ∷ rest) = if atomMatches a b then just 0 else Maybe.map suc (atomStoreIndex a rest) atomSpellings : AtomStore → List TermatomSpellings = map proj₁