1structure SharingTables :> SharingTables = 2struct 3 4open Term Type 5infix |> 6fun x |> f = f x 7 8structure Map = Binarymap 9exception SharingTables of string 10 11type 'a sexppr = 'a -> HOLsexp.t 12 13(* ---------------------------------------------------------------------- 14 string sharing table 15 ---------------------------------------------------------------------- *) 16 17type stringtable = 18 {size : int, map : (string,int) Map.dict, list : string list} 19type id = {Thy : string, Other : string} 20type idtable = {idsize : int, 21 idmap : (id, int) Map.dict, 22 idlist : (int * int) list} 23 24val empty_strtable : stringtable = 25 {size = 0, map = Map.mkDict String.compare, list = []} 26 27local 28 open HOLsexp 29in 30fun enc_strtable (strtable : stringtable) = 31 tagged_encode "string-table" (list_encode String) 32 (List.rev (#list strtable)) 33val dec_strings = 34 Option.map Vector.fromList o 35 tagged_decode "string-table" (list_decode string_decode) 36 37fun enc_idtable (idtable : idtable) = 38 tagged_encode "id-table" (list_encode (pair_encode(Integer,Integer))) 39 (List.rev (#idlist idtable)) 40fun dec_ids strv = 41 Option.map (Vector.fromList o 42 map (fn (i,j) => {Thy = Vector.sub(strv,i), 43 Other = Vector.sub(strv,j)})) o 44 tagged_decode "id-table" (list_decode (pair_decode(int_decode,int_decode))) 45 46end (* local *) 47 48 49fun new_string s (strtable as {size,list,map}:stringtable) = 50 case Map.peek(map, s) of 51 SOME i => (i, strtable) 52 | NONE => (size, {size = size + 1, 53 list = s :: list, 54 map = Map.insert(map,s,size)}) 55 56(* ---------------------------------------------------------------------- 57 IDs (also known as Theory-X pairs, where X is a Name for a constant, 58 or Tyops for types) 59 ---------------------------------------------------------------------- *) 60 61 62fun make_shared_id (id as {Thy,Other} : id) (strtable, idtable) = 63 case Map.peek(#idmap idtable, id) of 64 SOME i => (i, strtable, idtable) 65 | NONE => let 66 val {idsize, idmap, idlist} = idtable 67 val (thyi, strtable) = new_string Thy strtable 68 val (otheri, strtable) = new_string Other strtable 69 in 70 (idsize, strtable, 71 {idsize = idsize + 1, idmap = Map.insert(idmap, id, idsize), 72 idlist = (thyi,otheri) :: idlist}) 73 end 74fun id_compare ({Other = id1, Thy = thy1}, {Other = id2, Thy = thy2}) = 75 case String.compare(id1, id2) of 76 EQUAL => String.compare(thy1, thy2) 77 | x => x 78 79val empty_idtable : idtable = {idsize = 0, 80 idmap = Map.mkDict id_compare, 81 idlist = []} 82 83 84fun build_id_vector strings intpairs = 85 Vector.fromList 86 (map (fn (thyi,otheri) => {Thy = Vector.sub(strings,thyi), 87 Other = Vector.sub(strings,otheri)}) 88 intpairs) 89 90 91(* ---------------------------------------------------------------------- 92 Types 93 ---------------------------------------------------------------------- *) 94 95datatype shared_type = TYV of string 96 | TYOP of int list 97 98type typetable = {tysize : int, 99 tymap : (hol_type, int)Map.dict, 100 tylist : shared_type list} 101 102local 103 open HOLsexp 104in 105fun shared_type_encode (TYV s) = String s 106 | shared_type_encode (TYOP is) = List(map Integer is) 107 108fun shared_type_decode s = 109 case string_decode s of 110 SOME str => SOME (TYV str) 111 | _ => Option.map TYOP (list_decode int_decode s) 112 113val enc_tytable : typetable encoder = 114 tagged_encode "type-table" (list_encode shared_type_encode) o List.rev o 115 #tylist 116 117end (* local *) 118 119fun make_shared_type ty strtable idtable table = 120 case Map.peek(#tymap table, ty) of 121 SOME i => (i, strtable, idtable, table) 122 | NONE => let 123 in 124 if is_vartype ty then let 125 val {tysize, tymap, tylist} = table 126 in 127 (tysize, strtable, idtable, 128 {tysize = tysize + 1, 129 tymap = Map.insert(tymap, ty, tysize), 130 tylist = TYV (dest_vartype ty) :: tylist}) 131 end 132 else let 133 val {Thy, Tyop, Args} = dest_thy_type ty 134 val (id, strtable0, idtable0) = 135 make_shared_id {Thy = Thy, Other = Tyop} (strtable, idtable) 136 fun foldthis (tyarg, (results, strtable, idtable, table)) = let 137 val (result, strtable', idtable', table') = 138 make_shared_type tyarg strtable idtable table 139 in 140 (result::results, strtable', idtable', table') 141 end 142 val (newargs, strtable', idtable', table') = 143 List.foldr foldthis ([], strtable0, idtable0, table) Args 144 val {tysize, tymap, tylist} = table' 145 in 146 (tysize, strtable', idtable', 147 {tysize = tysize + 1, 148 tymap = Map.insert(tymap, ty, tysize), 149 tylist = TYOP (id :: newargs) :: tylist}) 150 end 151 end 152 153val empty_tytable : typetable = 154 {tysize = 0, tymap = Map.mkDict Type.compare, tylist = [] } 155 156fun build_type_vector idv shtylist = let 157 fun build1 (shty, (n, tymap)) = 158 case shty of 159 TYV s => (n + 1, Map.insert(tymap, n, Type.mk_vartype s)) 160 | TYOP idargs => let 161 val (id, Args) = valOf (List.getItem idargs) 162 fun mapthis i = 163 Map.find(tymap, i) 164 handle Map.NotFound => 165 raise SharingTables ("build_type_vector: (" ^ 166 String.concatWith " " 167 (map Int.toString Args) ^ 168 "), " ^ Int.toString i ^ 169 " not found") 170 val args = map mapthis Args 171 val {Thy,Other} = Vector.sub(idv, id) 172 in 173 (n + 1, 174 Map.insert(tymap, n, 175 Type.mk_thy_type {Thy = Thy, Tyop = Other, Args = args})) 176 end 177 val (_, tymap) = 178 List.foldl build1 (0, Map.mkDict Int.compare) shtylist 179in 180 Vector.fromList (map #2 (Map.listItems tymap)) 181end 182 183(* ---------------------------------------------------------------------- 184 Terms 185 ---------------------------------------------------------------------- *) 186 187datatype shared_term = TMV of string * int 188 | TMC of int * int 189 | TMAp of int * int 190 | TMAbs of int * int 191 192type termtable = {termsize : int, 193 termmap : (term, int)Map.dict, 194 termlist : shared_term list} 195 196local 197 open HOLsexp 198in 199fun shared_term_encode stm = 200 case stm of 201 TMV (s,i) => List[String s, Integer i] 202 | TMC (i,j) => List[Integer i, Integer j] 203 | TMAp(i,j) => List[Symbol "ap", Integer i, Integer j] 204 | TMAbs(i,j) => List[Symbol "ab", Integer i, Integer j] 205fun shared_term_decode s = 206 let 207 val (els, last) = strip_list s 208 in 209 if last <> NONE then NONE 210 else 211 case els of 212 [String s, Integer i] => SOME (TMV (s,i)) 213 | [Integer i, Integer j] => SOME (TMC(i,j)) 214 | [Symbol "ap", Integer i, Integer j] => SOME (TMAp(i,j)) 215 | [Symbol "ab", Integer i, Integer j] => SOME (TMAbs(i,j)) 216 | _ => NONE 217 end 218 219val enc_tmtable : termtable encoder = 220 tagged_encode "term-table" (list_encode shared_term_encode) o 221 List.rev o #termlist 222end (* local *) 223 224val empty_termtable : termtable = 225 {termsize = 0, termmap = Map.mkDict Term.compare, termlist = [] } 226 227fun make_shared_term tm (tables as (strtable,idtable,tytable,tmtable)) = 228 case Map.peek(#termmap tmtable, tm) of 229 SOME i => (i, tables) 230 | NONE => let 231 in 232 if is_var tm then let 233 val (s, ty) = dest_var tm 234 val (ty_i, strtable, idtable, tytable) = 235 make_shared_type ty strtable idtable tytable 236 val {termsize, termmap, termlist} = tmtable 237 in 238 (termsize, 239 (strtable, idtable, tytable, 240 {termsize = termsize + 1, 241 termmap = Map.insert(termmap, tm, termsize), 242 termlist = TMV (s, ty_i) :: termlist})) 243 end 244 else if is_const tm then let 245 val {Thy,Name,Ty} = dest_thy_const tm 246 val (id_i, strtable, idtable) = 247 make_shared_id {Thy = Thy, Other = Name} (strtable, idtable) 248 val (ty_i, strtable, idtable, tytable) = 249 make_shared_type Ty strtable idtable tytable 250 val {termsize, termmap, termlist} = tmtable 251 in 252 (termsize, 253 (strtable, idtable, tytable, 254 {termsize = termsize + 1, 255 termmap = Map.insert(termmap, tm, termsize), 256 termlist = TMC (id_i, ty_i) :: termlist})) 257 end 258 else if is_comb tm then let 259 val (f, x) = dest_comb tm 260 val (f_i, tables) = make_shared_term f tables 261 val (x_i, tables) = make_shared_term x tables 262 val (strtable, idtable, tytable, tmtable) = tables 263 val {termsize, termmap, termlist} = tmtable 264 in 265 (termsize, 266 (strtable, idtable, tytable, 267 {termsize = termsize + 1, 268 termmap = Map.insert(termmap, tm, termsize), 269 termlist = TMAp(f_i, x_i) :: termlist})) 270 end 271 else (* must be an abstraction *) let 272 val (v, body) = dest_abs tm 273 val (v_i, tables) = make_shared_term v tables 274 val (body_i, tables) = make_shared_term body tables 275 val (strtable, idtable, tytable, tmtable) = tables 276 val {termsize, termmap, termlist} = tmtable 277 in 278 (termsize, 279 (strtable, idtable, tytable, 280 {termsize = termsize + 1, 281 termmap = Map.insert(termmap, tm, termsize), 282 termlist = TMAbs(v_i, body_i) :: termlist})) 283 end 284 end 285 286fun build_term_vector idv tyv shtmlist = let 287 fun build1 (shtm, (n, tmmap)) = 288 case shtm of 289 TMV (s, tyn) => (n + 1, 290 Map.insert(tmmap, n, mk_var(s, Vector.sub(tyv, tyn)))) 291 | TMC (idn, tyn) => let 292 val {Thy, Other} = Vector.sub(idv, idn) 293 val ty = Vector.sub(tyv, tyn) 294 in 295 (n + 1, Map.insert(tmmap, n, mk_thy_const {Name = Other, Thy = Thy, 296 Ty = ty})) 297 end 298 | TMAp (f_n, xn) => 299 (n + 1, Map.insert(tmmap, n, mk_comb(Map.find(tmmap, f_n), 300 Map.find(tmmap, xn)))) 301 | TMAbs (vn, bodyn) => 302 (n + 1, Map.insert(tmmap, n, mk_abs(Map.find(tmmap, vn), 303 Map.find(tmmap, bodyn)))) 304 val (_, tmmap) = List.foldl build1 (0, Map.mkDict Int.compare) shtmlist 305in 306 Vector.fromList (map #2 (Map.listItems tmmap)) 307end 308 309(* ---------------------------------------------------------------------- 310 sharing table data more abstractly 311 ---------------------------------------------------------------------- *) 312 313type extract_data = 314 {named_terms : (string * Term.term) list, 315 unnamed_terms : Term.term list, 316 named_types : (string * Type.hol_type) list, 317 unnamed_types : Type.hol_type list, 318 theorems : (string * Thm.thm) list} 319 320datatype sharing_data_in = SDI of {strtable : stringtable, 321 idtable : idtable, 322 tytable : typetable, 323 tmtable : termtable, 324 exp : extract_data} 325 326fun empty_in exp = SDI{strtable = empty_strtable, 327 idtable = empty_idtable, 328 tytable = empty_tytable, 329 tmtable = empty_termtable, 330 exp = exp} 331 332fun add_strings strs (SDI {strtable,idtable,tytable,tmtable,exp}) = 333 let fun str1 (s, tab) = #2 (new_string s tab) 334 val strtable = List.foldl str1 strtable strs 335 in 336 SDI{strtable = strtable, idtable = idtable, tytable = tytable, 337 tmtable = tmtable, exp = exp} 338 end 339 340fun add_types tys (SDI{strtable,idtable,tytable,tmtable,exp}) = 341 let 342 fun dotypes (ty, (strtable, idtable, tytable)) = let 343 val (_, strtable, idtable, tytable) = 344 make_shared_type ty strtable idtable tytable 345 in 346 (strtable, idtable, tytable) 347 end 348 val (strtable,idtable,tytable) = 349 List.foldl dotypes (strtable, idtable, tytable) tys 350 in 351 SDI{strtable = strtable, idtable = idtable, tytable = tytable, 352 tmtable = tmtable, exp = exp} 353 end 354 355fun add_terms tms (SDI{strtable,idtable,tytable,tmtable,exp}) = 356 let 357 val tms = Term.all_atomsl tms empty_tmset |> HOLset.listItems 358 val (strtable,idtable,tytable,tmtable) = 359 List.foldl (fn (t,tables) => #2 (make_shared_term t tables)) 360 (strtable,idtable,tytable,tmtable) 361 tms 362 in 363 SDI{strtable = strtable, idtable = idtable, tytable = tytable, 364 tmtable = tmtable, exp = exp} 365 end 366 367fun thm_atoms acc th = Term.all_atomsl (Thm.concl th :: Thm.hyp th) acc 368 369fun thml_atoms thlist acc = 370 case thlist of 371 [] => acc 372 | (th::ths) => thml_atoms ths (thm_atoms acc th) 373 374fun enc_dep findstr ((s,n),dl) = 375 let open HOLsexp 376 fun f (thy,l) = Cons(findstr thy, list_encode Integer l) 377 in 378 list_encode f ((s,[n]) :: dl) 379 end 380 381fun dest_dep d = 382 case d of 383 Dep.DEP_SAVED (did,thydl) => (did,thydl) 384 | Dep.DEP_UNSAVED dl => raise SharingTables "Can't encode unsaved dep" 385 386fun enc_tag findstr tag = 387 let open HOLsexp 388 val dep = Tag.dep_of tag 389 val ocl = #1 (Tag.dest_tag tag) 390 in 391 pair_encode(enc_dep findstr o dest_dep, list_encode String) (dep,ocl) 392 end 393 394fun thm_strings th = 395 let val (sn, dl) = dest_dep (Tag.dep_of (Thm.tag th) ) 396 in 397 #1 sn :: map #1 dl 398 end 399 400fun build_sharing_data (ed : extract_data) = 401 let 402 val {named_types, named_terms, unnamed_types, unnamed_terms, theorems} = 403 ed 404 val sdi = empty_in ed 405 |> add_types (map #2 named_types) 406 |> add_types unnamed_types 407 val tm_atoms = 408 thml_atoms (map #2 theorems) empty_tmset 409 |> Term.all_atomsl (unnamed_terms @ map #2 named_terms) 410 in 411 sdi |> add_terms (HOLset.listItems tm_atoms) 412 |> add_strings (map #1 theorems) 413 |> add_strings (List.concat (map (thm_strings o #2) theorems)) 414 end 415 416fun write_string (SDI{strtable,...}) s = 417 Map.find(#map strtable,s) 418 handle Map.NotFound => 419 raise SharingTables ("write_string: can't find \"" ^ s ^ "\"") 420fun write_type (SDI{tytable,...}) ty = 421 Map.find(#tymap tytable,ty) 422fun write_term (SDI{tmtable,...}) = 423 Term.write_raw (fn t => Map.find(#termmap tmtable,t)) 424 handle Map.NotFound => raise SharingTables "write_term: can't find term" 425 426 427fun enc_sdata (sd as SDI{strtable,idtable,tytable,tmtable,exp}) = 428 let 429 open HOLsexp 430 val {unnamed_types,named_types,unnamed_terms,named_terms,theorems} = exp 431 val find_str = Integer o write_string sd 432 val ty_encode = Integer o write_type sd 433 val tm_encode = String o write_term sd 434 435 fun enc_thm(s,th) = 436 let 437 val (tag, asl, w) = (Thm.tag th, Thm.hyp th, Thm.concl th) 438 val i = Map.find(#map strtable, s) 439 in 440 pair3_encode (Integer,enc_tag find_str,list_encode tm_encode) 441 (i, tag, w::asl) 442 end 443 in 444 445 tagged_encode "core-data" ( 446 pair_encode ( 447 tagged_encode "tables" ( 448 pair4_encode(enc_strtable,enc_idtable,enc_tytable,enc_tmtable) 449 ), 450 tagged_encode "exports" ( 451 pair3_encode( 452 pair_encode( (* types *) 453 list_encode ty_encode, 454 list_encode (pair_encode(String,ty_encode)) 455 ), 456 pair_encode( (* terms *) 457 list_encode tm_encode, 458 list_encode (pair_encode(String,tm_encode)) 459 ), 460 list_encode enc_thm 461 ) 462 ) 463 ) 464 ) ((strtable,idtable,tytable,tmtable), 465 ((unnamed_types, named_types), (unnamed_terms, named_terms), theorems)) 466 end 467 468type sharing_data_out = 469 (string Vector.vector * id Vector.vector * Type.hol_type Vector.vector * 470 Term.term Vector.vector * extract_data) 471 472 473type 'a depinfo = {head : 'a * int, deps : ('a * int list) list} 474fun mapdepinfo f ({head = (a,i),deps}:'a depinfo) : 'b depinfo = 475 {head = (f a, i), deps = map (fn (a,l) => (f a, l)) deps} 476 477fun read_thm strv tmvector {name,depinfo:int depinfo,tagnames,encoded_hypscon} = 478 let 479 val depinfo = mapdepinfo (fn i => Vector.sub(strv,i)) depinfo 480 val dd = (#head depinfo, #deps depinfo) 481 val terms = map (Term.read_raw tmvector) encoded_hypscon 482 in 483 (Vector.sub(strv, name), Thm.disk_thm((dd,tagnames), terms)) 484 end 485 486val dep_decode = let 487 open HOLsexp 488 fun depmunge dilist = 489 case dilist of 490 [] => NONE 491 | (n,[i]) :: rest => SOME{head = (n,i), deps = rest} 492 | _ => NONE 493in 494 Option.mapPartial depmunge o 495 list_decode (pair_decode(int_decode, list_decode int_decode)) 496end 497val deptag_decode = let open HOLsexp in 498 pair_decode(dep_decode, list_decode string_decode) 499 end 500val thm_decode = 501 let 502 open HOLsexp 503 fun thmmunge(i,(di,tags),tms) = 504 {name = i, depinfo = di, tagnames = tags, encoded_hypscon = tms} 505 in 506 Option.map thmmunge o 507 pair3_decode (int_decode, deptag_decode, list_decode string_decode) 508 end 509 510val prsexp = HOLPP.pp_to_string 70 HOLsexp.printer 511fun force s dec t = 512 case dec t of 513 NONE => raise SharingTables ("Couldn't decode \""^s^"\": "^prsexp t) 514 | SOME t => t 515 516fun dec_sdata {with_strings,with_stridty} t = 517 let 518 open HOLsexp 519 val decoder = 520 tagged_decode "core-data" ( 521 pair_decode( 522 tagged_decode "tables" ( 523 pair4_decode( 524 dec_strings, 525 tagged_decode "id-table" 526 (list_decode (pair_decode(int_decode, int_decode))), 527 tagged_decode "type-table" (list_decode shared_type_decode), 528 tagged_decode "term-table" (list_decode shared_term_decode) 529 ) 530 ), 531 tagged_decode "exports" ( 532 pair3_decode( 533 pair_decode( (* types *) 534 list_decode int_decode, 535 list_decode (pair_decode(string_decode, int_decode)) 536 ), 537 pair_decode( (* terms *) 538 list_decode string_decode, 539 list_decode (pair_decode(string_decode, string_decode)) 540 ), 541 (* theorems *) list_decode thm_decode 542 ) 543 ) 544 ) 545 ) 546 in 547 case decoder t of 548 NONE => NONE 549 | SOME ((strv,intplist,shtylist,shtmlist), 550 ((raw_untys, raw_nmtys), (raw_untms, raw_nmtms), rawthms)) => 551 let 552 fun sub v i = Vector.sub(v,i) 553 val _ = with_strings (fn i => Vector.sub(strv,i)) 554 val idv = build_id_vector strv intplist 555 val tyv = build_type_vector idv shtylist 556 val _ = with_stridty (sub strv, sub idv, tyv) 557 val tmv = build_term_vector idv tyv shtmlist 558 val untys = map (fn i => Vector.sub(tyv,i)) raw_untys 559 val nmtys = map (fn (s,i) => (s, Vector.sub(tyv,i))) raw_nmtys 560 val untms = map (Term.read_raw tmv) raw_untms 561 val nmtms = map (fn (nm,s) => (nm, Term.read_raw tmv s)) raw_nmtms 562 val thms = map (read_thm strv tmv) rawthms 563 in 564 SOME (strv,idv,tyv,tmv, 565 {named_types = nmtys, unnamed_types = untys, 566 named_terms = nmtms, unnamed_terms = untms, 567 theorems = thms}) 568 end 569 end 570 571fun export_from_sharing_data (_, _, _, _, exp) = exp 572fun read_term (_,_,_,tmv,_) = Term.read_raw tmv 573fun read_string (strv,_,_,_,_) i = Vector.sub(strv,i) 574 575end; (* struct *) 576