33 |
33 |
34 (** code extraction **) |
34 (** code extraction **) |
35 |
35 |
36 (* theory data *) |
36 (* theory data *) |
37 |
37 |
38 type appgen = theory -> ((sort -> sort) * Sorts.algebra) * Consts.T |
|
39 -> CodegenFuncgr.T |
|
40 -> bool * string list option |
|
41 -> (string * typ) * term list -> CodegenThingol.transact -> iterm * CodegenThingol.transact; |
|
42 |
|
43 type appgens = (int * (appgen * stamp)) Symtab.table; |
|
44 |
|
45 fun merge_appgens (x : appgens * appgens) = |
|
46 Symtab.merge (fn ((bounds1, (_, stamp1)), (bounds2, (_, stamp2))) => |
|
47 bounds1 = bounds2 andalso stamp1 = stamp2) x; |
|
48 |
|
49 structure Code = CodeDataFun |
38 structure Code = CodeDataFun |
50 (struct |
39 (struct |
51 val name = "Pure/code"; |
40 val name = "Pure/code"; |
52 type T = CodegenThingol.code; |
41 type T = CodegenThingol.code; |
53 val empty = CodegenThingol.empty_code; |
42 val empty = CodegenThingol.empty_code; |
54 fun merge _ = CodegenThingol.merge_code; |
43 fun merge _ = CodegenThingol.merge_code; |
55 fun purge _ _ = CodegenThingol.empty_code; |
44 fun purge _ NONE _ = CodegenThingol.empty_code |
|
45 | purge NONE _ _ = CodegenThingol.empty_code |
|
46 | purge (SOME thy) (SOME cs) code = |
|
47 let |
|
48 val cs_exisiting = |
|
49 map_filter (CodegenNames.const_rev thy) (Graph.keys code); |
|
50 in |
|
51 Graph.del_nodes |
|
52 ((Graph.all_succs code |
|
53 o map (CodegenNames.const thy) |
|
54 o filter (member CodegenConsts.eq_const cs_exisiting) |
|
55 ) cs) |
|
56 code |
|
57 end; |
56 end); |
58 end); |
|
59 |
|
60 type appgen = theory -> ((sort -> sort) * Sorts.algebra) * Consts.T |
|
61 -> CodegenFuncgr.T |
|
62 -> bool * string list option |
|
63 -> (string * typ) * term list -> CodegenThingol.transact -> iterm * CodegenThingol.transact; |
|
64 |
|
65 type appgens = (int * (appgen * stamp)) Symtab.table; |
|
66 val merge_appgens : appgens * appgens -> appgens = |
|
67 Symtab.merge (fn ((bounds1, (_, stamp1)), (bounds2, (_, stamp2))) => |
|
68 bounds1 = bounds2 andalso stamp1 = stamp2); |
|
69 |
|
70 structure Consttab = CodegenConsts.Consttab; |
|
71 type abstypes = typ Symtab.table * CodegenConsts.const Consttab.table; |
|
72 fun merge_abstypes ((typs1, consts1) : abstypes, (typs2, consts2) : abstypes) = |
|
73 (Symtab.merge (Type.eq_type Vartab.empty) (typs1, typs2), |
|
74 Consttab.merge CodegenConsts.eq_const (consts1, consts2)); |
57 |
75 |
58 structure CodegenPackageData = TheoryDataFun |
76 structure CodegenPackageData = TheoryDataFun |
59 (struct |
77 (struct |
60 val name = "Pure/codegen_package"; |
78 val name = "Pure/codegen_package"; |
61 type T = appgens; |
79 type T = appgens * abstypes; |
62 val empty = Symtab.empty; |
80 val empty = (Symtab.empty, (Symtab.empty, Consttab.empty)); |
63 val copy = I; |
81 val copy = I; |
64 val extend = I; |
82 val extend = I; |
65 fun merge _ = merge_appgens; |
83 fun merge _ ((appgens1, abstypes1), (appgens2, abstypes2)) = |
|
84 (merge_appgens (appgens1, appgens2), merge_abstypes (abstypes1, abstypes2)); |
66 fun print _ _ = (); |
85 fun print _ _ = (); |
67 end); |
86 end); |
68 |
87 |
69 val _ = Context.add_setup (Code.init #> CodegenPackageData.init); |
88 val _ = Context.add_setup (Code.init #> CodegenPackageData.init); |
70 |
89 |
71 |
90 |
72 (* extraction kernel *) |
91 (* extraction kernel *) |
73 |
92 |
74 fun check_strict has_seri x (false, _) = |
93 fun check_strict (false, _) has_seri x = |
75 false |
94 false |
76 | check_strict has_seri x (_, SOME targets) = |
95 | check_strict (_, SOME targets) has_seri x = |
77 not (has_seri targets x) |
96 not (has_seri targets x) |
78 | check_strict has_seri x (true, _) = |
97 | check_strict (true, _) has_seri x = |
79 true; |
98 true; |
|
99 |
|
100 fun get_abstype thy (tyco, tys) = case Symtab.lookup ((fst o snd o CodegenPackageData.get) thy) tyco |
|
101 of SOME ty => SOME ((map_atyps (fn TFree (n, _) => nth tys (the (Int.fromString n)))) ty) |
|
102 | NONE => NONE; |
80 |
103 |
81 fun ensure_def_class thy (algbr as ((proj_sort, _), _)) funcgr strct class trns = |
104 fun ensure_def_class thy (algbr as ((proj_sort, _), _)) funcgr strct class trns = |
82 let |
105 let |
83 val (v, cs) = (ClassPackage.the_consts_sign thy) class; |
106 val (v, cs) = (ClassPackage.the_consts_sign thy) class; |
84 val superclasses = (proj_sort o Sign.super_classes thy) class; |
107 val superclasses = (proj_sort o Sign.super_classes thy) class; |
137 trns |
160 trns |
138 |> exprgen_type thy algbr funcgr strct t1 |
161 |> exprgen_type thy algbr funcgr strct t1 |
139 ||>> exprgen_type thy algbr funcgr strct t2 |
162 ||>> exprgen_type thy algbr funcgr strct t2 |
140 |-> (fn (t1', t2') => pair (t1' `-> t2')) |
163 |-> (fn (t1', t2') => pair (t1' `-> t2')) |
141 | exprgen_type thy algbr funcgr strct (Type (tyco, tys)) trns = |
164 | exprgen_type thy algbr funcgr strct (Type (tyco, tys)) trns = |
142 trns |
165 case get_abstype thy (tyco, tys) |
143 |> ensure_def_tyco thy algbr funcgr strct tyco |
166 of SOME ty => |
144 ||>> fold_map (exprgen_type thy algbr funcgr strct) tys |
167 trns |
145 |-> (fn (tyco, tys) => pair (tyco `%% tys)); |
168 |> exprgen_type thy algbr funcgr strct ty |
|
169 | NONE => |
|
170 trns |
|
171 |> ensure_def_tyco thy algbr funcgr strct tyco |
|
172 ||>> fold_map (exprgen_type thy algbr funcgr strct) tys |
|
173 |-> (fn (tyco, tys) => pair (tyco `%% tys)); |
146 |
174 |
147 exception CONSTRAIN of (string * typ) * typ; |
175 exception CONSTRAIN of (string * typ) * typ; |
148 |
176 |
149 fun exprgen_typinst thy (algbr as ((proj_sort, algebra), consts)) funcgr strct (ty_ctxt, sort_decl) trns = |
177 fun exprgen_typinst thy (algbr as ((proj_sort, algebra), consts)) funcgr strct (ty_ctxt, sort_decl) trns = |
150 let |
178 let |
316 ||>> exprgen_typinst_const thy algbr funcgr strct (c, ty) |
345 ||>> exprgen_typinst_const thy algbr funcgr strct (c, ty) |
317 ||>> fold_map (exprgen_term thy algbr funcgr strct) ts |
346 ||>> fold_map (exprgen_term thy algbr funcgr strct) ts |
318 |-> (fn (((c, ty), iss), ts) => |
347 |-> (fn (((c, ty), iss), ts) => |
319 pair (IConst (c, (iss, ty)) `$$ ts)) |
348 pair (IConst (c, (iss, ty)) `$$ ts)) |
320 and select_appgen thy algbr funcgr strct ((c, ty), ts) trns = |
349 and select_appgen thy algbr funcgr strct ((c, ty), ts) trns = |
321 case Symtab.lookup (CodegenPackageData.get thy) c |
350 case Symtab.lookup (fst (CodegenPackageData.get thy)) c |
322 of SOME (i, (appgen, _)) => |
351 of SOME (i, (appgen, _)) => |
323 if length ts < i then |
352 if length ts < i then |
324 let |
353 let |
325 val tys = Library.take (i - length ts, ((fst o strip_type) ty)); |
354 val tys = Library.take (i - length ts, ((fst o strip_type) ty)); |
326 val vs = Name.names (Name.declare c Name.context) "a" tys; |
355 val vs = Name.names (Name.declare c Name.context) "a" tys; |
413 ), e0)) |
442 ), e0)) |
414 | (_, e0) => pair e0); |
443 | (_, e0) => pair e0); |
415 |
444 |
416 fun add_appconst (c, appgen) thy = |
445 fun add_appconst (c, appgen) thy = |
417 let |
446 let |
418 val i = (length o fst o strip_type o Sign.the_const_type thy) c |
447 val i = (length o fst o strip_type o Sign.the_const_type thy) c; |
419 in CodegenPackageData.map (Symtab.update (c, (i, (appgen, stamp ())))) thy end; |
448 val _ = Code.change thy (K CodegenThingol.empty_code); |
|
449 in |
|
450 (CodegenPackageData.map o apfst) |
|
451 (Symtab.update (c, (i, (appgen, stamp ())))) thy |
|
452 end; |
|
453 |
|
454 |
|
455 |
|
456 (** abstype and constsubst interface **) |
|
457 |
|
458 fun gen_abstyp prep_const prep_typ (raw_abstyp, raw_substtyp) raw_absconsts thy = |
|
459 let |
|
460 val abstyp = Type.no_tvars (prep_typ thy raw_abstyp); |
|
461 val substtyp = Type.no_tvars (prep_typ thy raw_substtyp); |
|
462 val absconsts = (map o pairself) (prep_const thy) raw_absconsts; |
|
463 val Type (abstyco, tys) = abstyp handle BIND => error ("bad type: " ^ Sign.string_of_typ thy abstyp); |
|
464 val typarms = map (fst o dest_TFree) tys handle MATCH => error ("bad type: " ^ Sign.string_of_typ thy abstyp); |
|
465 fun mk_index v = |
|
466 let |
|
467 val k = find_index (fn w => v = w) typarms; |
|
468 in if k = ~1 |
|
469 then error ("free type variable: " ^ quote v) |
|
470 else TFree (string_of_int k, []) |
|
471 end; |
|
472 val typpat = map_atyps (fn TFree (v, _) => mk_index v) substtyp; |
|
473 fun apply_typpat (Type (tyco, tys)) = |
|
474 let |
|
475 val tys' = map apply_typpat tys; |
|
476 in if tyco = abstyco then |
|
477 (map_atyps (fn TFree (n, _) => nth tys' (the (Int.fromString n)))) typpat |
|
478 else |
|
479 Type (tyco, tys') |
|
480 end |
|
481 | apply_typpat ty = ty; |
|
482 val string_of_typ = setmp show_sorts true (Sign.string_of_typ thy); |
|
483 fun add_consts (c1, c2) = |
|
484 let |
|
485 val _ = if CodegenNames.has_nsp CodegenNames.nsp_fun (CodegenNames.const thy c2) |
|
486 then () |
|
487 else error ("not a function: " ^ CodegenConsts.string_of_const thy c2); |
|
488 val funcgr = CodegenFuncgr.mk_funcgr thy [c1, c2] []; |
|
489 val ty_map = CodegenFuncgr.get_func_typs funcgr; |
|
490 val ty1 = (apply_typpat o the o AList.lookup CodegenConsts.eq_const ty_map) c1; |
|
491 val ty2 = (the o AList.lookup CodegenConsts.eq_const ty_map) c2; |
|
492 val _ = if Sign.typ_equiv thy (ty1, ty2) then () else |
|
493 error ("Incompatiable type signatures of " ^ CodegenConsts.string_of_const thy c1 |
|
494 ^ " and " ^ CodegenConsts.string_of_const thy c2 ^ ":\n" |
|
495 ^ string_of_typ ty1 ^ "\n" ^ string_of_typ ty2); |
|
496 in Consttab.update (c1, c2) end; |
|
497 val _ = Code.change thy (K CodegenThingol.empty_code); |
|
498 in |
|
499 thy |
|
500 |> (CodegenPackageData.map o apsnd) (fn (abstypes, abscs) => |
|
501 (abstypes |
|
502 |> Symtab.update (abstyco, typpat), |
|
503 abscs |
|
504 |> fold add_consts absconsts) |
|
505 ) |
|
506 end; |
|
507 |
|
508 fun gen_constsubst prep_const raw_constsubsts thy = |
|
509 let |
|
510 val constsubsts = (map o pairself) (prep_const thy) raw_constsubsts; |
|
511 val string_of_typ = setmp show_sorts true (Sign.string_of_typ thy); |
|
512 fun add_consts (c1, c2) = |
|
513 let |
|
514 val _ = if CodegenNames.has_nsp CodegenNames.nsp_fun (CodegenNames.const thy c2) |
|
515 then () |
|
516 else error ("not a function: " ^ CodegenConsts.string_of_const thy c2); |
|
517 val funcgr = CodegenFuncgr.mk_funcgr thy [c1, c2] []; |
|
518 val ty_map = CodegenFuncgr.get_func_typs funcgr; |
|
519 val ty1 = (the o AList.lookup CodegenConsts.eq_const ty_map) c1; |
|
520 val ty2 = (the o AList.lookup CodegenConsts.eq_const ty_map) c2; |
|
521 val _ = if Sign.typ_equiv thy (ty1, ty2) then () else |
|
522 error ("Incompatiable type signatures of " ^ CodegenConsts.string_of_const thy c1 |
|
523 ^ " and " ^ CodegenConsts.string_of_const thy c2 ^ ":\n" |
|
524 ^ string_of_typ ty1 ^ "\n" ^ string_of_typ ty2); |
|
525 in Consttab.update (c1, c2) end; |
|
526 val _ = Code.change thy (K CodegenThingol.empty_code); |
|
527 in |
|
528 thy |
|
529 |> (CodegenPackageData.map o apsnd o apsnd) (fold add_consts constsubsts) |
|
530 end; |
|
531 |
|
532 val abstyp = gen_abstyp CodegenConsts.norm Sign.certify_typ; |
|
533 val abstyp_e = gen_abstyp CodegenConsts.read_const (fn thy => Sign.read_typ (thy, K NONE)); |
|
534 |
|
535 val constsubst = gen_constsubst CodegenConsts.norm; |
|
536 val constsubst_e = gen_constsubst CodegenConsts.read_const; |
420 |
537 |
421 |
538 |
422 |
539 |
423 (** code generation interfaces **) |
540 (** code generation interfaces **) |
424 |
541 |
425 fun generate thy (cs, rhss) targets init gen it = |
542 fun generate thy (cs, rhss) targets init gen it = |
426 let |
543 let |
427 val funcgr = CodegenFuncgr.mk_funcgr thy cs rhss; |
544 val raw_funcgr = CodegenFuncgr.mk_funcgr thy cs rhss; |
428 val qnaming = NameSpace.qualified_names NameSpace.default_naming |
545 val cs' = map_filter (Consttab.lookup ((snd o snd o CodegenPackageData.get) thy)) |
|
546 (CodegenFuncgr.Constgraph.keys raw_funcgr); |
|
547 val funcgr = CodegenFuncgr.mk_funcgr thy cs' []; |
|
548 val qnaming = NameSpace.qualified_names NameSpace.default_naming; |
429 val algebr = ClassPackage.operational_algebra thy; |
549 val algebr = ClassPackage.operational_algebra thy; |
430 val consttab = Consts.empty |
550 val consttab = Consts.empty |
431 |> fold (fn (c, ty) => Consts.declare qnaming |
551 |> fold (fn (c, ty) => Consts.declare qnaming |
432 ((CodegenNames.const thy c, ty), true)) |
552 ((CodegenNames.const thy c, ty), true)) |
433 (CodegenFuncgr.get_func_typs funcgr) |
553 (CodegenFuncgr.get_func_typs funcgr); |
434 val algbr = (algebr, consttab); |
554 val algbr = (algebr, consttab); |
435 in |
555 in |
436 Code.change_yield thy (CodegenThingol.start_transact init (gen thy algbr funcgr |
556 Code.change_yield thy (CodegenThingol.start_transact init (gen thy algbr funcgr |
437 (true, targets) it)) |
557 (true, targets) it)) |
438 |> (fn (x, modl) => x) |
558 |> (fn (x, modl) => x) |
502 val code = Code.get thy; |
622 val code = Code.get thy; |
503 in |
623 in |
504 (map (serialize' cs code) seris'; ()) |
624 (map (serialize' cs code) seris'; ()) |
505 end; |
625 end; |
506 |
626 |
507 fun reader_tyco thy rhss target dep = |
627 val (codeK, code_abstypeK, code_constsubstK) = |
508 generate thy rhss (SOME [target]) (SOME dep) (fold_map oooo exprgen_type); |
628 ("code_gen", "code_abstype", "code_constsubst"); |
509 |
|
510 fun reader_const thy rhss target dep = |
|
511 generate thy rhss (SOME [target]) (SOME dep) (fold_map oooo exprgen_term'); |
|
512 |
|
513 fun zip_list (x::xs) f g = |
|
514 f x #-> (fn y => fold_map (fn x => g |-- f x >> pair x) xs |
|
515 #-> (fn xys => pair ((x, y) :: xys))); |
|
516 |
|
517 fun parse_multi_syntax parse_thing parse_syntax = |
|
518 P.and_list1 parse_thing |
|
519 #-> (fn things => Scan.repeat1 (P.$$$ "(" |-- P.name :-- |
|
520 (fn target => zip_list things (parse_syntax target) |
|
521 (P.$$$ "and")) --| P.$$$ ")")) |
|
522 |
|
523 |
629 |
524 in |
630 in |
525 |
|
526 val (codeK, |
|
527 syntax_classK, syntax_instK, syntax_tycoK, syntax_constK) = |
|
528 ("code_gen", |
|
529 "code_class", "code_instance", "code_type", "code_const"); |
|
530 |
631 |
531 val codeP = |
632 val codeP = |
532 OuterSyntax.improper_command codeK "generate and serialize executable code for constants" K.diag ( |
633 OuterSyntax.improper_command codeK "generate and serialize executable code for constants" K.diag ( |
533 Scan.repeat P.term |
634 Scan.repeat P.term |
534 -- Scan.repeat (P.$$$ "(" |-- |
635 -- Scan.repeat (P.$$$ "(" |-- |
535 P.name -- P.arguments |
636 P.name -- P.arguments |
536 --| P.$$$ ")") |
637 --| P.$$$ ")") |
537 >> (fn (raw_cs, seris) => Toplevel.keep (code raw_cs seris o Toplevel.theory_of)) |
638 >> (fn (raw_cs, seris) => Toplevel.keep (code raw_cs seris o Toplevel.theory_of)) |
538 ); |
639 ); |
539 |
640 |
540 val syntax_classP = |
641 val code_abstypeP = |
541 OuterSyntax.command syntax_classK "define code syntax for class" K.thy_decl ( |
642 OuterSyntax.command code_abstypeK "axiomatic abstypes for code generation" K.thy_decl ( |
542 parse_multi_syntax P.xname |
643 (P.typ -- P.typ -- Scan.optional (P.$$$ "where" |-- Scan.repeat1 |
543 (fn _ => fn _ => P.string -- Scan.optional (P.$$$ "where" |-- Scan.repeat1 |
644 (P.term --| (P.$$$ "\\<equiv>" || P.$$$ "==") -- P.term)) []) |
544 (P.term --| (P.$$$ "\\<equiv>" || P.$$$ "==") -- P.string)) []) |
645 >> (Toplevel.theory o uncurry abstyp_e) |
545 >> (Toplevel.theory oo fold) (fn (target, syns) => |
|
546 fold (fn (raw_class, syn) => CodegenSerializer.add_syntax_class target raw_class syn) syns) |
|
547 ); |
646 ); |
548 |
647 |
549 val syntax_instP = |
648 val code_constsubstP = |
550 OuterSyntax.command syntax_instK "define code syntax for instance" K.thy_decl ( |
649 OuterSyntax.command code_constsubstK "axiomatic constant substitutions for code generation" K.thy_decl ( |
551 parse_multi_syntax (P.xname --| P.$$$ "::" -- P.xname) |
650 Scan.repeat1 (P.term --| (P.$$$ "\\<equiv>" || P.$$$ "==") -- P.term) |
552 (fn _ => fn _ => P.name #-> |
651 >> (Toplevel.theory o constsubst_e) |
553 (fn "-" => Scan.succeed () | _ => Scan.fail_with (fn _ => "\"-\" expected") ())) |
|
554 >> (Toplevel.theory oo fold) (fn (target, syns) => |
|
555 fold (fn (raw_inst, ()) => CodegenSerializer.add_syntax_inst target raw_inst) syns) |
|
556 ); |
652 ); |
557 |
653 |
558 val syntax_tycoP = |
654 val _ = OuterSyntax.add_parsers [codeP, code_abstypeP, code_constsubstP]; |
559 OuterSyntax.command syntax_tycoK "define code syntax for type constructor" K.thy_decl ( |
|
560 Scan.repeat1 ( |
|
561 parse_multi_syntax P.xname (CodegenSerializer.parse_syntax_tyco reader_tyco) |
|
562 ) |
|
563 >> (Toplevel.theory o (fold o fold) (fold snd o snd)) |
|
564 ); |
|
565 |
|
566 val syntax_constP = |
|
567 OuterSyntax.command syntax_constK "define code syntax for constant" K.thy_decl ( |
|
568 Scan.repeat1 ( |
|
569 parse_multi_syntax P.term (CodegenSerializer.parse_syntax_const reader_const) |
|
570 ) |
|
571 >> (Toplevel.theory o (fold o fold) (fold snd o snd)) |
|
572 ); |
|
573 |
|
574 val _ = OuterSyntax.add_parsers [codeP, |
|
575 syntax_classP, syntax_instP, syntax_tycoP, syntax_constP]; |
|
576 |
655 |
577 end; (* local *) |
656 end; (* local *) |
578 |
657 |
579 end; (* struct *) |
658 end; (* struct *) |