Source file signature.ml
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
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
open UtilsLib
open Table
open Logic.Lambda
open Logic.Abstract_syntax
type sig_entry =
| Type_declaration of string * int * Lambda.kind
| Type_definition of string * int * Lambda.kind * Lambda.stype
| Term_declaration of string * int * Abstract_syntax.syntactic_behavior * Lambda.stype
| Term_definition of string * int * Abstract_syntax.syntactic_behavior * Lambda.stype * Lambda.term
module Log = (val Logs.src_log (Logs.Src.create "ACGtkLib.signature" ~doc:"logs ACGtkLib signature events") : Logs.LOG)
module Make(Symbols:TABLE with type key=String.t)(Id:TABLE with type key=int) =
struct
exception Duplicate_type_definition
exception Duplicate_term_definition
exception Not_found
exception Not_functional_type
type entry = sig_entry
type t = {name:string*Abstract_syntax.location;
size:int;
terms:entry Symbols.t;
types:entry Symbols.t;
precedence: (float * string option) Symbols.t ;
max_pred : float * string option ;
ids:entry Id.t;
is_2nd_order:bool;
extension_timestamp:float;
definition_timestamp:float}
type term = Lambda.term
type stype = Lambda.stype
type data =
| Type of stype
| Term of (term*stype)
let find_term sym {terms=syms;_} =
match Symbols.find sym syms with
| Term_declaration (x,id,_,const_type) when sym=x-> Lambda.Const id,const_type
| Term_declaration _ -> failwith "Bug in find_term"
| Term_definition (x,id,_,const_type,_) when sym=x-> Lambda.DConst id,const_type
| Term_definition _ -> failwith "Bug in find_term"
| _ -> failwith "Bug in find_term"
| exception Symbols.Not_found -> raise Not_found
let id_to_string {ids=ids;_} i =
match Id.find i ids with
| Type_declaration(s,_,_) -> Abstract_syntax.Default,s
| Type_definition(s,_,_,_) -> Abstract_syntax.Default,s
| Term_declaration(s,_,behavior,_) -> behavior,s
| Term_definition(s,_,behavior,_,_) -> behavior,s
let type_to_string ty sg = Lambda.type_to_string ty (id_to_string sg)
let term_to_string t sg = Lambda.term_to_string t (id_to_string sg)
let type_to_formatted_string fmt ty sg = Lambda.type_to_formatted_string fmt ty (id_to_string sg)
let term_to_formatted_string fmt t sg = Lambda.term_to_formatted_string fmt t (id_to_string sg)
let empty n =
let timestamp = Unix.time () in
{name=n;
size=0;
terms=Symbols.empty;
types=Symbols.empty;
ids=Id.empty;
is_2nd_order=true;
precedence = Symbols.empty;
max_pred = 0., None ;
definition_timestamp=timestamp;
extension_timestamp=timestamp}
let name {name=n;_} = n
let find_atomic_type s {types=syms;_} =
match Symbols.find s syms with
| Type_declaration (x,id,_) when x=s -> Lambda.Atom id
| Type_declaration _ -> failwith "Bug in find_atomic_type"
| Type_definition (x,id,_,_) when x=s -> Lambda.DAtom id
| Type_definition _ -> failwith "Bug in find_atomic_type"
| _ -> failwith "Bug in find_atomic_type"
| exception Symbols.Not_found -> failwith "Bug in find_atomic_type"
let find_type s sg =
match Symbols.find s sg.types with
| Type_declaration (x,id,_) when x=s -> Lambda.Atom id
| Type_definition (x,id,_,_) when x=s -> Lambda.DAtom id
| _ -> failwith "Bug in find_type"
| exception Symbols.Not_found -> raise Not_found
[@@warning "-32"]
let rec convert_type ty sg =
match ty with
| Abstract_syntax.Type_atom (s,_,_) -> find_atomic_type s sg
| Abstract_syntax.Linear_arrow (ty1,ty2,_) ->
Lambda.LFun (convert_type ty1 sg,convert_type ty2 sg)
| Abstract_syntax.Arrow (ty1,ty2,_) -> Lambda.Fun (convert_type ty1 sg,convert_type ty2 sg)
let abstract_on_dependent_types lst sg=
List.fold_right
(fun x acc -> Lambda.Depend(convert_type x sg,acc))
lst
Lambda.Type
let add_sig_type t e ({size=s;types=syms;ids=ids;_} as sg) =
try
let new_symbols = Symbols.add t e syms in
{sg with
size=s+1;
types=new_symbols;
ids=Id.add s e ids;}
with
| Symbols.Conflict -> raise Duplicate_type_definition
| Id.Conflict -> raise Duplicate_type_definition
let add_sig_term t e ({size=s;terms=syms;ids=ids;_} as sg) =
try
let new_symbols = Symbols.add t e syms in
{sg with size=s+1;terms= new_symbols;ids=Id.add s e ids}
with
| Symbols.Conflict -> raise Duplicate_term_definition
| Id.Conflict -> raise Duplicate_term_definition
let rec expand_type ty ({ids=ids;_} as sg) =
match ty with
| Lambda.Atom _ -> ty
| Lambda.DAtom i ->
(match Id.find i ids with
| Type_definition (_,_,_,ty1) -> expand_type ty1 sg
| _ -> failwith "Bug in expand type")
| Lambda.LFun (ty1,ty2) -> Lambda.LFun(expand_type ty1 sg,expand_type ty2 sg)
| Lambda.Fun (ty1,ty2) -> Lambda.Fun(expand_type ty1 sg,expand_type ty2 sg)
| _ -> failwith "Not yet implemented"
let rec expand_term t ({ids=ids;_} as sg) =
match t with
| (Lambda.Var _| Lambda.LVar _ | Lambda.Const _) -> t
| Lambda.DConst i ->
(match Id.find i ids with
| Term_definition (_,_,_,_,u) -> expand_term u sg
| _ -> failwith "Bug in expand term")
| Lambda.Abs (x,u) -> Lambda.Abs (x,expand_term u sg)
| Lambda.LAbs (x,u) -> Lambda.LAbs (x,expand_term u sg)
| Lambda.App (u,v) -> Lambda.App (expand_term u sg,expand_term v sg)
| _ -> failwith "Not yet implemented"
let unfold_type_definition i ({ids=ids;_} as sg) =
match Id.find i ids with
| Type_definition (_,_,_,ty1) -> expand_type ty1 sg
| _ -> failwith "Bug in unfold_type_definition"
let unfold_term_definition i ({ids=ids;_} as sg) =
match Id.find i ids with
| Term_definition (_,_,_,_,t) -> expand_term t sg
| _ -> failwith "Bug in unfold_term_definition"
let get_type_of_const_id i ({ids=ids;_} as sg) =
match Id.find i ids with
| Term_declaration (_,_,_,ty) -> expand_type ty sg
| Term_definition (_,_,_,ty,_) -> expand_type ty sg
| _ -> failwith "Should be applied only on constants"
| exception Id.Not_found -> failwith "Bug in get_type_of_const_id"
let rec decompose_functional_type ty ({ids=ids;_} as sg) =
match ty with
| Lambda.LFun (ty1,ty2) -> ty1,ty2,Abstract_syntax.Linear
| Lambda.Fun (ty1,ty2) -> ty1,ty2,Abstract_syntax.Non_linear
| Lambda.DAtom i ->
(match Id.find i ids with
| Type_definition (_,_,_,ty1) -> decompose_functional_type ty1 sg
| _ -> failwith "Bug in decompose_functional_type")
| _ -> raise Not_functional_type
let get_binder_argument_functional_type x ({terms=terms;_} as sg) =
let ty =
match Symbols.find x terms with
| Term_declaration (_,_,_,ty) -> ty
| Term_definition (_,_,_,ty,_) -> ty
| _ -> failwith (Printf.sprintf "Bug: Request of the type of the non constant \"%s\"" x) in
try
let ty1,_,_ = decompose_functional_type ty sg in
let _,_,lin = decompose_functional_type ty1 sg in
Some lin
with
| Not_functional_type -> None
let eta_long_form term stype sg =
let expanded_type= expand_type stype sg in
let expanded_term= expand_term term sg in
let res = Lambda.eta_long_form expanded_term expanded_type (fun id -> get_type_of_const_id id sg) in
Log.debug (fun m -> m "term: %s:%s" (term_to_string term sg) (type_to_string stype sg));
Log.debug (fun m -> m "eta_long_form: %s:%s" (term_to_string res sg) (type_to_string expanded_type sg));
res
let unfold t sg = Lambda.normalize (expand_term t sg)
type temp_t=t
module Type_System=Type_system.Type_System.Make(
struct
exception Not_found
type t=temp_t
let expand_type = expand_type
let find_term = find_term
let type_to_string = type_to_string
let term_to_string = term_to_string
end)
let typecheck=Type_System.typecheck
let stamp_declaration sg = {sg with extension_timestamp = Unix.time ()}
let stamp_definition sg = {sg with definition_timestamp = Unix.time ()}
let add_entry e ({size=s;_} as sg) =
match e with
| Abstract_syntax.Type_decl (t,_,Abstract_syntax.K k) ->
stamp_declaration (add_sig_type t (Type_declaration (t,s,abstract_on_dependent_types k sg)) sg)
| Abstract_syntax.Type_def (t,_,ty,Abstract_syntax.K k) ->
stamp_definition (add_sig_type t (Type_definition (t,s,abstract_on_dependent_types k sg,convert_type ty sg)) sg)
| Abstract_syntax.Term_decl (t,behavior,_,ty) ->
let t_type = convert_type ty sg in
let sg_is_2nd_order = sg.is_2nd_order && (Lambda.is_2nd_order t_type (fun i -> unfold_type_definition i sg)) in
stamp_declaration (add_sig_term t (Term_declaration (t,s,behavior,convert_type ty sg)) {sg with is_2nd_order=sg_is_2nd_order})
| Abstract_syntax.Term_def (t,behavior,_,term,ty) ->
let t_type = convert_type ty sg in
let t_term = typecheck term t_type sg in
stamp_definition (add_sig_term t (Term_definition (t,s,behavior,t_type,t_term)) sg)
let is_type s {types=syms;_} =
match Symbols.find s syms with
| Type_declaration _ -> true
| Type_definition _ -> true
| _ -> false
| exception Symbols.Not_found -> false
let is_constant s {terms=syms;_} =
match Symbols.find s syms with
| Term_declaration (_,_,behavior,_) -> true,Some behavior
| Term_definition (_,_,behavior,_,_) -> true,Some behavior
| _ -> false,None
| exception Symbols.Not_found -> false,None
let new_precedence ?before id sg =
match before, sg.max_pred with
| None, (f, None) ->
let p = f +. 1. in
p, {sg with
max_pred = p, Some id;
precedence = Symbols.add id (p,None) sg.precedence}
| None, (f, (Some _ as max)) ->
let p = f +. 1. in
p, {sg with
max_pred = p, Some id;
precedence = Symbols.add id (p,max) sg.precedence}
| Some _, (f, None) ->
let p = f +. 1. in
p, {sg with
max_pred = p, Some id;
precedence = Symbols.add id (p,None) sg.precedence}
| Some upper_bound, _ ->
(match Symbols.find upper_bound sg.precedence with
| f_up, None ->
let f_down = 0. in
let p = (f_up +. f_down)/. 2. in
let new_pred =
Symbols.add ~overwrite:true upper_bound
(f_up,Some id)
(Symbols.add id (p,None) sg.precedence) in
p, {sg with precedence = new_pred}
| f_up, Some lower_bound ->
let f_down,_ = Symbols.find lower_bound sg.precedence in
let p = (f_up +. f_down)/. 2. in
let new_pred =
Symbols.add upper_bound
(f_up,Some id)
(Symbols.add id (p,Some lower_bound) sg.precedence) in
p, {sg with precedence = new_pred}
| exception Not_found -> failwith "Bug: Shouldn't happen")
let add_warnings _ sg = sg
let get_warnings _ = []
[@@warning "-32"]
let raw_to_string t = Lambda.raw_to_string t
[@@warning "-32"]
let behavior_to_string = function
| Abstract_syntax.Default -> ""
| Abstract_syntax.Prefix -> "prefix "
| Abstract_syntax.Infix _ -> "infix "
| Abstract_syntax.Binder -> "binder "
let entry_to_string f decl =
let buff=Buffer.create 10 in
let temp_str_formatter = Format.formatter_of_buffer buff in
let () = Utils.fterm_set_size temp_str_formatter in
let () =
match decl with
| Type_declaration(s,_,k) ->
let () = Utils.fformat temp_str_formatter "@[<hov 4>%s :@ @[%s" s (Lambda.kind_to_string k f) in
Utils.fformat temp_str_formatter "@];@]"
| Type_definition(s,_,k,ty) ->
let () = Utils.fformat temp_str_formatter "@[<hov 4>%s =@ @[" s in
let () = Lambda.type_to_formatted_string temp_str_formatter ty f in
let () = Utils.fformat temp_str_formatter " :@ @[" in
let () = Lambda.kind_to_formatted_string temp_str_formatter k f in
Utils.fformat temp_str_formatter "@];@]@]"
| Term_declaration(s,_,behavior,ty) ->
let () = Utils.fformat temp_str_formatter "@[<hov 4>%s%s :@ @[" (behavior_to_string behavior) s in
let () = Lambda.type_to_formatted_string temp_str_formatter ty f in
Utils.fformat temp_str_formatter "@];@]"
| Term_definition(s,_,behavior,ty,t) ->
let () = Utils.fformat temp_str_formatter "@[<hov 4>%s%s =@ @[" (behavior_to_string behavior) s in
let () = Lambda.term_to_formatted_string temp_str_formatter t f in
let () = Utils.fformat temp_str_formatter " :@ @[" in
let () = Lambda.type_to_formatted_string temp_str_formatter ty f in
Utils.fformat temp_str_formatter "@];@]@]" in
let () = Format.pp_print_flush temp_str_formatter () in
Buffer.contents buff
let entry_to_formatted_string f decl =
let () =
match decl with
| Type_declaration(s,_,k) ->
let () = Utils.sformat "@[<hov 4>%s :@ @[" s in
let () = Lambda.kind_to_formatted_string Format.str_formatter k f in
Utils.sformat "@];@]"
| Type_definition(s,_,k,ty) ->
let () = Utils.sformat "@[<hov 4>%s =@ @[" s in
let () = Lambda.type_to_formatted_string Format.str_formatter ty f in
let () = Utils.sformat " :@ @[" in
let () = Lambda.kind_to_formatted_string Format.str_formatter k f in
Utils.sformat "@];@]@]"
| Term_declaration(s,_,behavior,ty) ->
let () = Utils.sformat "@[<hov 4>%s%s :@ @[" (behavior_to_string behavior) s in
let () = Lambda.type_to_formatted_string Format.str_formatter ty f in
Utils.sformat "@];@]"
| Term_definition(s,_,behavior,ty,t) ->
let () = Utils.sformat "@[<hov 4>%s%s =@ @[" (behavior_to_string behavior) s in
let () = Lambda.term_to_formatted_string Format.str_formatter t f in
let () = Utils.sformat " :@ @[" in
let () = Lambda.type_to_formatted_string Format.str_formatter ty f in
Utils.sformat "@];@]@]" in
()
[@@warning "-32"]
let to_string ({name=n;ids=ids;_} as sg) =
Printf.sprintf "signature %s = \n%send\n"
(fst n)
(fst (Id.fold
(fun _ e (acc,b) ->
match b with
| true -> Printf.sprintf "%s%s\n" acc (entry_to_string (id_to_string sg) e),true
| false -> Printf.sprintf "%s\n" (entry_to_string (id_to_string sg) e),true)
("",false)
ids))
let convert_term t ty sg =
let t_type = convert_type ty sg in
let t=typecheck t t_type sg in
t,t_type
let type_of_constant x {terms=syms;_} =
match Symbols.find x syms with
| Term_declaration (s,_,_,ty) when x = s -> ty
| Term_definition (s,_,_,ty,_) when x = s -> ty
| _ -> failwith "Bug in type_of_constant"
| exception Symbols.Not_found -> failwith "Bug in type_of_constant"
let fold f a {ids=ids;_} =
Id.fold
(fun _ att acc -> f att acc)
a
ids
let is_declared e _ =
match e with
| Type_declaration (s,_,_) -> Some s
| Term_declaration (s,_,_,_) -> Some s
| _ -> None
let is_2nd_order {is_2nd_order;_} = is_2nd_order
let entry_to_data e =
match e with
| Type_declaration (_,id,_) -> Type(Lambda.Atom id)
| Type_definition (_,_,_,stype) -> Type stype
| Term_declaration (_,id,_,stype) -> Term(Lambda.Const id,stype)
| Term_definition (_,_,_,stype,term) -> Term (term,stype)
end
module Table = Table.Make_table(struct let b = 10 end)
module Data_Signature = Make(Tries.Tries)(Table)