src/Tools/Code/code_haskell.ML
author haftmann
Mon, 30 Aug 2010 09:28:02 +0200
changeset 39092 9070a7c356c9
parent 39012 89f654951200
child 39136 6af1d8673cbf
permissions -rw-r--r--
code checking: compiler invocation happens in same directory as generated file -- avoid problem with different path representations on cygwin
     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_prefix reserved module_alias program =
   265   let
   266     val reserved = Name.make_context reserved;
   267     val mk_name_module = mk_name_module reserved module_prefix module_alias program;
   268     fun add_stmt (name, (stmt, deps)) =
   269       let
   270         val (module_name, base) = dest_name name;
   271         val module_name' = mk_name_module module_name;
   272         val mk_name_stmt = yield_singleton Name.variants;
   273         fun add_fun upper (nsp_fun, nsp_typ) =
   274           let
   275             val (base', nsp_fun') =
   276               mk_name_stmt (if upper then first_upper base else base) nsp_fun
   277           in (base', (nsp_fun', nsp_typ)) end;
   278         fun add_typ (nsp_fun, nsp_typ) =
   279           let
   280             val (base', nsp_typ') = mk_name_stmt (first_upper base) nsp_typ
   281           in (base', (nsp_fun, nsp_typ')) end;
   282         val add_name = case stmt
   283          of Code_Thingol.Fun (_, (_, SOME _)) => pair base
   284           | Code_Thingol.Fun _ => add_fun false
   285           | Code_Thingol.Datatype _ => add_typ
   286           | Code_Thingol.Datatypecons _ => add_fun true
   287           | Code_Thingol.Class _ => add_typ
   288           | Code_Thingol.Classrel _ => pair base
   289           | Code_Thingol.Classparam _ => add_fun false
   290           | Code_Thingol.Classinst _ => pair base;
   291         fun add_stmt' base' = case stmt
   292          of Code_Thingol.Fun (_, (_, SOME _)) =>
   293               I
   294           | Code_Thingol.Datatypecons _ =>
   295               cons (name, (Long_Name.append module_name' base', NONE))
   296           | Code_Thingol.Classrel _ => I
   297           | Code_Thingol.Classparam _ =>
   298               cons (name, (Long_Name.append module_name' base', NONE))
   299           | _ => cons (name, (Long_Name.append module_name' base', SOME stmt));
   300       in
   301         Symtab.map_default (module_name', ([], ([], (reserved, reserved))))
   302               (apfst (fold (insert (op = : string * string -> bool)) deps))
   303         #> `(fn program => add_name ((snd o snd o the o Symtab.lookup program) module_name'))
   304         #-> (fn (base', names) =>
   305               (Symtab.map_entry module_name' o apsnd) (fn (stmts, _) =>
   306               (add_stmt' base' stmts, names)))
   307       end;
   308     val hs_program = fold add_stmt (AList.make (fn name =>
   309       (Graph.get_node program name, Graph.imm_succs program name))
   310       (Graph.strong_conn program |> flat)) Symtab.empty;
   311     fun deresolver name = (fst o the o AList.lookup (op =) ((fst o snd o the
   312       o Symtab.lookup hs_program) ((mk_name_module o fst o dest_name) name))) name
   313       handle Option => error ("Unknown statement name: " ^ labelled_name name);
   314   in (deresolver, hs_program) end;
   315 
   316 fun serialize_haskell module_prefix module_name string_classes labelled_name
   317     raw_reserved includes module_alias
   318     syntax_class syntax_tyco syntax_const (code_of_pretty, code_writeln) program
   319     (stmt_names, presentation_stmt_names) destination =
   320   let
   321     val reserved = fold (insert (op =) o fst) includes raw_reserved;
   322     val (deresolver, hs_program) = haskell_program_of_program labelled_name
   323       module_prefix reserved module_alias program;
   324     val contr_classparam_typs = Code_Thingol.contr_classparam_typs program;
   325     fun deriving_show tyco =
   326       let
   327         fun deriv _ "fun" = false
   328           | deriv tycos tyco = not (tyco = Code_Thingol.fun_tyco)
   329               andalso (member (op =) tycos tyco
   330               orelse case try (Graph.get_node program) tyco
   331                 of SOME (Code_Thingol.Datatype (_, (_, cs))) => forall (deriv' (tyco :: tycos))
   332                     (maps snd cs)
   333                  | NONE => true)
   334         and deriv' tycos (tyco `%% tys) = deriv tycos tyco
   335               andalso forall (deriv' tycos) tys
   336           | deriv' _ (ITyVar _) = true
   337       in deriv [] tyco end;
   338     val reserved = make_vars reserved;
   339     fun print_stmt qualified = print_haskell_stmt labelled_name
   340       syntax_class syntax_tyco syntax_const reserved
   341       (if qualified then deresolver else Long_Name.base_name o deresolver)
   342       contr_classparam_typs
   343       (if string_classes then deriving_show else K false);
   344     fun print_module name content =
   345       (name, Pretty.chunks2 [
   346         str ("module " ^ name ^ " where {"),
   347         content,
   348         str "}"
   349       ]);
   350     fun serialize_module1 (module_name', (deps, (stmts, _))) =
   351       let
   352         val stmt_names = map fst stmts;
   353         val qualified = is_none module_name;
   354         val imports = subtract (op =) stmt_names deps
   355           |> distinct (op =)
   356           |> map_filter (try deresolver)
   357           |> map Long_Name.qualifier
   358           |> distinct (op =);
   359         fun print_import_include (name, _) = str ("import qualified " ^ name ^ ";");
   360         fun print_import_module name = str ((if qualified
   361           then "import qualified "
   362           else "import ") ^ name ^ ";");
   363         val import_ps = map print_import_include includes @ map print_import_module imports
   364         val content = Pretty.chunks2 ((if null import_ps then [] else [Pretty.chunks import_ps])
   365             @ map_filter
   366               (fn (name, (_, SOME stmt)) => SOME (print_stmt qualified (name, stmt))
   367                 | (_, (_, NONE)) => NONE) stmts
   368           );
   369       in print_module module_name' content end;
   370     fun serialize_module2 (_, (_, (stmts, _))) = Pretty.chunks2 (map_filter
   371         (fn (name, (_, SOME stmt)) => if null presentation_stmt_names
   372               orelse member (op =) presentation_stmt_names name
   373               then SOME (print_stmt false (name, stmt))
   374               else NONE
   375           | (_, (_, NONE)) => NONE) stmts);
   376     val serialize_module =
   377       if null presentation_stmt_names then serialize_module1 else pair "" o serialize_module2;
   378     fun check_destination destination =
   379       (File.check destination; destination);
   380     fun write_module destination (modlname, content) =
   381       let
   382         val filename = case modlname
   383          of "" => Path.explode "Main.hs"
   384           | _ => (Path.ext "hs" o Path.explode o implode o separate "/"
   385                 o Long_Name.explode) modlname;
   386         val pathname = Path.append destination filename;
   387         val _ = File.mkdir_leaf (Path.dir pathname);
   388       in File.write pathname
   389         ("{-# OPTIONS_GHC -fglasgow-exts #-}\n\n"
   390           ^ code_of_pretty content)
   391       end
   392   in
   393     Code_Target.mk_serialization target
   394       (fn NONE => K () o map (code_writeln o (fn p => Pretty.block [p, Pretty.fbrk]) o snd)
   395         | SOME file => K () o map (write_module (check_destination file)))
   396       (rpair [] o cat_lines o map (code_of_pretty o snd))
   397       (map (uncurry print_module) includes
   398         @ map serialize_module (Symtab.dest hs_program))
   399       destination
   400   end;
   401 
   402 val literals = let
   403   fun char_haskell c =
   404     let
   405       val s = ML_Syntax.print_char c;
   406     in if s = "'" then "\\'" else s end;
   407   fun numeral_haskell k = if k >= 0 then string_of_int k
   408     else Library.enclose "(" ")" (signed_string_of_int k);
   409 in Literals {
   410   literal_char = Library.enclose "'" "'" o char_haskell,
   411   literal_string = quote o translate_string char_haskell,
   412   literal_numeral = numeral_haskell,
   413   literal_positive_numeral = numeral_haskell,
   414   literal_alternative_numeral = numeral_haskell,
   415   literal_naive_numeral = numeral_haskell,
   416   literal_list = enum "," "[" "]",
   417   infix_cons = (5, ":")
   418 } end;
   419 
   420 
   421 (** optional monad syntax **)
   422 
   423 fun pretty_haskell_monad c_bind =
   424   let
   425     fun dest_bind t1 t2 = case Code_Thingol.split_pat_abs t2
   426      of SOME ((pat, ty), t') =>
   427           SOME ((SOME ((pat, ty), true), t1), t')
   428       | NONE => NONE;
   429     fun dest_monad c_bind_name (IConst (c, _) `$ t1 `$ t2) =
   430           if c = c_bind_name then dest_bind t1 t2
   431           else NONE
   432       | dest_monad _ t = case Code_Thingol.split_let t
   433          of SOME (((pat, ty), tbind), t') =>
   434               SOME ((SOME ((pat, ty), false), tbind), t')
   435           | NONE => NONE;
   436     fun implode_monad c_bind_name = Code_Thingol.unfoldr (dest_monad c_bind_name);
   437     fun print_monad print_bind print_term (NONE, t) vars =
   438           (semicolon [print_term vars NOBR t], vars)
   439       | print_monad print_bind print_term (SOME ((bind, _), true), t) vars = vars
   440           |> print_bind NOBR bind
   441           |>> (fn p => semicolon [p, str "<-", print_term vars NOBR t])
   442       | print_monad print_bind print_term (SOME ((bind, _), false), t) vars = vars
   443           |> print_bind NOBR bind
   444           |>> (fn p => semicolon [str "let", str "{", p, str "=", print_term vars NOBR t, str "}"]);
   445     fun pretty _ [c_bind'] print_term thm vars fxy [(t1, _), (t2, _)] = case dest_bind t1 t2
   446      of SOME (bind, t') => let
   447           val (binds, t'') = implode_monad c_bind' t'
   448           val (ps, vars') = fold_map (print_monad (gen_print_bind (K print_term) thm) print_term)
   449             (bind :: binds) vars;
   450         in
   451           (brackify fxy o single o enclose "do { " " }" o Pretty.breaks)
   452             (ps @| print_term vars' NOBR t'')
   453         end
   454       | NONE => brackify_infix (1, L) fxy
   455           (print_term vars (INFX (1, L)) t1, str ">>=", print_term vars (INFX (1, X)) t2)
   456   in (2, ([c_bind], pretty)) end;
   457 
   458 fun add_monad target' raw_c_bind thy =
   459   let
   460     val c_bind = Code.read_const thy raw_c_bind;
   461   in if target = target' then
   462     thy
   463     |> Code_Target.add_syntax_const target c_bind
   464         (SOME (Code_Printer.complex_const_syntax (pretty_haskell_monad c_bind)))
   465   else error "Only Haskell target allows for monad syntax" end;
   466 
   467 
   468 (** Isar setup **)
   469 
   470 fun isar_serializer module_name =
   471   Code_Target.parse_args (Scan.option (Args.$$$ "root" -- Args.colon |-- Args.name)
   472     -- Scan.optional (Args.$$$ "string_classes" >> K true) false
   473     >> (fn (module_prefix, string_classes) =>
   474       serialize_haskell module_prefix module_name string_classes));
   475 
   476 val _ =
   477   Outer_Syntax.command "code_monad" "define code syntax for monads" Keyword.thy_decl (
   478     Parse.term_group -- Parse.name >> (fn (raw_bind, target) =>
   479       Toplevel.theory  (add_monad target raw_bind))
   480   );
   481 
   482 val setup =
   483   Code_Target.add_target
   484     (target, { serializer = isar_serializer, literals = literals,
   485       check = { env_var = "EXEC_GHC", make_destination = I,
   486         make_command = fn ghc => fn module_name =>
   487           ghc ^ " -fglasgow-exts -odir build -hidir build -stubdir build -e \"\" " ^ module_name ^ ".hs" } })
   488   #> Code_Target.add_syntax_tyco target "fun" (SOME (2, fn print_typ => fn fxy => fn [ty1, ty2] =>
   489       brackify_infix (1, R) fxy (
   490         print_typ (INFX (1, X)) ty1,
   491         str "->",
   492         print_typ (INFX (1, R)) ty2
   493       )))
   494   #> fold (Code_Target.add_reserved target) [
   495       "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr",
   496       "import", "default", "forall", "let", "in", "class", "qualified", "data",
   497       "newtype", "instance", "if", "then", "else", "type", "as", "do", "module"
   498     ]
   499   #> fold (Code_Target.add_reserved target) [
   500       "Prelude", "Main", "Bool", "Maybe", "Either", "Ordering", "Char", "String", "Int",
   501       "Integer", "Float", "Double", "Rational", "IO", "Eq", "Ord", "Enum", "Bounded",
   502       "Num", "Real", "Integral", "Fractional", "Floating", "RealFloat", "Monad", "Functor",
   503       "AlreadyExists", "ArithException", "ArrayException", "AssertionFailed", "AsyncException",
   504       "BlockedOnDeadMVar", "Deadlock", "Denormal", "DivideByZero", "DotNetException", "DynException",
   505       "Dynamic", "EOF", "EQ", "EmptyRec", "ErrorCall", "ExitException", "ExitFailure",
   506       "ExitSuccess", "False", "GT", "HeapOverflow",
   507       "IOError", "IOException", "IllegalOperation",
   508       "IndexOutOfBounds", "Just", "Key", "LT", "Left", "LossOfPrecision", "NoMethodError",
   509       "NoSuchThing", "NonTermination", "Nothing", "Obj", "OtherError", "Overflow",
   510       "PatternMatchFail", "PermissionDenied", "ProtocolError", "RecConError", "RecSelError",
   511       "RecUpdError", "ResourceBusy", "ResourceExhausted", "Right", "StackOverflow",
   512       "ThreadKilled", "True", "TyCon", "TypeRep", "UndefinedElement", "Underflow",
   513       "UnsupportedOperation", "UserError", "abs", "absReal", "acos", "acosh", "all",
   514       "and", "any", "appendFile", "asTypeOf", "asciiTab", "asin", "asinh", "atan",
   515       "atan2", "atanh", "basicIORun", "blockIO", "boundedEnumFrom", "boundedEnumFromThen",
   516       "boundedEnumFromThenTo", "boundedEnumFromTo", "boundedPred", "boundedSucc", "break",
   517       "catch", "catchException", "ceiling", "compare", "concat", "concatMap", "const",
   518       "cos", "cosh", "curry", "cycle", "decodeFloat", "denominator", "div", "divMod",
   519       "doubleToRatio", "doubleToRational", "drop", "dropWhile", "either", "elem",
   520       "emptyRec", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo",
   521       "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter", "flip",
   522       "floatDigits", "floatProperFraction", "floatRadix", "floatRange", "floatToRational",
   523       "floor", "fmap", "foldl", "foldl'", "foldl1", "foldr", "foldr1", "fromDouble",
   524       "fromEnum", "fromEnum_0", "fromInt", "fromInteger", "fromIntegral", "fromObj",
   525       "fromRational", "fst", "gcd", "getChar", "getContents", "getLine", "head",
   526       "id", "inRange", "index", "init", "intToRatio", "interact", "ioError", "isAlpha",
   527       "isAlphaNum", "isDenormalized", "isDigit", "isHexDigit", "isIEEE", "isInfinite",
   528       "isLower", "isNaN", "isNegativeZero", "isOctDigit", "isSpace", "isUpper", "iterate", "iterate'",
   529       "last", "lcm", "length", "lex", "lexDigits", "lexLitChar", "lexmatch", "lines", "log",
   530       "logBase", "lookup", "loop", "map", "mapM", "mapM_", "max", "maxBound", "maximum",
   531       "maybe", "min", "minBound", "minimum", "mod", "negate", "nonnull", "not", "notElem",
   532       "null", "numerator", "numericEnumFrom", "numericEnumFromThen", "numericEnumFromThenTo",
   533       "numericEnumFromTo", "odd", "or", "otherwise", "pi", "pred", 
   534       "print", "product", "properFraction", "protectEsc", "putChar", "putStr", "putStrLn",
   535       "quot", "quotRem", "range", "rangeSize", "rationalToDouble", "rationalToFloat",
   536       "rationalToRealFloat", "read", "readDec", "readField", "readFieldName", "readFile",
   537       "readFloat", "readHex", "readIO", "readInt", "readList", "readLitChar", "readLn",
   538       "readOct", "readParen", "readSigned", "reads", "readsPrec", "realFloatToRational",
   539       "realToFrac", "recip", "reduce", "rem", "repeat", "replicate", "return", "reverse",
   540       "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq", "sequence",
   541       "sequence_", "show", "showChar", "showException", "showField", "showList",
   542       "showLitChar", "showParen", "showString", "shows", "showsPrec", "significand",
   543       "signum", "signumReal", "sin", "sinh", "snd", "span", "splitAt", "sqrt", "subtract",
   544       "succ", "sum", "tail", "take", "takeWhile", "takeWhile1", "tan", "tanh", "threadToIOResult",
   545       "throw", "toEnum", "toInt", "toInteger", "toObj", "toRational", "truncate", "uncurry",
   546       "undefined", "unlines", "unsafeCoerce", "unsafeIndex", "unsafeRangeSize", "until", "unwords",
   547       "unzip", "unzip3", "userError", "words", "writeFile", "zip", "zip3", "zipWith", "zipWith3"
   548     ] (*due to weird handling of ':', we can't do anything else than to import *all* prelude symbols*);
   549 
   550 end; (*struct*)