346 | pr_typ fxy (ITyVar v) = |
343 | pr_typ fxy (ITyVar v) = |
347 str ("'" ^ v); |
344 str ("'" ^ v); |
348 fun pr_term vars fxy (IConst c) = |
345 fun pr_term vars fxy (IConst c) = |
349 pr_app vars fxy (c, []) |
346 pr_app vars fxy (c, []) |
350 | pr_term vars fxy (IVar v) = |
347 | pr_term vars fxy (IVar v) = |
351 str (lookup_var vars v) |
348 str (CodegenThingol.lookup_var vars v) |
352 | pr_term vars fxy (t as t1 `$ t2) = |
349 | pr_term vars fxy (t as t1 `$ t2) = |
353 (case CodegenThingol.unfold_const_app t |
350 (case CodegenThingol.unfold_const_app t |
354 of SOME c_ts => pr_app vars fxy c_ts |
351 of SOME c_ts => pr_app vars fxy c_ts |
355 | NONE => |
352 | NONE => |
356 brackify fxy [pr_term vars NOBR t1, pr_term vars BR t2]) |
353 brackify fxy [pr_term vars NOBR t1, pr_term vars BR t2]) |
357 | pr_term vars fxy (t as _ `|-> _) = |
354 | pr_term vars fxy (t as _ `|-> _) = |
358 let |
355 let |
359 val (ps, t') = CodegenThingol.unfold_abs t; |
356 val (ps, t') = CodegenThingol.unfold_abs t; |
360 fun pr ((v, NONE), _) vars = |
357 fun pr ((v, NONE), _) vars = |
361 let |
358 let |
362 val vars' = intro_vars [v] vars; |
359 val vars' = CodegenThingol.intro_vars [v] vars; |
363 in |
360 in |
364 ((Pretty.block o Pretty.breaks) [str "fn", str (lookup_var vars' v), str "=>"], vars') |
361 ((Pretty.block o Pretty.breaks) [str "fn", str (CodegenThingol.lookup_var vars' v), str "=>"], vars') |
365 end |
362 end |
366 | pr ((v, SOME p), _) vars = |
363 | pr ((v, SOME p), _) vars = |
367 let |
364 let |
368 val vs = CodegenThingol.fold_varnames (insert (op =)) p [v]; |
365 val vs = CodegenThingol.fold_varnames (insert (op =)) p [v]; |
369 val vars' = intro_vars vs vars; |
366 val vars' = CodegenThingol.intro_vars vs vars; |
370 in |
367 in |
371 ((Pretty.block o Pretty.breaks) [str "fn", str (lookup_var vars' v), str "as", |
368 ((Pretty.block o Pretty.breaks) [str "fn", str (CodegenThingol.lookup_var vars' v), str "as", |
372 pr_term vars' NOBR p, str "=>"], vars') |
369 pr_term vars' NOBR p, str "=>"], vars') |
373 end; |
370 end; |
374 val (ps', vars') = fold_map pr ps vars; |
371 val (ps', vars') = fold_map pr ps vars; |
375 in brackify BR (ps' @ [pr_term vars' NOBR t']) end |
372 in brackify BR (ps' @ [pr_term vars' NOBR t']) end |
376 | pr_term vars fxy (INum n) = |
373 | pr_term vars fxy (INum n) = |
653 brackify fxy [ |
650 brackify fxy [ |
654 pr_term vars NOBR t1, |
651 pr_term vars NOBR t1, |
655 pr_term vars BR t2 |
652 pr_term vars BR t2 |
656 ]) |
653 ]) |
657 | pr_term vars fxy (IVar v) = |
654 | pr_term vars fxy (IVar v) = |
658 (str o lookup_var vars) v |
655 (str o CodegenThingol.lookup_var vars) v |
659 | pr_term vars fxy (t as _ `|-> _) = |
656 | pr_term vars fxy (t as _ `|-> _) = |
660 let |
657 let |
661 val (ps, t') = CodegenThingol.unfold_abs t; |
658 val (ps, t') = CodegenThingol.unfold_abs t; |
662 fun pr ((v, SOME p), _) vars = |
659 fun pr ((v, SOME p), _) vars = |
663 let |
660 let |
664 val vs = CodegenThingol.fold_varnames (insert (op =)) p [v]; |
661 val vs = CodegenThingol.fold_varnames (insert (op =)) p [v]; |
665 val vars' = intro_vars vs vars; |
662 val vars' = CodegenThingol.intro_vars vs vars; |
666 in ((Pretty.block o Pretty.breaks) [str (lookup_var vars' v), str "@", pr_term vars' BR p], vars') end |
663 in ((Pretty.block o Pretty.breaks) [str (CodegenThingol.lookup_var vars' v), str "@", pr_term vars' BR p], vars') end |
667 | pr ((v, NONE), _) vars = |
664 | pr ((v, NONE), _) vars = |
668 let |
665 let |
669 val vars' = intro_vars [v] vars; |
666 val vars' = CodegenThingol.intro_vars [v] vars; |
670 in (str (lookup_var vars' v), vars') end; |
667 in (str (CodegenThingol.lookup_var vars' v), vars') end; |
671 val (ps', vars') = fold_map pr ps vars; |
668 val (ps', vars') = fold_map pr ps vars; |
672 in |
669 in |
673 brackify BR ( |
670 brackify BR ( |
674 str "\\" |
671 str "\\" |
675 :: ps' @ [ |
672 :: ps' @ [ |
733 (str o deresolv) c :: map (pr_term vars BR) ts |
730 (str o deresolv) c :: map (pr_term vars BR) ts |
734 and pr_app vars fxy = |
731 and pr_app vars fxy = |
735 mk_app (pr_app' vars) (pr_term vars) const_syntax fxy; |
732 mk_app (pr_app' vars) (pr_term vars) const_syntax fxy; |
736 fun pr_def (name, CodegenThingol.Fun (funn as (eqs, (vs, ty)))) = |
733 fun pr_def (name, CodegenThingol.Fun (funn as (eqs, (vs, ty)))) = |
737 let |
734 let |
738 val tyvars = intro_vars (map fst vs) keyword_vars; |
735 val tyvars = CodegenThingol.intro_vars (map fst vs) keyword_vars; |
739 fun pr_eq (ts, t) = |
736 fun pr_eq (ts, t) = |
740 let |
737 let |
741 val consts = map_filter |
738 val consts = map_filter |
742 (fn c => if (is_some o const_syntax) c |
739 (fn c => if (is_some o const_syntax) c |
743 then NONE else (SOME o NameSpace.base o deresolv) c) |
740 then NONE else (SOME o NameSpace.base o deresolv) c) |
744 ((fold o CodegenThingol.fold_constnames) (insert (op =)) (t :: ts) []); |
741 ((fold o CodegenThingol.fold_constnames) (insert (op =)) (t :: ts) []); |
745 val vars = keyword_vars |
742 val vars = keyword_vars |
746 |> intro_vars consts |
743 |> CodegenThingol.intro_vars consts |
747 |> intro_vars ((fold o CodegenThingol.fold_unbound_varnames) (insert (op =)) (t :: ts) []); |
744 |> CodegenThingol.intro_vars ((fold o CodegenThingol.fold_unbound_varnames) (insert (op =)) (t :: ts) []); |
748 in |
745 in |
749 (Pretty.block o Pretty.breaks) ( |
746 (Pretty.block o Pretty.breaks) ( |
750 (str o deresolv_here) name |
747 (str o deresolv_here) name |
751 :: map (pr_term vars BR) ts |
748 :: map (pr_term vars BR) ts |
752 @ [str "=", pr_term vars NOBR t] |
749 @ [str "=", pr_term vars NOBR t] |
759 Pretty.brk 1, |
756 Pretty.brk 1, |
760 pr_typscheme tyvars (vs, ty) |
757 pr_typscheme tyvars (vs, ty) |
761 ] |
758 ] |
762 :: (map pr_eq o fst o snd o constructive_fun) (name, funn) |
759 :: (map pr_eq o fst o snd o constructive_fun) (name, funn) |
763 ) |
760 ) |
764 end |> SOME |
761 end |
765 | pr_def (name, CodegenThingol.Datatype (vs, [(co, [ty])])) = |
762 | pr_def (name, CodegenThingol.Datatype (vs, [(co, [ty])])) = |
766 let |
763 let |
767 val tyvars = intro_vars (map fst vs) keyword_vars; |
764 val tyvars = CodegenThingol.intro_vars (map fst vs) keyword_vars; |
768 in |
765 in |
769 (Pretty.block o Pretty.breaks) [ |
766 (Pretty.block o Pretty.breaks) ([ |
770 str "newtype", |
767 str "newtype", |
771 pr_typscheme_expr tyvars (vs, (deresolv_here name, map (ITyVar o fst) vs)), |
768 pr_typscheme_expr tyvars (vs, (deresolv_here name, map (ITyVar o fst) vs)), |
772 str "=", |
769 str "=", |
773 (str o deresolv_here) co, |
770 (str o deresolv_here) co, |
774 pr_typ tyvars BR ty |
771 pr_typ tyvars BR ty |
775 ] |
772 ] @ (if deriving_show name then [str "deriving Read, Show"] else [])) |
776 end |> SOME |
773 end |
777 | pr_def (name, CodegenThingol.Datatype (vs, co :: cos)) = |
774 | pr_def (name, CodegenThingol.Datatype (vs, co :: cos)) = |
778 let |
775 let |
779 val tyvars = intro_vars (map fst vs) keyword_vars; |
776 val tyvars = CodegenThingol.intro_vars (map fst vs) keyword_vars; |
780 fun pr_co (co, tys) = |
777 fun pr_co (co, tys) = |
781 (Pretty.block o Pretty.breaks) ( |
778 (Pretty.block o Pretty.breaks) ( |
782 (str o deresolv_here) co |
779 (str o deresolv_here) co |
783 :: map (pr_typ tyvars BR) tys |
780 :: map (pr_typ tyvars BR) tys |
784 ) |
781 ) |
785 in |
782 in |
786 (Pretty.block o Pretty.breaks) ( |
783 (Pretty.block o Pretty.breaks) (( |
787 str "data" |
784 str "data" |
788 :: pr_typscheme_expr tyvars (vs, (deresolv_here name, map (ITyVar o fst) vs)) |
785 :: pr_typscheme_expr tyvars (vs, (deresolv_here name, map (ITyVar o fst) vs)) |
789 :: str "=" |
786 :: str "=" |
790 :: pr_co co |
787 :: pr_co co |
791 :: map ((fn p => Pretty.block [str "| ", p]) o pr_co) cos |
788 :: map ((fn p => Pretty.block [str "| ", p]) o pr_co) cos |
792 ) |
789 ) @ (if deriving_show name then [str "deriving Read, Show"] else [])) |
793 end |> SOME |
790 end |
794 | pr_def (_, CodegenThingol.Datatypecons _) = |
|
795 NONE |
|
796 | pr_def (name, CodegenThingol.Class (superclasss, (v, classops))) = |
791 | pr_def (name, CodegenThingol.Class (superclasss, (v, classops))) = |
797 let |
792 let |
798 val tyvars = intro_vars [v] keyword_vars; |
793 val tyvars = CodegenThingol.intro_vars [v] keyword_vars; |
799 fun pr_classop (classop, ty) = |
794 fun pr_classop (classop, ty) = |
800 Pretty.block [ |
795 Pretty.block [ |
801 str (deresolv_here classop ^ " ::"), |
796 str (deresolv_here classop ^ " ::"), |
802 Pretty.brk 1, |
797 Pretty.brk 1, |
803 pr_typ tyvars NOBR ty |
798 pr_typ tyvars NOBR ty |
804 ] |
799 ] |
805 in |
800 in |
806 Pretty.block [ |
801 Pretty.block [ |
807 str "class ", |
802 str "class ", |
808 pr_typparms tyvars [(v, superclasss)], |
803 pr_typparms tyvars [(v, superclasss)], |
809 str (deresolv_here name ^ " " ^ v), |
804 str (deresolv_here name ^ " " ^ CodegenThingol.lookup_var tyvars v), |
810 str " where", |
805 str " where", |
811 Pretty.fbrk, |
806 Pretty.fbrk, |
812 Pretty.chunks (map pr_classop classops) |
807 Pretty.chunks (map pr_classop classops) |
813 ] |
808 ] |
814 end |> SOME |
809 end |
815 | pr_def (_, CodegenThingol.Classmember _) = |
|
816 NONE |
|
817 | pr_def (_, CodegenThingol.Classinst ((class, (tyco, vs)), (_, classop_defs))) = |
810 | pr_def (_, CodegenThingol.Classinst ((class, (tyco, vs)), (_, classop_defs))) = |
818 let |
811 let |
819 val tyvars = intro_vars (map fst vs) keyword_vars; |
812 val tyvars = CodegenThingol.intro_vars (map fst vs) keyword_vars; |
820 in |
813 in |
821 Pretty.block [ |
814 Pretty.block [ |
822 str "instance ", |
815 str "instance ", |
823 pr_typparms tyvars vs, |
816 pr_typparms tyvars vs, |
824 str (class_name class ^ " "), |
817 str (class_name class ^ " "), |
830 val consts = map_filter |
823 val consts = map_filter |
831 (fn c => if (is_some o const_syntax) c |
824 (fn c => if (is_some o const_syntax) c |
832 then NONE else (SOME o NameSpace.base o deresolv) c) |
825 then NONE else (SOME o NameSpace.base o deresolv) c) |
833 (CodegenThingol.fold_constnames (insert (op =)) t []); |
826 (CodegenThingol.fold_constnames (insert (op =)) t []); |
834 val vars = keyword_vars |
827 val vars = keyword_vars |
835 |> intro_vars consts; |
828 |> CodegenThingol.intro_vars consts; |
836 in |
829 in |
837 (Pretty.block o Pretty.breaks) [ |
830 (Pretty.block o Pretty.breaks) [ |
838 (str o classop_name class) classop, |
831 (str o classop_name class) classop, |
839 str "=", |
832 str "=", |
840 pr_term vars NOBR t |
833 pr_term vars NOBR t |
841 ] |
834 ] |
842 end |
835 end |
843 ) classop_defs) |
836 ) classop_defs) |
844 ] |
837 ] |
845 end |> SOME |
838 end; |
846 | pr_def (_, CodegenThingol.Bot) = |
|
847 NONE; |
|
848 in pr_def def end; |
839 in pr_def def end; |
849 |
840 |
850 val reserved_haskell = [ |
841 val reserved_haskell = [ |
851 "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr", |
842 "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr", |
852 "import", "default", "forall", "let", "in", "class", "qualified", "data", |
843 "import", "default", "forall", "let", "in", "class", "qualified", "data", |
853 "newtype", "instance", "if", "then", "else", "type", "as", "do", "module" |
844 "newtype", "instance", "if", "then", "else", "type", "as", "do", "module" |
854 ]; |
845 ]; |
855 |
846 |
856 fun seri_haskell module_prefix destination reserved_user module_alias module_prolog |
847 fun seri_haskell module_prefix destination string_classes reserved_user module_alias module_prolog |
857 class_syntax tyco_syntax const_syntax code = |
848 class_syntax tyco_syntax const_syntax code = |
858 let |
849 let |
859 val init_vars = make_vars (reserved_haskell @ reserved_user); |
850 val _ = Option.map File.assert destination; |
860 in () end; |
851 val empty_names = Name.make_context (reserved_haskell @ reserved_user); |
861 |
852 fun prefix_modlname modlname = case module_prefix |
|
853 of NONE => modlname |
|
854 | SOME module_prefix => NameSpace.append module_prefix modlname; |
|
855 fun add_def (name, (def, deps)) = |
|
856 let |
|
857 val (modl, (shallow, base)) = dest_name name; |
|
858 val base' = if member (op =) |
|
859 [CodegenNames.nsp_class, CodegenNames.nsp_tyco, CodegenNames.nsp_dtco] shallow |
|
860 then first_upper base else base; |
|
861 fun mk name = (the_single o fst) (Name.variants [name] empty_names); |
|
862 fun mk' name names = names |> Name.variants [name] |>> the_single; |
|
863 val modlname = NameSpace.pack modl; |
|
864 val modlname' = case module_alias modlname |
|
865 of SOME modlname' => prefix_modlname modlname' |
|
866 | NONE => NameSpace.pack (map_filter I (module_prefix :: map (SOME o mk) modl)); |
|
867 val deps' = remove (op =) modlname (map (NameSpace.qualifier o NameSpace.qualifier) deps); |
|
868 fun add_def base' = |
|
869 case def |
|
870 of CodegenThingol.Datatypecons _ => I |
|
871 cons (name, ((NameSpace.append modlname' base', base'), NONE)) |
|
872 | CodegenThingol.Classop _ => |
|
873 cons (name, ((NameSpace.append modlname' base', base'), NONE)) |
|
874 | CodegenThingol.Bot => I |
|
875 | _ => cons (name, ((NameSpace.append modlname' base', base'), SOME def)); |
|
876 in |
|
877 Symtab.map_default (modlname, (modlname', ([], ([], empty_names)))) |
|
878 ((apsnd o apfst) (fold (insert (op =)) deps')) |
|
879 #> `(fn code => mk' base' ((snd o snd o snd o the o Symtab.lookup code) modlname)) |
|
880 #-> (fn (base', names) => |
|
881 Symtab.map_entry modlname ((apsnd o apsnd) (fn (defs, _) => |
|
882 (add_def base' defs, names)))) |
|
883 end; |
|
884 val code' = |
|
885 fold add_def (AList.make (fn name => (Graph.get_node code name, Graph.imm_succs code name)) |
|
886 (Graph.strong_conn code |> flat)) Symtab.empty; |
|
887 val init_vars = CodegenThingol.make_vars (reserved_haskell @ reserved_user); |
|
888 fun deresolv name = |
|
889 (fst o fst o the o AList.lookup (op =) ((fst o snd o snd o the |
|
890 o Symtab.lookup code') ((NameSpace.qualifier o NameSpace.qualifier) name))) name; |
|
891 fun deresolv_here name = |
|
892 (snd o fst o the o AList.lookup (op =) ((fst o snd o snd o the |
|
893 o Symtab.lookup code') ((NameSpace.qualifier o NameSpace.qualifier) name))) name; |
|
894 val deresolv_module = fst o the o Symtab.lookup code'; |
|
895 fun deriving_show tyco = |
|
896 let |
|
897 fun deriv tycos tyco = member (op =) tycos tyco orelse |
|
898 case Graph.get_node code tyco |
|
899 of CodegenThingol.Bot => true |
|
900 | CodegenThingol.Datatype (_, cs) => forall (deriv' (tyco :: tycos)) |
|
901 (maps snd cs) |
|
902 and deriv' tycos (tyco `%% tys) = deriv tycos tyco |
|
903 andalso forall (deriv' tycos) tys |
|
904 | deriv' _ (_ `-> _) = false |
|
905 | deriv' _ (ITyVar _) = true |
|
906 in deriv [] tyco end; |
|
907 val seri_def = pr_haskell class_syntax tyco_syntax const_syntax init_vars |
|
908 deresolv_here deresolv (if string_classes then deriving_show else K false); |
|
909 fun write_module (SOME destination) modlname p = |
|
910 let |
|
911 val filename = case modlname |
|
912 of "" => Path.unpack "Main.hs" |
|
913 | _ => (Path.ext "hs" o Path.unpack o implode o separate "/" o NameSpace.unpack) modlname; |
|
914 val pathname = Path.append destination filename; |
|
915 val _ = File.mkdir (Path.dir pathname); |
|
916 in File.write pathname (Pretty.setmp_margin 999999 Pretty.output p ^ "\n") end |
|
917 | write_module NONE _ p = |
|
918 writeln (Pretty.setmp_margin 999999 Pretty.output p ^ "\n"); |
|
919 fun seri_module (modlname, (modlname', (imports, (defs, _)))) = |
|
920 Pretty.chunks ( |
|
921 str ("module " ^ modlname' ^ " where") |
|
922 :: map str (distinct (op =) (map (prefix "import qualified " o deresolv_module) imports)) @ ( |
|
923 (case module_prolog modlname |
|
924 of SOME prolog => [str "", prolog, str ""] |
|
925 | NONE => [str ""]) |
|
926 @ separate (str "") (map_filter |
|
927 (fn (name, (_, SOME def)) => SOME (seri_def (name, def)) |
|
928 | (_, (_, NONE)) => NONE) defs)) |
|
929 ) |> write_module destination modlname'; |
|
930 in Symtab.fold (fn modl => fn () => seri_module modl) code' () end; |
|
931 |
|
932 val isar_seri_haskell = |
|
933 parse_args (Scan.option (Args.$$$ "root" -- Args.colon |-- Args.name) |
|
934 -- Scan.optional (Args.$$$ "string_classes" >> K true) false |
|
935 -- (Args.$$$ "-" >> K NONE || Args.name >> SOME) |
|
936 >> (fn ((module_prefix, string_classes), destination) => |
|
937 seri_haskell module_prefix (Option.map Path.unpack destination) string_classes)); |
862 |
938 |
863 |
939 |
864 (** diagnosis serializer **) |
940 (** diagnosis serializer **) |
865 |
941 |
866 fun seri_diagnosis _ _ _ _ _ code = |
942 fun seri_diagnosis _ _ _ _ _ code = |
867 let |
943 let |
868 val init_vars = make_vars reserved_haskell; |
944 val init_vars = CodegenThingol.make_vars reserved_haskell; |
869 val pr = pr_haskell (K NONE) (K NONE) (K NONE) init_vars I I; |
945 val pr = pr_haskell (K NONE) (K NONE) (K NONE) init_vars I I (K false); |
870 in |
946 in |
871 [] |
947 [] |
872 |> Graph.fold (fn (name, (def, _)) => |
948 |> Graph.fold (fn (name, (def, _)) => cons (pr (name, def))) code |
873 case pr (name, def) of SOME p => cons p | NONE => I) code |
|
874 |> separate (Pretty.str "") |
949 |> separate (Pretty.str "") |
875 |> Pretty.chunks |
950 |> Pretty.chunks |
876 |> Pretty.writeln |
951 |> Pretty.writeln |
877 end; |
952 end; |
878 |
953 |
879 |
954 |
880 |
955 |
881 (** generic abstract serializer **) |
956 (** ML abstract serializer -- FIXME to be refactored **) |
882 |
957 |
883 structure NameMangler = NameManglerFun ( |
958 structure NameMangler = NameManglerFun ( |
884 type ctxt = (string * string -> string) * (string -> string option); |
959 type ctxt = (string * string -> string) * (string -> string option); |
885 type src = string * string; |
960 type src = string * string; |
886 val ord = prod_ord string_ord string_ord; |
961 val ord = prod_ord string_ord string_ord; |
972 val (common, (_, rem)) = chop_prefix (op =) (prefix, NameSpace.unpack name); |
1047 val (common, (_, rem)) = chop_prefix (op =) (prefix, NameSpace.unpack name); |
973 val (_, SOME tab') = get_path_name common tab; |
1048 val (_, SOME tab') = get_path_name common tab; |
974 val (name', _) = get_path_name rem tab'; |
1049 val (name', _) = get_path_name rem tab'; |
975 in NameSpace.pack name' end handle BIND => (error ("Missing name: " ^ quote name ^ ", in " ^ quote (NameSpace.pack prefix))); |
1050 in NameSpace.pack name' end handle BIND => (error ("Missing name: " ^ quote name ^ ", in " ^ quote (NameSpace.pack prefix))); |
976 in deresolv (mk module (AList.make (K NameMangler.empty) nsp_conn) Symtab.empty) end; |
1051 in deresolv (mk module (AList.make (K NameMangler.empty) nsp_conn) Symtab.empty) end; |
977 fun allimports_of modl = |
|
978 let |
|
979 fun imps_of prfx (Module modl) imps tab = |
|
980 let |
|
981 val this = NameSpace.pack prfx; |
|
982 val name_con = (rev o Graph.strong_conn) modl; |
|
983 in |
|
984 tab |
|
985 |> pair [] |
|
986 |> fold (fn names => fn (imps', tab) => |
|
987 tab |
|
988 |> fold_map (fn name => |
|
989 imps_of (prfx @ [name]) (Graph.get_node modl name) (imps' @ imps)) names |
|
990 |-> (fn imps'' => pair (flat imps'' @ imps'))) name_con |
|
991 |-> (fn imps' => |
|
992 Symtab.update_new (this, imps' @ imps) |
|
993 #> pair (this :: imps')) |
|
994 end |
|
995 | imps_of prfx (Def _) imps tab = |
|
996 ([], tab); |
|
997 in snd (imps_of [] (Module modl) [] Symtab.empty) end; |
|
998 fun add_def ((names_mod, name_id), def) = |
1052 fun add_def ((names_mod, name_id), def) = |
999 let |
1053 let |
1000 fun add [] = |
1054 fun add [] = |
1001 Graph.new_node (name_id, Def def) |
1055 Graph.new_node (name_id, Def def) |
1002 | add (m::ms) = |
1056 | add (m::ms) = |
1029 Graph.empty |
1083 Graph.empty |
1030 |> Graph.fold (fn (name, (def, _)) => add_def (dest_name name, def)) code |
1084 |> Graph.fold (fn (name, (def, _)) => add_def (dest_name name, def)) code |
1031 |> Graph.fold (fn (name, (_, (_, deps))) => |
1085 |> Graph.fold (fn (name, (_, (_, deps))) => |
1032 fold (curry add_dep name) deps) code; |
1086 fold (curry add_dep name) deps) code; |
1033 val names = map fst (Graph.dest root_module); |
1087 val names = map fst (Graph.dest root_module); |
1034 val imptab = allimports_of root_module; |
|
1035 val resolver = mk_deresolver root_module nsp_conn postprocess validate; |
1088 val resolver = mk_deresolver root_module nsp_conn postprocess validate; |
1036 fun sresolver s = (resolver o NameSpace.unpack) s |
1089 fun sresolver s = (resolver o NameSpace.unpack) s |
1037 fun mk_name prfx name = |
1090 fun mk_name prfx name = |
1038 let |
1091 let |
1039 val name_qual = NameSpace.pack (prfx @ [name]) |
1092 val name_qual = NameSpace.pack (prfx @ [name]) |
1040 in (name_qual, resolver prfx name_qual) end; |
1093 in (name_qual, resolver prfx name_qual) end; |
1041 fun is_bot (_, (Def Bot)) = true |
|
1042 | is_bot _ = false; |
|
1043 fun mk_contents prfx module = |
1094 fun mk_contents prfx module = |
1044 map_filter (seri prfx) |
1095 map_filter (seri prfx) |
1045 ((map (AList.make (Graph.get_node module)) o rev o Graph.strong_conn) module) |
1096 ((map (AList.make (Graph.get_node module)) o rev o Graph.strong_conn) module) |
1046 and seri prfx [(name, Module modl)] = |
1097 and seri prfx [(name, Module modl)] = |
1047 seri_module (resolver []) (map (resolver []) ((the o Symtab.lookup imptab) (NameSpace.pack (prfx @ [name])))) |
1098 seri_module (resolver []) (mk_name prfx name, mk_contents (prfx @ [name]) modl) |
1048 (mk_name prfx name, mk_contents (prfx @ [name]) modl) |
|
1049 | seri prfx ds = |
1099 | seri prfx ds = |
1050 seri_defs sresolver (NameSpace.pack prfx) |
1100 seri_defs sresolver (NameSpace.pack prfx) |
1051 (map (fn (name, Def def) => (fst (mk_name prfx name), def)) ds) |
1101 (map (fn (name, Def def) => (fst (mk_name prfx name), def)) ds) |
1052 in |
1102 in |
1053 seri_module (resolver []) (map (resolver []) ((the o Symtab.lookup imptab) "")) |
1103 seri_module (resolver []) |
1054 (("", name_root), (mk_contents [] root_module)) |
1104 (("", name_root), (mk_contents [] root_module)) |
1055 end; |
1105 end; |
1056 |
1106 |
1057 fun abstract_serializer nspgrp name_root (from_defs, from_module, validator, postproc) |
1107 fun abstract_serializer nspgrp name_root (from_defs, from_module, validator, postproc) |
1058 postprocess |
1108 postprocess |
1059 reserved_user module_alias module_prolog class_syntax tyco_syntax const_syntax |
1109 reserved_user module_alias module_prolog class_syntax tyco_syntax const_syntax |
1060 code = |
1110 code = |
1061 let |
1111 let |
1062 fun from_module' resolv imps ((name_qual, name), defs) = |
1112 fun from_module' resolv ((name_qual, name), defs) = |
1063 from_module resolv imps ((name_qual, name), defs) |
1113 from_module resolv ((name_qual, name), defs) |
1064 |> postprocess (resolv name_qual); |
1114 |> postprocess (resolv name_qual); |
1065 in |
1115 in |
1066 code_serialize (from_defs (class_syntax, tyco_syntax, const_syntax)) |
1116 code_serialize (from_defs (class_syntax, tyco_syntax, const_syntax)) |
1067 from_module' validator postproc nspgrp name_root code |
1117 from_module' validator postproc nspgrp name_root code |
1068 |> K () |
1118 |> K () |
1084 |> translate_string replace_invalid |
1134 |> translate_string replace_invalid |
1085 |> suffix_it |
1135 |> suffix_it |
1086 |> (fn name' => if name = name' then NONE else SOME name') |
1136 |> (fn name' => if name = name' then NONE else SOME name') |
1087 end; |
1137 end; |
1088 |
1138 |
1089 fun write_file mkdir path p = ( |
1139 fun write_file path p = (File.write path (Pretty.output p ^ "\n"); p); |
1090 if mkdir |
|
1091 then |
|
1092 File.mkdir (Path.dir path) |
|
1093 else (); |
|
1094 File.write path (Pretty.output p ^ "\n"); |
|
1095 p |
|
1096 ); |
|
1097 |
|
1098 fun mk_module_file postprocess_module ext path name p = |
|
1099 let |
|
1100 val prfx = Path.dir path; |
|
1101 val name' = case name |
|
1102 of "" => Path.base path |
|
1103 | _ => (Path.ext ext o Path.unpack o implode o separate "/" o NameSpace.unpack) name; |
|
1104 in |
|
1105 p |
|
1106 |> Pretty.setmp_margin 999999 (write_file true (Path.append prfx name')) |
|
1107 |> postprocess_module name |
|
1108 end; |
|
1109 |
|
1110 fun parse_args f args = |
|
1111 case f args |
|
1112 of (x, []) => x |
|
1113 | (_, _) => error "bad serializer arguments"; |
|
1114 |
1140 |
1115 val sml_code_width = ref 80; |
1141 val sml_code_width = ref 80; |
1116 |
1142 |
1117 fun parse_single_file serializer = |
1143 fun parse_single_file serializer = |
1118 parse_args (Args.name |
1144 parse_args (Args.name |
1119 >> (fn path => serializer |
1145 >> (fn path => serializer |
1120 (fn "" => Pretty.setmp_margin (!sml_code_width) (write_file false (Path.unpack path)) #> K NONE |
1146 (fn "" => Pretty.setmp_margin (!sml_code_width) (write_file (Path.unpack path)) #> K NONE |
1121 | _ => SOME))); |
1147 | _ => SOME))); |
1122 |
|
1123 fun parse_multi_file postprocess_module ext serializer = |
|
1124 parse_args (Args.name |
|
1125 >> (fn path => (serializer o mk_module_file postprocess_module ext) (Path.unpack path))); |
|
1126 |
1148 |
1127 fun parse_internal serializer = |
1149 fun parse_internal serializer = |
1128 parse_args (Args.name |
1150 parse_args (Args.name |
1129 >> (fn "-" => serializer |
1151 >> (fn "-" => serializer |
1130 (fn "" => (fn p => (use_text Output.ml_output false (Pretty.output p); NONE)) |
1152 (fn "" => (fn p => (use_text Output.ml_output false (Pretty.output p); NONE)) |
1176 ) |
1197 ) |
1177 #> MLDatas; |
1198 #> MLDatas; |
1178 fun filter_class defs = |
1199 fun filter_class defs = |
1179 case map_filter |
1200 case map_filter |
1180 (fn (name, CodegenThingol.Class info) => SOME (name, info) |
1201 (fn (name, CodegenThingol.Class info) => SOME (name, info) |
1181 | (name, CodegenThingol.Classmember _) => NONE |
1202 | (name, CodegenThingol.Classop _) => NONE |
1182 | (name, def) => error ("Class block containing illegal def: " ^ quote name) |
1203 | (name, def) => error ("Class block containing illegal def: " ^ quote name) |
1183 ) defs |
1204 ) defs |
1184 of [class] => MLClass class |
1205 of [class] => MLClass class |
1185 | _ => error ("Class block without class: " ^ (commas o map (quote o fst)) defs) |
1206 | _ => error ("Class block without class: " ^ (commas o map (quote o fst)) defs) |
1186 in case defs |
1207 in case defs |
1187 of (_, CodegenThingol.Fun _)::_ => (seri o filter_funs) defs |
1208 of (_, CodegenThingol.Fun _)::_ => (seri o filter_funs) defs |
1188 | (_, CodegenThingol.Datatypecons _)::_ => (seri o filter_datatype) defs |
1209 | (_, CodegenThingol.Datatypecons _)::_ => (seri o filter_datatype) defs |
1189 | (_, CodegenThingol.Datatype _)::_ => (seri o filter_datatype) defs |
1210 | (_, CodegenThingol.Datatype _)::_ => (seri o filter_datatype) defs |
1190 | (_, CodegenThingol.Class _)::_ => (seri o filter_class) defs |
1211 | (_, CodegenThingol.Class _)::_ => (seri o filter_class) defs |
1191 | (_, CodegenThingol.Classmember _)::_ => (seri o filter_class) defs |
1212 | (_, CodegenThingol.Classop _)::_ => (seri o filter_class) defs |
1192 | [(inst, CodegenThingol.Classinst info)] => seri (MLClassinst (inst, info)) |
1213 | [(inst, CodegenThingol.Classinst info)] => seri (MLClassinst (inst, info)) |
1193 | defs => error ("Illegal mutual dependencies: " ^ (commas o map fst) defs) |
1214 | defs => error ("Illegal mutual dependencies: " ^ (commas o map fst) defs) |
1194 end; |
1215 end; |
1195 |
1216 |
1196 fun ml_serializer root_name nspgrp = |
1217 fun ml_serializer root_name nspgrp = |
1197 let |
1218 let |
1198 fun ml_from_module resolv _ ((_, name), ps) = |
1219 fun ml_from_module resolv ((_, name), ps) = |
1199 Pretty.chunks ([ |
1220 Pretty.chunks ([ |
1200 str ("structure " ^ name ^ " = "), |
1221 str ("structure " ^ name ^ " = "), |
1201 str "struct", |
1222 str "struct", |
1202 str "" |
1223 str "" |
1203 ] @ separate (str "") ps @ [ |
1224 ] @ separate (str "") ps @ [ |
1204 str "", |
1225 str "", |
1205 str ("end; (* struct " ^ name ^ " *)") |
1226 str ("end; (* struct " ^ name ^ " *)") |
1206 ]); |
1227 ]); |
1207 fun postproc (shallow, n) = |
1228 fun postproc (shallow, n) = |
1208 let |
1229 if shallow = CodegenNames.nsp_dtco |
1209 fun ch_first f = String.implode o nth_map 0 f o String.explode; |
1230 then first_upper n |
1210 in if shallow = CodegenNames.nsp_dtco |
1231 else n; |
1211 then ch_first Char.toUpper n |
|
1212 else n |
|
1213 end; |
|
1214 in abstract_serializer nspgrp |
1232 in abstract_serializer nspgrp |
1215 root_name (ml_from_defs, ml_from_module, |
1233 root_name (ml_from_defs, ml_from_module, |
1216 abstract_validator (ThmDatabase.ml_reserved @ reserved_ml'), postproc) end; |
1234 abstract_validator (ThmDatabase.ml_reserved @ reserved_ml'), postproc) end; |
1217 |
1235 |
1218 in |
1236 in |
1219 |
1237 |
1220 fun ml_from_thingol args = |
1238 fun ml_from_thingol args = |
1221 let |
1239 let |
1222 val serializer = ml_serializer "ROOT" [[nsp_module], [nsp_class, nsp_tyco], |
1240 val serializer = ml_serializer "ROOT" [[nsp_module], [nsp_class, nsp_tyco], |
1223 [nsp_fun, nsp_dtco, nsp_class, nsp_classop, nsp_inst]] |
1241 [nsp_fun, nsp_dtco, nsp_class, nsp_inst]] |
1224 val parse_multi = |
1242 in |
1225 Args.name |
1243 (parse_internal serializer |
1226 #-> (fn "dir" => |
|
1227 parse_multi_file |
|
1228 (K o SOME o str o suffix ";" o prefix "val _ = use " |
|
1229 o quote o suffix ".ML" o translate_string (fn "." => "/" | s => s)) "ML" serializer |
|
1230 | _ => Scan.fail ()); |
|
1231 in |
|
1232 (parse_multi |
|
1233 || parse_internal serializer |
|
1234 || parse_stdout serializer |
1244 || parse_stdout serializer |
1235 || parse_single_file serializer) args |
1245 || parse_single_file serializer) args |
1236 end; |
1246 end; |
1237 |
1247 |
1238 val eval_verbose = ref false; |
1248 val eval_verbose = ref false; |
1256 of NONE => error ("Could not retrieve value of ML reference " ^ quote ref_name |
1266 of NONE => error ("Could not retrieve value of ML reference " ^ quote ref_name |
1257 ^ " (reference probably has been shadowed)") |
1267 ^ " (reference probably has been shadowed)") |
1258 | SOME value => value |
1268 | SOME value => value |
1259 end; |
1269 end; |
1260 |
1270 |
1261 structure NameMangler = NameManglerFun ( |
|
1262 type ctxt = string list; |
|
1263 type src = string; |
|
1264 val ord = string_ord; |
|
1265 fun mk reserved_ml (name, i) = |
|
1266 (Symbol.alphanum o NameSpace.base) name ^ replicate_string i "'"; |
|
1267 fun is_valid (reserved_ml : string list) = not o member (op =) reserved_ml; |
|
1268 fun maybe_unique _ _ = NONE; |
|
1269 fun re_mangle _ dst = error ("No such definition name: " ^ quote dst); |
|
1270 ); |
|
1271 |
|
1272 fun mk_flat_ml_resolver names = |
|
1273 let |
|
1274 val mangler = |
|
1275 NameMangler.empty |
|
1276 |> fold_map (NameMangler.declare (ThmDatabase.ml_reserved @ reserved_ml')) names |
|
1277 |-> (fn _ => I) |
|
1278 in NameMangler.get (ThmDatabase.ml_reserved @ reserved_ml') mangler end; |
|
1279 |
|
1280 end; (* local *) |
1271 end; (* local *) |
1281 |
|
1282 |
|
1283 (** haskell serializer **) |
|
1284 |
|
1285 fun hs_from_thingol args = |
|
1286 let |
|
1287 fun hs_from_defs keyword_vars (class_syntax, tyco_syntax, const_syntax) deresolver prefix defs = |
|
1288 let |
|
1289 val deresolv = deresolver ""; |
|
1290 val deresolv_here = deresolver prefix; |
|
1291 val hs_from_def = pr_haskell class_syntax tyco_syntax const_syntax |
|
1292 keyword_vars deresolv_here deresolv; |
|
1293 in case map_filter hs_from_def defs |
|
1294 of [] => NONE |
|
1295 | ps => (SOME o Pretty.chunks o separate (str "")) ps |
|
1296 end; |
|
1297 val reserved_hs = [ |
|
1298 "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr", |
|
1299 "import", "default", "forall", "let", "in", "class", "qualified", "data", |
|
1300 "newtype", "instance", "if", "then", "else", "type", "as", "do", "module" |
|
1301 ] @ [ |
|
1302 "Bool", "Integer", "Maybe", "True", "False", "Nothing", "Just", "not", "negate", |
|
1303 "String", "Char" |
|
1304 ]; |
|
1305 fun hs_from_module resolv imps ((_, name), ps) = |
|
1306 (Pretty.chunks) ( |
|
1307 str ("module " ^ name ^ " where") |
|
1308 :: map (str o prefix "import qualified ") imps @ ( |
|
1309 str "" |
|
1310 :: separate (str "") ps |
|
1311 )); |
|
1312 fun postproc (shallow, n) = |
|
1313 let |
|
1314 fun ch_first f = String.implode o nth_map 0 f o String.explode; |
|
1315 in if member (op =) [nsp_module, nsp_class, nsp_tyco, nsp_dtco] shallow |
|
1316 then ch_first Char.toUpper n |
|
1317 else ch_first Char.toLower n |
|
1318 end; |
|
1319 val serializer = abstract_serializer [[nsp_module], |
|
1320 [nsp_class], [nsp_tyco], [nsp_fun, nsp_classop], [nsp_dtco], [nsp_inst]] |
|
1321 "Main" (hs_from_defs (make_vars reserved_hs), hs_from_module, abstract_validator reserved_hs, postproc); |
|
1322 in |
|
1323 (parse_multi_file ((K o K) NONE) "hs" serializer) args |
|
1324 end; |
|
1325 |
1272 |
1326 |
1273 |
1327 |
1274 |
1328 (** theory data **) |
1275 (** theory data **) |
1329 |
1276 |
1665 P.name -- Scan.repeat1 P.name |
1617 P.name -- Scan.repeat1 P.name |
1666 >> (fn (target, reserveds) => (Toplevel.theory o fold (add_reserved target)) reserveds) |
1618 >> (fn (target, reserveds) => (Toplevel.theory o fold (add_reserved target)) reserveds) |
1667 ) |
1619 ) |
1668 |
1620 |
1669 val code_modulenameP = |
1621 val code_modulenameP = |
1670 OuterSyntax.command code_reservedK "alias module to other name" K.thy_decl ( |
1622 OuterSyntax.command code_modulenameK "alias module to other name" K.thy_decl ( |
1671 P.name -- Scan.repeat1 (P.name -- P.name) |
1623 P.name -- Scan.repeat1 (P.name -- P.name) |
1672 >> (fn (target, modlnames) => (Toplevel.theory o fold (add_modl_alias target)) modlnames) |
1624 >> (fn (target, modlnames) => (Toplevel.theory o fold (add_modl_alias target)) modlnames) |
1673 ) |
1625 ) |
1674 |
1626 |
1675 val code_moduleprologP = |
1627 val code_moduleprologP = |
1676 OuterSyntax.command code_reservedK "add prolog to module" K.thy_decl ( |
1628 OuterSyntax.command code_moduleprologK "add prolog to module" K.thy_decl ( |
1677 P.name -- Scan.repeat1 (P.name -- (P.string >> (fn "-" => NONE | s => SOME s))) |
1629 P.name -- Scan.repeat1 (P.name -- (P.string >> (fn "-" => NONE | s => SOME s))) |
1678 >> (fn (target, prologs) => (Toplevel.theory o fold (add_modl_prolog target)) prologs) |
1630 >> (fn (target, prologs) => (Toplevel.theory o fold (add_modl_prolog target)) prologs) |
1679 ) |
1631 ) |
1680 |
1632 |
1681 val _ = OuterSyntax.add_parsers [code_classP, code_instanceP, code_typeP, code_constP, |
1633 val _ = OuterSyntax.add_parsers [code_classP, code_instanceP, code_typeP, code_constP, |
1682 code_reservedP, code_modulenameP, code_moduleprologP]; |
1634 code_reservedP, code_modulenameP, code_moduleprologP]; |
1683 |
1635 |
|
1636 val _ = Context.add_setup (add_reserved "Haskell" "Show" #> add_reserved "Haskell" "Read") |
|
1637 |
1684 end; (*local*) |
1638 end; (*local*) |
1685 |
1639 |
1686 end; (* struct *) |
1640 end; (* struct *) |