src/Tools/Code/code_haskell.ML
author haftmann
Fri, 22 Jan 2010 13:38:28 +0100
changeset 34931 970e1466028d
parent 34262 b5c99df2e4b1
child 35228 ac2cab4583f4
permissions -rw-r--r--
code literals: distinguish numeral classes by different entries
     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 setup: theory -> theory
    10 end;
    11 
    12 structure Code_Haskell : CODE_HASKELL =
    13 struct
    14 
    15 val target = "Haskell";
    16 
    17 open Basic_Code_Thingol;
    18 open Code_Printer;
    19 
    20 infixr 5 @@;
    21 infixr 5 @|;
    22 
    23 
    24 (** Haskell serializer **)
    25 
    26 fun print_haskell_stmt labelled_name syntax_class syntax_tyco syntax_const
    27     reserved deresolve contr_classparam_typs deriving_show =
    28   let
    29     val deresolve_base = Long_Name.base_name o deresolve;
    30     fun class_name class = case syntax_class class
    31      of NONE => deresolve class
    32       | SOME class => class;
    33     fun print_typcontext tyvars vs = case maps (fn (v, sort) => map (pair v) sort) vs
    34      of [] => []
    35       | classbinds => enum "," "(" ")" (
    36           map (fn (v, class) =>
    37             str (class_name class ^ " " ^ lookup_var tyvars v)) classbinds)
    38           @@ str " => ";
    39     fun print_typforall tyvars vs = case map fst vs
    40      of [] => []
    41       | vnames => str "forall " :: Pretty.breaks
    42           (map (str o lookup_var tyvars) vnames) @ str "." @@ Pretty.brk 1;
    43     fun print_tyco_expr tyvars fxy (tyco, tys) =
    44       brackify fxy (str tyco :: map (print_typ tyvars BR) tys)
    45     and print_typ tyvars fxy (tycoexpr as tyco `%% tys) = (case syntax_tyco tyco
    46          of NONE => print_tyco_expr tyvars fxy (deresolve tyco, tys)
    47           | SOME (i, print) => print (print_typ tyvars) fxy tys)
    48       | print_typ tyvars fxy (ITyVar v) = (str o lookup_var tyvars) v;
    49     fun print_typdecl tyvars (vs, tycoexpr) =
    50       Pretty.block (print_typcontext tyvars vs @| print_tyco_expr tyvars NOBR tycoexpr);
    51     fun print_typscheme tyvars (vs, ty) =
    52       Pretty.block (print_typforall tyvars vs @ print_typcontext tyvars vs @| print_typ tyvars NOBR ty);
    53     fun print_term tyvars thm vars fxy (IConst c) =
    54           print_app tyvars thm vars fxy (c, [])
    55       | print_term tyvars thm vars fxy (t as (t1 `$ t2)) =
    56           (case Code_Thingol.unfold_const_app t
    57            of SOME app => print_app tyvars thm vars fxy app
    58             | _ =>
    59                 brackify fxy [
    60                   print_term tyvars thm vars NOBR t1,
    61                   print_term tyvars thm vars BR t2
    62                 ])
    63       | print_term tyvars thm vars fxy (IVar NONE) =
    64           str "_"
    65       | print_term tyvars thm vars fxy (IVar (SOME v)) =
    66           (str o lookup_var vars) v
    67       | print_term tyvars thm vars fxy (t as _ `|=> _) =
    68           let
    69             val (binds, t') = Code_Thingol.unfold_pat_abs t;
    70             val (ps, vars') = fold_map (print_bind tyvars thm BR o fst) binds vars;
    71           in brackets (str "\\" :: ps @ str "->" @@ print_term tyvars thm vars' NOBR t') end
    72       | print_term tyvars thm vars fxy (ICase (cases as (_, t0))) =
    73           (case Code_Thingol.unfold_const_app t0
    74            of SOME (c_ts as ((c, _), _)) => if is_none (syntax_const c)
    75                 then print_case tyvars thm vars fxy cases
    76                 else print_app tyvars thm vars fxy c_ts
    77             | NONE => print_case tyvars thm vars fxy cases)
    78     and print_app_expr tyvars thm vars ((c, (_, tys)), ts) = case contr_classparam_typs c
    79      of [] => (str o deresolve) c :: map (print_term tyvars thm vars BR) ts
    80       | fingerprint => let
    81           val ts_fingerprint = ts ~~ take (length ts) fingerprint;
    82           val needs_annotation = forall (fn (_, NONE) => true | (t, SOME _) =>
    83             (not o Code_Thingol.locally_monomorphic) t) ts_fingerprint;
    84           fun print_term_anno (t, NONE) _ = print_term tyvars thm vars BR t
    85             | print_term_anno (t, SOME _) ty =
    86                 brackets [print_term tyvars thm vars NOBR t, str "::", print_typ tyvars NOBR ty];
    87         in
    88           if needs_annotation then
    89             (str o deresolve) c :: map2 print_term_anno ts_fingerprint (take (length ts) tys)
    90           else (str o deresolve) c :: map (print_term tyvars thm vars BR) ts
    91         end
    92     and print_app tyvars = gen_print_app (print_app_expr tyvars) (print_term tyvars) syntax_const
    93     and print_bind tyvars thm fxy p = gen_print_bind (print_term tyvars) thm fxy p
    94     and print_case tyvars thm vars fxy (cases as ((_, [_]), _)) =
    95           let
    96             val (binds, body) = Code_Thingol.unfold_let (ICase cases);
    97             fun print_match ((pat, ty), t) vars =
    98               vars
    99               |> print_bind tyvars thm BR pat
   100               |>> (fn p => semicolon [p, str "=", print_term tyvars thm vars NOBR t])
   101             val (ps, vars') = fold_map print_match binds vars;
   102           in brackify_block fxy (str "let {")
   103             ps
   104             (concat [str "}", str "in", print_term tyvars thm vars' NOBR body])
   105           end
   106       | print_case tyvars thm vars fxy (((t, ty), clauses as _ :: _), _) =
   107           let
   108             fun print_select (pat, body) =
   109               let
   110                 val (p, vars') = print_bind tyvars thm NOBR pat vars;
   111               in semicolon [p, str "->", print_term tyvars thm vars' NOBR body] end;
   112           in brackify_block fxy
   113             (concat [str "case", print_term tyvars thm vars NOBR t, str "of", str "{"])
   114             (map print_select clauses)
   115             (str "}") 
   116           end
   117       | print_case tyvars 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), (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 thm vars BR) ts
   143                   @ str "="
   144                   @@ print_term tyvars 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, (superclasses, 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 superclasses)]),
   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_insts))) =
   219           let
   220             val tyvars = intro_vars (map fst vs) reserved;
   221             fun print_instdef ((classparam, c_inst), (thm, _)) = case syntax_const classparam
   222              of NONE => semicolon [
   223                     (str o deresolve_base) classparam,
   224                     str "=",
   225                     print_app tyvars thm reserved NOBR (c_inst, [])
   226                   ]
   227               | SOME (k, pr) =>
   228                   let
   229                     val (c_inst_name, (_, tys)) = c_inst;
   230                     val const = if (is_some o syntax_const) c_inst_name
   231                       then NONE else (SOME o Long_Name.base_name o deresolve) c_inst_name;
   232                     val proto_rhs = Code_Thingol.eta_expand k (c_inst, []);
   233                     val (vs, rhs) = (apfst o map) fst (Code_Thingol.unfold_abs proto_rhs);
   234                     val vars = reserved
   235                       |> intro_vars (the_list const)
   236                       |> intro_vars (map_filter I 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 thm vars NOBR lhs,
   242                       str "=",
   243                       print_term tyvars 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_instdef classparam_insts)
   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 _ => add_fun false
   281           | Code_Thingol.Datatype _ => add_typ
   282           | Code_Thingol.Datatypecons _ => add_fun true
   283           | Code_Thingol.Class _ => add_typ
   284           | Code_Thingol.Classrel _ => pair base
   285           | Code_Thingol.Classparam _ => add_fun false
   286           | Code_Thingol.Classinst _ => pair base;
   287         fun add_stmt' base' = case stmt
   288          of Code_Thingol.Datatypecons _ =>
   289               cons (name, (Long_Name.append module_name' base', NONE))
   290           | Code_Thingol.Classrel _ => I
   291           | Code_Thingol.Classparam _ =>
   292               cons (name, (Long_Name.append module_name' base', NONE))
   293           | _ => cons (name, (Long_Name.append module_name' base', SOME stmt));
   294       in
   295         Symtab.map_default (module_name', ([], ([], (reserved, reserved))))
   296               (apfst (fold (insert (op = : string * string -> bool)) deps))
   297         #> `(fn program => add_name ((snd o snd o the o Symtab.lookup program) module_name'))
   298         #-> (fn (base', names) =>
   299               (Symtab.map_entry module_name' o apsnd) (fn (stmts, _) =>
   300               (add_stmt' base' stmts, names)))
   301       end;
   302     val hs_program = fold add_stmt (AList.make (fn name =>
   303       (Graph.get_node program name, Graph.imm_succs program name))
   304       (Graph.strong_conn program |> flat)) Symtab.empty;
   305     fun deresolver name = (fst o the o AList.lookup (op =) ((fst o snd o the
   306       o Symtab.lookup hs_program) ((mk_name_module o fst o dest_name) name))) name
   307       handle Option => error ("Unknown statement name: " ^ labelled_name name);
   308   in (deresolver, hs_program) end;
   309 
   310 fun serialize_haskell module_prefix raw_module_name string_classes labelled_name
   311     raw_reserved includes raw_module_alias
   312     syntax_class syntax_tyco syntax_const (code_of_pretty, code_writeln) program cs destination =
   313   let
   314     val stmt_names = Code_Target.stmt_names_of_destination destination;
   315     val module_name = if null stmt_names then raw_module_name else SOME "Code";
   316     val reserved = fold (insert (op =) o fst) includes raw_reserved;
   317     val (deresolver, hs_program) = haskell_program_of_program labelled_name
   318       module_name module_prefix reserved raw_module_alias program;
   319     val contr_classparam_typs = Code_Thingol.contr_classparam_typs program;
   320     fun deriving_show tyco =
   321       let
   322         fun deriv _ "fun" = false
   323           | deriv tycos tyco = not (tyco = Code_Thingol.fun_tyco)
   324               andalso (member (op =) tycos tyco
   325               orelse case try (Graph.get_node program) tyco
   326                 of SOME (Code_Thingol.Datatype (_, (_, cs))) => forall (deriv' (tyco :: tycos))
   327                     (maps snd cs)
   328                  | NONE => true)
   329         and deriv' tycos (tyco `%% tys) = deriv tycos tyco
   330               andalso forall (deriv' tycos) tys
   331           | deriv' _ (ITyVar _) = true
   332       in deriv [] tyco end;
   333     val reserved = make_vars reserved;
   334     fun print_stmt qualified = print_haskell_stmt labelled_name
   335       syntax_class syntax_tyco syntax_const reserved
   336       (if qualified then deresolver else Long_Name.base_name o deresolver)
   337       contr_classparam_typs
   338       (if string_classes then deriving_show else K false);
   339     fun print_module name content =
   340       (name, Pretty.chunks [
   341         str ("module " ^ name ^ " where {"),
   342         str "",
   343         content,
   344         str "",
   345         str "}"
   346       ]);
   347     fun serialize_module1 (module_name', (deps, (stmts, _))) =
   348       let
   349         val stmt_names = map fst stmts;
   350         val qualified = is_none module_name;
   351         val imports = subtract (op =) stmt_names deps
   352           |> distinct (op =)
   353           |> map_filter (try deresolver)
   354           |> map Long_Name.qualifier
   355           |> distinct (op =);
   356         fun print_import_include (name, _) = str ("import qualified " ^ name ^ ";");
   357         fun print_import_module name = str ((if qualified
   358           then "import qualified "
   359           else "import ") ^ name ^ ";");
   360         val import_ps = map print_import_include includes @ map print_import_module imports
   361         val content = Pretty.chunks2 ((if null import_ps then [] else [Pretty.chunks import_ps])
   362             @ map_filter
   363               (fn (name, (_, SOME stmt)) => SOME (print_stmt qualified (name, stmt))
   364                 | (_, (_, NONE)) => NONE) stmts
   365           );
   366       in print_module module_name' content end;
   367     fun serialize_module2 (_, (_, (stmts, _))) = Pretty.chunks2 (map_filter
   368         (fn (name, (_, SOME stmt)) => if null stmt_names
   369               orelse member (op =) stmt_names name
   370               then SOME (print_stmt false (name, stmt))
   371               else NONE
   372           | (_, (_, NONE)) => NONE) stmts);
   373     val serialize_module =
   374       if null stmt_names then serialize_module1 else pair "" o serialize_module2;
   375     fun check_destination destination =
   376       (File.check destination; destination);
   377     fun write_module destination (modlname, content) =
   378       let
   379         val filename = case modlname
   380          of "" => Path.explode "Main.hs"
   381           | _ => (Path.ext "hs" o Path.explode o implode o separate "/"
   382                 o Long_Name.explode) modlname;
   383         val pathname = Path.append destination filename;
   384         val _ = File.mkdir (Path.dir pathname);
   385       in File.write pathname
   386         ("{-# OPTIONS_GHC -fglasgow-exts #-}\n\n"
   387           ^ code_of_pretty content)
   388       end
   389   in
   390     Code_Target.mk_serialization target NONE
   391       (fn NONE => K () o map (code_writeln o snd) | SOME file => K () o map
   392         (write_module (check_destination file)))
   393       (rpair [] o cat_lines o map (code_of_pretty o snd))
   394       (map (uncurry print_module) includes
   395         @ map serialize_module (Symtab.dest hs_program))
   396       destination
   397   end;
   398 
   399 val literals = let
   400   fun char_haskell c =
   401     let
   402       val s = ML_Syntax.print_char c;
   403     in if s = "'" then "\\'" else s end;
   404   fun numeral_haskell k = if k >= 0 then string_of_int k
   405     else Library.enclose "(" ")" (signed_string_of_int k);
   406 in Literals {
   407   literal_char = Library.enclose "'" "'" o char_haskell,
   408   literal_string = quote o translate_string char_haskell,
   409   literal_numeral = numeral_haskell,
   410   literal_positive_numeral = numeral_haskell,
   411   literal_naive_numeral = numeral_haskell,
   412   literal_list = enum "," "[" "]",
   413   infix_cons = (5, ":")
   414 } end;
   415 
   416 
   417 (** optional monad syntax **)
   418 
   419 fun pretty_haskell_monad c_bind =
   420   let
   421     fun dest_bind t1 t2 = case Code_Thingol.split_pat_abs t2
   422      of SOME ((pat, ty), t') =>
   423           SOME ((SOME ((pat, ty), true), t1), t')
   424       | NONE => NONE;
   425     fun dest_monad c_bind_name (IConst (c, _) `$ t1 `$ t2) =
   426           if c = c_bind_name then dest_bind t1 t2
   427           else NONE
   428       | dest_monad _ t = case Code_Thingol.split_let t
   429          of SOME (((pat, ty), tbind), t') =>
   430               SOME ((SOME ((pat, ty), false), tbind), t')
   431           | NONE => NONE;
   432     fun implode_monad c_bind_name = Code_Thingol.unfoldr (dest_monad c_bind_name);
   433     fun print_monad print_bind print_term (NONE, t) vars =
   434           (semicolon [print_term vars NOBR t], vars)
   435       | print_monad print_bind print_term (SOME ((bind, _), true), t) vars = vars
   436           |> print_bind NOBR bind
   437           |>> (fn p => semicolon [p, str "<-", print_term vars NOBR t])
   438       | print_monad print_bind print_term (SOME ((bind, _), false), t) vars = vars
   439           |> print_bind NOBR bind
   440           |>> (fn p => semicolon [str "let", p, str "=", print_term vars NOBR t]);
   441     fun pretty _ [c_bind'] print_term thm vars fxy [(t1, _), (t2, _)] = case dest_bind t1 t2
   442      of SOME (bind, t') => let
   443           val (binds, t'') = implode_monad c_bind' t'
   444           val (ps, vars') = fold_map (print_monad (gen_print_bind (K print_term) thm) print_term)
   445             (bind :: binds) vars;
   446         in
   447           (brackify fxy o single o enclose "do {" "}" o Pretty.breaks)
   448             (ps @| print_term vars' NOBR t'')
   449         end
   450       | NONE => brackify_infix (1, L) fxy
   451           [print_term vars (INFX (1, L)) t1, str ">>=", print_term vars (INFX (1, X)) t2]
   452   in (2, ([c_bind], pretty)) end;
   453 
   454 fun add_monad target' raw_c_bind thy =
   455   let
   456     val c_bind = Code.read_const thy raw_c_bind;
   457   in if target = target' then
   458     thy
   459     |> Code_Target.add_syntax_const target c_bind
   460         (SOME (pretty_haskell_monad c_bind))
   461   else error "Only Haskell target allows for monad syntax" end;
   462 
   463 
   464 (** Isar setup **)
   465 
   466 fun isar_seri_haskell module_name =
   467   Code_Target.parse_args (Scan.option (Args.$$$ "root" -- Args.colon |-- Args.name)
   468     -- Scan.optional (Args.$$$ "string_classes" >> K true) false
   469     >> (fn (module_prefix, string_classes) =>
   470       serialize_haskell module_prefix module_name string_classes));
   471 
   472 val _ =
   473   OuterSyntax.command "code_monad" "define code syntax for monads" OuterKeyword.thy_decl (
   474     OuterParse.term_group -- OuterParse.name >> (fn (raw_bind, target) =>
   475       Toplevel.theory  (add_monad target raw_bind))
   476   );
   477 
   478 val setup =
   479   Code_Target.add_target (target, (isar_seri_haskell, literals))
   480   #> Code_Target.add_syntax_tyco target "fun" (SOME (2, fn print_typ => fn fxy => fn [ty1, ty2] =>
   481       brackify_infix (1, R) fxy [
   482         print_typ (INFX (1, X)) ty1,
   483         str "->",
   484         print_typ (INFX (1, R)) ty2
   485       ]))
   486   #> fold (Code_Target.add_reserved target) [
   487       "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr",
   488       "import", "default", "forall", "let", "in", "class", "qualified", "data",
   489       "newtype", "instance", "if", "then", "else", "type", "as", "do", "module"
   490     ]
   491   #> fold (Code_Target.add_reserved target) [
   492       "Prelude", "Main", "Bool", "Maybe", "Either", "Ordering", "Char", "String", "Int",
   493       "Integer", "Float", "Double", "Rational", "IO", "Eq", "Ord", "Enum", "Bounded",
   494       "Num", "Real", "Integral", "Fractional", "Floating", "RealFloat", "Monad", "Functor",
   495       "AlreadyExists", "ArithException", "ArrayException", "AssertionFailed", "AsyncException",
   496       "BlockedOnDeadMVar", "Deadlock", "Denormal", "DivideByZero", "DotNetException", "DynException",
   497       "Dynamic", "EOF", "EQ", "EmptyRec", "ErrorCall", "ExitException", "ExitFailure",
   498       "ExitSuccess", "False", "GT", "HeapOverflow",
   499       "IOError", "IOException", "IllegalOperation",
   500       "IndexOutOfBounds", "Just", "Key", "LT", "Left", "LossOfPrecision", "NoMethodError",
   501       "NoSuchThing", "NonTermination", "Nothing", "Obj", "OtherError", "Overflow",
   502       "PatternMatchFail", "PermissionDenied", "ProtocolError", "RecConError", "RecSelError",
   503       "RecUpdError", "ResourceBusy", "ResourceExhausted", "Right", "StackOverflow",
   504       "ThreadKilled", "True", "TyCon", "TypeRep", "UndefinedElement", "Underflow",
   505       "UnsupportedOperation", "UserError", "abs", "absReal", "acos", "acosh", "all",
   506       "and", "any", "appendFile", "asTypeOf", "asciiTab", "asin", "asinh", "atan",
   507       "atan2", "atanh", "basicIORun", "blockIO", "boundedEnumFrom", "boundedEnumFromThen",
   508       "boundedEnumFromThenTo", "boundedEnumFromTo", "boundedPred", "boundedSucc", "break",
   509       "catch", "catchException", "ceiling", "compare", "concat", "concatMap", "const",
   510       "cos", "cosh", "curry", "cycle", "decodeFloat", "denominator", "div", "divMod",
   511       "doubleToRatio", "doubleToRational", "drop", "dropWhile", "either", "elem",
   512       "emptyRec", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo",
   513       "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter", "flip",
   514       "floatDigits", "floatProperFraction", "floatRadix", "floatRange", "floatToRational",
   515       "floor", "fmap", "foldl", "foldl'", "foldl1", "foldr", "foldr1", "fromDouble",
   516       "fromEnum", "fromEnum_0", "fromInt", "fromInteger", "fromIntegral", "fromObj",
   517       "fromRational", "fst", "gcd", "getChar", "getContents", "getLine", "head",
   518       "id", "inRange", "index", "init", "intToRatio", "interact", "ioError", "isAlpha",
   519       "isAlphaNum", "isDenormalized", "isDigit", "isHexDigit", "isIEEE", "isInfinite",
   520       "isLower", "isNaN", "isNegativeZero", "isOctDigit", "isSpace", "isUpper", "iterate", "iterate'",
   521       "last", "lcm", "length", "lex", "lexDigits", "lexLitChar", "lexmatch", "lines", "log",
   522       "logBase", "lookup", "loop", "map", "mapM", "mapM_", "max", "maxBound", "maximum",
   523       "maybe", "min", "minBound", "minimum", "mod", "negate", "nonnull", "not", "notElem",
   524       "null", "numerator", "numericEnumFrom", "numericEnumFromThen", "numericEnumFromThenTo",
   525       "numericEnumFromTo", "odd", "or", "otherwise", "pi", "pred", 
   526       "print", "product", "properFraction", "protectEsc", "putChar", "putStr", "putStrLn",
   527       "quot", "quotRem", "range", "rangeSize", "rationalToDouble", "rationalToFloat",
   528       "rationalToRealFloat", "read", "readDec", "readField", "readFieldName", "readFile",
   529       "readFloat", "readHex", "readIO", "readInt", "readList", "readLitChar", "readLn",
   530       "readOct", "readParen", "readSigned", "reads", "readsPrec", "realFloatToRational",
   531       "realToFrac", "recip", "reduce", "rem", "repeat", "replicate", "return", "reverse",
   532       "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq", "sequence",
   533       "sequence_", "show", "showChar", "showException", "showField", "showList",
   534       "showLitChar", "showParen", "showString", "shows", "showsPrec", "significand",
   535       "signum", "signumReal", "sin", "sinh", "snd", "span", "splitAt", "sqrt", "subtract",
   536       "succ", "sum", "tail", "take", "takeWhile", "takeWhile1", "tan", "tanh", "threadToIOResult",
   537       "throw", "toEnum", "toInt", "toInteger", "toObj", "toRational", "truncate", "uncurry",
   538       "undefined", "unlines", "unsafeCoerce", "unsafeIndex", "unsafeRangeSize", "until", "unwords",
   539       "unzip", "unzip3", "userError", "words", "writeFile", "zip", "zip3", "zipWith", "zipWith3"
   540     ] (*due to weird handling of ':', we can't do anything else than to import *all* prelude symbols*);
   541 
   542 end; (*struct*)