src/Pure/Tools/codegen_serializer.ML
changeset 19953 2f54a51f1801
parent 19936 18b4e43ac583
child 20105 454f4be984b7
equal deleted inserted replaced
19952:eaf2c25654d3 19953:2f54a51f1801
    21   val parse_syntax: ('b -> int) -> (string -> 'b -> 'a * 'b) -> OuterParse.token list ->
    21   val parse_syntax: ('b -> int) -> (string -> 'b -> 'a * 'b) -> OuterParse.token list ->
    22     ('b -> 'a pretty_syntax * 'b) * OuterParse.token list;
    22     ('b -> 'a pretty_syntax * 'b) * OuterParse.token list;
    23   val pretty_list: string -> string -> int * string -> CodegenThingol.iexpr pretty_syntax;
    23   val pretty_list: string -> string -> int * string -> CodegenThingol.iexpr pretty_syntax;
    24   val serializers: {
    24   val serializers: {
    25     ml: string * (string * string * (string -> bool) -> serializer),
    25     ml: string * (string * string * (string -> bool) -> serializer),
    26     haskell: string * (string list -> serializer)
    26     haskell: string * (string * string list -> serializer)
    27   };
    27   };
    28   val mk_flat_ml_resolver: string list -> string -> string;
    28   val mk_flat_ml_resolver: string list -> string -> string;
    29   val ml_fun_datatype: string * string * (string -> bool)
    29   val ml_fun_datatype: string * string * (string -> bool)
    30     -> ((string -> CodegenThingol.itype pretty_syntax option)
    30     -> ((string -> CodegenThingol.itype pretty_syntax option)
    31         * (string -> CodegenThingol.iexpr pretty_syntax option))
    31         * (string -> CodegenThingol.iexpr pretty_syntax option))
   257     p
   257     p
   258     |> write_file true (Path.append prfx name')
   258     |> write_file true (Path.append prfx name')
   259     |> postprocess_module name
   259     |> postprocess_module name
   260   end;
   260   end;
   261 
   261 
   262 fun constructive_fun (name, (eqs, ty)) =
   262 fun constructive_fun is_cons (name, (eqs, ty)) =
   263   let
   263   let
   264     fun check_eq (eq as (lhs, rhs)) =
   264     fun check_eq (eq as (lhs, rhs)) =
   265       if forall CodegenThingol.is_pat lhs
   265       if forall (CodegenThingol.is_pat is_cons) lhs
   266       then SOME eq
   266       then SOME eq
   267       else (warning ("in function " ^ quote name ^ ", throwing away one "
   267       else (warning ("in function " ^ quote name ^ ", throwing away one "
   268         ^ "non-executable function clause"); NONE)
   268         ^ "non-executable function clause"); NONE)
   269   in case map_filter check_eq eqs
   269   in case map_filter check_eq eqs
   270    of [] => error ("in function " ^ quote name ^ ", no "
   270    of [] => error ("in function " ^ quote name ^ ", no "
   340 fun ml_expr_seri (is_cons, needs_type) (tyco_syntax, const_syntax) resolv =
   340 fun ml_expr_seri (is_cons, needs_type) (tyco_syntax, const_syntax) resolv =
   341   let
   341   let
   342     val ml_from_label =
   342     val ml_from_label =
   343       str o translate_string (fn "_" => "__" | "." => "_" | c => c)
   343       str o translate_string (fn "_" => "__" | "." => "_" | c => c)
   344         o NameSpace.base o resolv;
   344         o NameSpace.base o resolv;
   345     fun ml_from_tyvar (v, sort) =
   345     fun ml_from_tyvar (v, []) =
   346       let
   346           str "()"
   347         fun mk_class v class =
   347       | ml_from_tyvar (v, sort) =
   348           str (prefix "'" v ^ " " ^ resolv class);
   348           let
   349       in
   349             val w = (Char.toString o Char.toUpper o the o Char.fromString) v;
   350         Pretty.block [
   350             fun mk_class class =
   351           str "(",
   351               str (prefix "'" v ^ " " ^ resolv class);
   352           str v,
   352           in
   353           str ":",
   353             Pretty.block [
   354           case sort
   354               str "(",
   355            of [] => str "unit"
   355               str w,
   356             | [class] => mk_class v class
   356               str ":",
   357             | _ => Pretty.enum " *" "" "" (map (mk_class v) sort),
   357               case sort
   358           str ")"
   358                of [class] => mk_class class
   359         ]
   359                 | _ => Pretty.enum " *" "" "" (map mk_class sort),
   360       end;
   360               str ")"
       
   361             ]
       
   362           end;
   361     fun ml_from_sortlookup fxy lss =
   363     fun ml_from_sortlookup fxy lss =
   362       let
   364       let
   363         fun from_label l =
   365         fun from_label l =
   364           Pretty.block [str "#",
   366           Pretty.block [str "#",
   365             if (is_some o Int.fromString) l then str l
   367             if (is_some o Int.fromString) l then str l
   366             else ml_from_label l
   368             else ml_from_label l
   367           ];
   369           ];
   368         fun from_lookup fxy [] p = p
   370         fun from_lookup fxy [] v =
   369           | from_lookup fxy [l] p =
   371               v
       
   372           | from_lookup fxy [l] v =
   370               brackify fxy [
   373               brackify fxy [
   371                 from_label l,
   374                 from_label l,
   372                 p
   375                 v
   373               ]
   376               ]
   374           | from_lookup fxy ls p =
   377           | from_lookup fxy ls v =
   375               brackify fxy [
   378               brackify fxy [
   376                 Pretty.enum " o" "(" ")" (map from_label ls),
   379                 Pretty.enum " o" "(" ")" (map from_label ls),
   377                 p
   380                 v
   378               ];
   381               ];
   379         fun from_classlookup fxy (Instance (inst, lss)) =
   382         fun from_classlookup fxy (Instance (inst, lss)) =
   380               brackify fxy (
   383               brackify fxy (
   381                 (str o resolv) inst
   384                 (str o resolv) inst
   382                 :: map (ml_from_sortlookup BR) lss
   385                 :: map (ml_from_sortlookup BR) lss
   383               )
   386               )
   384           | from_classlookup fxy (Lookup (classes, (v, ~1))) =
   387           | from_classlookup fxy (Lookup (classes, (v, ~1))) =
   385               from_lookup BR classes (str v)
   388               from_lookup BR classes
       
   389                 ((str o Char.toString o Char.toUpper o the o Char.fromString) v)
   386           | from_classlookup fxy (Lookup (classes, (v, i))) =
   390           | from_classlookup fxy (Lookup (classes, (v, i))) =
   387               from_lookup BR (string_of_int (i+1) :: classes) (str v)
   391               from_lookup BR (string_of_int (i+1) :: classes)
       
   392                 ((str o Char.toString o Char.toUpper o the o Char.fromString) v)
   388       in case lss
   393       in case lss
   389        of [] => str "()"
   394        of [] => str "()"
   390         | [ls] => from_classlookup fxy ls
   395         | [ls] => from_classlookup fxy ls
   391         | lss => (Pretty.list "(" ")" o map (from_classlookup NOBR)) lss
   396         | lss => (Pretty.list "(" ")" o map (from_classlookup NOBR)) lss
   392       end;
   397       end;
   594             (Pretty.block o Pretty.fbreaks o shift) (
   599             (Pretty.block o Pretty.fbreaks o shift) (
   595               mk_eq definer eq
   600               mk_eq definer eq
   596               :: map (mk_eq "|") eq_tl
   601               :: map (mk_eq "|") eq_tl
   597             )
   602             )
   598           end;
   603           end;
   599         val def' :: defs' = map (apsnd eta_expand_poly_fun o constructive_fun) defs
   604         val def' :: defs' = map (apsnd eta_expand_poly_fun o constructive_fun is_cons) defs
   600       in
   605       in
   601         chunk_defs (
   606         chunk_defs (
   602           (mk_fun (the (fold check_args defs NONE))) def'
   607           (mk_fun (the (fold check_args defs NONE))) def'
   603           :: map (mk_fun "and") defs'
   608           :: map (mk_fun "and") defs'
   604         )
   609         )
   651                 ^ (Pretty.output o CodegenThingol.pretty_def) def)) defs
   656                 ^ (Pretty.output o CodegenThingol.pretty_def) def)) defs
   652        of [class] => class
   657        of [class] => class
   653         | _ => error ("class block without class: " ^ (commas o map (quote o fst)) defs)
   658         | _ => error ("class block without class: " ^ (commas o map (quote o fst)) defs)
   654     fun ml_from_class (name, (supclasses, (v, membrs))) =
   659     fun ml_from_class (name, (supclasses, (v, membrs))) =
   655       let
   660       let
       
   661         val w = (Char.toString o Char.toUpper o the o Char.fromString) v;
   656         fun from_supclass class =
   662         fun from_supclass class =
   657           Pretty.block [
   663           Pretty.block [
   658             ml_from_label class,
   664             ml_from_label class,
   659             str ":",
   665             str ":",
   660             Pretty.brk 1,
   666             Pretty.brk 1,
   671           ];
   677           ];
   672         fun from_membr_fun (m, _) =
   678         fun from_membr_fun (m, _) =
   673           (Pretty.block o Pretty.breaks) [
   679           (Pretty.block o Pretty.breaks) [
   674             str "fun",
   680             str "fun",
   675             (str o resolv) m, 
   681             (str o resolv) m, 
   676             Pretty.enclose "(" ")" [str (v ^ ":'" ^ v ^ " " ^ resolv name)],
   682             Pretty.enclose "(" ")" [str (w ^ ":'" ^ v ^ " " ^ resolv name)],
   677             str "=",
   683             str "=",
   678             Pretty.block [str "#", ml_from_label m],
   684             Pretty.block [str "#", ml_from_label m],
   679             str (v ^ ";")
   685             str (w ^ ";")
   680           ];
   686           ];
   681       in
   687       in
   682         Pretty.chunks (
   688         Pretty.chunks (
   683           (Pretty.block o Pretty.breaks) [
   689           (Pretty.block o Pretty.breaks) [
   684             str "type",
   690             str "type",
   704             ]
   710             ]
   705           ) |> SOME
   711           ) |> SOME
   706       | ml_from_def (name, CodegenThingol.Classinst (((class, (tyco, arity)), suparities), memdefs)) =
   712       | ml_from_def (name, CodegenThingol.Classinst (((class, (tyco, arity)), suparities), memdefs)) =
   707           let
   713           let
   708             val definer = if null arity then "val" else "fun"
   714             val definer = if null arity then "val" else "fun"
   709             fun from_supclass (supclass, (supinst, lss)) =
   715             fun from_supclass (supclass, ls) =
   710               (Pretty.block o Pretty.breaks) (
   716               (Pretty.block o Pretty.breaks) [
   711                 ml_from_label supclass
   717                 ml_from_label supclass,
   712                 :: str "="
   718                 str "=",
   713                 :: (str o resolv) supinst
   719                 ml_from_sortlookup NOBR ls
   714                 :: (if null lss andalso (not o null) arity
   720               ];
   715                      then [str "()"]
       
   716                      else map (ml_from_sortlookup NOBR) lss)
       
   717               );
       
   718             fun from_memdef (m, ((m', def), lss)) =
   721             fun from_memdef (m, ((m', def), lss)) =
   719               (ml_from_funs [(m', def)], (Pretty.block o Pretty.breaks) (
   722               (ml_from_funs [(m', def)], (Pretty.block o Pretty.breaks) (
   720                 ml_from_label m
   723                 ml_from_label m
   721                 :: str "="
   724                 :: str "="
   722                 :: (str o resolv) m'
   725                 :: (str o resolv) m'
   829 
   832 
   830 end; (* local *)
   833 end; (* local *)
   831 
   834 
   832 local
   835 local
   833 
   836 
   834 fun hs_from_defs with_typs (class_syntax, tyco_syntax, const_syntax)
   837 fun hs_from_defs (is_cons, with_typs) (class_syntax, tyco_syntax, const_syntax)
   835     resolver prefix defs =
   838     resolver prefix defs =
   836   let
   839   let
   837     val resolv = resolver "";
   840     val resolv = resolver "";
   838     val resolv_here = resolver prefix;
   841     val resolv_here = resolver prefix;
   839     fun hs_from_sctxt vs =
   842     fun hs_from_sctxt vs =
   963             Pretty.brk 1,
   966             Pretty.brk 1,
   964             str ("="),
   967             str ("="),
   965             Pretty.brk 1,
   968             Pretty.brk 1,
   966             hs_from_expr NOBR rhs
   969             hs_from_expr NOBR rhs
   967           ]
   970           ]
   968       in Pretty.chunks ((map from_eq o fst o snd o constructive_fun) def) end;
   971       in Pretty.chunks ((map from_eq o fst o snd o constructive_fun is_cons) def) end;
   969     fun hs_from_def (name, CodegenThingol.Fun (def as (_, (sctxt, ty)))) =
   972     fun hs_from_def (name, CodegenThingol.Fun (def as (_, (sctxt, ty)))) =
   970           let
   973           let
   971             val body = hs_from_funeqs (name, def);
   974             val body = hs_from_funeqs (name, def);
   972           in if with_typs then
   975           in if with_typs then
   973             Pretty.chunks [
   976             Pretty.chunks [
  1042       | l => (SOME o Pretty.chunks o separate (str "")) l
  1045       | l => (SOME o Pretty.chunks o separate (str "")) l
  1043   end;
  1046   end;
  1044 
  1047 
  1045 in
  1048 in
  1046 
  1049 
  1047 fun hs_from_thingol target nsps_upper nspgrp =
  1050 fun hs_from_thingol target (nsp_dtcon, nsps_upper) nspgrp =
  1048   let
  1051   let
  1049     val reserved_hs = [
  1052     val reserved_hs = [
  1050       "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr",
  1053       "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr",
  1051       "import", "default", "forall", "let", "in", "class", "qualified", "data",
  1054       "import", "default", "forall", "let", "in", "class", "qualified", "data",
  1052       "newtype", "instance", "if", "then", "else", "type", "as", "do", "module"
  1055       "newtype", "instance", "if", "then", "else", "type", "as", "do", "module"
  1053     ] @ [
  1056     ] @ [
  1054       "Bool", "Integer", "Maybe", "True", "False", "Nothing", "Just", "not", "negate"
  1057       "Bool", "Integer", "Maybe", "True", "False", "Nothing", "Just", "not", "negate"
  1055     ];
  1058     ];
       
  1059     fun is_cons c = CodegenThingol.has_nsp c nsp_dtcon;
  1056     fun hs_from_module resolv imps ((_, name), ps) =
  1060     fun hs_from_module resolv imps ((_, name), ps) =
  1057       (Pretty.chunks) (
  1061       (Pretty.chunks) (
  1058         str ("module " ^ name ^ " where")
  1062         str ("module " ^ name ^ " where")
  1059         :: map (str o prefix "import qualified ") imps @ (
  1063         :: map (str o prefix "import qualified ") imps @ (
  1060           str ""
  1064           str ""
  1066       in if member (op =) nsps_upper shallow
  1070       in if member (op =) nsps_upper shallow
  1067         then ch_first Char.toUpper n
  1071         then ch_first Char.toUpper n
  1068         else ch_first Char.toLower n
  1072         else ch_first Char.toLower n
  1069       end;
  1073       end;
  1070     fun serializer with_typs = abstract_serializer (target, nspgrp)
  1074     fun serializer with_typs = abstract_serializer (target, nspgrp)
  1071       "Main" (hs_from_defs with_typs, hs_from_module, abstract_validator reserved_hs, postproc);
  1075       "Main" (hs_from_defs (is_cons, with_typs), hs_from_module, abstract_validator reserved_hs, postproc);
  1072     fun eta_expander const_syntax c =
  1076     fun eta_expander const_syntax c =
  1073       const_syntax c
  1077       const_syntax c
  1074       |> Option.map (fst o fst)
  1078       |> Option.map (fst o fst)
  1075       |> the_default 0;
  1079       |> the_default 0;
  1076   in
  1080   in