restrict unqualified imports from Haskell Prelude to a small set of fundamental operations
authorhaftmann
Mon, 23 Jul 2012 09:28:03 +0200
changeset 494466efff142bb54
parent 49445 6cbfe187a0f9
child 49447 60759d07df24
child 49458 6f2762eedca0
child 49468 2421ff8c57a5
restrict unqualified imports from Haskell Prelude to a small set of fundamental operations
NEWS
src/HOL/Code_Numeral.thy
src/HOL/Library/Code_Char.thy
src/HOL/Library/Code_Char_chr.thy
src/HOL/Library/Code_Integer.thy
src/HOL/Library/Efficient_Nat.thy
src/Tools/Code/code_haskell.ML
     1.1 --- a/NEWS	Mon Jul 23 09:26:55 2012 +0200
     1.2 +++ b/NEWS	Mon Jul 23 09:28:03 2012 +0200
     1.3 @@ -15,6 +15,9 @@
     1.4  
     1.5  *** Pure ***
     1.6  
     1.7 +* Code generation for Haskell: restrict unqualified imports from
     1.8 +Haskell Prelude to a small set of fundamental operations.
     1.9 +
    1.10  * Command "export_code": relative file names are interpreted
    1.11  relatively to master directory of current theory rather than
    1.12  the rather arbitrary current working directory.
     2.1 --- a/src/HOL/Code_Numeral.thy	Mon Jul 23 09:26:55 2012 +0200
     2.2 +++ b/src/HOL/Code_Numeral.thy	Mon Jul 23 09:28:03 2012 +0200
     2.3 @@ -298,7 +298,7 @@
     2.4  code_const "minus \<Colon> code_numeral \<Rightarrow> code_numeral \<Rightarrow> code_numeral"
     2.5    (SML "Int.max/ (0 : int,/ Int.-/ ((_),/ (_)))")
     2.6    (OCaml "Big'_int.max'_big'_int/ Big'_int.zero'_big'_int/ (Big'_int.sub'_big'_int/ _/ _)")
     2.7 -  (Haskell "max/ (0 :: Integer)/ (_/ -/ _)")
     2.8 +  (Haskell "Prelude.max/ (0 :: Integer)/ (_/ -/ _)")
     2.9    (Scala "!(_/ -/ _).max(0)")
    2.10    (Eval "Integer.max/ 0/ (_/ -/ _)")
    2.11  
     3.1 --- a/src/HOL/Library/Code_Char.thy	Mon Jul 23 09:26:55 2012 +0200
     3.2 +++ b/src/HOL/Library/Code_Char.thy	Mon Jul 23 09:28:03 2012 +0200
     3.3 @@ -11,7 +11,7 @@
     3.4  code_type char
     3.5    (SML "char")
     3.6    (OCaml "char")
     3.7 -  (Haskell "Char")
     3.8 +  (Haskell "Prelude.Char")
     3.9    (Scala "Char")
    3.10  
    3.11  setup {*
    3.12 @@ -58,7 +58,4 @@
    3.13    (Haskell "_")
    3.14    (Scala "!(_.toList)")
    3.15  
    3.16 -
    3.17 -(*declare Quickcheck_Exhaustive.char.bounded_forall_char.simps [code del]*)
    3.18 -
    3.19  end
     4.1 --- a/src/HOL/Library/Code_Char_chr.thy	Mon Jul 23 09:26:55 2012 +0200
     4.2 +++ b/src/HOL/Library/Code_Char_chr.thy	Mon Jul 23 09:28:03 2012 +0200
     4.3 @@ -25,7 +25,7 @@
     4.4  code_const int_of_char and char_of_int
     4.5    (SML "!(IntInf.fromInt o Char.ord)" and "!(Char.chr o IntInf.toInt)")
     4.6    (OCaml "Big'_int.big'_int'_of'_int (Char.code _)" and "Char.chr (Big'_int.int'_of'_big'_int _)")
     4.7 -  (Haskell "toInteger (fromEnum (_ :: Char))" and "!(let chr k | (0 <= k && k < 256) = toEnum k :: Char in chr . fromInteger)")
     4.8 +  (Haskell "Prelude.toInteger (Prelude.fromEnum (_ :: Prelude.Char))" and "!(let chr k | (0 <= k && k < 256) = Prelude.toEnum k :: Prelude.Char in chr . Prelude.fromInteger)")
     4.9    (Scala "BigInt(_.toInt)" and "!((k: BigInt) => if (BigInt(0) <= k && k < BigInt(256)) k.charValue else error(\"character value out of range\"))")
    4.10  
    4.11  end
     5.1 --- a/src/HOL/Library/Code_Integer.thy	Mon Jul 23 09:26:55 2012 +0200
     5.2 +++ b/src/HOL/Library/Code_Integer.thy	Mon Jul 23 09:28:03 2012 +0200
     5.3 @@ -151,7 +151,7 @@
     5.4  code_const Code_Numeral.int_of
     5.5    (SML "IntInf.fromInt")
     5.6    (OCaml "_")
     5.7 -  (Haskell "toInteger")
     5.8 +  (Haskell "Prelude.toInteger")
     5.9    (Scala "!_.as'_BigInt")
    5.10    (Eval "_")
    5.11  
     6.1 --- a/src/HOL/Library/Efficient_Nat.thy	Mon Jul 23 09:26:55 2012 +0200
     6.2 +++ b/src/HOL/Library/Efficient_Nat.thy	Mon Jul 23 09:28:03 2012 +0200
     6.3 @@ -162,7 +162,7 @@
     6.4  text {* For Haskell and Scala, things are slightly different again. *}
     6.5  
     6.6  code_const int and nat
     6.7 -  (Haskell "toInteger" and "fromInteger")
     6.8 +  (Haskell "Prelude.toInteger" and "Prelude.fromInteger")
     6.9    (Scala "!_.as'_BigInt" and "Nat")
    6.10  
    6.11  text {* Alternativ implementation for @{const of_nat} *}
    6.12 @@ -189,14 +189,14 @@
    6.13  code_const Code_Numeral.of_nat
    6.14    (SML "IntInf.toInt")
    6.15    (OCaml "_")
    6.16 -  (Haskell "!(fromInteger/ ./ toInteger)")
    6.17 +  (Haskell "!(Prelude.fromInteger/ ./ Prelude.toInteger)")
    6.18    (Scala "!Natural(_.as'_BigInt)")
    6.19    (Eval "_")
    6.20  
    6.21  code_const Code_Numeral.nat_of
    6.22    (SML "IntInf.fromInt")
    6.23    (OCaml "_")
    6.24 -  (Haskell "!(fromInteger/ ./ toInteger)")
    6.25 +  (Haskell "!(Prelude.fromInteger/ ./ Prelude.toInteger)")
    6.26    (Scala "!Nat(_.as'_BigInt)")
    6.27    (Eval "_")
    6.28  
     7.1 --- a/src/Tools/Code/code_haskell.ML	Mon Jul 23 09:26:55 2012 +0200
     7.2 +++ b/src/Tools/Code/code_haskell.ML	Mon Jul 23 09:28:03 2012 +0200
     7.3 @@ -303,6 +303,27 @@
     7.4          modify_stmt = fn stmt => if select_stmt stmt then SOME stmt else NONE }
     7.5    end;
     7.6  
     7.7 +val prelude_import_operators = [
     7.8 +  "==", "/=", "<", "<=", ">=", ">", "+", "-", "*", "/", "**", ">>=", ">>", "=<<", "&&", "||", "^", "^^", ".", "$", "$!", "++", "!!"
     7.9 +];
    7.10 +
    7.11 +val prelude_import_unqualified = [
    7.12 +  "Eq",
    7.13 +  "error",
    7.14 +  "id",
    7.15 +  "return",
    7.16 +  "not",
    7.17 +  "fst", "snd",
    7.18 +  "map", "filter", "concat", "concatMap", "reverse", "zip", "null", "takeWhile", "dropWhile", "all", "any",
    7.19 +  "Integer", "negate", "abs", "divMod",
    7.20 +  "String"
    7.21 +];
    7.22 +
    7.23 +val prelude_import_unqualified_constr = [
    7.24 +  ("Bool", ["True", "False"]),
    7.25 +  ("Maybe", ["Nothing", "Just"])
    7.26 +];
    7.27 +
    7.28  fun serialize_haskell module_prefix string_classes { labelled_name, reserved_syms,
    7.29      includes, module_alias, class_syntax, tyco_syntax, const_syntax } program =
    7.30    let
    7.31 @@ -331,23 +352,28 @@
    7.32        deresolve (if string_classes then deriving_show else K false);
    7.33  
    7.34      (* print modules *)
    7.35 -    val import_includes_ps =
    7.36 -      map (fn (name, _) => str ("import qualified " ^ name ^ ";")) includes;
    7.37      fun print_module_frame module_name ps =
    7.38        (module_name, Pretty.chunks2 (
    7.39          str ("module " ^ module_name ^ " where {")
    7.40          :: ps
    7.41          @| str "}"
    7.42        ));
    7.43 +    fun print_qualified_import module_name = semicolon [str "import qualified", str module_name];
    7.44 +    val import_common_ps =
    7.45 +      enclose "import Prelude (" ");" (commas (map str
    7.46 +        (map (Library.enclose "(" ")") prelude_import_operators @ prelude_import_unqualified)
    7.47 +          @ map (fn (tyco, constrs) => (enclose (tyco ^ "(") ")" o commas o map str) constrs) prelude_import_unqualified_constr))
    7.48 +      :: print_qualified_import "Prelude"
    7.49 +      :: map (print_qualified_import o fst) includes;
    7.50      fun print_module module_name (gr, imports) =
    7.51        let
    7.52 -        val deresolve = deresolver module_name
    7.53 +        val deresolve = deresolver module_name;
    7.54          fun print_import module_name = (semicolon o map str) ["import qualified", module_name];
    7.55 -        val import_ps = import_includes_ps @ map (print_import o fst) imports;
    7.56 -        fun print_stmt' gr name = case Graph.get_node gr name
    7.57 +        val import_ps = import_common_ps @ map (print_qualified_import o fst) imports;
    7.58 +        fun print_stmt' name = case Graph.get_node gr name
    7.59           of (_, NONE) => NONE
    7.60            | (_, SOME stmt) => SOME (markup_stmt name (print_stmt deresolve (name, stmt)));
    7.61 -        val body_ps = map_filter (print_stmt' gr) ((flat o rev o Graph.strong_conn) gr);
    7.62 +        val body_ps = map_filter print_stmt' ((flat o rev o Graph.strong_conn) gr);
    7.63        in
    7.64          print_module_frame module_name
    7.65            ((if null import_ps then [] else [Pretty.chunks import_ps]) @ body_ps)
    7.66 @@ -472,55 +498,8 @@
    7.67        "import", "default", "forall", "let", "in", "class", "qualified", "data",
    7.68        "newtype", "instance", "if", "then", "else", "type", "as", "do", "module"
    7.69      ]
    7.70 -  #> fold (Code_Target.add_reserved target) [
    7.71 -      "Prelude", "Main", "Bool", "Maybe", "Either", "Ordering", "Char", "String", "Int",
    7.72 -      "Integer", "Float", "Double", "Rational", "IO", "Eq", "Ord", "Enum", "Bounded",
    7.73 -      "Num", "Real", "Integral", "Fractional", "Floating", "RealFloat", "Monad", "Functor",
    7.74 -      "AlreadyExists", "ArithException", "ArrayException", "AssertionFailed", "AsyncException",
    7.75 -      "BlockedOnDeadMVar", "Deadlock", "Denormal", "DivideByZero", "DotNetException", "DynException",
    7.76 -      "Dynamic", "EOF", "EQ", "EmptyRec", "ErrorCall", "ExitException", "ExitFailure",
    7.77 -      "ExitSuccess", "False", "GT", "HeapOverflow",
    7.78 -      "IOError", "IOException", "IllegalOperation",
    7.79 -      "IndexOutOfBounds", "Just", "Key", "LT", "Left", "LossOfPrecision", "NoMethodError",
    7.80 -      "NoSuchThing", "NonTermination", "Nothing", "Obj", "OtherError", "Overflow",
    7.81 -      "PatternMatchFail", "PermissionDenied", "ProtocolError", "RecConError", "RecSelError",
    7.82 -      "RecUpdError", "ResourceBusy", "ResourceExhausted", "Right", "StackOverflow",
    7.83 -      "ThreadKilled", "True", "TyCon", "TypeRep", "UndefinedElement", "Underflow",
    7.84 -      "UnsupportedOperation", "UserError", "abs", "absReal", "acos", "acosh", "all",
    7.85 -      "and", "any", "appendFile", "asTypeOf", "asciiTab", "asin", "asinh", "atan",
    7.86 -      "atan2", "atanh", "basicIORun", "blockIO", "boundedEnumFrom", "boundedEnumFromThen",
    7.87 -      "boundedEnumFromThenTo", "boundedEnumFromTo", "boundedPred", "boundedSucc", "break",
    7.88 -      "catch", "catchException", "ceiling", "compare", "concat", "concatMap", "const",
    7.89 -      "cos", "cosh", "curry", "cycle", "decodeFloat", "denominator", "div", "divMod",
    7.90 -      "doubleToRatio", "doubleToRational", "drop", "dropWhile", "either", "elem",
    7.91 -      "emptyRec", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo",
    7.92 -      "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter", "flip",
    7.93 -      "floatDigits", "floatProperFraction", "floatRadix", "floatRange", "floatToRational",
    7.94 -      "floor", "fmap", "foldl", "foldl'", "foldl1", "foldr", "foldr1", "fromDouble",
    7.95 -      "fromEnum", "fromEnum_0", "fromInt", "fromInteger", "fromIntegral", "fromObj",
    7.96 -      "fromRational", "fst", "gcd", "getChar", "getContents", "getLine", "head",
    7.97 -      "id", "inRange", "index", "init", "intToRatio", "interact", "ioError", "isAlpha",
    7.98 -      "isAlphaNum", "isDenormalized", "isDigit", "isHexDigit", "isIEEE", "isInfinite",
    7.99 -      "isLower", "isNaN", "isNegativeZero", "isOctDigit", "isSpace", "isUpper", "iterate", "iterate'",
   7.100 -      "last", "lcm", "length", "lex", "lexDigits", "lexLitChar", "lexmatch", "lines", "log",
   7.101 -      "logBase", "lookup", "loop", "map", "mapM", "mapM_", "max", "maxBound", "maximum",
   7.102 -      "maybe", "min", "minBound", "minimum", "mod", "negate", "nonnull", "not", "notElem",
   7.103 -      "null", "numerator", "numericEnumFrom", "numericEnumFromThen", "numericEnumFromThenTo",
   7.104 -      "numericEnumFromTo", "odd", "or", "otherwise", "pi", "pred", 
   7.105 -      "print", "product", "properFraction", "protectEsc", "putChar", "putStr", "putStrLn",
   7.106 -      "quot", "quotRem", "range", "rangeSize", "rationalToDouble", "rationalToFloat",
   7.107 -      "rationalToRealFloat", "read", "readDec", "readField", "readFieldName", "readFile",
   7.108 -      "readFloat", "readHex", "readIO", "readInt", "readList", "readLitChar", "readLn",
   7.109 -      "readOct", "readParen", "readSigned", "reads", "readsPrec", "realFloatToRational",
   7.110 -      "realToFrac", "recip", "reduce", "rem", "repeat", "replicate", "return", "reverse",
   7.111 -      "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq", "sequence",
   7.112 -      "sequence_", "show", "showChar", "showException", "showField", "showList",
   7.113 -      "showLitChar", "showParen", "showString", "shows", "showsPrec", "significand",
   7.114 -      "signum", "signumReal", "sin", "sinh", "snd", "span", "splitAt", "sqrt", "subtract",
   7.115 -      "succ", "sum", "tail", "take", "takeWhile", "takeWhile1", "tan", "tanh", "threadToIOResult",
   7.116 -      "throw", "toEnum", "toInt", "toInteger", "toObj", "toRational", "truncate", "uncurry",
   7.117 -      "undefined", "unlines", "unsafeCoerce", "unsafeIndex", "unsafeRangeSize", "until", "unwords",
   7.118 -      "unzip", "unzip3", "userError", "words", "writeFile", "zip", "zip3", "zipWith", "zipWith3"
   7.119 -    ] (*due to weird handling of ':', we can't do anything else than to import *all* prelude symbols*);
   7.120 +  #> fold (Code_Target.add_reserved target) prelude_import_unqualified
   7.121 +  #> fold (Code_Target.add_reserved target o fst) prelude_import_unqualified_constr
   7.122 +  #> fold (fold (Code_Target.add_reserved target) o snd) prelude_import_unqualified_constr;
   7.123  
   7.124  end; (*struct*)