Skip to content

Commit da286d0

Browse files
authored
Annotated reflected syntax (#1325)
1 parent aa62961 commit da286d0

File tree

4 files changed

+405
-0
lines changed

4 files changed

+405
-0
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ New modules
6565
* Added `Reflection.DeBruijn` with weakening, strengthening and free variable operations
6666
on reflected terms.
6767
* Added `Reflection.Universe` defining a universe for the reflected syntax types.
68+
* Added `Reflection.Annotated` defining annotated reflected syntax and
69+
functions to compute annotations and traverse terms based on annotations.
70+
* Added `Reflection.Annotated.Free` implementing free variable annotations for
71+
reflected terms.
6872

6973
Other major changes
7074
-------------------

GenerateEverything.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ withKModules = map modToFile
6262
, "Data.Star.Pointer"
6363
, "Data.Star.Vec"
6464
, "Data.String.Unsafe"
65+
, "Reflection.Annotated"
66+
, "Reflection.Annotated.Free"
6567
, "Relation.Binary.HeterogeneousEquality"
6668
, "Relation.Binary.HeterogeneousEquality.Core"
6769
, "Relation.Binary.HeterogeneousEquality.Quotients.Examples"

src/Reflection/Annotated.agda

Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Annotated reflected syntax.
5+
--
6+
-- NOTE: This file does not check under --without-K due to restrictions
7+
-- in the termination checker. In particular recursive functions
8+
-- over a universe of types is not supported by --without-K.
9+
------------------------------------------------------------------------
10+
11+
{-# OPTIONS --safe --with-K #-}
12+
13+
module Reflection.Annotated where
14+
15+
open import Level using (Level; 0ℓ; suc; _⊔_)
16+
open import Category.Applicative using (RawApplicative)
17+
open import Data.Bool.Base using (Bool; false; true; if_then_else_)
18+
open import Data.List.Base using (List; []; _∷_)
19+
open import Data.List.Relation.Unary.All as All using (All; _∷_; [])
20+
open import Data.Product using (_×_; _,_; proj₁; proj₂)
21+
open import Data.String.Base using (String)
22+
23+
open import Reflection
24+
open import Reflection.Universe
25+
26+
open Clause
27+
open Pattern
28+
open Sort
29+
30+
------------------------------------------------------------------------
31+
-- Annotations and annotated types
32+
33+
-- An Annotation is a type indexed by a reflected term.
34+
Annotation : Set (suc ℓ)
35+
Annotation ℓ = {u} ⟦ u ⟧ Set
36+
37+
-- An annotated type is a family over an Annotation and a reflected term.
38+
Typeₐ : Univ Set (suc ℓ)
39+
Typeₐ ℓ u = Annotation ℓ ⟦ u ⟧ Set
40+
41+
private
42+
variable
43+
: Level
44+
u : Univ
45+
Ann Ann₁ Ann₂ : Annotation ℓ
46+
47+
-- ⟪_⟫ packs up an element of an annotated type with a top-level annotation.
48+
infixr 30 ⟨_⟩_
49+
data ⟪_⟫ {u} (Tyₐ : Typeₐ ℓ u) : Typeₐ ℓ u where
50+
⟨_⟩_ : {t} Ann t Tyₐ Ann t ⟪ Tyₐ ⟫ Ann t
51+
52+
ann : {Tyₐ : Typeₐ ℓ u} {t : ⟦ u ⟧} ⟪ Tyₐ ⟫ Ann t Ann t
53+
ann (⟨ α ⟩ _) = α
54+
55+
56+
------------------------------------------------------------------------
57+
-- Annotated reflected syntax
58+
59+
-- Annotated lists are lists (All) of annotated values. No top-level
60+
-- annotation added, since we don't want an annotation for every tail
61+
-- of a list. Instead a top-level annotation is added on the outside.
62+
-- See Argsₐ.
63+
Listₐ : Typeₐ ℓ u Typeₐ ℓ (⟨list⟩ u)
64+
Listₐ Tyₐ Ann = All (Tyₐ Ann)
65+
66+
-- We define the rest of the annotated types in two variants:
67+
-- The primed variant which has annotations on subterms, and the
68+
-- non-primed variant which adds a top-level annotation to the primed
69+
-- one.
70+
71+
data Absₐ′ (Tyₐ : Typeₐ ℓ u) : Typeₐ ℓ (⟨abs⟩ u) where
72+
abs : {t} x Tyₐ Ann t Absₐ′ Tyₐ Ann (abs x t)
73+
74+
Absₐ : Typeₐ ℓ u Typeₐ ℓ (⟨abs⟩ u)
75+
Absₐ Tyₐ = ⟪ Absₐ′ Tyₐ ⟫
76+
77+
data Argₐ′ (Tyₐ : Typeₐ ℓ u) : Typeₐ ℓ (⟨arg⟩ u) where
78+
arg : {t} i Tyₐ Ann t Argₐ′ Tyₐ Ann (arg i t)
79+
80+
Argₐ : Typeₐ ℓ u Typeₐ ℓ (⟨arg⟩ u)
81+
Argₐ Tyₐ = ⟪ Argₐ′ Tyₐ ⟫
82+
83+
data Namedₐ′ (Tyₐ : Typeₐ ℓ u) : Typeₐ ℓ (⟨named⟩ u) where
84+
_,_ : {t} x Tyₐ Ann t Namedₐ′ Tyₐ Ann (x , t)
85+
86+
Namedₐ : Typeₐ ℓ u Typeₐ ℓ (⟨named⟩ u)
87+
Namedₐ Tyₐ = ⟪ Namedₐ′ Tyₐ ⟫
88+
89+
-- Add a top-level annotation for Args.
90+
Argsₐ : Typeₐ ℓ u Typeₐ ℓ (⟨list⟩ (⟨arg⟩ u))
91+
Argsₐ Tyₐ = ⟪ Listₐ (Argₐ Tyₐ) ⟫
92+
93+
mutual
94+
Termₐ : Typeₐ ℓ ⟨term⟩
95+
Termₐ = ⟪ Termₐ′ ⟫
96+
97+
Patternₐ : Typeₐ ℓ ⟨pat⟩
98+
Patternₐ = ⟪ Patternₐ′ ⟫
99+
100+
Sortₐ : Typeₐ ℓ ⟨sort⟩
101+
Sortₐ = ⟪ Sortₐ′ ⟫
102+
103+
Clauseₐ : Typeₐ ℓ ⟨clause⟩
104+
Clauseₐ = ⟪ Clauseₐ′ ⟫
105+
106+
Clausesₐ : Typeₐ ℓ (⟨list⟩ ⟨clause⟩)
107+
Clausesₐ = ⟪ Listₐ Clauseₐ ⟫
108+
109+
Telₐ : Typeₐ ℓ ⟨tel⟩
110+
Telₐ = ⟪ Listₐ (Namedₐ (Argₐ Termₐ)) ⟫
111+
112+
data Termₐ′ {ℓ} : Typeₐ ℓ ⟨term⟩ where
113+
var : x {args} Argsₐ Termₐ Ann args Termₐ′ Ann (var x args)
114+
con : c {args} Argsₐ Termₐ Ann args Termₐ′ Ann (con c args)
115+
def : f {args} Argsₐ Termₐ Ann args Termₐ′ Ann (def f args)
116+
lam : v {b} Absₐ Termₐ Ann b Termₐ′ Ann (lam v b)
117+
pat-lam : {cs args} Clausesₐ Ann cs Argsₐ Termₐ Ann args
118+
Termₐ′ Ann (pat-lam cs args)
119+
pi : {a b} Argₐ Termₐ Ann a Absₐ Termₐ Ann b Termₐ′ Ann (pi a b)
120+
agda-sort : {s} Sortₐ Ann s Termₐ′ Ann (agda-sort s)
121+
lit : l Termₐ′ Ann (lit l)
122+
meta : x {args} Argsₐ Termₐ Ann args Termₐ′ Ann (meta x args)
123+
unknown : Termₐ′ Ann unknown
124+
125+
data Clauseₐ′ {ℓ} : Typeₐ ℓ ⟨clause⟩ where
126+
clause : {tel ps t} Telₐ Ann tel Argsₐ Patternₐ Ann ps
127+
Termₐ Ann t Clauseₐ′ Ann (clause tel ps t)
128+
absurd-clause : {tel ps} Telₐ Ann tel Argsₐ Patternₐ Ann ps
129+
Clauseₐ′ Ann (absurd-clause tel ps)
130+
131+
data Sortₐ′ {ℓ} : Typeₐ ℓ ⟨sort⟩ where
132+
set : {t} Termₐ Ann t Sortₐ′ Ann (set t)
133+
lit : n Sortₐ′ Ann (lit n)
134+
unknown : Sortₐ′ Ann unknown
135+
136+
data Patternₐ′ {ℓ} : Typeₐ ℓ ⟨pat⟩ where
137+
con : c {ps} Argsₐ Patternₐ Ann ps Patternₐ′ Ann (con c ps)
138+
dot : {t} Termₐ Ann t Patternₐ′ Ann (dot t)
139+
var : x Patternₐ′ Ann (var x)
140+
lit : l Patternₐ′ Ann (lit l)
141+
proj : f Patternₐ′ Ann (proj f)
142+
absurd : Patternₐ′ Ann absurd
143+
144+
145+
-- Mapping a code in the universe to its corresponding primed and
146+
-- non-primed annotated type.
147+
148+
mutual
149+
Annotated′ : Typeₐ ℓ u
150+
Annotated′ {u = ⟨term⟩} = Termₐ′
151+
Annotated′ {u = ⟨pat⟩} = Patternₐ′
152+
Annotated′ {u = ⟨sort⟩} = Sortₐ′
153+
Annotated′ {u = ⟨clause⟩} = Clauseₐ′
154+
Annotated′ {u = ⟨list⟩ u} = Listₐ Annotated
155+
Annotated′ {u = ⟨arg⟩ u} = Argₐ′ Annotated
156+
Annotated′ {u = ⟨abs⟩ u} = Absₐ′ Annotated
157+
Annotated′ {u = ⟨named⟩ u} = Namedₐ′ Annotated
158+
159+
Annotated : Typeₐ ℓ u
160+
Annotated = ⟪ Annotated′ ⟫
161+
162+
163+
------------------------------------------------------------------------
164+
-- Annotating terms
165+
166+
-- An annotation function computes the top-level annotation given a
167+
-- term annotated at all sub-terms.
168+
AnnotationFun : Annotation ℓ Set
169+
AnnotationFun Ann = u {t : ⟦ u ⟧} Annotated′ Ann t Ann t
170+
171+
172+
-- Given an annotation function we can do the bottom-up traversal of a
173+
-- reflected term to compute an annotated version.
174+
module _ (annFun : AnnotationFun Ann) where
175+
176+
private
177+
annotated : {t : ⟦ u ⟧} Annotated′ Ann t Annotated Ann t
178+
annotated ps = ⟨ annFun _ ps ⟩ ps
179+
180+
mutual
181+
annotate′ : (t : ⟦ u ⟧) Annotated′ Ann t
182+
annotate′ {⟨term⟩} (var x args) = var x (annotate args)
183+
annotate′ {⟨term⟩} (con c args) = con c (annotate args)
184+
annotate′ {⟨term⟩} (def f args) = def f (annotate args)
185+
annotate′ {⟨term⟩} (lam v t) = lam v (annotate t)
186+
annotate′ {⟨term⟩} (pat-lam cs args) = pat-lam (annotate cs) (annotate args)
187+
annotate′ {⟨term⟩} (pi a b) = pi (annotate a) (annotate b)
188+
annotate′ {⟨term⟩} (agda-sort s) = agda-sort (annotate s)
189+
annotate′ {⟨term⟩} (lit l) = lit l
190+
annotate′ {⟨term⟩} (meta x args) = meta x (annotate args)
191+
annotate′ {⟨term⟩} unknown = unknown
192+
annotate′ {⟨pat⟩} (con c ps) = con c (annotate ps)
193+
annotate′ {⟨pat⟩} (dot t) = dot (annotate t)
194+
annotate′ {⟨pat⟩} (var x) = var x
195+
annotate′ {⟨pat⟩} (lit l) = lit l
196+
annotate′ {⟨pat⟩} (proj f) = proj f
197+
annotate′ {⟨pat⟩} absurd = absurd
198+
annotate′ {⟨sort⟩} (set t) = set (annotate t)
199+
annotate′ {⟨sort⟩} (lit n) = lit n
200+
annotate′ {⟨sort⟩} unknown = unknown
201+
annotate′ {⟨clause⟩} (clause tel ps t) = clause (annotate tel) (annotate ps) (annotate t)
202+
annotate′ {⟨clause⟩} (absurd-clause tel ps) = absurd-clause (annotate tel) (annotate ps)
203+
annotate′ {⟨abs⟩ u} (abs x t) = abs x (annotate t)
204+
annotate′ {⟨arg⟩ u} (arg i t) = arg i (annotate t)
205+
annotate′ {⟨list⟩ u} [] = []
206+
annotate′ {⟨list⟩ u} (x ∷ xs) = annotate x ∷ annotate′ xs
207+
annotate′ {⟨named⟩ u} (x , t) = x , annotate t
208+
209+
annotate : (t : ⟦ u ⟧) Annotated Ann t
210+
annotate t = annotated (annotate′ t)
211+
212+
213+
------------------------------------------------------------------------
214+
-- Annotation function combinators
215+
216+
-- Mapping over annotations
217+
mutual
218+
map′ : u ( {u} {t : ⟦ u ⟧} Ann₁ t Ann₂ t) {t : ⟦ u ⟧} Annotated′ Ann₁ t Annotated′ Ann₂ t
219+
map′ ⟨term⟩ f (var x args) = var x (map f args)
220+
map′ ⟨term⟩ f (con c args) = con c (map f args)
221+
map′ ⟨term⟩ f (def h args) = def h (map f args)
222+
map′ ⟨term⟩ f (lam v b) = lam v (map f b)
223+
map′ ⟨term⟩ f (pat-lam cs args) = pat-lam (map f cs) (map f args)
224+
map′ ⟨term⟩ f (pi a b) = pi (map f a) (map f b)
225+
map′ ⟨term⟩ f (agda-sort s) = agda-sort (map f s)
226+
map′ ⟨term⟩ f (lit l) = lit l
227+
map′ ⟨term⟩ f (meta x args) = meta x (map f args)
228+
map′ ⟨term⟩ f unknown = unknown
229+
map′ ⟨pat⟩ f (con c ps) = con c (map f ps)
230+
map′ ⟨pat⟩ f (dot t) = dot (map f t)
231+
map′ ⟨pat⟩ f (var x) = var x
232+
map′ ⟨pat⟩ f (lit l) = lit l
233+
map′ ⟨pat⟩ f (proj g) = proj g
234+
map′ ⟨pat⟩ f absurd = absurd
235+
map′ ⟨sort⟩ f (set t) = set (map f t)
236+
map′ ⟨sort⟩ f (lit n) = lit n
237+
map′ ⟨sort⟩ f unknown = unknown
238+
map′ ⟨clause⟩ f (clause Γ ps args) = clause (map f Γ) (map f ps) (map f args)
239+
map′ ⟨clause⟩ f (absurd-clause Γ ps) = absurd-clause (map f Γ) (map f ps)
240+
map′ (⟨list⟩ u) f [] = []
241+
map′ (⟨list⟩ u) f (x ∷ xs) = map f x ∷ map′ _ f xs
242+
map′ (⟨arg⟩ u) f (arg i x) = arg i (map f x)
243+
map′ (⟨abs⟩ u) f (abs x t) = abs x (map f t)
244+
map′ (⟨named⟩ u) f (x , t) = x , map f t
245+
246+
map : ( {u} {t : ⟦ u ⟧} Ann₁ t Ann₂ t) {u} {t : ⟦ u ⟧} Annotated Ann₁ t Annotated Ann₂ t
247+
map f {u = u} (⟨ α ⟩ t) = ⟨ f α ⟩ map′ u f t
248+
249+
250+
module _ {W : Set ℓ} (ε : W) (_∪_ : W W W) where
251+
252+
-- This annotation function does nothing except combine ε's with _∪_.
253+
-- Lets you skip the boring cases when defining non-dependent
254+
-- annotation functions by adding a catch-all calling defaultAnn.
255+
defaultAnn : AnnotationFun (λ _ W)
256+
defaultAnn ⟨term⟩ (var x args) = ann args
257+
defaultAnn ⟨term⟩ (con c args) = ann args
258+
defaultAnn ⟨term⟩ (def f args) = ann args
259+
defaultAnn ⟨term⟩ (lam v b) = ann b
260+
defaultAnn ⟨term⟩ (pat-lam cs args) = ann cs ∪ ann args
261+
defaultAnn ⟨term⟩ (pi a b) = ann a ∪ ann b
262+
defaultAnn ⟨term⟩ (agda-sort s) = ann s
263+
defaultAnn ⟨term⟩ (lit l) = ε
264+
defaultAnn ⟨term⟩ (meta x args) = ann args
265+
defaultAnn ⟨term⟩ unknown = ε
266+
defaultAnn ⟨pat⟩ (con c args) = ann args
267+
defaultAnn ⟨pat⟩ (dot t) = ann t
268+
defaultAnn ⟨pat⟩ (var x) = ε
269+
defaultAnn ⟨pat⟩ (lit l) = ε
270+
defaultAnn ⟨pat⟩ (proj f) = ε
271+
defaultAnn ⟨pat⟩ absurd = ε
272+
defaultAnn ⟨sort⟩ (set t) = ann t
273+
defaultAnn ⟨sort⟩ (lit n) = ε
274+
defaultAnn ⟨sort⟩ unknown = ε
275+
defaultAnn ⟨clause⟩ (clause Γ ps t) = ann Γ ∪ (ann ps ∪ ann t)
276+
defaultAnn ⟨clause⟩ (absurd-clause Γ ps) = ann Γ ∪ ann ps
277+
defaultAnn (⟨list⟩ u) [] = ε
278+
defaultAnn (⟨list⟩ u) (x ∷ xs) = ann x ∪ defaultAnn _ xs
279+
defaultAnn (⟨arg⟩ u) (arg i x) = ann x
280+
defaultAnn (⟨abs⟩ u) (abs x t) = ann t
281+
defaultAnn (⟨named⟩ u) (x , t) = ann t
282+
283+
284+
-- Cartisian product of two annotation functions.
285+
infixr 4 _⊗_
286+
_⊗_ : AnnotationFun Ann₁ AnnotationFun Ann₂ AnnotationFun (λ t Ann₁ t × Ann₂ t)
287+
(f ⊗ g) u t = f u (map′ u proj₁ t) , g u (map′ u proj₂ t)
288+
289+
290+
------------------------------------------------------------------------
291+
-- Annotation-driven traversal
292+
293+
-- Top-down applicative traversal of an annotated term. Applies an
294+
-- action (without going into subterms) to terms whose annotation
295+
-- satisfies a given criterion. Returns an unannotated term.
296+
297+
module Traverse {M : Set Set} (appl : RawApplicative M) where
298+
299+
open RawApplicative appl renaming (_⊛_ to _<*>_)
300+
301+
module _ (apply? : {u} {t : ⟦ u ⟧} Ann t Bool)
302+
(action : {u} {t : ⟦ u ⟧} Annotated Ann t M ⟦ u ⟧) where
303+
304+
mutual
305+
traverse′ : {t : ⟦ u ⟧} Annotated′ Ann t M ⟦ u ⟧
306+
traverse′ {⟨term⟩} (var x args) = var x <$> traverse args
307+
traverse′ {⟨term⟩} (con c args) = con c <$> traverse args
308+
traverse′ {⟨term⟩} (def f args) = def f <$> traverse args
309+
traverse′ {⟨term⟩} (lam v b) = lam v <$> traverse b
310+
traverse′ {⟨term⟩} (pat-lam cs args) = pat-lam <$> traverse cs <*> traverse args
311+
traverse′ {⟨term⟩} (pi a b) = pi <$> traverse a <*> traverse b
312+
traverse′ {⟨term⟩} (agda-sort s) = agda-sort <$> traverse s
313+
traverse′ {⟨term⟩} (lit l) = pure (lit l)
314+
traverse′ {⟨term⟩} (meta x args) = meta x <$> traverse args
315+
traverse′ {⟨term⟩} unknown = pure unknown
316+
traverse′ {⟨pat⟩} (con c args) = con c <$> traverse args
317+
traverse′ {⟨pat⟩} (dot t) = dot <$> traverse t
318+
traverse′ {⟨pat⟩} (var x) = pure (var x)
319+
traverse′ {⟨pat⟩} (lit l) = pure (lit l)
320+
traverse′ {⟨pat⟩} (proj f) = pure (proj f)
321+
traverse′ {⟨pat⟩} absurd = pure absurd
322+
traverse′ {⟨sort⟩} (set t) = set <$> traverse t
323+
traverse′ {⟨sort⟩} (lit n) = pure (lit n)
324+
traverse′ {⟨sort⟩} unknown = pure unknown
325+
traverse′ {⟨clause⟩} (clause Γ ps t) = clause <$> traverse Γ <*> traverse ps <*> traverse t
326+
traverse′ {⟨clause⟩} (absurd-clause Γ ps) = absurd-clause <$> traverse Γ <*> traverse ps
327+
traverse′ {⟨list⟩ u} [] = pure []
328+
traverse′ {⟨list⟩ u} (x ∷ xs) = _∷_ <$> traverse x <*> traverse′ xs
329+
traverse′ {⟨arg⟩ u} (arg i x) = arg i <$> traverse x
330+
traverse′ {⟨abs⟩ u} (abs x t) = abs x <$> traverse t
331+
traverse′ {⟨named⟩ u} (x , t) = x ,_ <$> traverse t
332+
333+
traverse : {t : ⟦ u ⟧} Annotated Ann t M ⟦ u ⟧
334+
traverse t@(⟨ α ⟩ tₐ) = if apply? α then action t else traverse′ tₐ

0 commit comments

Comments
 (0)