src/Tools/Code/code_haskell.ML
changeset 33991 45d94947426a
parent 33421 3789fe962a08
child 33994 fc8af744f63c
equal deleted inserted replaced
33990:febc68c02b63 33991:45d94947426a
    21 infixr 5 @|;
    21 infixr 5 @|;
    22 
    22 
    23 
    23 
    24 (** Haskell serializer **)
    24 (** Haskell serializer **)
    25 
    25 
    26 fun pr_haskell_stmt labelled_name syntax_class syntax_tyco syntax_const
    26 fun print_haskell_stmt labelled_name syntax_class syntax_tyco syntax_const
    27     reserved deresolve contr_classparam_typs deriving_show =
    27     reserved deresolve contr_classparam_typs deriving_show =
    28   let
    28   let
    29     val deresolve_base = Long_Name.base_name o deresolve;
    29     val deresolve_base = Long_Name.base_name o deresolve;
    30     fun class_name class = case syntax_class class
    30     fun class_name class = case syntax_class class
    31      of NONE => deresolve class
    31      of NONE => deresolve class
    32       | SOME class => class;
    32       | SOME class => class;
    33     fun pr_typcontext tyvars vs = case maps (fn (v, sort) => map (pair v) sort) vs
    33     fun print_typcontext tyvars vs = case maps (fn (v, sort) => map (pair v) sort) vs
    34      of [] => []
    34      of [] => []
    35       | classbinds => Pretty.enum "," "(" ")" (
    35       | classbinds => Pretty.list "(" ")" (
    36           map (fn (v, class) =>
    36           map (fn (v, class) =>
    37             str (class_name class ^ " " ^ lookup_var tyvars v)) classbinds)
    37             str (class_name class ^ " " ^ lookup_var tyvars v)) classbinds)
    38           @@ str " => ";
    38           @@ str " => ";
    39     fun pr_typforall tyvars vs = case map fst vs
    39     fun print_typforall tyvars vs = case map fst vs
    40      of [] => []
    40      of [] => []
    41       | vnames => str "forall " :: Pretty.breaks
    41       | vnames => str "forall " :: Pretty.breaks
    42           (map (str o lookup_var tyvars) vnames) @ str "." @@ Pretty.brk 1;
    42           (map (str o lookup_var tyvars) vnames) @ str "." @@ Pretty.brk 1;
    43     fun pr_tycoexpr tyvars fxy (tyco, tys) =
    43     fun print_tyco_expr tyvars fxy (tyco, tys) =
    44       brackify fxy (str tyco :: map (pr_typ tyvars BR) tys)
    44       brackify fxy (str tyco :: map (print_typ tyvars BR) tys)
    45     and pr_typ tyvars fxy (tycoexpr as tyco `%% tys) = (case syntax_tyco tyco
    45     and print_typ tyvars fxy (tycoexpr as tyco `%% tys) = (case syntax_tyco tyco
    46          of NONE => pr_tycoexpr tyvars fxy (deresolve tyco, tys)
    46          of NONE => print_tyco_expr tyvars fxy (deresolve tyco, tys)
    47           | SOME (i, pr) => pr (pr_typ tyvars) fxy tys)
    47           | SOME (i, print) => print (print_typ tyvars) fxy tys)
    48       | pr_typ tyvars fxy (ITyVar v) = (str o lookup_var tyvars) v;
    48       | print_typ tyvars fxy (ITyVar v) = (str o lookup_var tyvars) v;
    49     fun pr_typdecl tyvars (vs, tycoexpr) =
    49     fun print_typdecl tyvars (vs, tycoexpr) =
    50       Pretty.block (pr_typcontext tyvars vs @| pr_tycoexpr tyvars NOBR tycoexpr);
    50       Pretty.block (print_typcontext tyvars vs @| print_tyco_expr tyvars NOBR tycoexpr);
    51     fun pr_typscheme tyvars (vs, ty) =
    51     fun print_typscheme tyvars (vs, ty) =
    52       Pretty.block (pr_typforall tyvars vs @ pr_typcontext tyvars vs @| pr_typ tyvars NOBR ty);
    52       Pretty.block (print_typforall tyvars vs @ print_typcontext tyvars vs @| print_typ tyvars NOBR ty);
    53     fun pr_term tyvars thm vars fxy (IConst c) =
    53     fun print_term tyvars thm vars fxy (IConst c) =
    54           pr_app tyvars thm vars fxy (c, [])
    54           print_app tyvars thm vars fxy (c, [])
    55       | pr_term tyvars thm vars fxy (t as (t1 `$ t2)) =
    55       | print_term tyvars thm vars fxy (t as (t1 `$ t2)) =
    56           (case Code_Thingol.unfold_const_app t
    56           (case Code_Thingol.unfold_const_app t
    57            of SOME app => pr_app tyvars thm vars fxy app
    57            of SOME app => print_app tyvars thm vars fxy app
    58             | _ =>
    58             | _ =>
    59                 brackify fxy [
    59                 brackify fxy [
    60                   pr_term tyvars thm vars NOBR t1,
    60                   print_term tyvars thm vars NOBR t1,
    61                   pr_term tyvars thm vars BR t2
    61                   print_term tyvars thm vars BR t2
    62                 ])
    62                 ])
    63       | pr_term tyvars thm vars fxy (IVar NONE) =
    63       | print_term tyvars thm vars fxy (IVar NONE) =
    64           str "_"
    64           str "_"
    65       | pr_term tyvars thm vars fxy (IVar (SOME v)) =
    65       | print_term tyvars thm vars fxy (IVar (SOME v)) =
    66           (str o lookup_var vars) v
    66           (str o lookup_var vars) v
    67       | pr_term tyvars thm vars fxy (t as _ `|=> _) =
    67       | print_term tyvars thm vars fxy (t as _ `|=> _) =
    68           let
    68           let
    69             val (binds, t') = Code_Thingol.unfold_pat_abs t;
    69             val (binds, t') = Code_Thingol.unfold_pat_abs t;
    70             val (ps, vars') = fold_map (pr_bind tyvars thm BR o fst) binds vars;
    70             val (ps, vars') = fold_map (print_bind tyvars thm BR o fst) binds vars;
    71           in brackets (str "\\" :: ps @ str "->" @@ pr_term tyvars thm vars' NOBR t') end
    71           in brackets (str "\\" :: ps @ str "->" @@ print_term tyvars thm vars' NOBR t') end
    72       | pr_term tyvars thm vars fxy (ICase (cases as (_, t0))) =
    72       | print_term tyvars thm vars fxy (ICase (cases as (_, t0))) =
    73           (case Code_Thingol.unfold_const_app t0
    73           (case Code_Thingol.unfold_const_app t0
    74            of SOME (c_ts as ((c, _), _)) => if is_none (syntax_const c)
    74            of SOME (c_ts as ((c, _), _)) => if is_none (syntax_const c)
    75                 then pr_case tyvars thm vars fxy cases
    75                 then print_case tyvars thm vars fxy cases
    76                 else pr_app tyvars thm vars fxy c_ts
    76                 else print_app tyvars thm vars fxy c_ts
    77             | NONE => pr_case tyvars thm vars fxy cases)
    77             | NONE => print_case tyvars thm vars fxy cases)
    78     and pr_app' tyvars thm vars ((c, (_, tys)), ts) = case contr_classparam_typs c
    78     and print_app_expr tyvars thm vars ((c, (_, tys)), ts) = case contr_classparam_typs c
    79      of [] => (str o deresolve) c :: map (pr_term tyvars thm vars BR) ts
    79      of [] => (str o deresolve) c :: map (print_term tyvars thm vars BR) ts
    80       | fingerprint => let
    80       | fingerprint => let
    81           val ts_fingerprint = ts ~~ curry Library.take (length ts) fingerprint;
    81           val ts_fingerprint = ts ~~ curry Library.take (length ts) fingerprint;
    82           val needs_annotation = forall (fn (_, NONE) => true | (t, SOME _) =>
    82           val needs_annotation = forall (fn (_, NONE) => true | (t, SOME _) =>
    83             (not o Code_Thingol.locally_monomorphic) t) ts_fingerprint;
    83             (not o Code_Thingol.locally_monomorphic) t) ts_fingerprint;
    84           fun pr_term_anno (t, NONE) _ = pr_term tyvars thm vars BR t
    84           fun print_term_anno (t, NONE) _ = print_term tyvars thm vars BR t
    85             | pr_term_anno (t, SOME _) ty =
    85             | print_term_anno (t, SOME _) ty =
    86                 brackets [pr_term tyvars thm vars NOBR t, str "::", pr_typ tyvars NOBR ty];
    86                 brackets [print_term tyvars thm vars NOBR t, str "::", print_typ tyvars NOBR ty];
    87         in
    87         in
    88           if needs_annotation then
    88           if needs_annotation then
    89             (str o deresolve) c :: map2 pr_term_anno ts_fingerprint (curry Library.take (length ts) tys)
    89             (str o deresolve) c :: map2 print_term_anno ts_fingerprint (curry Library.take (length ts) tys)
    90           else (str o deresolve) c :: map (pr_term tyvars thm vars BR) ts
    90           else (str o deresolve) c :: map (print_term tyvars thm vars BR) ts
    91         end
    91         end
    92     and pr_app tyvars = gen_pr_app (pr_app' tyvars) (pr_term tyvars) syntax_const
    92     and print_app tyvars = gen_print_app (print_app_expr tyvars) (print_term tyvars) syntax_const
    93     and pr_bind tyvars thm fxy p = gen_pr_bind (pr_term tyvars) thm fxy p
    93     and print_bind tyvars thm fxy p = gen_print_bind (print_term tyvars) thm fxy p
    94     and pr_case tyvars thm vars fxy (cases as ((_, [_]), _)) =
    94     and print_case tyvars thm vars fxy (cases as ((_, [_]), _)) =
    95           let
    95           let
    96             val (binds, body) = Code_Thingol.unfold_let (ICase cases);
    96             val (binds, body) = Code_Thingol.unfold_let (ICase cases);
    97             fun pr ((pat, ty), t) vars =
    97             fun print_match ((pat, ty), t) vars =
    98               vars
    98               vars
    99               |> pr_bind tyvars thm BR pat
    99               |> print_bind tyvars thm BR pat
   100               |>> (fn p => semicolon [p, str "=", pr_term tyvars thm vars NOBR t])
   100               |>> (fn p => semicolon [p, str "=", print_term tyvars thm vars NOBR t])
   101             val (ps, vars') = fold_map pr binds vars;
   101             val (ps, vars') = fold_map print_match binds vars;
   102           in brackify_block fxy (str "let {")
   102           in brackify_block fxy (str "let {")
   103             ps
   103             ps
   104             (concat [str "}", str "in", pr_term tyvars thm vars' NOBR body])
   104             (concat [str "}", str "in", print_term tyvars thm vars' NOBR body])
   105           end
   105           end
   106       | pr_case tyvars thm vars fxy (((t, ty), clauses as _ :: _), _) =
   106       | print_case tyvars thm vars fxy (((t, ty), clauses as _ :: _), _) =
   107           let
   107           let
   108             fun pr (pat, body) =
   108             fun print_select (pat, body) =
   109               let
   109               let
   110                 val (p, vars') = pr_bind tyvars thm NOBR pat vars;
   110                 val (p, vars') = print_bind tyvars thm NOBR pat vars;
   111               in semicolon [p, str "->", pr_term tyvars thm vars' NOBR body] end;
   111               in semicolon [p, str "->", print_term tyvars thm vars' NOBR body] end;
   112           in brackify_block fxy
   112           in brackify_block fxy
   113             (concat [str "case", pr_term tyvars thm vars NOBR t, str "of", str "{"])
   113             (concat [str "case", print_term tyvars thm vars NOBR t, str "of", str "{"])
   114             (map pr clauses)
   114             (map print_select clauses)
   115             (str "}") 
   115             (str "}") 
   116           end
   116           end
   117       | pr_case tyvars thm vars fxy ((_, []), _) =
   117       | print_case tyvars thm vars fxy ((_, []), _) =
   118           (brackify fxy o Pretty.breaks o map str) ["error", "\"empty case\""];
   118           (brackify fxy o Pretty.breaks o map str) ["error", "\"empty case\""];
   119     fun pr_stmt (name, Code_Thingol.Fun (_, ((vs, ty), []))) =
   119     fun print_stmt (name, Code_Thingol.Fun (_, ((vs, ty), []))) =
   120           let
   120           let
   121             val tyvars = intro_vars (map fst vs) reserved;
   121             val tyvars = intro_vars (map fst vs) reserved;
   122             val n = (length o fst o Code_Thingol.unfold_fun) ty;
   122             val n = (length o fst o Code_Thingol.unfold_fun) ty;
   123           in
   123           in
   124             Pretty.chunks [
   124             Pretty.chunks [
   125               Pretty.block [
   125               semicolon [
   126                 (str o suffix " ::" o deresolve_base) name,
   126                 (str o suffix " ::" o deresolve_base) name,
   127                 Pretty.brk 1,
   127                 print_typscheme tyvars (vs, ty)
   128                 pr_typscheme tyvars (vs, ty),
       
   129                 str ";"
       
   130               ],
   128               ],
   131               concat (
   129               semicolon (
   132                 (str o deresolve_base) name
   130                 (str o deresolve_base) name
   133                 :: map str (replicate n "_")
   131                 :: map str (replicate n "_")
   134                 @ str "="
   132                 @ str "="
   135                 :: str "error"
   133                 :: str "error"
   136                 @@ (str o (fn s => s ^ ";") o ML_Syntax.print_string
   134                 @@ (str o ML_Syntax.print_string
   137                     o Long_Name.base_name o Long_Name.qualifier) name
   135                     o Long_Name.base_name o Long_Name.qualifier) name
   138               )
   136               )
   139             ]
   137             ]
   140           end
   138           end
   141       | pr_stmt (name, Code_Thingol.Fun (_, ((vs, ty), raw_eqs))) =
   139       | print_stmt (name, Code_Thingol.Fun (_, ((vs, ty), raw_eqs))) =
   142           let
   140           let
   143             val eqs = filter (snd o snd) raw_eqs;
   141             val eqs = filter (snd o snd) raw_eqs;
   144             val tyvars = intro_vars (map fst vs) reserved;
   142             val tyvars = intro_vars (map fst vs) reserved;
   145             fun pr_eq ((ts, t), (thm, _)) =
   143             fun print_eqn ((ts, t), (thm, _)) =
   146               let
   144               let
   147                 val consts = fold Code_Thingol.add_constnames (t :: ts) [];
   145                 val consts = fold Code_Thingol.add_constnames (t :: ts) [];
   148                 val vars = reserved
   146                 val vars = reserved
   149                   |> intro_base_names
   147                   |> intro_base_names
   150                       (is_none o syntax_const) deresolve consts
   148                       (is_none o syntax_const) deresolve consts
   151                   |> intro_vars ((fold o Code_Thingol.fold_varnames)
   149                   |> intro_vars ((fold o Code_Thingol.fold_varnames)
   152                       (insert (op =)) ts []);
   150                       (insert (op =)) ts []);
   153               in
   151               in
   154                 semicolon (
   152                 semicolon (
   155                   (str o deresolve_base) name
   153                   (str o deresolve_base) name
   156                   :: map (pr_term tyvars thm vars BR) ts
   154                   :: map (print_term tyvars thm vars BR) ts
   157                   @ str "="
   155                   @ str "="
   158                   @@ pr_term tyvars thm vars NOBR t
   156                   @@ print_term tyvars thm vars NOBR t
   159                 )
   157                 )
   160               end;
   158               end;
   161           in
   159           in
   162             Pretty.chunks (
   160             Pretty.chunks (
   163               Pretty.block [
   161               semicolon [
   164                 (str o suffix " ::" o deresolve_base) name,
   162                 (str o suffix " ::" o deresolve_base) name,
   165                 Pretty.brk 1,
   163                 print_typscheme tyvars (vs, ty)
   166                 pr_typscheme tyvars (vs, ty),
       
   167                 str ";"
       
   168               ]
   164               ]
   169               :: map pr_eq eqs
   165               :: map print_eqn eqs
   170             )
   166             )
   171           end
   167           end
   172       | pr_stmt (name, Code_Thingol.Datatype (_, (vs, []))) =
   168       | print_stmt (name, Code_Thingol.Datatype (_, (vs, []))) =
   173           let
   169           let
   174             val tyvars = intro_vars (map fst vs) reserved;
   170             val tyvars = intro_vars (map fst vs) reserved;
   175           in
   171           in
   176             semicolon [
   172             semicolon [
   177               str "data",
   173               str "data",
   178               pr_typdecl tyvars (vs, (deresolve_base name, map (ITyVar o fst) vs))
   174               print_typdecl tyvars (vs, (deresolve_base name, map (ITyVar o fst) vs))
   179             ]
   175             ]
   180           end
   176           end
   181       | pr_stmt (name, Code_Thingol.Datatype (_, (vs, [(co, [ty])]))) =
   177       | print_stmt (name, Code_Thingol.Datatype (_, (vs, [(co, [ty])]))) =
   182           let
   178           let
   183             val tyvars = intro_vars (map fst vs) reserved;
   179             val tyvars = intro_vars (map fst vs) reserved;
   184           in
   180           in
   185             semicolon (
   181             semicolon (
   186               str "newtype"
   182               str "newtype"
   187               :: pr_typdecl tyvars (vs, (deresolve_base name, map (ITyVar o fst) vs))
   183               :: print_typdecl tyvars (vs, (deresolve_base name, map (ITyVar o fst) vs))
   188               :: str "="
   184               :: str "="
   189               :: (str o deresolve_base) co
   185               :: (str o deresolve_base) co
   190               :: pr_typ tyvars BR ty
   186               :: print_typ tyvars BR ty
   191               :: (if deriving_show name then [str "deriving (Read, Show)"] else [])
   187               :: (if deriving_show name then [str "deriving (Read, Show)"] else [])
   192             )
   188             )
   193           end
   189           end
   194       | pr_stmt (name, Code_Thingol.Datatype (_, (vs, co :: cos))) =
   190       | print_stmt (name, Code_Thingol.Datatype (_, (vs, co :: cos))) =
   195           let
   191           let
   196             val tyvars = intro_vars (map fst vs) reserved;
   192             val tyvars = intro_vars (map fst vs) reserved;
   197             fun pr_co (co, tys) =
   193             fun print_co (co, tys) =
   198               concat (
   194               concat (
   199                 (str o deresolve_base) co
   195                 (str o deresolve_base) co
   200                 :: map (pr_typ tyvars BR) tys
   196                 :: map (print_typ tyvars BR) tys
   201               )
   197               )
   202           in
   198           in
   203             semicolon (
   199             semicolon (
   204               str "data"
   200               str "data"
   205               :: pr_typdecl tyvars (vs, (deresolve_base name, map (ITyVar o fst) vs))
   201               :: print_typdecl tyvars (vs, (deresolve_base name, map (ITyVar o fst) vs))
   206               :: str "="
   202               :: str "="
   207               :: pr_co co
   203               :: print_co co
   208               :: map ((fn p => Pretty.block [str "| ", p]) o pr_co) cos
   204               :: map ((fn p => Pretty.block [str "| ", p]) o print_co) cos
   209               @ (if deriving_show name then [str "deriving (Read, Show)"] else [])
   205               @ (if deriving_show name then [str "deriving (Read, Show)"] else [])
   210             )
   206             )
   211           end
   207           end
   212       | pr_stmt (name, Code_Thingol.Class (_, (v, (superclasses, classparams)))) =
   208       | print_stmt (name, Code_Thingol.Class (_, (v, (superclasses, classparams)))) =
   213           let
   209           let
   214             val tyvars = intro_vars [v] reserved;
   210             val tyvars = intro_vars [v] reserved;
   215             fun pr_classparam (classparam, ty) =
   211             fun print_classparam (classparam, ty) =
   216               semicolon [
   212               semicolon [
   217                 (str o deresolve_base) classparam,
   213                 (str o deresolve_base) classparam,
   218                 str "::",
   214                 str "::",
   219                 pr_typ tyvars NOBR ty
   215                 print_typ tyvars NOBR ty
   220               ]
   216               ]
   221           in
   217           in
   222             Pretty.block_enclose (
   218             Pretty.block_enclose (
   223               Pretty.block [
   219               Pretty.block [
   224                 str "class ",
   220                 str "class ",
   225                 Pretty.block (pr_typcontext tyvars [(v, map fst superclasses)]),
   221                 Pretty.block (print_typcontext tyvars [(v, map fst superclasses)]),
   226                 str (deresolve_base name ^ " " ^ lookup_var tyvars v),
   222                 str (deresolve_base name ^ " " ^ lookup_var tyvars v),
   227                 str " where {"
   223                 str " where {"
   228               ],
   224               ],
   229               str "};"
   225               str "};"
   230             ) (map pr_classparam classparams)
   226             ) (map print_classparam classparams)
   231           end
   227           end
   232       | pr_stmt (_, Code_Thingol.Classinst ((class, (tyco, vs)), (_, classparam_insts))) =
   228       | print_stmt (_, Code_Thingol.Classinst ((class, (tyco, vs)), (_, classparam_insts))) =
   233           let
   229           let
   234             val tyvars = intro_vars (map fst vs) reserved;
   230             val tyvars = intro_vars (map fst vs) reserved;
   235             fun pr_instdef ((classparam, c_inst), (thm, _)) = case syntax_const classparam
   231             fun print_instdef ((classparam, c_inst), (thm, _)) = case syntax_const classparam
   236              of NONE => semicolon [
   232              of NONE => semicolon [
   237                     (str o deresolve_base) classparam,
   233                     (str o deresolve_base) classparam,
   238                     str "=",
   234                     str "=",
   239                     pr_app tyvars thm reserved NOBR (c_inst, [])
   235                     print_app tyvars thm reserved NOBR (c_inst, [])
   240                   ]
   236                   ]
   241               | SOME (k, pr) =>
   237               | SOME (k, pr) =>
   242                   let
   238                   let
   243                     val (c_inst_name, (_, tys)) = c_inst;
   239                     val (c_inst_name, (_, tys)) = c_inst;
   244                     val const = if (is_some o syntax_const) c_inst_name
   240                     val const = if (is_some o syntax_const) c_inst_name
   250                       |> intro_vars (map_filter I vs);
   246                       |> intro_vars (map_filter I vs);
   251                     val lhs = IConst (classparam, (([], []), tys)) `$$ map IVar vs;
   247                     val lhs = IConst (classparam, (([], []), tys)) `$$ map IVar vs;
   252                       (*dictionaries are not relevant at this late stage*)
   248                       (*dictionaries are not relevant at this late stage*)
   253                   in
   249                   in
   254                     semicolon [
   250                     semicolon [
   255                       pr_term tyvars thm vars NOBR lhs,
   251                       print_term tyvars thm vars NOBR lhs,
   256                       str "=",
   252                       str "=",
   257                       pr_term tyvars thm vars NOBR rhs
   253                       print_term tyvars thm vars NOBR rhs
   258                     ]
   254                     ]
   259                   end;
   255                   end;
   260           in
   256           in
   261             Pretty.block_enclose (
   257             Pretty.block_enclose (
   262               Pretty.block [
   258               Pretty.block [
   263                 str "instance ",
   259                 str "instance ",
   264                 Pretty.block (pr_typcontext tyvars vs),
   260                 Pretty.block (print_typcontext tyvars vs),
   265                 str (class_name class ^ " "),
   261                 str (class_name class ^ " "),
   266                 pr_typ tyvars BR (tyco `%% map (ITyVar o fst) vs),
   262                 print_typ tyvars BR (tyco `%% map (ITyVar o fst) vs),
   267                 str " where {"
   263                 str " where {"
   268               ],
   264               ],
   269               str "};"
   265               str "};"
   270             ) (map pr_instdef classparam_insts)
   266             ) (map print_instdef classparam_insts)
   271           end;
   267           end;
   272   in pr_stmt end;
   268   in print_stmt end;
   273 
   269 
   274 fun haskell_program_of_program labelled_name module_name module_prefix reserved raw_module_alias program =
   270 fun haskell_program_of_program labelled_name module_name module_prefix reserved raw_module_alias program =
   275   let
   271   let
   276     val module_alias = if is_some module_name then K module_name else raw_module_alias;
   272     val module_alias = if is_some module_name then K module_name else raw_module_alias;
   277     val reserved = Name.make_context reserved;
   273     val reserved = Name.make_context reserved;
   342         and deriv' tycos (tyco `%% tys) = deriv tycos tyco
   338         and deriv' tycos (tyco `%% tys) = deriv tycos tyco
   343               andalso forall (deriv' tycos) tys
   339               andalso forall (deriv' tycos) tys
   344           | deriv' _ (ITyVar _) = true
   340           | deriv' _ (ITyVar _) = true
   345       in deriv [] tyco end;
   341       in deriv [] tyco end;
   346     val reserved = make_vars reserved;
   342     val reserved = make_vars reserved;
   347     fun pr_stmt qualified = pr_haskell_stmt labelled_name
   343     fun print_stmt qualified = print_haskell_stmt labelled_name
   348       syntax_class syntax_tyco syntax_const reserved
   344       syntax_class syntax_tyco syntax_const reserved
   349       (if qualified then deresolver else Long_Name.base_name o deresolver)
   345       (if qualified then deresolver else Long_Name.base_name o deresolver)
   350       contr_classparam_typs
   346       contr_classparam_typs
   351       (if string_classes then deriving_show else K false);
   347       (if string_classes then deriving_show else K false);
   352     fun pr_module name content =
   348     fun print_module name content =
   353       (name, Pretty.chunks [
   349       (name, Pretty.chunks [
   354         str ("module " ^ name ^ " where {"),
   350         str ("module " ^ name ^ " where {"),
   355         str "",
   351         str "",
   356         content,
   352         content,
   357         str "",
   353         str "",
   364         val imports = subtract (op =) stmt_names deps
   360         val imports = subtract (op =) stmt_names deps
   365           |> distinct (op =)
   361           |> distinct (op =)
   366           |> map_filter (try deresolver)
   362           |> map_filter (try deresolver)
   367           |> map Long_Name.qualifier
   363           |> map Long_Name.qualifier
   368           |> distinct (op =);
   364           |> distinct (op =);
   369         fun pr_import_include (name, _) = str ("import qualified " ^ name ^ ";");
   365         fun print_import_include (name, _) = str ("import qualified " ^ name ^ ";");
   370         val pr_import_module = str o (if qualified
   366         val print_import_module = str o (if qualified
   371           then prefix "import qualified "
   367           then prefix "import qualified "
   372           else prefix "import ") o suffix ";";
   368           else prefix "import ") o suffix ";";
   373         val content = Pretty.chunks (
   369         val import_ps = map print_import_include includes @ map print_import_module imports
   374             map pr_import_include includes
   370         val content = Pretty.chunks2 (if null import_ps then [] else [Pretty.block import_ps]
   375             @ map pr_import_module imports
   371             @ map_filter
   376             @ str ""
   372               (fn (name, (_, SOME stmt)) => SOME (print_stmt qualified (name, stmt))
   377             :: separate (str "") (map_filter
   373                 | (_, (_, NONE)) => NONE) stmts
   378               (fn (name, (_, SOME stmt)) => SOME (pr_stmt qualified (name, stmt))
   374           );
   379                 | (_, (_, NONE)) => NONE) stmts)
   375       in print_module module_name' content end;
   380           )
   376     fun serialize_module2 (_, (_, (stmts, _))) = Pretty.chunks2 (map_filter
   381       in pr_module module_name' content end;
       
   382     fun serialize_module2 (_, (_, (stmts, _))) = Pretty.chunks (
       
   383       separate (str "") (map_filter
       
   384         (fn (name, (_, SOME stmt)) => if null stmt_names
   377         (fn (name, (_, SOME stmt)) => if null stmt_names
   385               orelse member (op =) stmt_names name
   378               orelse member (op =) stmt_names name
   386               then SOME (pr_stmt false (name, stmt))
   379               then SOME (print_stmt false (name, stmt))
   387               else NONE
   380               else NONE
   388           | (_, (_, NONE)) => NONE) stmts));
   381           | (_, (_, NONE)) => NONE) stmts);
   389     val serialize_module =
   382     val serialize_module =
   390       if null stmt_names then serialize_module1 else pair "" o serialize_module2;
   383       if null stmt_names then serialize_module1 else pair "" o serialize_module2;
   391     fun check_destination destination =
   384     fun check_destination destination =
   392       (File.check destination; destination);
   385       (File.check destination; destination);
   393     fun write_module destination (modlname, content) =
   386     fun write_module destination (modlname, content) =
   405   in
   398   in
   406     Code_Target.mk_serialization target NONE
   399     Code_Target.mk_serialization target NONE
   407       (fn NONE => K () o map (Code_Target.code_writeln o snd) | SOME file => K () o map
   400       (fn NONE => K () o map (Code_Target.code_writeln o snd) | SOME file => K () o map
   408         (write_module (check_destination file)))
   401         (write_module (check_destination file)))
   409       (rpair [] o cat_lines o map (Code_Target.code_of_pretty o snd))
   402       (rpair [] o cat_lines o map (Code_Target.code_of_pretty o snd))
   410       (map (uncurry pr_module) includes
   403       (map (uncurry print_module) includes
   411         @ map serialize_module (Symtab.dest hs_program))
   404         @ map serialize_module (Symtab.dest hs_program))
   412       destination
   405       destination
   413   end;
   406   end;
   414 
   407 
   415 val literals = let
   408 val literals = let
   441       | dest_monad _ t = case Code_Thingol.split_let t
   434       | dest_monad _ t = case Code_Thingol.split_let t
   442          of SOME (((pat, ty), tbind), t') =>
   435          of SOME (((pat, ty), tbind), t') =>
   443               SOME ((SOME ((pat, ty), false), tbind), t')
   436               SOME ((SOME ((pat, ty), false), tbind), t')
   444           | NONE => NONE;
   437           | NONE => NONE;
   445     fun implode_monad c_bind_name = Code_Thingol.unfoldr (dest_monad c_bind_name);
   438     fun implode_monad c_bind_name = Code_Thingol.unfoldr (dest_monad c_bind_name);
   446     fun pr_monad pr_bind pr (NONE, t) vars =
   439     fun print_monad print_bind print_term (NONE, t) vars =
   447           (semicolon [pr vars NOBR t], vars)
   440           (semicolon [print_term vars NOBR t], vars)
   448       | pr_monad pr_bind pr (SOME ((bind, _), true), t) vars = vars
   441       | print_monad print_bind print_term (SOME ((bind, _), true), t) vars = vars
   449           |> pr_bind NOBR bind
   442           |> print_bind NOBR bind
   450           |>> (fn p => semicolon [p, str "<-", pr vars NOBR t])
   443           |>> (fn p => semicolon [p, str "<-", print_term vars NOBR t])
   451       | pr_monad pr_bind pr (SOME ((bind, _), false), t) vars = vars
   444       | print_monad print_bind print_term (SOME ((bind, _), false), t) vars = vars
   452           |> pr_bind NOBR bind
   445           |> print_bind NOBR bind
   453           |>> (fn p => semicolon [str "let", p, str "=", pr vars NOBR t]);
   446           |>> (fn p => semicolon [str "let", p, str "=", print_term vars NOBR t]);
   454     fun pretty _ [c_bind'] pr thm vars fxy [(t1, _), (t2, _)] = case dest_bind t1 t2
   447     fun pretty _ [c_bind'] print_term thm vars fxy [(t1, _), (t2, _)] = case dest_bind t1 t2
   455      of SOME (bind, t') => let
   448      of SOME (bind, t') => let
   456           val (binds, t'') = implode_monad c_bind' t'
   449           val (binds, t'') = implode_monad c_bind' t'
   457           val (ps, vars') = fold_map (pr_monad (gen_pr_bind (K pr) thm) pr) (bind :: binds) vars;
   450           val (ps, vars') = fold_map (print_monad (gen_print_bind (K print_term) thm) print_term)
   458         in (brackify fxy o single o Pretty.enclose "do {" "}" o Pretty.breaks) (ps @| pr vars' NOBR t'') end
   451             (bind :: binds) vars;
       
   452         in
       
   453           (brackify fxy o single o Pretty.enclose "do {" "}" o Pretty.breaks)
       
   454             (ps @| print_term vars' NOBR t'')
       
   455         end
   459       | NONE => brackify_infix (1, L) fxy
   456       | NONE => brackify_infix (1, L) fxy
   460           [pr vars (INFX (1, L)) t1, str ">>=", pr vars (INFX (1, X)) t2]
   457           [print_term vars (INFX (1, L)) t1, str ">>=", print_term vars (INFX (1, X)) t2]
   461   in (2, ([c_bind], pretty)) end;
   458   in (2, ([c_bind], pretty)) end;
   462 
   459 
   463 fun add_monad target' raw_c_bind thy =
   460 fun add_monad target' raw_c_bind thy =
   464   let
   461   let
   465     val c_bind = Code.read_const thy raw_c_bind;
   462     val c_bind = Code.read_const thy raw_c_bind;
   470   else error "Only Haskell target allows for monad syntax" end;
   467   else error "Only Haskell target allows for monad syntax" end;
   471 
   468 
   472 
   469 
   473 (** Isar setup **)
   470 (** Isar setup **)
   474 
   471 
   475 fun isar_seri_haskell module =
   472 fun isar_seri_haskell module_name =
   476   Code_Target.parse_args (Scan.option (Args.$$$ "root" -- Args.colon |-- Args.name)
   473   Code_Target.parse_args (Scan.option (Args.$$$ "root" -- Args.colon |-- Args.name)
   477     -- Scan.optional (Args.$$$ "string_classes" >> K true) false
   474     -- Scan.optional (Args.$$$ "string_classes" >> K true) false
   478     >> (fn (module_prefix, string_classes) =>
   475     >> (fn (module_prefix, string_classes) =>
   479       serialize_haskell module_prefix module string_classes));
   476       serialize_haskell module_prefix module_name string_classes));
   480 
   477 
   481 val _ =
   478 val _ =
   482   OuterSyntax.command "code_monad" "define code syntax for monads" OuterKeyword.thy_decl (
   479   OuterSyntax.command "code_monad" "define code syntax for monads" OuterKeyword.thy_decl (
   483     OuterParse.term_group -- OuterParse.name >> (fn (raw_bind, target) =>
   480     OuterParse.term_group -- OuterParse.name >> (fn (raw_bind, target) =>
   484       Toplevel.theory  (add_monad target raw_bind))
   481       Toplevel.theory  (add_monad target raw_bind))
   485   );
   482   );
   486 
   483 
   487 val setup =
   484 val setup =
   488   Code_Target.add_target (target, (isar_seri_haskell, literals))
   485   Code_Target.add_target (target, (isar_seri_haskell, literals))
   489   #> Code_Target.add_syntax_tyco target "fun" (SOME (2, fn pr_typ => fn fxy => fn [ty1, ty2] =>
   486   #> Code_Target.add_syntax_tyco target "fun" (SOME (2, fn print_typ => fn fxy => fn [ty1, ty2] =>
   490       brackify_infix (1, R) fxy [
   487       brackify_infix (1, R) fxy [
   491         pr_typ (INFX (1, X)) ty1,
   488         print_typ (INFX (1, X)) ty1,
   492         str "->",
   489         str "->",
   493         pr_typ (INFX (1, R)) ty2
   490         print_typ (INFX (1, R)) ty2
   494       ]))
   491       ]))
   495   #> fold (Code_Target.add_reserved target) [
   492   #> fold (Code_Target.add_reserved target) [
   496       "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr",
   493       "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr",
   497       "import", "default", "forall", "let", "in", "class", "qualified", "data",
   494       "import", "default", "forall", "let", "in", "class", "qualified", "data",
   498       "newtype", "instance", "if", "then", "else", "type", "as", "do", "module"
   495       "newtype", "instance", "if", "then", "else", "type", "as", "do", "module"