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