src/Tools/Code/code_haskell.ML
author haftmann
Sat, 24 Jul 2010 18:08:41 +0200
changeset 38195 9728342bcd56
parent 37854 096c8397c989
child 38942 0e2596019119
child 39001 ecc713816e33
permissions -rw-r--r--
another refinement chapter in the neverending numeral story
     1 (*  Title:      Tools/Code/code_haskell.ML
     2     Author:     Florian Haftmann, TU Muenchen
     3 
     4 Serializer for Haskell.
     5 *)
     6 
     7 signature CODE_HASKELL =
     8 sig
     9   val target: string
    10   val setup: theory -> theory
    11 end;
    12 
    13 structure Code_Haskell : CODE_HASKELL =
    14 struct
    15 
    16 val target = "Haskell";
    17 
    18 open Basic_Code_Thingol;
    19 open Code_Printer;
    20 
    21 infixr 5 @@;
    22 infixr 5 @|;
    23 
    24 
    25 (** Haskell serializer **)
    26 
    27 fun print_haskell_stmt labelled_name syntax_class syntax_tyco syntax_const
    28     reserved deresolve contr_classparam_typs deriving_show =
    29   let
    30     val deresolve_base = Long_Name.base_name o deresolve;
    31     fun class_name class = case syntax_class class
    32      of NONE => deresolve class
    33       | SOME class => class;
    34     fun print_typcontext tyvars vs = case maps (fn (v, sort) => map (pair v) sort) vs
    35      of [] => []
    36       | constraints => enum "," "(" ")" (
    37           map (fn (v, class) =>
    38             str (class_name class ^ " " ^ lookup_var tyvars v)) constraints)
    39           @@ str " => ";
    40     fun print_typforall tyvars vs = case map fst vs
    41      of [] => []
    42       | vnames => str "forall " :: Pretty.breaks
    43           (map (str o lookup_var tyvars) vnames) @ str "." @@ Pretty.brk 1;
    44     fun print_tyco_expr tyvars fxy (tyco, tys) =
    45       brackify fxy (str tyco :: map (print_typ tyvars BR) tys)
    46     and print_typ tyvars fxy (tycoexpr as tyco `%% tys) = (case syntax_tyco tyco
    47          of NONE => print_tyco_expr tyvars fxy (deresolve tyco, tys)
    48           | SOME (i, print) => print (print_typ tyvars) fxy tys)
    49       | print_typ tyvars fxy (ITyVar v) = (str o lookup_var tyvars) v;
    50     fun print_typdecl tyvars (vs, tycoexpr) =
    51       Pretty.block (print_typcontext tyvars vs @| print_tyco_expr tyvars NOBR tycoexpr);
    52     fun print_typscheme tyvars (vs, ty) =
    53       Pretty.block (print_typforall tyvars vs @ print_typcontext tyvars vs @| print_typ tyvars NOBR ty);
    54     fun print_term tyvars some_thm vars fxy (IConst c) =
    55           print_app tyvars some_thm vars fxy (c, [])
    56       | print_term tyvars some_thm vars fxy (t as (t1 `$ t2)) =
    57           (case Code_Thingol.unfold_const_app t
    58            of SOME app => print_app tyvars some_thm vars fxy app
    59             | _ =>
    60                 brackify fxy [
    61                   print_term tyvars some_thm vars NOBR t1,
    62                   print_term tyvars some_thm vars BR t2
    63                 ])
    64       | print_term tyvars some_thm vars fxy (IVar NONE) =
    65           str "_"
    66       | print_term tyvars some_thm vars fxy (IVar (SOME v)) =
    67           (str o lookup_var vars) v
    68       | print_term tyvars some_thm vars fxy (t as _ `|=> _) =
    69           let
    70             val (binds, t') = Code_Thingol.unfold_pat_abs t;
    71             val (ps, vars') = fold_map (print_bind tyvars some_thm BR o fst) binds vars;
    72           in brackets (str "\\" :: ps @ str "->" @@ print_term tyvars some_thm vars' NOBR t') end
    73       | print_term tyvars some_thm vars fxy (ICase (cases as (_, t0))) =
    74           (case Code_Thingol.unfold_const_app t0
    75            of SOME (c_ts as ((c, _), _)) => if is_none (syntax_const c)
    76                 then print_case tyvars some_thm vars fxy cases
    77                 else print_app tyvars some_thm vars fxy c_ts
    78             | NONE => print_case tyvars some_thm vars fxy cases)
    79     and print_app_expr tyvars some_thm vars ((c, (_, function_typs)), ts) = case contr_classparam_typs c
    80      of [] => (str o deresolve) c :: map (print_term tyvars some_thm vars BR) ts
    81       | fingerprint => let
    82           val ts_fingerprint = ts ~~ take (length ts) fingerprint;
    83           val needs_annotation = forall (fn (_, NONE) => true | (t, SOME _) =>
    84             (not o Code_Thingol.locally_monomorphic) t) ts_fingerprint;
    85           fun print_term_anno (t, NONE) _ = print_term tyvars some_thm vars BR t
    86             | print_term_anno (t, SOME _) ty =
    87                 brackets [print_term tyvars some_thm vars NOBR t, str "::", print_typ tyvars NOBR ty];
    88         in
    89           if needs_annotation then
    90             (str o deresolve) c :: map2 print_term_anno ts_fingerprint (take (length ts) function_typs)
    91           else (str o deresolve) c :: map (print_term tyvars some_thm vars BR) ts
    92         end
    93     and print_app tyvars = gen_print_app (print_app_expr tyvars) (print_term tyvars) syntax_const
    94     and print_bind tyvars some_thm fxy p = gen_print_bind (print_term tyvars) some_thm fxy p
    95     and print_case tyvars some_thm vars fxy (cases as ((_, [_]), _)) =
    96           let
    97             val (binds, body) = Code_Thingol.unfold_let (ICase cases);
    98             fun print_match ((pat, ty), t) vars =
    99               vars
   100               |> print_bind tyvars some_thm BR pat
   101               |>> (fn p => semicolon [p, str "=", print_term tyvars some_thm vars NOBR t])
   102             val (ps, vars') = fold_map print_match binds vars;
   103           in brackify_block fxy (str "let {")
   104             ps
   105             (concat [str "}", str "in", print_term tyvars some_thm vars' NOBR body])
   106           end
   107       | print_case tyvars some_thm vars fxy (((t, ty), clauses as _ :: _), _) =
   108           let
   109             fun print_select (pat, body) =
   110               let
   111                 val (p, vars') = print_bind tyvars some_thm NOBR pat vars;
   112               in semicolon [p, str "->", print_term tyvars some_thm vars' NOBR body] end;
   113           in Pretty.block_enclose
   114             (concat [str "(case", print_term tyvars some_thm vars NOBR t, str "of", str "{"], str "})")
   115             (map print_select clauses)
   116           end
   117       | print_case tyvars some_thm vars fxy ((_, []), _) =
   118           (brackify fxy o Pretty.breaks o map str) ["error", "\"empty case\""];
   119     fun print_stmt (name, Code_Thingol.Fun (_, (((vs, ty), raw_eqs), _))) =
   120           let
   121             val tyvars = intro_vars (map fst vs) reserved;
   122             fun print_err n =
   123               semicolon (
   124                 (str o deresolve_base) name
   125                 :: map str (replicate n "_")
   126                 @ str "="
   127                 :: str "error"
   128                 @@ (str o ML_Syntax.print_string
   129                     o Long_Name.base_name o Long_Name.qualifier) name
   130               );
   131             fun print_eqn ((ts, t), (some_thm, _)) =
   132               let
   133                 val consts = fold Code_Thingol.add_constnames (t :: ts) [];
   134                 val vars = reserved
   135                   |> intro_base_names
   136                       (is_none o syntax_const) deresolve consts
   137                   |> intro_vars ((fold o Code_Thingol.fold_varnames)
   138                       (insert (op =)) ts []);
   139               in
   140                 semicolon (
   141                   (str o deresolve_base) name
   142                   :: map (print_term tyvars some_thm vars BR) ts
   143                   @ str "="
   144                   @@ print_term tyvars some_thm vars NOBR t
   145                 )
   146               end;
   147           in
   148             Pretty.chunks (
   149               semicolon [
   150                 (str o suffix " ::" o deresolve_base) name,
   151                 print_typscheme tyvars (vs, ty)
   152               ]
   153               :: (case filter (snd o snd) raw_eqs
   154                of [] => [print_err ((length o fst o Code_Thingol.unfold_fun) ty)]
   155                 | eqs => map print_eqn eqs)
   156             )
   157           end
   158       | print_stmt (name, Code_Thingol.Datatype (_, (vs, []))) =
   159           let
   160             val tyvars = intro_vars (map fst vs) reserved;
   161           in
   162             semicolon [
   163               str "data",
   164               print_typdecl tyvars (vs, (deresolve_base name, map (ITyVar o fst) vs))
   165             ]
   166           end
   167       | print_stmt (name, Code_Thingol.Datatype (_, (vs, [((co, _), [ty])]))) =
   168           let
   169             val tyvars = intro_vars (map fst vs) reserved;
   170           in
   171             semicolon (
   172               str "newtype"
   173               :: print_typdecl tyvars (vs, (deresolve_base name, map (ITyVar o fst) vs))
   174               :: str "="
   175               :: (str o deresolve_base) co
   176               :: print_typ tyvars BR ty
   177               :: (if deriving_show name then [str "deriving (Read, Show)"] else [])
   178             )
   179           end
   180       | print_stmt (name, Code_Thingol.Datatype (_, (vs, co :: cos))) =
   181           let
   182             val tyvars = intro_vars (map fst vs) reserved;
   183             fun print_co ((co, _), tys) =
   184               concat (
   185                 (str o deresolve_base) co
   186                 :: map (print_typ tyvars BR) tys
   187               )
   188           in
   189             semicolon (
   190               str "data"
   191               :: print_typdecl tyvars (vs, (deresolve_base name, map (ITyVar o fst) vs))
   192               :: str "="
   193               :: print_co co
   194               :: map ((fn p => Pretty.block [str "| ", p]) o print_co) cos
   195               @ (if deriving_show name then [str "deriving (Read, Show)"] else [])
   196             )
   197           end
   198       | print_stmt (name, Code_Thingol.Class (_, (v, (super_classes, classparams)))) =
   199           let
   200             val tyvars = intro_vars [v] reserved;
   201             fun print_classparam (classparam, ty) =
   202               semicolon [
   203                 (str o deresolve_base) classparam,
   204                 str "::",
   205                 print_typ tyvars NOBR ty
   206               ]
   207           in
   208             Pretty.block_enclose (
   209               Pretty.block [
   210                 str "class ",
   211                 Pretty.block (print_typcontext tyvars [(v, map fst super_classes)]),
   212                 str (deresolve_base name ^ " " ^ lookup_var tyvars v),
   213                 str " where {"
   214               ],
   215               str "};"
   216             ) (map print_classparam classparams)
   217           end
   218       | print_stmt (_, Code_Thingol.Classinst ((class, (tyco, vs)), (_, (classparam_instances, _)))) =
   219           let
   220             val tyvars = intro_vars (map fst vs) reserved;
   221             fun requires_args classparam = case syntax_const classparam
   222              of NONE => 0
   223               | SOME (Code_Printer.Plain_const_syntax _) => 0
   224               | SOME (Code_Printer.Complex_const_syntax (k,_ )) => k;
   225             fun print_classparam_instance ((classparam, const), (thm, _)) =
   226               case requires_args classparam
   227                of 0 => semicolon [
   228                       (str o deresolve_base) classparam,
   229                       str "=",
   230                       print_app tyvars (SOME thm) reserved NOBR (const, [])
   231                     ]
   232                 | k =>
   233                     let
   234                       val (c, (_, tys)) = const;
   235                       val (vs, rhs) = (apfst o map) fst
   236                         (Code_Thingol.unfold_abs (Code_Thingol.eta_expand k (const, [])));
   237                       val s = if (is_some o syntax_const) c
   238                         then NONE else (SOME o Long_Name.base_name o deresolve) c;
   239                       val vars = reserved
   240                         |> intro_vars (map_filter I (s :: vs));
   241                       val lhs = IConst (classparam, (([], []), tys)) `$$ map IVar vs;
   242                         (*dictionaries are not relevant at this late stage*)
   243                     in
   244                       semicolon [
   245                         print_term tyvars (SOME thm) vars NOBR lhs,
   246                         str "=",
   247                         print_term tyvars (SOME thm) vars NOBR rhs
   248                       ]
   249                     end;
   250           in
   251             Pretty.block_enclose (
   252               Pretty.block [
   253                 str "instance ",
   254                 Pretty.block (print_typcontext tyvars vs),
   255                 str (class_name class ^ " "),
   256                 print_typ tyvars BR (tyco `%% map (ITyVar o fst) vs),
   257                 str " where {"
   258               ],
   259               str "};"
   260             ) (map print_classparam_instance classparam_instances)
   261           end;
   262   in print_stmt end;
   263 
   264 fun haskell_program_of_program labelled_name module_name module_prefix reserved raw_module_alias program =
   265   let
   266     val module_alias = if is_some module_name then K module_name else raw_module_alias;
   267     val reserved = Name.make_context reserved;
   268     val mk_name_module = mk_name_module reserved module_prefix module_alias program;
   269     fun add_stmt (name, (stmt, deps)) =
   270       let
   271         val (module_name, base) = dest_name name;
   272         val module_name' = mk_name_module module_name;
   273         val mk_name_stmt = yield_singleton Name.variants;
   274         fun add_fun upper (nsp_fun, nsp_typ) =
   275           let
   276             val (base', nsp_fun') =
   277               mk_name_stmt (if upper then first_upper base else base) nsp_fun
   278           in (base', (nsp_fun', nsp_typ)) end;
   279         fun add_typ (nsp_fun, nsp_typ) =
   280           let
   281             val (base', nsp_typ') = mk_name_stmt (first_upper base) nsp_typ
   282           in (base', (nsp_fun, nsp_typ')) end;
   283         val add_name = case stmt
   284          of Code_Thingol.Fun (_, (_, SOME _)) => pair base
   285           | Code_Thingol.Fun _ => add_fun false
   286           | Code_Thingol.Datatype _ => add_typ
   287           | Code_Thingol.Datatypecons _ => add_fun true
   288           | Code_Thingol.Class _ => add_typ
   289           | Code_Thingol.Classrel _ => pair base
   290           | Code_Thingol.Classparam _ => add_fun false
   291           | Code_Thingol.Classinst _ => pair base;
   292         fun add_stmt' base' = case stmt
   293          of Code_Thingol.Fun (_, (_, SOME _)) =>
   294               I
   295           | Code_Thingol.Datatypecons _ =>
   296               cons (name, (Long_Name.append module_name' base', NONE))
   297           | Code_Thingol.Classrel _ => I
   298           | Code_Thingol.Classparam _ =>
   299               cons (name, (Long_Name.append module_name' base', NONE))
   300           | _ => cons (name, (Long_Name.append module_name' base', SOME stmt));
   301       in
   302         Symtab.map_default (module_name', ([], ([], (reserved, reserved))))
   303               (apfst (fold (insert (op = : string * string -> bool)) deps))
   304         #> `(fn program => add_name ((snd o snd o the o Symtab.lookup program) module_name'))
   305         #-> (fn (base', names) =>
   306               (Symtab.map_entry module_name' o apsnd) (fn (stmts, _) =>
   307               (add_stmt' base' stmts, names)))
   308       end;
   309     val hs_program = fold add_stmt (AList.make (fn name =>
   310       (Graph.get_node program name, Graph.imm_succs program name))
   311       (Graph.strong_conn program |> flat)) Symtab.empty;
   312     fun deresolver name = (fst o the o AList.lookup (op =) ((fst o snd o the
   313       o Symtab.lookup hs_program) ((mk_name_module o fst o dest_name) name))) name
   314       handle Option => error ("Unknown statement name: " ^ labelled_name name);
   315   in (deresolver, hs_program) end;
   316 
   317 fun serialize_haskell module_prefix raw_module_name string_classes labelled_name
   318     raw_reserved includes raw_module_alias
   319     syntax_class syntax_tyco syntax_const (code_of_pretty, code_writeln) program stmt_names destination =
   320   let
   321     val presentation_stmt_names = Code_Target.stmt_names_of_destination destination;
   322     val module_name = if null presentation_stmt_names then raw_module_name else SOME "Code";
   323     val reserved = fold (insert (op =) o fst) includes raw_reserved;
   324     val (deresolver, hs_program) = haskell_program_of_program labelled_name
   325       module_name module_prefix reserved raw_module_alias program;
   326     val contr_classparam_typs = Code_Thingol.contr_classparam_typs program;
   327     fun deriving_show tyco =
   328       let
   329         fun deriv _ "fun" = false
   330           | deriv tycos tyco = not (tyco = Code_Thingol.fun_tyco)
   331               andalso (member (op =) tycos tyco
   332               orelse case try (Graph.get_node program) tyco
   333                 of SOME (Code_Thingol.Datatype (_, (_, cs))) => forall (deriv' (tyco :: tycos))
   334                     (maps snd cs)
   335                  | NONE => true)
   336         and deriv' tycos (tyco `%% tys) = deriv tycos tyco
   337               andalso forall (deriv' tycos) tys
   338           | deriv' _ (ITyVar _) = true
   339       in deriv [] tyco end;
   340     val reserved = make_vars reserved;
   341     fun print_stmt qualified = print_haskell_stmt labelled_name
   342       syntax_class syntax_tyco syntax_const reserved
   343       (if qualified then deresolver else Long_Name.base_name o deresolver)
   344       contr_classparam_typs
   345       (if string_classes then deriving_show else K false);
   346     fun print_module name content =
   347       (name, Pretty.chunks [
   348         str ("module " ^ name ^ " where {"),
   349         str "",
   350         content,
   351         str "",
   352         str "}"
   353       ]);
   354     fun serialize_module1 (module_name', (deps, (stmts, _))) =
   355       let
   356         val stmt_names = map fst stmts;
   357         val qualified = is_none module_name;
   358         val imports = subtract (op =) stmt_names deps
   359           |> distinct (op =)
   360           |> map_filter (try deresolver)
   361           |> map Long_Name.qualifier
   362           |> distinct (op =);
   363         fun print_import_include (name, _) = str ("import qualified " ^ name ^ ";");
   364         fun print_import_module name = str ((if qualified
   365           then "import qualified "
   366           else "import ") ^ name ^ ";");
   367         val import_ps = map print_import_include includes @ map print_import_module imports
   368         val content = Pretty.chunks2 ((if null import_ps then [] else [Pretty.chunks import_ps])
   369             @ map_filter
   370               (fn (name, (_, SOME stmt)) => SOME (print_stmt qualified (name, stmt))
   371                 | (_, (_, NONE)) => NONE) stmts
   372           );
   373       in print_module module_name' content end;
   374     fun serialize_module2 (_, (_, (stmts, _))) = Pretty.chunks2 (map_filter
   375         (fn (name, (_, SOME stmt)) => if null presentation_stmt_names
   376               orelse member (op =) presentation_stmt_names name
   377               then SOME (print_stmt false (name, stmt))
   378               else NONE
   379           | (_, (_, NONE)) => NONE) stmts);
   380     val serialize_module =
   381       if null presentation_stmt_names then serialize_module1 else pair "" o serialize_module2;
   382     fun check_destination destination =
   383       (File.check destination; destination);
   384     fun write_module destination (modlname, content) =
   385       let
   386         val filename = case modlname
   387          of "" => Path.explode "Main.hs"
   388           | _ => (Path.ext "hs" o Path.explode o implode o separate "/"
   389                 o Long_Name.explode) modlname;
   390         val pathname = Path.append destination filename;
   391         val _ = File.mkdir_leaf (Path.dir pathname);
   392       in File.write pathname
   393         ("{-# OPTIONS_GHC -fglasgow-exts #-}\n\n"
   394           ^ code_of_pretty content)
   395       end
   396   in
   397     Code_Target.mk_serialization target
   398       (fn NONE => K () o map (code_writeln o snd) | SOME file => K () o map
   399         (write_module (check_destination file)))
   400       (rpair [] o cat_lines o map (code_of_pretty o snd))
   401       (map (uncurry print_module) includes
   402         @ map serialize_module (Symtab.dest hs_program))
   403       destination
   404   end;
   405 
   406 val literals = let
   407   fun char_haskell c =
   408     let
   409       val s = ML_Syntax.print_char c;
   410     in if s = "'" then "\\'" else s end;
   411   fun numeral_haskell k = if k >= 0 then string_of_int k
   412     else Library.enclose "(" ")" (signed_string_of_int k);
   413 in Literals {
   414   literal_char = Library.enclose "'" "'" o char_haskell,
   415   literal_string = quote o translate_string char_haskell,
   416   literal_numeral = numeral_haskell,
   417   literal_positive_numeral = numeral_haskell,
   418   literal_alternative_numeral = numeral_haskell,
   419   literal_naive_numeral = numeral_haskell,
   420   literal_list = enum "," "[" "]",
   421   infix_cons = (5, ":")
   422 } end;
   423 
   424 
   425 (** optional monad syntax **)
   426 
   427 fun pretty_haskell_monad c_bind =
   428   let
   429     fun dest_bind t1 t2 = case Code_Thingol.split_pat_abs t2
   430      of SOME ((pat, ty), t') =>
   431           SOME ((SOME ((pat, ty), true), t1), t')
   432       | NONE => NONE;
   433     fun dest_monad c_bind_name (IConst (c, _) `$ t1 `$ t2) =
   434           if c = c_bind_name then dest_bind t1 t2
   435           else NONE
   436       | dest_monad _ t = case Code_Thingol.split_let t
   437          of SOME (((pat, ty), tbind), t') =>
   438               SOME ((SOME ((pat, ty), false), tbind), t')
   439           | NONE => NONE;
   440     fun implode_monad c_bind_name = Code_Thingol.unfoldr (dest_monad c_bind_name);
   441     fun print_monad print_bind print_term (NONE, t) vars =
   442           (semicolon [print_term vars NOBR t], vars)
   443       | print_monad print_bind print_term (SOME ((bind, _), true), t) vars = vars
   444           |> print_bind NOBR bind
   445           |>> (fn p => semicolon [p, str "<-", print_term vars NOBR t])
   446       | print_monad print_bind print_term (SOME ((bind, _), false), t) vars = vars
   447           |> print_bind NOBR bind
   448           |>> (fn p => semicolon [str "let", str "{", p, str "=", print_term vars NOBR t, str "}"]);
   449     fun pretty _ [c_bind'] print_term thm vars fxy [(t1, _), (t2, _)] = case dest_bind t1 t2
   450      of SOME (bind, t') => let
   451           val (binds, t'') = implode_monad c_bind' t'
   452           val (ps, vars') = fold_map (print_monad (gen_print_bind (K print_term) thm) print_term)
   453             (bind :: binds) vars;
   454         in
   455           (brackify fxy o single o enclose "do { " " }" o Pretty.breaks)
   456             (ps @| print_term vars' NOBR t'')
   457         end
   458       | NONE => brackify_infix (1, L) fxy
   459           (print_term vars (INFX (1, L)) t1, str ">>=", print_term vars (INFX (1, X)) t2)
   460   in (2, ([c_bind], pretty)) end;
   461 
   462 fun add_monad target' raw_c_bind thy =
   463   let
   464     val c_bind = Code.read_const thy raw_c_bind;
   465   in if target = target' then
   466     thy
   467     |> Code_Target.add_syntax_const target c_bind
   468         (SOME (Code_Printer.complex_const_syntax (pretty_haskell_monad c_bind)))
   469   else error "Only Haskell target allows for monad syntax" end;
   470 
   471 
   472 (** Isar setup **)
   473 
   474 fun isar_serializer module_name =
   475   Code_Target.parse_args (Scan.option (Args.$$$ "root" -- Args.colon |-- Args.name)
   476     -- Scan.optional (Args.$$$ "string_classes" >> K true) false
   477     >> (fn (module_prefix, string_classes) =>
   478       serialize_haskell module_prefix module_name string_classes));
   479 
   480 val _ =
   481   Outer_Syntax.command "code_monad" "define code syntax for monads" Keyword.thy_decl (
   482     Parse.term_group -- Parse.name >> (fn (raw_bind, target) =>
   483       Toplevel.theory  (add_monad target raw_bind))
   484   );
   485 
   486 val setup =
   487   Code_Target.add_target
   488     (target, { serializer = isar_serializer, literals = literals,
   489       check = { env_var = "EXEC_GHC", make_destination = I,
   490         make_command = fn ghc => fn p => fn module_name =>
   491           ghc ^ " -fglasgow-exts -odir build -hidir build -stubdir build -e \"\" " ^ module_name ^ ".hs" } })
   492   #> Code_Target.add_syntax_tyco target "fun" (SOME (2, fn print_typ => fn fxy => fn [ty1, ty2] =>
   493       brackify_infix (1, R) fxy (
   494         print_typ (INFX (1, X)) ty1,
   495         str "->",
   496         print_typ (INFX (1, R)) ty2
   497       )))
   498   #> fold (Code_Target.add_reserved target) [
   499       "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr",
   500       "import", "default", "forall", "let", "in", "class", "qualified", "data",
   501       "newtype", "instance", "if", "then", "else", "type", "as", "do", "module"
   502     ]
   503   #> fold (Code_Target.add_reserved target) [
   504       "Prelude", "Main", "Bool", "Maybe", "Either", "Ordering", "Char", "String", "Int",
   505       "Integer", "Float", "Double", "Rational", "IO", "Eq", "Ord", "Enum", "Bounded",
   506       "Num", "Real", "Integral", "Fractional", "Floating", "RealFloat", "Monad", "Functor",
   507       "AlreadyExists", "ArithException", "ArrayException", "AssertionFailed", "AsyncException",
   508       "BlockedOnDeadMVar", "Deadlock", "Denormal", "DivideByZero", "DotNetException", "DynException",
   509       "Dynamic", "EOF", "EQ", "EmptyRec", "ErrorCall", "ExitException", "ExitFailure",
   510       "ExitSuccess", "False", "GT", "HeapOverflow",
   511       "IOError", "IOException", "IllegalOperation",
   512       "IndexOutOfBounds", "Just", "Key", "LT", "Left", "LossOfPrecision", "NoMethodError",
   513       "NoSuchThing", "NonTermination", "Nothing", "Obj", "OtherError", "Overflow",
   514       "PatternMatchFail", "PermissionDenied", "ProtocolError", "RecConError", "RecSelError",
   515       "RecUpdError", "ResourceBusy", "ResourceExhausted", "Right", "StackOverflow",
   516       "ThreadKilled", "True", "TyCon", "TypeRep", "UndefinedElement", "Underflow",
   517       "UnsupportedOperation", "UserError", "abs", "absReal", "acos", "acosh", "all",
   518       "and", "any", "appendFile", "asTypeOf", "asciiTab", "asin", "asinh", "atan",
   519       "atan2", "atanh", "basicIORun", "blockIO", "boundedEnumFrom", "boundedEnumFromThen",
   520       "boundedEnumFromThenTo", "boundedEnumFromTo", "boundedPred", "boundedSucc", "break",
   521       "catch", "catchException", "ceiling", "compare", "concat", "concatMap", "const",
   522       "cos", "cosh", "curry", "cycle", "decodeFloat", "denominator", "div", "divMod",
   523       "doubleToRatio", "doubleToRational", "drop", "dropWhile", "either", "elem",
   524       "emptyRec", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo",
   525       "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter", "flip",
   526       "floatDigits", "floatProperFraction", "floatRadix", "floatRange", "floatToRational",
   527       "floor", "fmap", "foldl", "foldl'", "foldl1", "foldr", "foldr1", "fromDouble",
   528       "fromEnum", "fromEnum_0", "fromInt", "fromInteger", "fromIntegral", "fromObj",
   529       "fromRational", "fst", "gcd", "getChar", "getContents", "getLine", "head",
   530       "id", "inRange", "index", "init", "intToRatio", "interact", "ioError", "isAlpha",
   531       "isAlphaNum", "isDenormalized", "isDigit", "isHexDigit", "isIEEE", "isInfinite",
   532       "isLower", "isNaN", "isNegativeZero", "isOctDigit", "isSpace", "isUpper", "iterate", "iterate'",
   533       "last", "lcm", "length", "lex", "lexDigits", "lexLitChar", "lexmatch", "lines", "log",
   534       "logBase", "lookup", "loop", "map", "mapM", "mapM_", "max", "maxBound", "maximum",
   535       "maybe", "min", "minBound", "minimum", "mod", "negate", "nonnull", "not", "notElem",
   536       "null", "numerator", "numericEnumFrom", "numericEnumFromThen", "numericEnumFromThenTo",
   537       "numericEnumFromTo", "odd", "or", "otherwise", "pi", "pred", 
   538       "print", "product", "properFraction", "protectEsc", "putChar", "putStr", "putStrLn",
   539       "quot", "quotRem", "range", "rangeSize", "rationalToDouble", "rationalToFloat",
   540       "rationalToRealFloat", "read", "readDec", "readField", "readFieldName", "readFile",
   541       "readFloat", "readHex", "readIO", "readInt", "readList", "readLitChar", "readLn",
   542       "readOct", "readParen", "readSigned", "reads", "readsPrec", "realFloatToRational",
   543       "realToFrac", "recip", "reduce", "rem", "repeat", "replicate", "return", "reverse",
   544       "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq", "sequence",
   545       "sequence_", "show", "showChar", "showException", "showField", "showList",
   546       "showLitChar", "showParen", "showString", "shows", "showsPrec", "significand",
   547       "signum", "signumReal", "sin", "sinh", "snd", "span", "splitAt", "sqrt", "subtract",
   548       "succ", "sum", "tail", "take", "takeWhile", "takeWhile1", "tan", "tanh", "threadToIOResult",
   549       "throw", "toEnum", "toInt", "toInteger", "toObj", "toRational", "truncate", "uncurry",
   550       "undefined", "unlines", "unsafeCoerce", "unsafeIndex", "unsafeRangeSize", "until", "unwords",
   551       "unzip", "unzip3", "userError", "words", "writeFile", "zip", "zip3", "zipWith", "zipWith3"
   552     ] (*due to weird handling of ':', we can't do anything else than to import *all* prelude symbols*);
   553 
   554 end; (*struct*)