src/Pure/Tools/codegen_serializer.ML
changeset 20401 f01ae74f29f2
parent 20389 8b6ecb22ef35
child 20428 67fa1c6ba89e
equal deleted inserted replaced
20400:0ad2f3bbd4f0 20401:f01ae74f29f2
    18       -> string list * string list option
    18       -> string list * string list option
    19       -> CodegenThingol.module -> unit)
    19       -> CodegenThingol.module -> unit)
    20       * OuterParse.token list;
    20       * OuterParse.token list;
    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.iterm pretty_syntax;
    23   val pretty_list: string -> string -> (Pretty.T list -> Pretty.T)
       
    24     -> ((string -> string) * (string -> string)) option
       
    25     -> int * string -> CodegenThingol.iterm pretty_syntax;
       
    26   val pretty_ml_string: string -> string -> (string -> string) -> (string -> string)
       
    27     -> string -> CodegenThingol.iterm pretty_syntax;
    24   val serializers: {
    28   val serializers: {
    25     ml: string * (string -> serializer),
    29     ml: string * (string -> serializer),
    26     haskell: string * (string * string list -> serializer)
    30     haskell: string * (string * string list -> serializer)
    27   };
    31   };
    28   val mk_flat_ml_resolver: string list -> string -> string;
    32   val mk_flat_ml_resolver: string list -> string -> string;
   303   >> (fn "_" => serializer
   307   >> (fn "_" => serializer
   304         (fn "" => (fn p => (Pretty.writeln p; NONE))
   308         (fn "" => (fn p => (Pretty.writeln p; NONE))
   305           | _ => SOME)
   309           | _ => SOME)
   306        | _ => Scan.fail ());
   310        | _ => Scan.fail ());
   307 
   311 
   308 (* list serializer *)
   312 
   309 
   313 (* list and string serializers *)
   310 fun pretty_list thingol_nil thingol_cons (target_pred, target_cons) =
   314 
       
   315 fun implode_list c_nil c_cons e =
   311   let
   316   let
   312     fun dest_cons (IConst (c, _) `$ e1 `$ e2) =
   317     fun dest_cons (IConst (c, _) `$ e1 `$ e2) =
   313           if c = thingol_cons
   318           if c = c_cons
   314           then SOME (e1, e2)
   319           then SOME (e1, e2)
   315           else NONE
   320           else NONE
   316       | dest_cons  _ = NONE;
   321       | dest_cons  _ = NONE;
   317     fun pretty_default fxy pr e1 e2 =
   322     val (es, e') = CodegenThingol.unfoldr dest_cons e;
   318       brackify_infix (target_pred, R) fxy [
   323   in case e'
   319         pr (INFX (target_pred, X)) e1,
   324    of IConst (c, _) => if c = c_nil then SOME es else NONE
       
   325     | _ => NONE
       
   326   end;
       
   327 
       
   328 fun implode_string mk_char mk_string es =
       
   329   if forall (fn IChar _ => true | _ => false) es
       
   330   then (SOME o str o mk_string o implode o map (fn IChar (c, _) => mk_char c)) es
       
   331   else NONE;
       
   332 
       
   333 fun pretty_ml_string c_nil c_cons mk_char mk_string target_implode =
       
   334   let
       
   335     fun pretty fxy pr [e] =
       
   336       case implode_list c_nil c_cons e
       
   337        of SOME es => (case implode_string mk_char mk_string es
       
   338            of SOME p => p
       
   339             | NONE => Pretty.block [str target_implode, Pretty.brk 1, pr BR e])
       
   340         | NONE => Pretty.block [str target_implode, Pretty.brk 1, pr BR e]
       
   341   in ((1, 1), pretty) end;
       
   342 
       
   343 fun pretty_list c_nil c_cons mk_list mk_char_string (target_fxy, target_cons) =
       
   344   let
       
   345     fun default fxy pr e1 e2 =
       
   346       brackify_infix (target_fxy, R) fxy [
       
   347         pr (INFX (target_fxy, X)) e1,
   320         str target_cons,
   348         str target_cons,
   321         pr (INFX (target_pred, R)) e2
   349         pr (INFX (target_fxy, R)) e2
   322       ];
   350       ];
   323     fun pretty_compact fxy pr [e1, e2] =
   351     fun pretty fxy pr [e1, e2] =
   324       case CodegenThingol.unfoldr dest_cons e2
   352       case Option.map (cons e1) (implode_list c_nil c_cons e2)
   325        of (es, IConst (c, _)) =>
   353        of SOME es =>
   326             if c = thingol_nil
   354             (case mk_char_string
   327             then Pretty.enum "," "[" "]" (map (pr NOBR) (e1::es))
   355              of SOME (mk_char, mk_string) =>
   328             else pretty_default fxy pr e1 e2
   356                   (case implode_string mk_char mk_string es
   329         | _ => pretty_default fxy pr e1 e2;
   357                    of SOME p => p
   330   in ((2, 2), pretty_compact) end;
   358                     | NONE => mk_list (map (pr NOBR) es))
       
   359               | NONE => mk_list (map (pr NOBR) es))
       
   360         | NONE => default fxy pr e1 e2;
       
   361   in ((2, 2), pretty) end;
   331 
   362 
   332 
   363 
   333 
   364 
   334 (** ML serializer **)
   365 (** ML serializer **)
   335 
   366 
   336 local
   367 local
   337 
   368 
   338 val reserved_ml = ThmDatabase.ml_reserved @ [
   369 val reserved_ml = ThmDatabase.ml_reserved @ [
   339   "bool", "int", "list", "unit", "option", "true", "false", "not", "None", "Some", "o"
   370   "bool", "int", "list", "unit", "option", "true", "false", "not", "NONE", "SOME",
   340 ];  (* FIXME None/Some no longer used *)
   371   "o", "string", "char", "String", "Term"
       
   372 ];
   341 
   373 
   342 structure NameMangler = NameManglerFun (
   374 structure NameMangler = NameManglerFun (
   343   type ctxt = string list;
   375   type ctxt = string list;
   344   type src = string;
   376   type src = string;
   345   val ord = string_ord;
   377   val ord = string_ord;
   353 fun ml_expr_seri is_cons (tyco_syntax, const_syntax) resolv =
   385 fun ml_expr_seri is_cons (tyco_syntax, const_syntax) resolv =
   354   let
   386   let
   355     val ml_from_label =
   387     val ml_from_label =
   356       str o translate_string (fn "_" => "__" | "." => "_" | c => c)
   388       str o translate_string (fn "_" => "__" | "." => "_" | c => c)
   357         o NameSpace.base o resolv;
   389         o NameSpace.base o resolv;
       
   390     fun ml_from_dictvar v = 
       
   391       str (Symbol.to_ascii_upper v ^ "_");
   358     fun ml_from_tyvar (v, []) =
   392     fun ml_from_tyvar (v, []) =
   359           str "()"
   393           str "()"
   360       | ml_from_tyvar (v, sort) =
   394       | ml_from_tyvar (v, sort) =
   361           let
   395           let
   362             val w = Symbol.to_ascii_upper v;
       
   363             fun mk_class class =
   396             fun mk_class class =
   364               str (prefix "'" v ^ " " ^ resolv class);
   397               str (prefix "'" v ^ " " ^ resolv class);
   365           in
   398           in
   366             Pretty.block [
   399             Pretty.block [
   367               str "(",
   400               str "(",
   368               str w,
   401               ml_from_dictvar v,
   369               str ":",
   402               str ":",
   370               case sort
   403               case sort
   371                of [class] => mk_class class
   404                of [class] => mk_class class
   372                 | _ => Pretty.enum " *" "" "" (map mk_class sort),
   405                 | _ => Pretty.enum " *" "" "" (map mk_class sort),
   373             str ")"
   406             str ")"
   378         fun from_label l =
   411         fun from_label l =
   379           Pretty.block [str "#",
   412           Pretty.block [str "#",
   380             if (is_some o Int.fromString) l then str l
   413             if (is_some o Int.fromString) l then str l
   381             else ml_from_label l
   414             else ml_from_label l
   382           ];
   415           ];
   383         fun from_lookup fxy [] v =
   416         fun from_lookup fxy [] p =
   384               v
   417               p
   385           | from_lookup fxy [l] v =
   418           | from_lookup fxy [l] p =
   386               brackify fxy [
   419               brackify fxy [
   387                 from_label l,
   420                 from_label l,
   388                 v
   421                 p
   389               ]
   422               ]
   390           | from_lookup fxy ls v =
   423           | from_lookup fxy ls p =
   391               brackify fxy [
   424               brackify fxy [
   392                 Pretty.enum " o" "(" ")" (map from_label ls),
   425                 Pretty.enum " o" "(" ")" (map from_label ls),
   393                 v
   426                 p
   394               ];
   427               ];
   395         fun from_classlookup fxy (Instance (inst, lss)) =
   428         fun from_classlookup fxy (Instance (inst, lss)) =
   396               brackify fxy (
   429               brackify fxy (
   397                 (str o resolv) inst
   430                 (str o resolv) inst
   398                 :: map (ml_from_sortlookup BR) lss
   431                 :: map (ml_from_sortlookup BR) lss
   399               )
   432               )
   400           | from_classlookup fxy (Lookup (classes, (v, ~1))) =
   433           | from_classlookup fxy (Lookup (classes, (v, ~1))) =
   401               from_lookup BR classes
   434               from_lookup BR classes
   402                 ((str o Symbol.to_ascii_upper) v)
   435                 (ml_from_dictvar v)
   403           | from_classlookup fxy (Lookup (classes, (v, i))) =
   436           | from_classlookup fxy (Lookup (classes, (v, i))) =
   404               from_lookup BR (string_of_int (i+1) :: classes)
   437               from_lookup BR (string_of_int (i+1) :: classes)
   405                 ((str o Symbol.to_ascii_upper) v)
   438                 (ml_from_dictvar v)
   406       in case lss
   439       in case lss
   407        of [] => str "()"
   440        of [] => str "()"
   408         | [ls] => from_classlookup fxy ls
   441         | [ls] => from_classlookup fxy ls
   409         | lss => (Pretty.list "(" ")" o map (from_classlookup NOBR)) lss
   442         | lss => (Pretty.list "(" ")" o map (from_classlookup NOBR)) lss
   410       end;
   443       end;
   755       ] @ separate (str "") ps @ [
   788       ] @ separate (str "") ps @ [
   756         str "",
   789         str "",
   757         str ("end; (* struct " ^ name ^ " *)")
   790         str ("end; (* struct " ^ name ^ " *)")
   758       ]);
   791       ]);
   759     val is_cons = ml_annotators nsp_dtcon;
   792     val is_cons = ml_annotators nsp_dtcon;
       
   793     fun postproc (shallow, n) =
       
   794       let
       
   795         fun ch_first f = String.implode o nth_map 0 f o String.explode;
       
   796       in if shallow = nsp_dtcon
       
   797         then ch_first Char.toUpper n
       
   798         else n
       
   799       end;
   760   in abstract_serializer (target, nspgrp)
   800   in abstract_serializer (target, nspgrp)
   761     root_name (ml_from_defs is_cons, ml_from_module,
   801     root_name (ml_from_defs is_cons, ml_from_module,
   762      abstract_validator reserved_ml, snd) end;
   802      abstract_validator reserved_ml, postproc) end;
   763 
   803 
   764 in
   804 in
   765 
   805 
   766 fun ml_from_thingol target nsp_dtcon nspgrp =
   806 fun ml_from_thingol target nsp_dtcon nspgrp =
   767   let
   807   let
   784 
   824 
   785 fun eval_term nsp_eval nsp_dtcon nspgrp (syntax_tyco, syntax_const) hidden ((ref_name, reff), e) modl =
   825 fun eval_term nsp_eval nsp_dtcon nspgrp (syntax_tyco, syntax_const) hidden ((ref_name, reff), e) modl =
   786   let
   826   let
   787     val (val_name, modl') = CodegenThingol.add_eval_def (nsp_eval, e) modl;
   827     val (val_name, modl') = CodegenThingol.add_eval_def (nsp_eval, e) modl;
   788     val struct_name = "EVAL";
   828     val struct_name = "EVAL";
       
   829     fun output p = if !eval_verbose then (Pretty.writeln p; Pretty.output p)
       
   830       else Pretty.output p;
   789     val serializer = ml_serializer struct_name "ml" nsp_dtcon nspgrp
   831     val serializer = ml_serializer struct_name "ml" nsp_dtcon nspgrp
   790       (fn "" => (fn p => (use_text Context.ml_output (!eval_verbose) (Pretty.output p); NONE))
   832       (fn "" => (fn p => (use_text Context.ml_output (!eval_verbose) (output p); NONE))
   791         | _ => SOME) (K NONE, syntax_tyco, syntax_const) (hidden, SOME [NameSpace.pack [nsp_eval, val_name]]);
   833         | _ => SOME) (K NONE, syntax_tyco, syntax_const) (hidden, SOME [NameSpace.pack [nsp_eval, val_name]]);
   792     val _ = serializer modl';
   834     val _ = serializer modl';
   793     val val_name_struct = NameSpace.append struct_name val_name;
   835     val val_name_struct = NameSpace.append struct_name val_name;
   794     val _ = use_text Context.ml_output (!eval_verbose) ("val _ = (" ^ ref_name ^ " := " ^ val_name_struct ^ "())");
   836     val _ = use_text Context.ml_output (!eval_verbose) ("val _ = (" ^ ref_name ^ " := " ^ val_name_struct ^ "())");
   795     val value = ! reff;
   837     val value = ! reff;
   949               ],
   991               ],
   950               body
   992               body
   951             ] |> SOME
   993             ] |> SOME
   952           else SOME body end
   994           else SOME body end
   953       | hs_from_def (name, CodegenThingol.Typesyn (sctxt, ty)) =
   995       | hs_from_def (name, CodegenThingol.Typesyn (sctxt, ty)) =
   954           Pretty.block [
   996           (Pretty.block o Pretty.breaks) [
   955             str "type ",
   997             str "type",
   956             hs_from_sctxt_tycoexpr (sctxt, (resolv_here name, map (ITyVar o fst) sctxt)),
   998             hs_from_sctxt_tycoexpr (sctxt, (resolv_here name, map (ITyVar o fst) sctxt)),
   957             str " =",
   999             str "=",
   958             Pretty.brk 1,
       
   959             hs_from_sctxt_type ([], ty)
  1000             hs_from_sctxt_type ([], ty)
   960           ] |> SOME
  1001           ] |> SOME
   961       | hs_from_def (name, CodegenThingol.Datatype (sctxt, [(co, tys)])) =
  1002       | hs_from_def (name, CodegenThingol.Datatype (sctxt, [(co, [ty])])) =
   962           (Pretty.block o Pretty.breaks) [
  1003           (Pretty.block o Pretty.breaks) [
   963             str "newtype",
  1004             str "newtype",
   964             hs_from_sctxt_tycoexpr (sctxt, (resolv_here name, map (ITyVar o fst) sctxt)),
  1005             hs_from_sctxt_tycoexpr (sctxt, (resolv_here name, map (ITyVar o fst) sctxt)),
   965             str "=",
  1006             str "=",
   966             (Pretty.block o Pretty.breaks) (
  1007             (str o resolv_here) co,
   967               (str o resolv_here) co
  1008             hs_from_type BR ty
   968               :: map (hs_from_type BR) tys
       
   969             )
       
   970           ] |> SOME
  1009           ] |> SOME
   971       | hs_from_def (name, CodegenThingol.Datatype (sctxt, constrs)) =
  1010       | hs_from_def (name, CodegenThingol.Datatype (sctxt, constrs)) =
   972           let
  1011           let
   973             fun mk_cons (co, tys) =
  1012             fun mk_cons (co, tys) =
   974               (Pretty.block o Pretty.breaks) (
  1013               (Pretty.block o Pretty.breaks) (
  1034     val reserved_hs = [
  1073     val reserved_hs = [
  1035       "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr",
  1074       "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr",
  1036       "import", "default", "forall", "let", "in", "class", "qualified", "data",
  1075       "import", "default", "forall", "let", "in", "class", "qualified", "data",
  1037       "newtype", "instance", "if", "then", "else", "type", "as", "do", "module"
  1076       "newtype", "instance", "if", "then", "else", "type", "as", "do", "module"
  1038     ] @ [
  1077     ] @ [
  1039       "Bool", "Integer", "Maybe", "True", "False", "Nothing", "Just", "not", "negate"
  1078       "Bool", "Integer", "Maybe", "True", "False", "Nothing", "Just", "not", "negate",
       
  1079       "String", "Char"
  1040     ];
  1080     ];
  1041     fun is_cons c = CodegenThingol.has_nsp c nsp_dtcon;
  1081     fun is_cons c = CodegenThingol.has_nsp c nsp_dtcon;
  1042     fun hs_from_module resolv imps ((_, name), ps) =
  1082     fun hs_from_module resolv imps ((_, name), ps) =
  1043       (Pretty.chunks) (
  1083       (Pretty.chunks) (
  1044         str ("module " ^ name ^ " where")
  1084         str ("module " ^ name ^ " where")