summaryrefslogtreecommitdiff
path: root/src/Obs/NormalForm.idr
blob: 3139daf99b28b6991cfedfeffbf1d654d4a28d2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
module Obs.NormalForm

import Data.List.Elem

import Obs.Logging
import Obs.Pretty
import Obs.Substitution
import Obs.Universe

import Text.Bounded
import Text.PrettyPrint.Prettyprinter

%default total

-- Definition ------------------------------------------------------------------

data NormalForm  : Sorted.Family Relevance

public export
TypeNormalForm : Unsorted.Family Relevance
TypeNormalForm = NormalForm Relevant

public export
record DeclForm (ctx : List Relevance) where
  constructor MkDecl
  var : Maybe String
  type : TypeNormalForm ctx

public export
data Constructor : Unsorted.Family Relevance where
  Universe : (s : Universe) -> Constructor ctx
  Pi : (domainSort, codomainSort : Universe) ->
    (domain : DeclForm ctx) ->
    (codomain : TypeNormalForm (relevance domainSort :: ctx)) ->
    Constructor ctx
  Lambda : (domainRel : Relevance) ->
    (var : Maybe String) ->
    (body : NormalForm Relevant (domainRel :: ctx)) ->
    Constructor ctx
  Sigma : (indexSort, elementSort : Universe) ->
    (index : DeclForm ctx) ->
    (element : TypeNormalForm (relevance indexSort :: ctx)) ->
    Constructor ctx
  Pair : (indexRel, elementRel : Relevance) ->
    (prf : IsRelevant (pair indexRel elementRel)) ->
    (first : NormalForm indexRel ctx) ->
    (second : NormalForm elementRel ctx) ->
    Constructor ctx
  Bool : Constructor ctx
  True : Constructor ctx
  False : Constructor ctx
  Box : (prop : TypeNormalForm ctx) -> Constructor ctx
  MkBox : Constructor ctx
  Top : Constructor ctx
  Bottom : Constructor ctx

public export
data Neutral : Unsorted.Family Relevance where
  Var : (var : String) -> (i : Elem Relevant ctx) -> Neutral ctx
  App : (argRel : Relevance) -> (fun : Neutral ctx) -> (arg : NormalForm argRel ctx) -> Neutral ctx
  First : (secondRel : Relevance) -> (arg : Neutral ctx) -> Neutral ctx
  Second : (firstRel : Relevance) -> (arg : Neutral ctx) -> Neutral ctx
  If : (discriminant : Neutral ctx) -> (true, false : NormalForm Relevant ctx) -> Neutral ctx
  Absurd : Neutral ctx
  Equal : (type : Neutral ctx) -> (left, right : NormalForm Relevant ctx) -> Neutral ctx
  EqualL : (left : Neutral ctx) -> (right : TypeNormalForm ctx) -> Neutral ctx
  EqualR : (left : Constructor ctx) -> (right : Neutral ctx) -> Neutral ctx
  EqualStuck : (left, right : Constructor ctx) -> Neutral ctx
  CastL : (oldType : Neutral ctx) ->
    (newType : TypeNormalForm ctx) ->
    (value : NormalForm Relevant ctx) ->
    Neutral ctx
  CastR : (oldType : Constructor ctx) ->
    (newType : Neutral ctx) ->
    (value : NormalForm Relevant ctx) ->
    Neutral ctx
  CastStuck : (oldType, newType : Constructor ctx) ->
    (value : NormalForm Relevant ctx) ->
    Neutral ctx

public export
data NormalForm : Sorted.Family Relevance where
  Ntrl : Neutral ~|> NormalForm Relevant
  Cnstr : Constructor ~|> NormalForm Relevant
  Irrel : NormalForm Irrelevant ctx

%name Constructor t, u, v
%name Neutral t, u, v
%name NormalForm t, u, v

public export
record Parameter (ctx : List Relevance) where
  constructor MkParameter
  name : WithBounds String
  sort : Universe
  ty : TypeNormalForm ctx

public export
record Definition (ctx : List Relevance) where
  constructor MkDefinition
  name : WithBounds String
  sort : Universe
  ty   : TypeNormalForm ctx
  tm   : NormalForm (relevance sort) ctx

public export
data Context : List Relevance -> Type where
  Nil  : Context []
  (:<) : Context ctx -> (def : Definition ctx) -> Context (relevance def.sort :: ctx)
  (::<) : Context ctx -> (param : Parameter ctx) -> Context (relevance param.sort :: ctx)

%name Context ctx, ctx', ctx''

-- Convenience Casts -----------------------------------------------------------

public export
Cast Universe (Constructor ctx) where
  cast s = Universe s

public export
Cast Universe (NormalForm Relevant ctx) where
  cast s = Cnstr $ cast s

-- Pretty Print ----------------------------------------------------------------

prettyPrec : Prec -> NormalForm b ctx -> Doc ann

prettyPrecDecl : DeclForm ctx -> Doc ann
prettyPrecDecl (MkDecl var type) = prettyDecl var (prettyPrec Open type)

prettyPrecCnstr : Prec -> Constructor ctx -> Doc ann
prettyPrecCnstr d (Universe {s}) = prettyPrec d s
prettyPrecCnstr d (Pi {domainSort, codomainSort, domain, codomain}) =
  prettyDeclForm d [prettyPrecDecl domain] "->" (prettyPrec Open codomain)
prettyPrecCnstr d (Lambda {domainRel, var, body}) =
  prettyLambda d (maybe "_" id var) (prettyPrec Open body)
prettyPrecCnstr d (Sigma {indexSort, elementSort, index, element}) =
  prettyDeclForm d [prettyPrecDecl index] "**" (prettyPrec Open element)
prettyPrecCnstr d (Pair {indexRel, elementRel, prf, first, second}) =
  prettyPair (prettyPrec Open first) (prettyPrec Open second)
prettyPrecCnstr d Bool = pretty "Bool"
prettyPrecCnstr d True = pretty "True"
prettyPrecCnstr d False = pretty "False"
prettyPrecCnstr d (Box {prop}) = prettyApp d (pretty "Box") [prettyPrec App prop]
prettyPrecCnstr d MkBox = prettyApp d (pretty "box") [pretty "_"]
prettyPrecCnstr d Top = pretty "()"
prettyPrecCnstr d Bottom = pretty "Void"

prettyPrecNtrl : Prec -> Neutral ctx -> Doc ann
prettyPrecNtrl d (Var {var, i}) = pretty "\{var}@\{show $ elemToNat i}"
prettyPrecNtrl d (App {argRel, fun, arg}) =
  prettyApp d (prettyPrecNtrl Open fun) [prettyPrec App arg]
prettyPrecNtrl d (First {secondRel, arg}) =
  prettyApp d (pretty "fst") [prettyPrecNtrl App arg]
prettyPrecNtrl d (Second {firstRel, arg}) =
  prettyApp d (pretty "snd") [prettyPrecNtrl App arg]
prettyPrecNtrl d (If {discriminant, true, false}) =
  prettyApp d (pretty "if") $
  [pretty "_", prettyPrecNtrl App discriminant, prettyPrec App true, prettyPrec App false]
prettyPrecNtrl d Absurd = prettyApp d (pretty "absurd") [pretty "_"]
prettyPrecNtrl d (Equal {type, left, right}) =
  prettyEqual d (prettyPrec Equal left) (prettyPrec Equal right)
prettyPrecNtrl d (EqualL {left, right}) =
  prettyEqual d (prettyPrecNtrl Equal left) (prettyPrec Equal right)
prettyPrecNtrl d (EqualR {left, right}) =
  prettyEqual d (prettyPrecCnstr Equal left) (prettyPrecNtrl Equal right)
prettyPrecNtrl d (EqualStuck {left, right}) =
  prettyEqual d (prettyPrecCnstr Equal left) (prettyPrecCnstr Equal right)
prettyPrecNtrl d (CastL {oldType, newType, value}) =
  prettyApp d (pretty "cast") $
  [prettyPrecNtrl App oldType, prettyPrec App newType, pretty "_", prettyPrec App value]
prettyPrecNtrl d (CastR {oldType, newType, value}) =
  prettyApp d (pretty "cast") $
  [prettyPrecCnstr App oldType, prettyPrecNtrl App newType, pretty "_", prettyPrec App value]
prettyPrecNtrl d (CastStuck {oldType, newType, value}) =
  prettyApp d (pretty "cast") $
  [prettyPrecCnstr App oldType, prettyPrecCnstr App newType, pretty "_", prettyPrec App value]

prettyPrec d (Ntrl t) = prettyPrecNtrl d t
prettyPrec d (Cnstr t) = prettyPrecCnstr d t
prettyPrec d Irrel = pretty "_"

export
Pretty (Constructor ctx) where
  prettyPrec = prettyPrecCnstr

export
Pretty (Neutral ctx) where
  prettyPrec = prettyPrecNtrl

export
Pretty (NormalForm b ctx) where
  prettyPrec = NormalForm.prettyPrec

-- Renaming --------------------------------------------------------------------

rename : NormalForm ~|> Hom Elem NormalForm

renameDecl : DeclForm ~|> Hom Elem DeclForm
renameDecl (MkDecl var type) f = MkDecl var (rename type f)

renameCnstr : Constructor ~|> Hom Elem Constructor
renameCnstr (Universe {s}) f = Universe {s}
renameCnstr (Pi {domainSort, codomainSort, domain, codomain}) f =
  Pi
    { domainSort
    , codomainSort
    , domain = renameDecl domain f
    , codomain = rename codomain (lift [(_ ** ())] f)
    }
renameCnstr (Lambda {domainRel, var, body}) f =
  Lambda {domainRel, var, body = rename body (lift [(_ ** ())] f)}
renameCnstr (Sigma {indexSort, elementSort, index, element}) f =
  Sigma
    { indexSort
    , elementSort
    , index = renameDecl index f
    , element = rename element (lift [(_ ** ())] f)
    }
renameCnstr (Pair {indexRel, elementRel, prf, first, second}) f =
  Pair
    { indexRel
    , elementRel
    , prf
    , first = rename first f
    , second = rename second f
    }
renameCnstr Bool f = Bool
renameCnstr True f = True
renameCnstr False f = False
renameCnstr (Box {prop}) f = Box {prop = rename prop f}
renameCnstr MkBox f = MkBox
renameCnstr Top f = Top
renameCnstr Bottom f = Bottom

renameNtrl : Neutral ~|> Hom Elem Neutral
renameNtrl (Var {var, i}) f = Var {var, i = f i}
renameNtrl (App {argRel, fun, arg}) f = App {argRel, fun = renameNtrl fun f, arg = rename arg f}
renameNtrl (First {secondRel, arg}) f = First {secondRel, arg = renameNtrl arg f}
renameNtrl (Second {firstRel, arg}) f = Second {firstRel, arg = renameNtrl arg f}
renameNtrl (If {discriminant, true, false}) f =
  If {discriminant = renameNtrl discriminant f, true = rename true f, false = rename false f}
renameNtrl Absurd f = Absurd
renameNtrl (Equal {type, left, right}) f =
  Equal {type = renameNtrl type f, left = rename left f, right = rename right f}
renameNtrl (EqualL {left, right}) f = EqualL {left = renameNtrl left f, right = rename right f}
renameNtrl (EqualR {left, right}) f =
  EqualR {left = renameCnstr left f, right = renameNtrl right f}
renameNtrl (EqualStuck {left, right}) f =
  EqualStuck {left = renameCnstr left f, right = renameCnstr right f}
renameNtrl (CastL {oldType, newType, value}) f =
 CastL {oldType = renameNtrl oldType f, newType = rename newType f, value = rename value f}
renameNtrl (CastR {oldType, newType, value}) f =
 CastR {oldType = renameCnstr oldType f, newType = renameNtrl newType f, value = rename value f}
renameNtrl (CastStuck {oldType, newType, value}) f =
 CastStuck
   { oldType = renameCnstr oldType f
   , newType = renameCnstr newType f
   , value = rename value f
   }

rename (Ntrl t) f = Ntrl $ renameNtrl t f
rename (Cnstr t) f = Cnstr $ renameCnstr t f
rename Irrel f = Irrel

export
Unsorted.Rename Relevance Constructor where
  rename = renameCnstr

export
Unsorted.Rename Relevance Neutral where
  rename = renameNtrl

export
Sorted.Rename Relevance NormalForm where
  rename = NormalForm.rename

export
PointedRename Relevance (\r => Maybe String) NormalForm where
  point {s = Irrelevant} _ _ = Irrel
  point {s = Relevant} var i =
    Ntrl (Var {var = maybe "" id var, i})

-- Useful Constructors ---------------------------------------------------------

public export
record ContainerTy (ctx : List Relevance) where
  constructor MkContainerTy
  inputSort, shapeSort, positionSort, outputSort : Universe
  input, output : TypeNormalForm ctx