right clean Generics library version added
authorcharlie <charlie.gerhardus@student.ru.nl>
Sun, 20 Dec 2015 15:50:47 +0000 (16:50 +0100)
committercharlie <charlie.gerhardus@student.ru.nl>
Sun, 20 Dec 2015 15:50:47 +0000 (16:50 +0100)
33 files changed:
a3/code/Generics/GenBimap.dcl [new file with mode: 0644]
a3/code/Generics/GenBimap.icl [new file with mode: 0644]
a3/code/Generics/GenCompress.dcl [new file with mode: 0644]
a3/code/Generics/GenCompress.icl [new file with mode: 0644]
a3/code/Generics/GenDefault.dcl [new file with mode: 0644]
a3/code/Generics/GenDefault.icl [new file with mode: 0644]
a3/code/Generics/GenEq.dcl [new file with mode: 0644]
a3/code/Generics/GenEq.icl [new file with mode: 0644]
a3/code/Generics/GenFMap.dcl [new file with mode: 0644]
a3/code/Generics/GenFMap.icl [new file with mode: 0644]
a3/code/Generics/GenHylo.dcl [new file with mode: 0644]
a3/code/Generics/GenHylo.icl [new file with mode: 0644]
a3/code/Generics/GenLexOrd.dcl [new file with mode: 0644]
a3/code/Generics/GenLexOrd.icl [new file with mode: 0644]
a3/code/Generics/GenLib.dcl [new file with mode: 0644]
a3/code/Generics/GenLib.icl [new file with mode: 0644]
a3/code/Generics/GenMap.dcl [new file with mode: 0644]
a3/code/Generics/GenMap.icl [new file with mode: 0644]
a3/code/Generics/GenMapSt.dcl [new file with mode: 0644]
a3/code/Generics/GenMapSt.icl [new file with mode: 0644]
a3/code/Generics/GenMonad.dcl [new file with mode: 0644]
a3/code/Generics/GenMonad.icl [new file with mode: 0644]
a3/code/Generics/GenParse.dcl [new file with mode: 0644]
a3/code/Generics/GenParse.icl [new file with mode: 0644]
a3/code/Generics/GenPrint.dcl [new file with mode: 0644]
a3/code/Generics/GenPrint.icl [new file with mode: 0644]
a3/code/Generics/GenReduce.dcl [new file with mode: 0644]
a3/code/Generics/GenReduce.icl [new file with mode: 0644]
a3/code/Generics/GenZip.dcl [new file with mode: 0644]
a3/code/Generics/GenZip.icl [new file with mode: 0644]
a3/code/Generics/_Array.dcl [new file with mode: 0644]
a3/code/Generics/_Array.icl [new file with mode: 0644]
a3/code/Generics/gentest.icl [new file with mode: 0644]

diff --git a/a3/code/Generics/GenBimap.dcl b/a3/code/Generics/GenBimap.dcl
new file mode 100644 (file)
index 0000000..382b611
--- /dev/null
@@ -0,0 +1,7 @@
+definition module GenBimap\r
+\r
+// from StdGeneric import generic bimap\r
+import StdGeneric\r
+from StdMaybe import :: Maybe\r
+\r
+derive bimap Maybe, [], (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
diff --git a/a3/code/Generics/GenBimap.icl b/a3/code/Generics/GenBimap.icl
new file mode 100644 (file)
index 0000000..ed4e0f8
--- /dev/null
@@ -0,0 +1,5 @@
+implementation module GenBimap\r
+\r
+import GenBimap\r
+\r
+derive bimap Maybe, [], (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
diff --git a/a3/code/Generics/GenCompress.dcl b/a3/code/Generics/GenCompress.dcl
new file mode 100644 (file)
index 0000000..b0d251b
--- /dev/null
@@ -0,0 +1,19 @@
+definition module GenCompress\r
+\r
+import StdGeneric, StdMaybe\r
+\r
+:: BitVector :== {#Int}\r
+\r
+:: CompressSt\r
+\r
+generic gCompress a :: !a -> *CompressSt -> *CompressSt\r
+derive gCompress Int, Real, Bool, Char, String, UNIT, PAIR, EITHER, CONS, FIELD, OBJECT, [], {}, {!}\r
+\r
+generic gCompressedSize a :: a -> Int\r
+derive gCompressedSize Int, Real, Bool, Char, String, UNIT, PAIR, EITHER, CONS, FIELD, OBJECT, [], {}, {!}\r
+\r
+generic gUncompress a :: (u:CompressSt -> ((Maybe a),u:CompressSt))\r
+derive gUncompress Int, Real, Bool, Char, String, UNIT, PAIR, EITHER, CONS, FIELD, OBJECT, [], {}, {!}\r
+\r
+compress :: !a -> BitVector | gCompressedSize{|*|} a & gCompress{|*|} a\r
+uncompress :: (BitVector -> Maybe a) | gUncompress{|*|} a\r
diff --git a/a3/code/Generics/GenCompress.icl b/a3/code/Generics/GenCompress.icl
new file mode 100644 (file)
index 0000000..1797ae4
--- /dev/null
@@ -0,0 +1,238 @@
+implementation module GenCompress\r
+\r
+import StdGeneric, StdEnv, StdMaybe, _Array\r
+\r
+//--------------------------------------------------\r
+// uncompressor monad\r
+\r
+ret :: !.a !u:CompressSt -> (!Maybe .a,!u:CompressSt)\r
+ret a st = (Just a, st)\r
+(>>=) infixl 5 \r
+(>>=) pa pb = bind pa pb\r
+where\r
+       bind pa pb st \r
+               #! (ma, st) = pa st\r
+               = case ma of\r
+                       Nothing -> (Nothing, st)\r
+                       Just x  -> pb x st\r
+\r
+//--------------------------------------------------\r
+\r
+:: BitVector :== {#Int}\r
+:: BitPos :== Int\r
+\r
+:: CompressSt = { cs_pos :: !Int, cs_bits :: !.{#Int} }\r
+mkCompressSt arr = { cs_pos = 0, cs_bits = arr}\r
+\r
+\r
+:: Compress a :== a -> *CompressSt -> *CompressSt\r
+:: Uncompress a :== .CompressSt -> .(.(Maybe a), .CompressSt)\r
+\r
+compressBool :: !Bool !*CompressSt -> *CompressSt\r
+compressBool bit {cs_pos = pos, cs_bits = bits}\r
+       #! s = size bits\r
+       #! int_pos = pos >> (IF_INT_64_OR_32 6 5)\r
+       #! bit_pos = pos bitand (IF_INT_64_OR_32 63 31)\r
+       | s == int_pos\r
+               = abort "reallocate" \r
+               #! int = bits.[int_pos]\r
+               #! bit_mask = 1 << bit_pos\r
+               #! new_int = if bit (int bitor bit_mask) (int bitand (bitnot bit_mask))\r
+               = {cs_pos = inc pos, cs_bits = {bits & [int_pos] = new_int}}\r
+\r
+uncompressBool :: !u:CompressSt -> (.(Maybe Bool),v:CompressSt), [u <= v]\r
+uncompressBool cs=:{cs_pos = pos, cs_bits = bits}\r
+       #! s = size bits\r
+       #! int_pos = pos >> (IF_INT_64_OR_32 6 5)\r
+       #! bit_pos = pos bitand (IF_INT_64_OR_32 63 31)\r
+       | s == int_pos\r
+               = (Nothing, cs) \r
+               #! int = bits.[int_pos]\r
+               #! bit_mask = 1 << bit_pos\r
+               #! bit = (bit_mask bitand int) <> 0\r
+               = (Just bit, {cs & cs_pos = inc pos})\r
+\r
+compressIntB :: !.Int !.Int -> .(*CompressSt -> .CompressSt)\r
+compressIntB num_bits int\r
+       = compress 0 num_bits int\r
+where\r
+       compress i n int\r
+               | i == n\r
+                       = id\r
+               | otherwise\r
+                       = compress (inc i) n (int >> 1) \r
+                       o compressBool ((int bitand 1) == 1)\r
+\r
+\r
+compressInt = compressIntB (IF_INT_64_OR_32 64 32)\r
+compressChar c = compressIntB 8 (toInt c)\r
+\r
+uncompressIntB :: !.Int -> u:CompressSt -> (.(Maybe Int),v:CompressSt), [u <= v]\r
+uncompressIntB num_bits\r
+       = uncompress 0 num_bits 0\r
+where\r
+       uncompress i n int\r
+               | i == n\r
+                       = ret int\r
+               | otherwise\r
+                       =       uncompressBool\r
+                       >>=     \bit -> uncompress (inc i) n int \r
+                       >>=     \x -> ret ((if bit 1 0) + (x << 1))\r
+\r
+uncompressInt :: (u:CompressSt -> (.(Maybe Int),v:CompressSt)), [u <= v]\r
+uncompressInt = uncompressIntB (IF_INT_64_OR_32 64 32)\r
+\r
+uncompressChar :: (u:CompressSt -> (.(Maybe Char),v:CompressSt)), [u <= v]\r
+uncompressChar = uncompressIntB 8 >>= ret o toChar \r
+\r
+realToBinary32 :: !Real -> (!Int,!Int);\r
+realToBinary32 _ = code {\r
+    pop_b 0\r
+    };\r
+\r
+realToBinary64 :: !Real -> Int;\r
+realToBinary64 _ = code {\r
+    pop_b 0\r
+    };\r
+\r
+binaryToReal32 :: !(!Int,!Int) -> Real;\r
+binaryToReal32 _ = code {\r
+    pop_b 0\r
+    };\r
+\r
+binaryToReal64 :: !Int -> Real;\r
+binaryToReal64 _ = code {\r
+    pop_b 0\r
+    };\r
+\r
+compressReal real\r
+       = IF_INT_64_OR_32\r
+               (compressInt (realToBinary64 real))\r
+               (let (i1, i2) = realToBinary32 real in compressInt i2 o compressInt i1)\r
+\r
+uncompressReal :: (u:CompressSt -> (.(Maybe Real),v:CompressSt)), [u <= v]\r
+uncompressReal\r
+       = IF_INT_64_OR_32\r
+               (uncompressInt\r
+               >>= \i -> ret (binaryToReal64 i))\r
+               (uncompressInt \r
+               >>= \i1 -> uncompressInt \r
+               >>= \i2 -> ret (binaryToReal32 (i1,i2)))\r
+\r
+compressArray :: (a -> u:(v:CompressSt -> w:CompressSt)) !.(b a) -> x:(*CompressSt -> y:CompressSt) | Array b a, [x <= u,w <= v,w <= y]\r
+compressArray f xs \r
+       = foldSt f [x \\ x <-: xs] o compressInt (size xs)\r
+\r
+foldSt f [] = id\r
+foldSt f [x:xs] = foldSt f xs o f x\r
+\r
+uncompressArray :: (u:CompressSt -> ((Maybe v:a),w:CompressSt)) -> .(x:CompressSt -> ((Maybe y:(b v:a)),z:CompressSt)) | Array b a, [x w <= u,y <= v,x w <= z]\r
+uncompressArray f \r
+       =       uncompressInt >>= \s -> uncompress_array 0 s (createArrayUnsafe s) \r
+where \r
+       uncompress_array i s arr\r
+               | i == s\r
+                       = ret arr\r
+                       = f >>= \x -> uncompress_array (inc i) s {arr & [i] = x} \r
+\r
+compressList :: (a *CompressSt -> *CompressSt) ![a] -> *CompressSt -> *CompressSt\r
+compressList c xs = compressArray c (list_to_arr xs)\r
+where\r
+       list_to_arr :: [b] -> {b} | Array {} b\r
+       list_to_arr xs = {x \\ x <- xs}\r
+\r
+\r
+uncompressList xs = uncompressArray xs >>= ret o arr_to_list\r
+where\r
+       arr_to_list :: {b} -> [b] | Array {} b\r
+       arr_to_list xs = [x \\ x <-: xs] \r
\r
+//--------------------------------------------------------------------------------------\r
+\r
+generic gCompress a :: !a -> *CompressSt -> *CompressSt\r
+gCompress{|Int|} x = compressInt x \r
+gCompress{|Real|} x = compressReal x \r
+gCompress{|Char|} x = compressChar x\r
+gCompress{|Bool|} x = compressBool x\r
+gCompress{|UNIT|} x = id\r
+gCompress{|PAIR|} cx cy (PAIR x y) = cy y o cx x\r
+gCompress{|EITHER|} cl cr (LEFT x) = cl x o compressBool False\r
+gCompress{|EITHER|} cl cr (RIGHT x) = cr x o compressBool True\r
+gCompress{|CONS|} c (CONS x) = c x\r
+gCompress{|FIELD|} c (FIELD x) = c x\r
+gCompress{|OBJECT|} c (OBJECT x) = c x\r
+gCompress{|{}|} c xs = compressArray c xs\r
+gCompress{|{!}|} c xs = compressArray c xs\r
+gCompress{|String|} xs = compressArray compressChar xs\r
+gCompress{|[]|} c xs = compressList c xs\r
+\r
+\r
+generic gCompressedSize a :: a -> Int\r
+gCompressedSize{|Int|} _ = IF_INT_64_OR_32 64 32\r
+gCompressedSize{|Real|} _ = 64\r
+gCompressedSize{|Char|} _ = 8\r
+gCompressedSize{|Bool|} _ = 1\r
+gCompressedSize{|UNIT|} _ = 0\r
+gCompressedSize{|PAIR|} cx cy (PAIR x y) = cx x + cy y\r
+gCompressedSize{|EITHER|} cl cr (LEFT x) = 1 + cl x\r
+gCompressedSize{|EITHER|} cl cr (RIGHT x) = 1 + cr x\r
+gCompressedSize{|CONS|} c (CONS x) = c x\r
+gCompressedSize{|FIELD|} c (FIELD x) = c x\r
+gCompressedSize{|OBJECT|} c (OBJECT x) = c x\r
+gCompressedSize{|[]|} c xs = foldSt (\x st -> c x + st) xs (IF_INT_64_OR_32 64 32) \r
+gCompressedSize{|{}|} c xs = foldSt (\x st -> c x + st) [x\\x<-:xs] (IF_INT_64_OR_32 64 32) \r
+gCompressedSize{|{!}|} c xs = foldSt (\x st -> c x + st) [x\\x<-:xs] (IF_INT_64_OR_32 64 32) \r
+gCompressedSize{|String|} xs = (IF_INT_64_OR_32 64 32) + size xs * 8\r
+\r
+generic gUncompress a :: (u:CompressSt -> ((Maybe a),u:CompressSt))\r
+gUncompress{|Int|} = uncompressInt\r
+gUncompress{|Real|} = uncompressReal\r
+gUncompress{|Char|} = uncompressChar\r
+gUncompress{|Bool|} = uncompressBool\r
+gUncompress{|UNIT|} = ret UNIT\r
+gUncompress{|PAIR|} fx fy = fx >>= \x -> fy >>= \y -> ret (PAIR x y)\r
+gUncompress{|EITHER|} fl fr = uncompressBool >>= either\r
+where\r
+       either is_right \r
+               | is_right\r
+                       = fr >>= ret o RIGHT\r
+                       = fl >>= ret o LEFT\r
+gUncompress{|CONS|} f = f >>= ret o CONS\r
+gUncompress{|FIELD|} f = f >>= ret o FIELD\r
+gUncompress{|OBJECT|} f = f >>= ret o OBJECT\r
+gUncompress{|[]|} f = uncompressList f \r
+gUncompress{|{}|} f = uncompressArray f \r
+gUncompress{|{!}|} f = uncompressArray f \r
+gUncompress{|String|} = uncompressArray uncompressChar \r
+\r
+\r
+//-------------------------------------------------------------------------------------\r
+\r
+uncompress :: (BitVector -> Maybe a) | gUncompress{|*|} a\r
+uncompress = fst o gUncompress{|*|} o mkCompressSt\r
+\r
+compress :: !a -> BitVector | gCompressedSize{|*|} a & gCompress{|*|} a\r
+compress x \r
+       #! compressed_size = gCompressedSize{|*|} x\r
+       #! arr_size = (compressed_size + (IF_INT_64_OR_32 63 31)) >> (IF_INT_64_OR_32 6 5)\r
+       #! bits = createArray arr_size 0\r
+       = (gCompress{|*|} x (mkCompressSt bits)).cs_bits\r
\r
+//-------------------------------------------------------------------------------------\r
+\r
+/*\r
+:: Tree a b = Tip a | Bin b (Tree a b) (Tree a b)\r
+:: Color = Red | Green | Blue\r
+\r
+derive bimap (,), (,,), Maybe\r
+derive gCompress Tree, Color\r
+derive gUncompress Tree, Color\r
+derive gCompressedSize Tree, Color\r
+               \r
+//Start :: Maybe (Tree Color Color)\r
+//Start = uncompress (compress (Bin Red (Bin Green (Tip Blue) (Tip Red)) (Tip Green)))\r
+//Start = gCompressedSize{|*|} (Bin Red (Bin Green (Tip Blue) (Tip Red)) (Tip Green))\r
+\r
+Start \r
+       = gCompressedSize{|*|} xs\r
+*/
\ No newline at end of file
diff --git a/a3/code/Generics/GenDefault.dcl b/a3/code/Generics/GenDefault.dcl
new file mode 100644 (file)
index 0000000..fe11fcb
--- /dev/null
@@ -0,0 +1,10 @@
+definition module GenDefault\r
+\r
+import StdGeneric\r
+\r
+generic gDefault a ::  a \r
+\r
+derive gDefault Int, Real, String, PAIR, EITHER, CONS, FIELD, OBJECT \r
+\r
+derive gDefault [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
diff --git a/a3/code/Generics/GenDefault.icl b/a3/code/Generics/GenDefault.icl
new file mode 100644 (file)
index 0000000..db3a257
--- /dev/null
@@ -0,0 +1,19 @@
+implementation module GenDefault\r
+\r
+//import StdClass, StdArray, StdInt, StdFunc\r
+import StdGeneric\r
+\r
+generic gDefault a ::  a \r
+gDefault{|Int|}                                = 0\r
+gDefault{|Real|}                               = 0.0\r
+gDefault{|String|}                     = ""\r
+gDefault{|UNIT|}                               = UNIT\r
+gDefault{|EITHER|} dl dr       = RIGHT  dr\r
+gDefault{|EITHER|} dl dr       = LEFT   dl\r
+gDefault{|PAIR|}   dl dr       = PAIR   dl dr\r
+gDefault{|CONS|}   dc          = CONS   dc\r
+gDefault{|FIELD|}  df          = FIELD  df\r
+gDefault{|OBJECT|} do          = OBJECT do\r
+\r
+derive gDefault [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
diff --git a/a3/code/Generics/GenEq.dcl b/a3/code/Generics/GenEq.dcl
new file mode 100644 (file)
index 0000000..af9248d
--- /dev/null
@@ -0,0 +1,14 @@
+definition module GenEq\r
+\r
+import StdGeneric\r
+\r
+generic gEq a  :: a a -> Bool\r
+\r
+// base cases\r
+derive gEq Int, Char, Bool, Real, String, UNIT, PAIR, EITHER, CONS, FIELD, OBJECT, {}, {!} \r
+\r
+// standard types\r
+derive gEq [], (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+(===) infix 4 :: a a -> Bool | gEq{|*|} a\r
+(=!=) infix 4 :: a a -> Bool | gEq{|*|} a\r
diff --git a/a3/code/Generics/GenEq.icl b/a3/code/Generics/GenEq.icl
new file mode 100644 (file)
index 0000000..6bb1c8b
--- /dev/null
@@ -0,0 +1,35 @@
+implementation module GenEq\r
+\r
+import StdGeneric, StdEnv\r
+\r
+generic gEq a  :: a a -> Bool\r
+gEq{|Int|}     x y                                                     = x == y\r
+gEq{|Char|} x y                                                        = x == y\r
+gEq{|Bool|} x y                                                        = x == y\r
+gEq{|Real|} x y                                                        = x == y\r
+gEq{|String|} x y                                                      = x == y\r
+gEq{|UNIT|} UNIT UNIT                                          = True\r
+gEq{|PAIR|} fx fy (PAIR x1 y1) (PAIR x2 y2) = fx x1 x2 && fy y1 y2\r
+gEq{|EITHER|} fl fr (LEFT x) (LEFT y)          = fl x y\r
+gEq{|EITHER|} fl fr (RIGHT x) (RIGHT y)        = fr x y\r
+gEq{|EITHER|} fl fr    _ _                             = False\r
+gEq{|CONS|} f (CONS x) (CONS y)                        = f x y\r
+gEq{|FIELD|} f (FIELD x) (FIELD y)                     = f x y\r
+gEq{|OBJECT|} f (OBJECT x) (OBJECT y)          = f x y\r
+gEq{|{}|} f xs ys                                                      = eqArray f xs ys\r
+gEq{|{!}|} f xs ys                                                     = eqArray f xs ys\r
+\r
+derive gEq [], (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+\r
+(===) infix 4 :: a a -> Bool | gEq{|*|} a\r
+(===) x y = gEq{|*|} x y\r
+\r
+(=!=) infix 4 :: a a -> Bool | gEq{|*|} a\r
+(=!=) x y = not (x === y)\r
+\r
+eqArray f xs ys = size xs == size ys && eq 0 (size xs) xs ys\r
+where\r
+       eq i n xs ys\r
+               | i == n        = True          \r
+               | i < n         = f xs.[i] ys.[i] && eq (inc i) n xs ys\r
diff --git a/a3/code/Generics/GenFMap.dcl b/a3/code/Generics/GenFMap.dcl
new file mode 100644 (file)
index 0000000..66219aa
--- /dev/null
@@ -0,0 +1,19 @@
+definition module GenFMap\r
+\r
+import StdGeneric, StdMaybe\r
+\r
+:: FMap v\r
+derive bimap FMap\r
+\r
+emptyFMap :: .FMap .v\r
+\r
+generic gLookupFMap key :: key (FMap value) -> FMap value\r
+derive gLookupFMap UNIT, PAIR, EITHER, CONS, FIELD, OBJECT, Char, Int, Bool, Real, String, [], {}, {!}\r
+derive gLookupFMap (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+generic gInsertFMap key :: key (FMap value, FMap value) -> (FMap value, FMap value)\r
+derive gInsertFMap UNIT, PAIR, EITHER, CONS, FIELD, OBJECT, Char, Int, Bool, Real, String, [], {}, {!}\r
+derive gInsertFMap (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+lookupFMap :: !k .(FMap v) -> .(Maybe v) | gLookupFMap{|*|} k & bimap{|*|} v\r
+(<<=) infixl 1 :: .(FMap v) !.(k,v) -> FMap v | gInsertFMap{|*|} k & bimap{|*|} v\r
diff --git a/a3/code/Generics/GenFMap.icl b/a3/code/Generics/GenFMap.icl
new file mode 100644 (file)
index 0000000..14b171f
--- /dev/null
@@ -0,0 +1,153 @@
+implementation module GenFMap \r
+\r
+import StdGeneric, StdEnv, StdMaybe, _Array, GenMonad\r
+\r
+derive bimap (,), [] \r
+\r
+:: FMap v \r
+       = FMEmpty\r
+       | FMValue v\r
+       | FMEither      .(FMap v) .(FMap v)\r
+       | FMChar .[.(Char, .FMap v)]\r
+       | FMInt  .[.(Int, .FMap v)]\r
+       | FMReal .[.(Real, .FMap v)]\r
+\r
+emptyFMap :: .FMap .v\r
+emptyFMap = FMEmpty\r
+\r
+lookupAssocList :: k v [(k,v)] -> v | == k\r
+lookupAssocList key default_val [] = default_val\r
+lookupAssocList key default_val [(k,v):xs]\r
+       | key == k\r
+               = v\r
+               = lookupAssocList key default_val xs \r
+               \r
+updateAssocList :: k v v [(k,v)] -> (v, [(k,v)]) | == k\r
+updateAssocList key value default_val [] = (default_val, [(key, value)])\r
+updateAssocList key value default_val [(k,v):xs]\r
+       | k == key\r
+               = (v, [(k, value):xs])\r
+               #! (old_val, xs) = updateAssocList key value default_val xs\r
+               = (old_val, [(k, v) : xs]) \r
+       \r
+derive bimap FMap, Maybe\r
+bimap{|{}|} bma = {map_to = mapArray bma.map_to, map_from = mapArray bma.map_from}\r
+\r
+generic gLookupFMap key :: key (FMap value) -> FMap value\r
+gLookupFMap{|Char|} key (FMChar xs) = lookupAssocList key FMEmpty xs\r
+gLookupFMap{|Char|} key FMEmpty        = FMEmpty\r
+\r
+gLookupFMap{|Int|} key (FMInt xs) = lookupAssocList key FMEmpty xs\r
+gLookupFMap{|Int|} key FMEmpty         = FMEmpty\r
+\r
+gLookupFMap{|Real|} key (FMReal xs) = lookupAssocList key FMEmpty xs\r
+gLookupFMap{|Real|} key FMEmpty        = FMEmpty\r
+\r
+gLookupFMap{|Bool|} False (FMEither ls rs)     = ls\r
+gLookupFMap{|Bool|} True  (FMEither ls rs)     = rs\r
+gLookupFMap{|Bool|} key FMEmpty                        = FMEmpty\r
+\r
+//gLookupFMap{|UNIT|} key (FMValue v)  = (FMValue v)\r
+//gLookupFMap{|UNIT|} key FMEmpty              = FMEmpty\r
+gLookupFMap{|UNIT|} key fm             = fm\r
+\r
+gLookupFMap{|PAIR|} fx fy (PAIR kx ky) fm = fy ky (fx kx fm)\r
+\r
+gLookupFMap{|EITHER|} fl fr (LEFT key) (FMEither ls rs) = fl key ls\r
+gLookupFMap{|EITHER|} fl fr (RIGHT key) (FMEither ls rs) = fr key rs\r
+gLookupFMap{|EITHER|} fl fr key FMEmpty        = FMEmpty \r
+\r
+gLookupFMap{|CONS|} f (CONS key) fm = f key fm\r
+gLookupFMap{|FIELD|} f (FIELD key) fm = f key fm\r
+gLookupFMap{|OBJECT|} f (OBJECT key) fm = f key fm\r
+\r
+derive gLookupFMap []\r
+\r
+gLookupFMap{|String|} arr fm = gLookupFMap{|*|} [x\\x<-:arr] fm\r
+gLookupFMap{|{}|} f arr fm = gLookupFMap{|*->*|} f [x\\x<-:arr] fm\r
+gLookupFMap{|{!}|} f arr fm = gLookupFMap{|*->*|} f [x\\x<-:arr] fm\r
+\r
+derive gLookupFMap (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+lookupFMap :: !k .(FMap v) -> .(Maybe v) | gLookupFMap{|*|} k & bimap{|*|} v\r
+lookupFMap key fmap = case gLookupFMap{|*|} key fmap of\r
+       FMValue v       -> Just v\r
+       FMEmpty         -> Nothing \r
+       _                       -> abort "erroneous FMap"\r
+\r
+\r
+//------------------------------------------------------------------------------------\r
+\r
+generic gInsertFMap key :: key (FMap value, FMap value) -> (FMap value, FMap value)\r
+\r
+gInsertFMap{|Char|} key (new_val, FMChar xs) \r
+       # (old_val, xs) = updateAssocList key new_val FMEmpty xs\r
+       = (old_val, FMChar xs)\r
+gInsertFMap{|Char|} key (new_val, FMEmpty)     \r
+       = (FMEmpty, FMChar [(key, new_val)])\r
+\r
+gInsertFMap{|Int|} key (new_val, FMInt xs) \r
+       # (old_val, xs) = updateAssocList key new_val FMEmpty xs\r
+       = (old_val, FMInt xs)\r
+gInsertFMap{|Int|} key (new_val, FMEmpty)      \r
+       = (FMEmpty, FMInt [(key, new_val)])\r
+\r
+gInsertFMap{|Real|} key (new_val, FMReal xs) \r
+       # (old_val, xs) = updateAssocList key new_val FMEmpty xs\r
+       = (old_val, FMReal xs)\r
+gInsertFMap{|Real|} key (new_val, FMEmpty)     \r
+       = (FMEmpty, FMReal [(key, new_val)])\r
+\r
+gInsertFMap{|Bool|} False (v, FMEither ls rs)  = (ls, FMEither v rs)\r
+gInsertFMap{|Bool|} False (v, FMEmpty)                         = (FMEmpty, FMEither v FMEmpty)\r
+gInsertFMap{|Bool|} True  (v, FMEither ls rs)  = (rs, FMEither ls v)\r
+gInsertFMap{|Bool|} True  (v, FMEmpty)                 = (FMEmpty, FMEither FMEmpty v)\r
+       \r
+gInsertFMap{|UNIT|} key (x, y)                 = (y, x)\r
+\r
+gInsertFMap{|PAIR|} fx fy (PAIR kx ky) (new_val, fmx) \r
+       #! (old_fmy, fmx1) = fx kx (FMEmpty, fmx)\r
+       #! (old_val, new_fmy) = fy ky (new_val, old_fmy)   \r
+       #! (empty_fmy, new_fmx) = fx kx (new_fmy, fmx) \r
+       = (old_val, new_fmx)\r
+\r
+gInsertFMap{|EITHER|} fl fr (LEFT key) (v, FMEither ls rs) \r
+       # (old_val, new_ls) = fl key (v,ls)\r
+       = (old_val, FMEither new_ls rs)\r
+gInsertFMap{|EITHER|} fl fr (LEFT key) (v, FMEmpty)\r
+       # (old_val, new_ls) = fl key (v,FMEmpty)\r
+       = (FMEmpty, FMEither new_ls FMEmpty)\r
+gInsertFMap{|EITHER|} fl fr (RIGHT key) (v, FMEither ls rs)\r
+       # (old_val, new_rs) = fr key (v,rs)\r
+       = (old_val, FMEither ls new_rs)\r
+gInsertFMap{|EITHER|} fl fr (RIGHT key) (v, FMEmpty)\r
+       # (old_val, new_rs) = fr key (v,FMEmpty)\r
+       = (FMEmpty, FMEither FMEmpty new_rs)\r
+       \r
+gInsertFMap{|CONS|} f (CONS key) x = f key x\r
+gInsertFMap{|FIELD|} f (FIELD key) x = f key x\r
+gInsertFMap{|OBJECT|} f (OBJECT key) x = f key x\r
+\r
+derive gInsertFMap []\r
+\r
+gInsertFMap{|String|} xs fm = gInsertFMap{|*|} [x\\x<-:xs] fm\r
+gInsertFMap{|{}|} f xs fm = gInsertFMap{|*->*|} f [x\\x<-:xs] fm\r
+gInsertFMap{|{!}|} f xs fm = gInsertFMap{|*->*|} f [x\\x<-:xs] fm\r
+\r
+derive gInsertFMap (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+(<<=) infixl 1 :: .(FMap v) !.(k,v) -> FMap v | gInsertFMap{|*|} k & bimap{|*|} v\r
+(<<=) fmap (key, value)\r
+       #! (old_val, fmap) = gInsertFMap{|*|} key (FMValue value, fmap)\r
+       = fmap \r
+\r
+//-----------------------------------------------------------------------------\r
+/* \r
+fmap = FMEmpty \r
+       <<= ("one", 1)\r
+       <<= ("two", 2)\r
+       <<= ("three", 3)\r
+       <<= ("four", 4)\r
+\r
+Start = lookupFMap "two" fmap \r
+*/\r
diff --git a/a3/code/Generics/GenHylo.dcl b/a3/code/Generics/GenHylo.dcl
new file mode 100644 (file)
index 0000000..fc54086
--- /dev/null
@@ -0,0 +1,11 @@
+definition module GenHylo\r
+\r
+import StdGeneric, GenMap\r
+\r
+:: Fix f = In (f .(Fix f))\r
+Out :: !u:(Fix v:a) -> v:(a w:(Fix v:a)), [u <= w]\r
+\r
+hylo :: ((.f .b) -> .b) (.a -> (.f .a)) -> (.a -> .b) | gMap{|*->*|} f\r
+cata :: (u:(f .a) -> .a) -> (Fix u:f) -> .a | gMap{|*->*|} f\r
+ana :: (.a -> u:(f .a)) -> .a -> (Fix u:f) | gMap{|*->*|} f\r
+\r
diff --git a/a3/code/Generics/GenHylo.icl b/a3/code/Generics/GenHylo.icl
new file mode 100644 (file)
index 0000000..d8e5876
--- /dev/null
@@ -0,0 +1,18 @@
+implementation module GenHylo \r
+\r
+import StdGeneric, GenMap, StdFunc\r
+\r
+:: Fix f = In (f .(Fix f))\r
+\r
+Out :: !u:(Fix v:a) -> v:(a w:(Fix v:a)), [u <= w]\r
+Out (In x) = x\r
+\r
+hylo :: ((.f .b) -> .b) (.a -> (.f .a)) -> (.a -> .b) | gMap{|*->*|} f\r
+hylo consume produce = consume o gMap{|*->*|} (hylo consume produce) o produce\r
+\r
+cata :: (u:(f .a) -> .a) -> (Fix u:f) -> .a | gMap{|*->*|} f\r
+cata f = hylo f Out \r
+\r
+ana :: (.a -> u:(f .a)) -> .a -> (Fix u:f) | gMap{|*->*|} f\r
+ana f = hylo In f\r
+\r
diff --git a/a3/code/Generics/GenLexOrd.dcl b/a3/code/Generics/GenLexOrd.dcl
new file mode 100644 (file)
index 0000000..bb11adf
--- /dev/null
@@ -0,0 +1,16 @@
+definition module GenLexOrd\r
+\r
+import StdGeneric, GenEq\r
+\r
+:: LexOrd = LT |EQ | GT\r
+derive gEq LexOrd\r
+\r
+generic gLexOrd a b :: a b -> LexOrd\r
+\r
+// base cases\r
+derive gLexOrd Char, Bool, Int, Real, String, UNIT, PAIR, EITHER, FIELD, CONS, OBJECT, [], {}, {!}\r
+\r
+// standard types\r
+derive gLexOrd (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+(=?=) infix 4 :: a a -> LexOrd | gLexOrd{|*|} a\r
diff --git a/a3/code/Generics/GenLexOrd.icl b/a3/code/Generics/GenLexOrd.icl
new file mode 100644 (file)
index 0000000..a597f99
--- /dev/null
@@ -0,0 +1,77 @@
+implementation module GenLexOrd\r
+\r
+import StdEnv\r
+import StdGeneric, GenEq\r
+\r
+:: LexOrd = LT |EQ | GT\r
+derive gEq LexOrd\r
+\r
+generic gLexOrd a b :: a b -> LexOrd\r
+gLexOrd{|Int|} x y\r
+       | x == y = EQ\r
+       | x < y  = LT\r
+                        = GT\r
+gLexOrd{|Bool|} True True = EQ\r
+gLexOrd{|Bool|} False True = LT\r
+gLexOrd{|Bool|} True False = GT\r
+gLexOrd{|Bool|} False False = EQ\r
+gLexOrd{|Real|} x y\r
+       | x == y = EQ\r
+       | x < y  = LT\r
+                        = GT\r
+gLexOrd{|Char|} x y\r
+       | x == y = EQ\r
+       | x < y  = LT\r
+                        = GT\r
+gLexOrd{|String|} x y\r
+       | x == y = EQ\r
+       | x < y  = LT\r
+                        = GT                    \r
+gLexOrd{|UNIT|} UNIT UNIT = EQ\r
+gLexOrd{|PAIR|} fx fy (PAIR x1 y1) (PAIR x2 y2) = case fx x1 x2 of\r
+               EQ -> fy y1 y2\r
+               LT -> LT\r
+               GT -> GT\r
+                       \r
+gLexOrd{|EITHER|} fl fr (LEFT x) (LEFT y) = fl x y \r
+gLexOrd{|EITHER|} fl fr (LEFT x) (RIGHT y) = LT\r
+gLexOrd{|EITHER|} fl fr (RIGHT x) (LEFT y) = GT\r
+gLexOrd{|EITHER|} fl fr (RIGHT x) (RIGHT y) = fr x y\r
+gLexOrd{|CONS|} f (CONS x) (CONS y) = f x y\r
+gLexOrd{|FIELD|} f (FIELD x) (FIELD y) = f x y\r
+gLexOrd{|OBJECT|} f (OBJECT x) (OBJECT y) = f x y\r
+\r
+// Instance on standard lists is needed because\r
+// standard lists have unnatural internal ordering of constructors: Cons < Nil,\r
+// i.e Cons is LEFT and Nil is RIGHT in the generic representation.\r
+// We want ordering Nil < Cons\r
+gLexOrd{|[]|} f [] [] = EQ\r
+gLexOrd{|[]|} f [] _  = LT\r
+gLexOrd{|[]|} f _ []  = GT\r
+gLexOrd{|[]|} f [x:xs] [y:ys] = gLexOrd{|*->*->*|} f (gLexOrd{|*->*|} f) (PAIR x xs) (PAIR y ys)\r
+\r
+gLexOrd{|{}|} f xs ys  = lexOrdArray f xs ys \r
+gLexOrd{|{!}|} f xs ys         = lexOrdArray f xs ys \r
+\r
+\r
+// standard types\r
+derive gLexOrd (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+   \r
+(=?=) infix 4 :: a a -> LexOrd | gLexOrd{|*|} a\r
+(=?=) x y = gLexOrd{|*|} x y                           \r
+\r
+\r
+lexOrdArray f xs ys\r
+       #! size_xs = size xs\r
+       #! size_ys = size ys\r
+       | size_xs < size_ys     = LT\r
+       | size_xs > size_ys = GT\r
+       | otherwise                     = lexord 0 size_xs xs ys\r
+where\r
+       lexord i n xs ys\r
+               | i == n                = EQ\r
+               | otherwise     = case f xs.[i] ys.[i] of\r
+                               LT -> LT\r
+                               GT -> GT        \r
+                               EQ -> lexord (inc i) n xs ys\r
diff --git a/a3/code/Generics/GenLib.dcl b/a3/code/Generics/GenLib.dcl
new file mode 100644 (file)
index 0000000..be990f8
--- /dev/null
@@ -0,0 +1,17 @@
+definition module GenLib\r
+\r
+import StdGeneric\r
+\r
+import GenEq\r
+import GenLexOrd\r
+import GenMap\r
+import GenMapSt\r
+import GenReduce\r
+import GenZip \r
+import GenPrint\r
+import GenParse\r
+import GenCompress\r
+import GenMonad\r
+import GenHylo\r
+import GenFMap\r
+import GenBimap
\ No newline at end of file
diff --git a/a3/code/Generics/GenLib.icl b/a3/code/Generics/GenLib.icl
new file mode 100644 (file)
index 0000000..7a2b04c
--- /dev/null
@@ -0,0 +1 @@
+implementation module GenLib
\ No newline at end of file
diff --git a/a3/code/Generics/GenMap.dcl b/a3/code/Generics/GenMap.dcl
new file mode 100644 (file)
index 0000000..e2b0e43
--- /dev/null
@@ -0,0 +1,8 @@
+definition module GenMap\r
+\r
+import StdGeneric\r
+\r
+generic gMap a b :: .a -> .b\r
+derive gMap c, PAIR, EITHER, CONS, FIELD, OBJECT, {}, {!} \r
+\r
+derive gMap [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
diff --git a/a3/code/Generics/GenMap.icl b/a3/code/Generics/GenMap.icl
new file mode 100644 (file)
index 0000000..6d13aa7
--- /dev/null
@@ -0,0 +1,18 @@
+implementation module GenMap\r
+\r
+import StdClass, StdArray, StdInt, StdFunc\r
+import StdGeneric, _Array\r
+\r
+generic gMap a b :: .a -> .b\r
+gMap{|c|} x                                    = x\r
+gMap{|PAIR|} fx fy (PAIR x y)  = PAIR (fx x) (fy y) \r
+gMap{|EITHER|} fl fr (LEFT x)  = LEFT (fl x)\r
+gMap{|EITHER|} fl fr (RIGHT x)         = RIGHT (fr x)\r
+gMap{|CONS|} f (CONS x)                = CONS (f x)\r
+gMap{|FIELD|} f (FIELD x)              = FIELD (f x)\r
+gMap{|OBJECT|} f (OBJECT x)    = OBJECT (f x)\r
+gMap{|{}|} f xs                                = mapArray f xs\r
+gMap{|{!}|} f xs                               = mapArray f xs\r
+\r
+derive gMap [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
diff --git a/a3/code/Generics/GenMapSt.dcl b/a3/code/Generics/GenMapSt.dcl
new file mode 100644 (file)
index 0000000..442c9cb
--- /dev/null
@@ -0,0 +1,12 @@
+definition module GenMapSt\r
+\r
+import StdGeneric\r
+\r
+generic gMapLSt a b :: .a .st -> (.b, .st)\r
+derive gMapLSt c, PAIR, EITHER, FIELD, CONS, OBJECT, {}, {!}\r
+derive gMapLSt [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+generic gMapRSt a b :: .a .st -> (.b, .st)\r
+derive gMapRSt c, PAIR, EITHER, FIELD, CONS, OBJECT, {}, {!} \r
+derive gMapRSt [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
diff --git a/a3/code/Generics/GenMapSt.icl b/a3/code/Generics/GenMapSt.icl
new file mode 100644 (file)
index 0000000..109843d
--- /dev/null
@@ -0,0 +1,53 @@
+implementation module GenMapSt\r
+\r
+import StdGeneric, _Array\r
+\r
+derive bimap (,)\r
+\r
+generic gMapLSt a b :: .a .st -> (.b, .st)\r
+gMapLSt{|c|} x st                              = (x, st)\r
+gMapLSt{|PAIR|} fx fy (PAIR x y) st\r
+       # (x, st) = fx x st     \r
+       # (y, st) = fy y st     \r
+       = (PAIR x y, st)        \r
+gMapLSt{|EITHER|} fl fr x st   = mapStEITHER fl fr x st\r
+gMapLSt{|CONS|} f x st                         = mapStCONS f x st\r
+gMapLSt{|FIELD|} f x st                = mapStFIELD f x st\r
+gMapLSt{|OBJECT|} f x st               = mapStOBJECT f x st\r
+gMapLSt{|{}|} f x st                   = mapArrayLSt f x st\r
+gMapLSt{|{!}|} f x st                  = mapArrayLSt f x st\r
+\r
+derive gMapLSt [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+generic gMapRSt a b :: .a .st -> (.b, .st)\r
+gMapRSt{|c|} x st = (x, st)\r
+gMapRSt{|PAIR|} fx fy (PAIR x y) st    \r
+       # (y, st) = fy y st     \r
+       # (x, st) = fx x st     \r
+       = (PAIR x y, st)        \r
+gMapRSt{|EITHER|} fx fy x st   = mapStEITHER fx fy x st        \r
+gMapRSt{|CONS|} f x st                         = mapStCONS f x st\r
+gMapRSt{|FIELD|} f x st                = mapStFIELD f x st\r
+gMapRSt{|OBJECT|} f x st               = mapStOBJECT f x st\r
+gMapRSt{|{}|} f x st                   = mapArrayRSt f x st\r
+gMapRSt{|{!}|} f x st                  = mapArrayRSt f x st\r
+\r
+derive gMapRSt [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+\r
+mapStEITHER fl fr (LEFT x) st\r
+       # (x, st) = fl x st \r
+       = (LEFT x, st)\r
+mapStEITHER fl fr (RIGHT x) st\r
+       # (x, st) = fr x st \r
+       = (RIGHT x, st)\r
+mapStCONS f (CONS x) st\r
+       # (x, st) = f x st      \r
+       = (CONS x, st)\r
+mapStFIELD f (FIELD x) st              \r
+       # (x, st) = f x st \r
+       = (FIELD x, st) \r
+mapStOBJECT f (OBJECT x) st            \r
+       # (x, st) = f x st \r
+       = (OBJECT x, st)        \r
+       
\ No newline at end of file
diff --git a/a3/code/Generics/GenMonad.dcl b/a3/code/Generics/GenMonad.dcl
new file mode 100644 (file)
index 0000000..e884bcc
--- /dev/null
@@ -0,0 +1,20 @@
+definition module GenMonad\r
+\r
+import StdGeneric, StdMaybe, StdList\r
+\r
+class Monad m where\r
+       ret :: a:a -> m:(m a:a), [m <= a]\r
+       (>>=) infixl 5 :: u:(m .a) v:(.a -> u:(m .b))  -> u:(m .b), [u <= v]\r
+       \r
+:: StMonad s a = { st_monad :: .(s -> *(a, s)) }\r
+derive bimap StMonad\r
+instance Monad Maybe, [], (StMonad .s)\r
+\r
+generic gMapLM a b :: a:a -> m:(m b:b) | Monad m, [m <= b]\r
+derive gMapLM c, PAIR, EITHER, CONS, FIELD, OBJECT\r
+derive gMapLM [], Maybe, (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+generic gMapRM a b :: a:a -> m:(m b:b) | Monad m, [m <= b]\r
+derive gMapRM c, PAIR, EITHER, CONS, FIELD, OBJECT\r
+derive gMapRM [], Maybe, (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
diff --git a/a3/code/Generics/GenMonad.icl b/a3/code/Generics/GenMonad.icl
new file mode 100644 (file)
index 0000000..7b99b9e
--- /dev/null
@@ -0,0 +1,57 @@
+implementation module GenMonad\r
+\r
+import StdGeneric, StdMaybe, StdList, StdFunc\r
+\r
+generic gMapLM a b :: a:a -> m:(m b:b) | Monad m, [m <= b]\r
+gMapLM{|c|} x                                          = ret x\r
+gMapLM{|PAIR|} fx fy (PAIR x y)        = fx x >>= \x1 -> fy y >>= \y1 -> ret (PAIR x1 y1)  \r
+gMapLM{|EITHER|} fl fr x                       = mapMEITHER fl fr x \r
+gMapLM{|CONS|} f (CONS x)                      = f x >>= ret o CONS\r
+gMapLM{|FIELD|} f (FIELD x)                    = f x >>= ret o FIELD\r
+gMapLM{|OBJECT|} f (OBJECT x)          = f x >>= ret o OBJECT\r
\r
+generic gMapRM a b :: a:a -> m:(m b:b) | Monad m, [m <= b]\r
+gMapRM{|c|} x                                          = ret x\r
+gMapRM{|PAIR|} fx fy (PAIR x y)                = fy y >>= \y1 -> fx x >>= \x1 -> ret (PAIR x1 y1)  \r
+gMapRM{|EITHER|} fl fr x                       = mapMEITHER fl fr x \r
+gMapRM{|CONS|} f (CONS x)                      = f x >>= ret o CONS\r
+gMapRM{|FIELD|} f (FIELD x)                    = f x >>= ret o FIELD\r
+gMapRM{|OBJECT|} f (OBJECT x)          = f x >>= ret o OBJECT\r
+\r
+derive gMapLM [], Maybe, (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+derive gMapRM [], Maybe, (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+mapMEITHER fl fr (LEFT x) = fl x >>= ret o LEFT\r
+mapMEITHER fl fr (RIGHT x) = fr x >>= ret o RIGHT \r
+\r
+//----------------------------------------------------------------------       \r
+instance Monad Maybe where\r
+       ret x = Just x\r
+       (>>=) Nothing f = Nothing\r
+       (>>=) (Just x) f = f x\r
+\r
+instance Monad [] where\r
+       ret x = [x]\r
+       //(>>=) xs f = flatten (map f xs)       // uniqueness typing makes it a problem because f is shared\r
+       (>>=) [x:xs] f = f x\r
+\r
+//-----------------------\r
+// state monad \r
+\r
+//retStMonad :: .a -> .(StMonad .s .a)\r
+retStMonad x = {st_monad = (\s -> (x, s))} \r
+\r
+//bindStMonad :: !.(StMonad .a .b) .(.b -> .(StMonad .a .c)) -> .(StMonad .a .c)\r
+bindStMonad {st_monad} f = {st_monad  = \s -> let (a, s1) = st_monad s in (f a).st_monad s1}\r
+\r
+mapFst f (x, y) = (f x, y)\r
+\r
+//mapStMonad :: .(a:a -> .b) !v:(StMonad s:s a:a) -> .(StMonad s:s .b), [v <= a,v <= s]\r
+mapStMonad f {st_monad} = {st_monad = mapFst f o st_monad}\r
+\r
+instance Monad (StMonad .s) where\r
+       ret x           = retStMonad x\r
+       (>>=) x f       = bindStMonad x f\r
+\r
+derive bimap (,)       \r
+derive bimap StMonad   
\ No newline at end of file
diff --git a/a3/code/Generics/GenParse.dcl b/a3/code/Generics/GenParse.dcl
new file mode 100644 (file)
index 0000000..98de10b
--- /dev/null
@@ -0,0 +1,20 @@
+definition module GenParse\r
+\r
+import StdGeneric, StdMaybe\r
+\r
+class ParseInput s where\r
+       parseInput :: s -> (Maybe Char, s)\r
+\r
+:: StringInput = { si_str :: !String, si_pos :: !Int}  \r
+mkStringInput :: String -> StringInput \r
+\r
+instance ParseInput    StringInput \r
+instance ParseInput File\r
+\r
+:: Expr\r
+generic gParse a :: Expr -> Maybe a\r
+\r
+derive gParse Int, Char, Bool, Real, String, UNIT, PAIR, EITHER, CONS, FIELD, OBJECT, [], {!}, {}\r
+\r
+parseString :: String -> Maybe a | gParse{|*|} a\r
+parseFile :: File -> Maybe a | gParse{|*|} a
\ No newline at end of file
diff --git a/a3/code/Generics/GenParse.icl b/a3/code/Generics/GenParse.icl
new file mode 100644 (file)
index 0000000..be4ccd7
--- /dev/null
@@ -0,0 +1,789 @@
+implementation module GenParse\r
+\r
+import StdGeneric, StdEnv, StdMaybe\r
+\r
+//---------------------------------------------------------------------------\r
+\r
+\r
+:: StringInput = { si_str :: !String, si_pos :: !Int} \r
+\r
+mkStringInput :: String -> StringInput \r
+mkStringInput str = {si_str = str, si_pos = 0}\r
+\r
+instance ParseInput StringInput where\r
+       parseInput s=:{si_pos, si_str}\r
+               #! size_str = size si_str\r
+               | size_str == si_pos \r
+                       = (Nothing, {s & si_str = si_str})\r
+               | otherwise\r
+                       #! ch = si_str.[si_pos]\r
+                       = (Just ch, {s & si_str = si_str, si_pos = inc si_pos})\r
+\r
+instance ParseInput File where \r
+       parseInput file \r
+               # (ok, c, file) = sfreadc file\r
+               | ok\r
+                       = (Just c, file)\r
+                       = (Nothing, file)\r
+                                               \r
+//---------------------------------------------------------------------------\r
+\r
+// lex tokens\r
+:: Token \r
+       = TokenInt Int\r
+       | TokenChar Char\r
+       | TokenReal Real \r
+       | TokenBool Bool\r
+       | TokenString String\r
+       | TokenIdent String\r
+       | TokenOpenPar\r
+       | TokenClosePar\r
+       | TokenOpenCurly\r
+       | TokenCloseCurly\r
+       | TokenOpenList\r
+       | TokenCloseList\r
+       | TokenComma\r
+       | TokenEnd\r
+       | TokenError String\r
+\r
+instance toString Token where\r
+       toString (TokenInt x) = toString x\r
+       toString (TokenChar x) = toString x\r
+       toString (TokenReal x) = toString x\r
+       toString (TokenBool x) = toString x\r
+       toString (TokenString x) = x\r
+       toString (TokenIdent x) = x\r
+       toString TokenOpenPar = "("\r
+       toString TokenClosePar = ")"\r
+       toString TokenOpenCurly = "{"\r
+       toString TokenCloseCurly = "}"\r
+       toString TokenOpenList = "["\r
+       toString TokenCloseList = "]"   \r
+       toString TokenComma = ","\r
+       toString TokenEnd = "<end>"\r
+       toString (TokenError err) = "<error: " +++ err +++ ">"\r
+\r
+// preparsed expressions\r
+:: Expr \r
+       = ExprInt Int\r
+       | ExprChar Char\r
+       | ExprReal Real \r
+       | ExprBool Bool\r
+       | ExprString String\r
+       | ExprIdent String\r
+       | ExprApp {Expr} \r
+       | ExprTuple {Expr}\r
+       | ExprField String Expr\r
+       | ExprRecord (Maybe String) {Expr}\r
+       | ExprList [Expr]\r
+       | ExprArray [Expr]\r
+       | ExprEnd Token\r
+       | ExprError String\r
+\r
+       // aux\r
+       | ExprUnit\r
+       | ExprAppInInfix {Expr} GenConsAssoc Int GenConsAssoc\r
+       | ExprPair Expr Expr\r
+\r
+\r
+instance toString Expr where\r
+       toString (ExprInt x) = toString x\r
+       toString (ExprChar x) = toString x\r
+       toString (ExprBool x) = toString x\r
+       toString (ExprReal x) = toString x\r
+       toString (ExprString x) = x\r
+       toString (ExprIdent x) = x\r
+       toString (ExprApp xs) = "(" +++ tostr [x\\x<-:xs] +++ ")"\r
+       where\r
+               tostr [] = ""\r
+               tostr [x] = toString x\r
+               tostr [x:xs] = toString x +++ " " +++ tostr xs\r
+       toString (ExprTuple xs) = "(" +++ tostr [x\\x<-:xs] +++ ")"\r
+       where\r
+               tostr [] = ""\r
+               tostr [x] = toString x\r
+               tostr [x:xs] = toString x +++ ", " +++ tostr xs\r
+       toString (ExprRecord name xs) = "{" +++ tostr [x\\x<-:xs] +++ "}"\r
+       where\r
+               tostr [] = ""\r
+               tostr [x] = toString x\r
+               tostr [x:xs] = toString x +++ ", " +++ tostr xs\r
+       toString (ExprField name expr) = name +++ "=" +++ toString expr\r
+\r
+               \r
+:: ParseState s =\r
+       { ps_input      :: !s                   // lex input\r
+       , ps_char       :: !Maybe Char  // unget char\r
+       , ps_tokens :: ![Token]         // unget tokens\r
+       }\r
+\r
+lexGetChar ps=:{ps_char=Nothing, ps_input}\r
+       # (mc, ps_input) = parseInput ps_input\r
+       = (mc, {ps & ps_input = ps_input})\r
+lexGetChar ps=:{ps_char} = (ps_char, {ps & ps_char = Nothing})\r
+\r
+lexUngetChar c ps=:{ps_char=Nothing} = {ps & ps_char = Just c}\r
+lexUngetChar c ps = abort "cannot unget\n"     \r
+\r
+isSpecialChar  :: !Char -> Bool\r
+isSpecialChar '~'      = True\r
+isSpecialChar '@'      = True\r
+isSpecialChar '#'      = True\r
+isSpecialChar '$'      = True\r
+isSpecialChar '%'      = True\r
+isSpecialChar '^'      = True\r
+isSpecialChar '?'      = True\r
+isSpecialChar '!'      = True\r
+isSpecialChar '+'      = True\r
+isSpecialChar '-'      = True\r
+isSpecialChar '*'      = True\r
+isSpecialChar '<'      = True\r
+isSpecialChar '>'      = True\r
+isSpecialChar '\\'     = True\r
+isSpecialChar '/'      = True\r
+isSpecialChar '|'      = True\r
+isSpecialChar '&'      = True\r
+isSpecialChar '='      = True\r
+isSpecialChar ':'      = True\r
+isSpecialChar '.'      = True\r
+isSpecialChar c                = False\r
+\r
+//----------------------------------------------------------------------------------           \r
+// lex input\r
+\r
+lexUngetToken token ps=:{ps_tokens} = {ps & ps_tokens = [token:ps_tokens]}\r
+\r
+lexGetToken ps=:{ps_tokens=[token:tokens]} = (token, {ps & ps_tokens = tokens})\r
+lexGetToken ps=:{ps_tokens=[]}\r
+       = lex ps\r
+where\r
+       lex s   \r
+               # (mc, s) = lexGetChar s\r
+               = case mc of\r
+                       Nothing  -> (TokenEnd, s)\r
+                       Just '\0' -> (TokenEnd, s)\r
+                       Just '(' -> (TokenOpenPar, s)\r
+                       Just ')' -> (TokenClosePar, s)\r
+                       Just '{' -> (TokenOpenCurly, s)\r
+                       Just '}' -> (TokenCloseCurly, s)\r
+                       Just '[' -> (TokenOpenList, s)\r
+                       Just ']' -> (TokenCloseList, s)\r
+                       Just ',' -> (TokenComma, s)\r
+                       Just '\'' -> lex_char 0 [] s\r
+                       Just '"'  -> lex_string 0 [] s\r
+                       Just '_' -> lex_ident 1 ['_'] s\r
+                       Just '`' -> lex_ident 1 ['`'] s\r
+                       Just '+'\r
+                               # (mc, s) = lexGetChar s\r
+                               -> case mc of\r
+                                       Nothing -> (TokenIdent "+", s)\r
+                                       Just c\r
+                                               | isDigit c\r
+                                                       -> lex_number +1 (lexUngetChar c s)\r
+                                               | otherwise\r
+                                                       -> lex_ident 1 ['+'] (lexUngetChar c s)\r
+                       Just '-'\r
+                               # (mc, s) = lexGetChar s\r
+                               -> case mc of\r
+                                       Nothing -> (TokenIdent "-", s)\r
+                                       Just c\r
+                                               | isDigit c\r
+                                                       -> lex_number -1 (lexUngetChar c s)\r
+                                               | otherwise\r
+                                                       -> lex_funny_ident 1 ['-'] (lexUngetChar c s) // PK\r
+       //                                              -> lex_ident 1 ['-'] (lexUngetChar c s)\r
+                       Just c\r
+                               | isSpace c\r
+                                       -> lex s \r
+                               | isDigit c\r
+                                       -> lex_number +1 (lexUngetChar c s)\r
+                               | isAlpha c\r
+                                       -> lex_ident 1 [c] s\r
+                               | isSpecialChar c\r
+                                       -> lex_funny_ident 1 [c] s\r
+                               | otherwise\r
+                                       -> (TokenError ("Unknown character " +++ toString c), s)\r
+\r
+       lex_digits s \r
+               = lex_digits_acc 0 [] s \r
+       lex_digits_acc num acc s\r
+               # (mc, s) = lexGetChar s\r
+               = case mc of\r
+                       Nothing \r
+                               -> (num, acc, s)\r
+                       Just c\r
+                               | isDigit c\r
+                                       -> lex_digits_acc (inc num) [digitToInt c:acc] s\r
+                               | otherwise \r
+                                       -> (num, acc, lexUngetChar c s)                                                                 \r
+\r
+       digits_to_int :: [Int] -> Int\r
+       digits_to_int [] = 0\r
+       digits_to_int [digit:digits] = digit + 10 * digits_to_int digits \r
+\r
+       digits_to_real :: [Int] -> Real \r
+       digits_to_real [] = 0.0\r
+       digits_to_real [digit:digits] = toReal digit + 10.0 * digits_to_real digits\r
+\r
+       lex_number sign s\r
+               #! (num_digits, digits, s) = lex_digits s\r
+               #! (mc, s) = lexGetChar s\r
+               = case mc of             \r
+                       Nothing -> (TokenInt (sign * digits_to_int digits), s)\r
+                       Just '.'\r
+                               -> lex_real_with_fraction (toReal sign) (digits_to_real digits) s\r
+                       Just 'E'\r
+                               #! real = toReal sign * digits_to_real digits \r
+                               -> lex_real_with_exp real s\r
+                       Just 'e'\r
+                               #! real = toReal sign * digits_to_real digits \r
+                               -> lex_real_with_exp real s\r
+                       Just c  \r
+                               -> (TokenInt (sign * digits_to_int digits), lexUngetChar c s)                                                                   \r
+\r
+       lex_real_with_fraction sign real s\r
+               #! (num_digits, digits, s) = lex_digits s\r
+               #! fraction = digits_to_real digits  / 10.0^ toReal num_digits  \r
+               #! real = sign * (real + fraction)      \r
+               #! (mc, s) = lexGetChar s\r
+               = case mc of             \r
+                       Nothing -> (TokenReal real, s)\r
+                       Just 'E'\r
+                               -> lex_real_with_exp real s\r
+                       Just 'e'\r
+                               -> lex_real_with_exp real s\r
+                       Just c  \r
+                               -> (TokenReal real, lexUngetChar c s)                                                                   \r
+\r
+       lex_real_with_exp real s\r
+               # (mc, s) = lexGetChar s\r
+               = case mc of\r
+                       Nothing -> (TokenReal real, s)\r
+                       Just '+' \r
+                               #! (num_digits, digits, s) = lex_digits s\r
+                               -> (TokenReal (real * 10.0 ^ digits_to_real digits), s)  \r
+                       Just '-' \r
+                               #! (num_digits, digits, s) = lex_digits s\r
+                               -> (TokenReal (real * 10.0 ^ (-1.0 * digits_to_real digits)), s)  \r
+                       Just c \r
+                               | isDigit c\r
+                                       #! (num_digits, digits, s) = lex_digits (lexUngetChar c s)\r
+                                       -> (TokenReal (real * 10.0 ^ digits_to_real digits), s)  \r
+                               | otherwise     \r
+                                       -> (TokenError "error in real constant", s)\r
+                                               \r
+       lex_ident num_chars acc_chars s\r
+               # (mc, s) = lexGetChar s\r
+               = case mc of\r
+                       Nothing -> (mktoken num_chars acc_chars, s)\r
+                       Just '_' -> lex_ident (inc num_chars) ['_':acc_chars] s\r
+                       Just '`' -> lex_ident (inc num_chars) ['`':acc_chars] s\r
+                       Just c  \r
+                               | isAlphanum c\r
+                                       -> lex_ident (inc num_chars) [c:acc_chars] s\r
+                               | otherwise  \r
+                                       -> (mktoken num_chars acc_chars, lexUngetChar c s)                                                                      \r
+       where\r
+               mktoken num_chars acc_chars\r
+                       = case mk_str num_chars acc_chars of\r
+                               "True"  -> TokenBool True\r
+                               "False" -> TokenBool False\r
+                               str             -> TokenIdent str                       \r
+\r
+       lex_funny_ident num_chars acc_chars s\r
+               # (mc, s) = lexGetChar s\r
+               = case mc of\r
+                       Nothing         -> (TokenIdent (mk_str num_chars acc_chars), s)\r
+                       Just c\r
+                               | isSpecialChar c\r
+                                       -> lex_funny_ident (inc num_chars) [c:acc_chars] s\r
+                               | otherwise             \r
+                                       -> (TokenIdent (mk_str num_chars acc_chars), lexUngetChar c s)                                                                  \r
+\r
+       lex_string num_chars acc_chars s\r
+               # (mc, s) = lexGetChar s\r
+               = case mc of\r
+                       Nothing -> (TokenError "error in string constant", s)\r
+                       Just '"' -> (TokenString (mk_str num_chars acc_chars), s)\r
+                       Just '\\' \r
+                               #! (mc, s) = lex_special_char s\r
+                               -> case mc of\r
+                                       Nothing -> (TokenError "error in string constant", s)\r
+                                       Just c -> lex_string (inc num_chars) [c:acc_chars] s\r
+                       Just c  -> lex_string (inc num_chars) [c:acc_chars] s\r
+\r
+\r
+       lex_char num_chars acc_chars s\r
+               # (mc, s) = lexGetChar s\r
+               = case mc of\r
+                       Nothing -> (TokenError "error in char constant", s)\r
+                       Just '\'' \r
+                               | num_chars == 1\r
+                                       -> (TokenChar (hd acc_chars), s)\r
+                               | num_chars == 0\r
+                                       -> (TokenError "char constant contains no characters ", s)\r
+                               | otherwise     \r
+                                       -> (TokenError "char constant contains more than one character", s)\r
+                       Just '\\' \r
+                               #! (mc, s) = lex_special_char s\r
+                               -> case mc of\r
+                                       Nothing -> (TokenError "error in char constant", s)\r
+                                       Just c -> lex_char (inc num_chars) [c:acc_chars] s\r
+                       Just c  -> lex_char (inc num_chars) [c:acc_chars] s\r
+\r
+       lex_special_char s \r
+               #! (mc, s) = lexGetChar s\r
+               = case mc of\r
+                       Just 'n' -> (Just '\n', s)\r
+                       Just 'r' -> (Just '\r', s)\r
+                       Just 'f' -> (Just '\f', s)\r
+                       Just 'b' -> (Just '\b', s)\r
+                       Just 't' -> (Just '\t', s)\r
+                       Just '\\' -> (Just '\\', s)\r
+                       Just '\'' -> (Just '\'', s)\r
+                       Just '\"' -> (Just '\"', s)\r
+                       Just '\0' -> (Just '\0', s)\r
+                       //Just '\x' -> abort "lex: hex char not implemented\n"\r
+                       //Just '\0' -> abort "lex: oct char not implemented\n"\r
+                       _ -> (mc, s)\r
+\r
+       mk_str num_chars acc_chars\r
+               # str = createArray num_chars ' '\r
+               = fill (dec num_chars) acc_chars str\r
+       where   \r
+               fill i [] str           = str\r
+               fill i [x:xs] str       = fill (dec i) xs {str & [i] = x}\r
+       \r
+\r
+//----------------------------------------------------------------------------------           \r
+// preparse input\r
+\r
+\r
+:: ParseEnv = PETop | PETuple | PEPar | PERecord | PEList\r
+\r
+preParse :: (ParseState s) -> (Expr, ParseState s) | ParseInput s\r
+preParse s \r
+       = parse_expr PETop s\r
+where\r
+       parse_expr env s\r
+               = parse_app env [] s\r
+       \r
+       parse_app env exprs s\r
+               #! (token, s) = lexGetToken s\r
+               = parse token env exprs s\r
+       where\r
+               parse TokenComma PETuple exprs  s       = (mkexpr exprs, lexUngetToken TokenComma s)\r
+               parse TokenComma PERecord exprs s       = (mkexpr exprs, lexUngetToken TokenComma s)\r
+               parse TokenComma PEList exprs   s       = (mkexpr exprs, lexUngetToken TokenComma s)\r
+               parse TokenComma PETop exprs s          = (ExprError "end of input expected instead of ,", s)\r
+               parse TokenComma PEPar exprs s          = (ExprError ") expected instead of ,", s)\r
+               parse TokenComma env exprs s            = abort "unknown env\n"\r
+\r
+               parse TokenClosePar PETuple     exprs s = (mkexpr exprs, lexUngetToken TokenClosePar s)\r
+               parse TokenClosePar PERecord exprs s = (ExprError "} expected instead of )", s)\r
+               parse TokenClosePar PEList exprs s  = (ExprError "] expected instead of )", s)\r
+               parse TokenClosePar PETop       exprs s = (ExprError "end of input expected instead of )", s)\r
+               parse TokenClosePar PEPar       exprs s = (mkexpr exprs, lexUngetToken TokenClosePar s)\r
+               parse TokenClosePar env exprs s         = abort "unknown env\n"\r
+\r
+               parse TokenCloseCurly PETuple   exprs s = (ExprError ") expected instead of }", s)\r
+               parse TokenCloseCurly PEList    exprs s = (ExprError "] expected instead of }", s)\r
+               parse TokenCloseCurly PERecord exprs s = (mkexpr exprs, lexUngetToken TokenCloseCurly s)\r
+               parse TokenCloseCurly PETop     exprs s = (ExprError "end of input expected instead of )", s)\r
+               parse TokenCloseCurly PEPar     exprs s = (mkexpr exprs, lexUngetToken TokenCloseCurly s)\r
+               parse TokenCloseCurly env exprs s       = abort "unknown env\n"\r
+\r
+               parse TokenCloseList PETuple exprs s    = (ExprError ") expected instead of ]", s)\r
+               parse TokenCloseList PERecord exprs s = (ExprError "} expected instead of ]", s)\r
+               parse TokenCloseList PEList exprs s = (mkexpr exprs, lexUngetToken TokenCloseList s)\r
+               parse TokenCloseList PETop      exprs s = (ExprError "end of input expected instead of )", s)\r
+               parse TokenCloseList PEPar      exprs s = (mkexpr exprs, lexUngetToken TokenCloseList s)\r
+               parse TokenCloseList env exprs s        = abort "unknown env\n"\r
+\r
+               parse TokenEnd PETuple exprs s          = (ExprError ") or, expected instead of end of input", s)\r
+               parse TokenEnd PERecord exprs s         = (ExprError "} or, expected instead of end of input", s)\r
+               parse TokenEnd PEList exprs s           = (ExprError "] or, expected instead of end of input", s)\r
+               parse TokenEnd PETop exprs s            = (mkexpr exprs, lexUngetToken TokenEnd s)\r
+               parse TokenEnd PEPar exprs s            = (ExprError ") expected instead of end of input",s)\r
+               parse TokenEnd env exprs s                      = abort "unknown env\n"\r
+       \r
+               parse (TokenInt x) env exprs s          = parse_app env [ExprInt x:exprs] s\r
+               parse (TokenBool x) env exprs s         = parse_app env [ExprBool x:exprs] s\r
+               parse (TokenReal x) env exprs s         = parse_app env [ExprReal x:exprs] s\r
+               parse (TokenChar x) env exprs s         = parse_app env [ExprChar x:exprs] s\r
+               parse (TokenString x) env exprs s       = parse_app env [ExprString x:exprs] s\r
+               parse (TokenIdent x) env exprs s        = parse_app env [ExprIdent x:exprs] s\r
+               parse TokenOpenPar env exprs s  \r
+                       # (expr, s)     = parse_par_expr s\r
+                       = case expr of\r
+                               ExprError err   -> (ExprError err, s)\r
+                               _                               ->  parse_app env [expr:exprs] s\r
+               parse TokenOpenCurly env exprs s\r
+                       # (expr, s) = parse_record_or_array s\r
+                       = case expr of\r
+                               ExprError err   -> (ExprError err, s)\r
+                               _                               ->  parse_app env [expr:exprs] s\r
+               parse TokenOpenList env exprs s \r
+                       # (expr, s) = parse_list s\r
+                       = case expr of\r
+                               ExprError err   -> (ExprError err, s)\r
+                               _                               ->  parse_app env [expr:exprs] s\r
+               parse (TokenError err) env exprs s \r
+                       = (ExprError ("lex error in parse_app: "  +++ err), s)          \r
+                               \r
+               parse token env exprs s \r
+                       = abort ("parse app - unknown token " +++ toString token)\r
+               \r
+               \r
+               mkexpr []               = ExprError "expression expected"\r
+               mkexpr [expr]   = expr\r
+               mkexpr exprs    = ExprApp {e\\e <- reverse exprs}\r
+\r
+       parse_par_expr s\r
+               #! (expr, s) = parse_expr PETuple s\r
+               = case expr of\r
+                       ExprError err -> (ExprError err, s)\r
+                       _\r
+                               #! (token, s) = lexGetToken s\r
+                               -> case token of\r
+                                       TokenClosePar -> (expr, s)\r
+                                       TokenComma -> parse_tuple [expr] (lexUngetToken token s)\r
+                                       _       -> (ExprError (", or ) expected, found " +++ toString token), s)\r
+                                                                                       \r
+       parse_tuple exprs s \r
+               #! (token, s) = lexGetToken s\r
+               = case token of\r
+                       TokenComma \r
+                               #! (expr, s) = parse_expr PETuple s\r
+                               -> case expr of\r
+                                       ExprError err -> (ExprError err, s)\r
+                                       _       -> parse_tuple [expr:exprs] s\r
+                       TokenClosePar \r
+                               -> (ExprTuple {e\\e<-reverse exprs}, s)\r
+                       _       \r
+                               -> (ExprError "parse tuple: , or ) expected", s)                \r
+\r
+       parse_list s\r
+               #! (token, s) = lexGetToken s\r
+               = case token of\r
+                       TokenCloseList \r
+                               -> (ExprList [], s)\r
+                       _  \r
+                               #! (expr, s) = parse_expr PEList (lexUngetToken token s)\r
+                               -> case expr of\r
+                                       ExprError err -> (ExprError (err +++ " ; parse list"), s)\r
+                                       _ -> parse_rest [expr] s\r
+       where\r
+               parse_rest exprs s              \r
+                       #! (token, s) = lexGetToken s\r
+                       = case token of\r
+                               TokenComma \r
+                                       #! (expr, s) = parse_expr PEList s\r
+                                       -> case expr of\r
+                                               ExprError err -> (ExprError err, s)\r
+                                               _       -> parse_rest [expr:exprs] s\r
+                               TokenCloseList \r
+                                       -> (ExprList (reverse exprs), s)\r
+                               _       \r
+                                       -> (ExprError "parse list: , or ] expected", s)                 \r
+\r
+               \r
+       parse_record_or_array s \r
+               #! (token, s) = lexGetToken s\r
+               = case token of\r
+                       TokenCloseCurly \r
+                               -> (ExprArray [], s)\r
+                       TokenIdent name\r
+                               #! (token, s) = lexGetToken s\r
+                               -> case token of\r
+                                       TokenIdent "="\r
+                                               #! (expr, s) = parse_expr PERecord s\r
+                                               -> parse_record Nothing [ExprField name expr] s\r
+                                       TokenIdent "|"\r
+                                               -> parse_record (Just ("_" +++ name)) [] (lexUngetToken TokenComma s)\r
+                                       _\r
+                                               #! (expr, s) = parse_expr PERecord \r
+                                                       (lexUngetToken (TokenIdent name) (lexUngetToken token s))\r
+                                               -> parse_array [expr] s\r
+                       _       \r
+                               #! (expr, s) = parse_expr PERecord (lexUngetToken token s)\r
+                               -> parse_array [expr] s\r
+       where\r
+               parse_record rec_name fields s\r
+                       #! (token, s) = lexGetToken s\r
+                       = case token of\r
+                               TokenCloseCurly \r
+                                       -> (ExprRecord rec_name {e\\e<- reverse fields}, s)\r
+                               TokenComma\r
+                                       #! (token, s) = lexGetToken     s\r
+                                       -> case token of\r
+                                               TokenIdent field_name\r
+                                                       #! (token, s) = lexGetToken     s\r
+                                                       -> case token of\r
+                                                               TokenIdent "=" \r
+                                                                       #! (expr, s) = parse_expr PERecord s\r
+                                                                       -> parse_record rec_name [ExprField field_name expr:fields] s\r
+                               _ -> (ExprError ("parse record failed on token " +++ toString token), s)                        \r
+\r
+               parse_array exprs s\r
+                       #! (token, s) = lexGetToken s\r
+                       = case token of\r
+                               TokenCloseCurly \r
+                                       -> (ExprArray (reverse exprs), s)\r
+                               TokenComma\r
+                                       #! (expr, s) = parse_expr PERecord s\r
+                                       -> parse_array [expr:exprs] s\r
+                               _ -> (ExprError ("parse array failed on token " +++ toString token), s)                 \r
+\r
+\r
+//----------------------------------------------------------------------------------           \r
+\r
+generic gParse a :: Expr -> Maybe a\r
+\r
+gParse{|Int|} (ExprInt x)                      = Just x \r
+gParse{|Int|} _                                                = Nothing\r
+\r
+gParse{|Char|} (ExprChar x)                    = Just x \r
+gParse{|Char|} _                                       = Nothing\r
+\r
+gParse{|Bool|} (ExprBool x)                    = Just x  \r
+gParse{|Bool|} _                                       = Nothing\r
+\r
+gParse{|Real|} (ExprReal x)                    = Just x  \r
+gParse{|Real|} _                                       = Nothing\r
+\r
+gParse{|String|} (ExprString x)                = Just x\r
+gParse{|String|} _                                     = Nothing \r
+\r
+gParse{|UNIT|} ExprUnit                        = Just UNIT\r
+gParse{|UNIT|} _                                       = Nothing \r
+\r
+gParse{|PAIR|} fx fy (ExprPair ex ey)  \r
+       = case fx ex of\r
+               Just x -> case fy ey of\r
+                       Just y                                  -> Just (PAIR x y)\r
+                       Nothing                                 -> Nothing\r
+               Nothing                                         -> Nothing\r
+gParse{|PAIR|} fx fy _                         = Nothing\r
+\r
+gParse{|EITHER|} fl fr expr    \r
+       = case fl expr of\r
+               Nothing                                         -> case fr expr of\r
+                       Nothing                                 -> Nothing\r
+                       Just x                                  -> Just (RIGHT x)\r
+               Just x                                          -> Just (LEFT x)        \r
+               \r
+gParse{|CONS of d|} parse_arg expr\r
+       | d.gcd_arity == 0      \r
+               = parse_nullary expr\r
+       | isEmpty d.gcd_fields\r
+               | is_tuple d.gcd_name\r
+                       = parse_tuple expr      \r
+               | otherwise\r
+                       = case d.gcd_prio of\r
+                               GenConsNoPrio                   \r
+                                       -> parse_nonfix expr\r
+                               GenConsPrio assoc prio  \r
+                                       -> parse_infix assoc prio expr                                          \r
+       | otherwise\r
+               = parse_record expr     \r
+where\r
+       mkprod []               = abort "mkprod\n"\r
+       mkprod [expr]   = expr\r
+       mkprod exprs    \r
+               # (xs, ys) = splitAt (length exprs / 2) exprs\r
+               = ExprPair (mkprod xs) (mkprod ys) \r
+       \r
+       parse_nullary (ExprIdent name)\r
+               | name == d.gcd_name\r
+                       = mapMaybe CONS (parse_arg ExprUnit)\r
+       parse_nullary _\r
+               = Nothing\r
+\r
+       parse_nonfix (ExprApp exprs)\r
+               = parse_nonfix1 exprs\r
+       parse_nonfix (ExprAppInInfix exprs _ _ _)\r
+               = parse_nonfix1 exprs\r
+       parse_nonfix _ \r
+               = Nothing\r
+\r
+       parse_nonfix1 exprs\r
+               #! size_exprs = size exprs\r
+               | size_exprs == d.gcd_arity + 1 && is_ident d.gcd_name exprs.[0]\r
+                       #! arg_exprs = [exprs.[i] \\ i <- [1 .. size_exprs - 1]]\r
+                       = mapMaybe CONS (parse_arg (mkprod arg_exprs))\r
+               | otherwise\r
+                       = Nothing\r
+       \r
+       is_ident wanted_name (ExprIdent name) = name == wanted_name\r
+       is_ident _ _ = False            \r
+\r
+       parse_tuple (ExprTuple exprs) \r
+               = mapMaybe CONS (parse_arg (mkprod [e\\e<-:exprs]))\r
+       parse_tuple expr = Nothing\r
+       \r
+       parse_record (ExprRecord rec_name exprs) \r
+               | check_name rec_name d.gcd_name\r
+                       = mapMaybe CONS (parse_arg (mkprod [e\\e<-:exprs]))\r
+                       = Nothing\r
+       where\r
+               check_name Nothing cons_name = True\r
+               check_name (Just rec_name) cons_name = rec_name == cons_name\r
+       parse_record expr = Nothing\r
+\r
+       parse_infix this_assoc this_prio (ExprApp exprs)\r
+               = parse_infix1 this_assoc this_prio exprs\r
+       parse_infix this_assoc this_prio (ExprAppInInfix exprs outer_assoc outer_prio branch)\r
+               | this_prio > outer_prio\r
+                       = parse_infix1 this_assoc this_prio exprs\r
+               | this_prio < outer_prio\r
+                       = Nothing\r
+               | otherwise\r
+                       = case (this_assoc, outer_assoc, branch) of\r
+                               (GenConsAssocLeft, GenConsAssocLeft, GenConsAssocLeft)\r
+                                       -> parse_infix1 this_assoc this_prio exprs\r
+                               (GenConsAssocRight, GenConsAssocRight, GenConsAssocRight)\r
+                                       -> parse_infix1 this_assoc this_prio exprs\r
+                               _ -> Nothing\r
+       parse_infix this_assoc this_prio expr\r
+               = Nothing\r
+               \r
+       parse_infix1 this_assoc this_prio exprs\r
+               #! size_exprs = size exprs\r
+               | size_exprs < 3 = Nothing\r
+               = case (case this_assoc of GenConsAssocLeft -> find_last; _ -> find_first) exprs of\r
+                       Nothing -> Nothing\r
+                       Just op_index\r
+                               #! left_arg  = mkarg GenConsAssocLeft {exprs.[i] \\ i <- [0 .. op_index - 1]}\r
+                               #! right_arg = mkarg GenConsAssocRight {exprs.[i] \\ i <- [op_index + 1 .. size_exprs - 1]}\r
+                               -> mapMaybe CONS (parse_arg (ExprPair left_arg right_arg))\r
+       where\r
+               mkarg branch exprs\r
+                       = case size exprs of\r
+                               0 -> abort "mkarg\n"\r
+                               1 -> exprs.[0]\r
+                               _ -> ExprAppInInfix exprs this_assoc this_prio branch\r
+       \r
+       find_last exprs \r
+               = find (size exprs - 2) exprs\r
+       where\r
+               find i exprs\r
+                       | i < 1\r
+                               = Nothing\r
+                       | otherwise     \r
+                               = case exprs.[i] of\r
+                                       ExprIdent s | s == d.gcd_name   -> Just i  \r
+                                       _                                                               -> find (dec i) exprs   \r
+       find_first exprs\r
+               = find 1 exprs\r
+       where\r
+               find i exprs\r
+                       | i >= size exprs - 1\r
+                               = Nothing\r
+                       | otherwise     \r
+                               = case exprs.[i] of\r
+                                       ExprIdent s | s == d.gcd_name   -> Just i  \r
+                                       _                                                               -> find (inc i) exprs   \r
+\r
+       is_tuple name \r
+               #! size_name = size name\r
+               = (size_name == 7 || size_name == 8)\r
+               && name.[0] == '_'\r
+               && name.[1] == 'T'\r
+               && name.[2] == 'u'\r
+               && name.[3] == 'p'\r
+               && name.[4] == 'l'\r
+               && name.[5] == 'e'\r
+               && isDigit name.[6]\r
+               && (size_name == 7 || isDigit name.[7])\r
+\r
+gParse{|FIELD of d|} parse_arg (ExprField name value) \r
+       | d.gfd_name == name\r
+               = mapMaybe FIELD (parse_arg value)\r
+               = Nothing\r
+gParse{|OBJECT|} parse_arg expr\r
+       = mapMaybe OBJECT (parse_arg expr)\r
+\r
+gParse{|[]|} parse_arg (ExprList exprs) \r
+       = maybeAll (map parse_arg exprs)\r
+gParse{|[]|} parse_arg _ = Nothing\r
+\r
+gParse{|{}|} parse_arg (ExprArray exprs)\r
+       = mapMaybe (\xs -> {x\\x<-xs}) (maybeAll (map parse_arg exprs)) \r
+gParse{|{}|} parse_arg _ = Nothing\r
+               \r
+gParse{|{!}|} parse_arg (ExprArray exprs)\r
+       = mapMaybe (\xs -> {x\\x<-xs}) (maybeAll (map parse_arg exprs))\r
+gParse{|{!}|} parse_arg _ = Nothing\r
+\r
+maybeAll []                    = Just []\r
+maybeAll [Nothing:_]   = Nothing\r
+maybeAll [Just x: mxs] \r
+       = case maybeAll mxs of\r
+               Nothing -> Nothing\r
+               Just xs -> Just [x:xs]  \r
+\r
+//----------------------------------------------------------------------------------           \r
+\r
+preParseInput :: s -> Expr | ParseInput s\r
+preParseInput input \r
+       # (expr, s) = preParse {ps_input=input, ps_char = Nothing, ps_tokens = [] }\r
+       = expr\r
+       \r
+preParseString :: String -> Expr\r
+preParseString str = preParseInput {si_pos = 0, si_str = str}\r
+\r
+preParseFile :: File -> Expr \r
+preParseFile file = preParseInput file\r
+\r
+parseString :: String -> Maybe a | gParse{|*|} a\r
+parseString str = gParse{|*|} (preParseString str)\r
+\r
+parseFile :: File -> Maybe a | gParse{|*|} a\r
+parseFile file = gParse{|*|} (preParseFile file)\r
+\r
+//Start = preParseString "{rec_field = A (B1, B2) (C D), rec_field2 = (X,Y)}"\r
+//Start = preParseString "123.456e1"\r
+//Start = preParseString "([1,2,3], [4,5,6])"\r
+//Start = preParseString "{A B D,X Y Z,I J K}"\r
+\r
+//----------------------------------------------------------------------------------           \r
+\r
+:: Tree a b = Tip a | Bin b (Tree a b) (Tree a b)\r
+:: T\r
+       = :+: infixl 2 T T\r
+       | :-: infixl 2 T T\r
+       | :*: infixl 3 T T\r
+       | :->: infixr 4 T T\r
+       | U\r
+\r
+:: Rec = { rec_x :: T, rec_y :: (.Tree Int Real, Real) }\r
+\r
+derive gParse (,), (,,), (,,,), Tree, T, Rec\r
+derive bimap Maybe, ParseState, []\r
+\r
+//Start :: Maybe T\r
+//Start = parseString "U :+: U :+: U"\r
+\r
+//Start :: Maybe (Tree Int Int)\r
+//Start = parseString "Bin 1 (Tip 2) (Tip 3)"\r
+\r
+//Start :: Maybe (Tree Int Int, Int)\r
+//Start = parseString "((Bin 1 (Tip (2)) (Tip 3), 1000))"\r
+\r
+//Start :: Maybe Rec\r
+//Start = parseString "{ Rec | rec_x = U :+: U :+: U, rec_y = (Bin 1.1 (Tip 2) (Tip 3), 1.09) }"\r
+\r
+//Start :: Maybe [Tree Int Int]\r
+//Start = parseString "[Bin 1 (Tip (2)) (Tip 3), Tip 100, Tip 200]" \r
+\r
+//Start = preParseString "1.23e12"\r
+\r
+/*\r
+Start :: *World -> (Maybe Rec, *World)\r
+Start w \r
+       #! (ok, f, w) = sfopen "test.txt" FReadText w\r
+       | not ok\r
+               = (abort "sfopen failed", w)\r
+               = (parseFile f, w)              \r
+*/
\ No newline at end of file
diff --git a/a3/code/Generics/GenPrint.dcl b/a3/code/Generics/GenPrint.dcl
new file mode 100644 (file)
index 0000000..07e1be5
--- /dev/null
@@ -0,0 +1,27 @@
+definition module GenPrint\r
+\r
+import StdGeneric\r
+\r
+class PrintOutput s where\r
+       printOutput :: Char *s -> *s\r
+       \r
+:: *StringOutput\r
+\r
+:: PrintState s\r
+\r
+mkPrintState :: *s -> PrintState *s | PrintOutput s\r
+mkStringPrintState :: PrintState StringOutput\r
+printToString :: a -> String | gPrint{|*|} a\r
+\r
+(<<-) infixl 0 :: (PrintState *s) a -> *(PrintState *s) \r
+       | gPrint{|*|} a & PrintOutput s\r
+\r
+\r
+instance PrintOutput StringOutput \r
+instance PrintOutput File\r
+\r
+generic gPrint a :: a (PrintState *s) -> (PrintState *s) | PrintOutput s\r
+\r
+derive gPrint Int, Real, Char, Bool, String, UNIT, PAIR, EITHER, FIELD, CONS, OBJECT, [], {!}, {}\r
+//derive bimap PrintState\r
+\r
diff --git a/a3/code/Generics/GenPrint.icl b/a3/code/Generics/GenPrint.icl
new file mode 100644 (file)
index 0000000..d75f190
--- /dev/null
@@ -0,0 +1,306 @@
+implementation module GenPrint\r
+\r
+import StdGeneric, StdEnv, StdMaybe\r
+\r
+//-------------------------------------------------------------------------------------\r
+\r
+:: *StringOutput = {so_str :: !*String, so_pos :: !Int}\r
+\r
+\r
+instance PrintOutput StringOutput where\r
+       printOutput ch s=:{so_str, so_pos} \r
+               #! new_str = realloc_if_needed so_pos so_str \r
+               = {s & so_str = {new_str & [so_pos] = ch}, so_pos = inc so_pos}\r
+       where\r
+               realloc_if_needed :: Int u:String -> v:String, [u <= v]\r
+               realloc_if_needed pos str\r
+                       #! size_str = size str\r
+                       | pos == size_str\r
+                               #! new_str = createArray ((size_str + 1) * 3 /2) '\0'\r
+                               #! (new_str, str) = fill 0 size_str new_str str\r
+                               = new_str\r
+                       | otherwise     \r
+                               = str \r
+               fill i n new_str str \r
+                       | i == n\r
+                               = (new_str, str)\r
+                       | otherwise     \r
+                               #! (ch, str) = str![i] \r
+                               = fill (inc i) n {new_str & [i] = ch} str       \r
+                                       \r
+instance PrintOutput File where\r
+       printOutput x s\r
+               = fwritec x s\r
+\r
+\r
+//-------------------------------------------------------------------------------------\r
+\r
+\r
+($) infixl 9\r
+($) x y = y o x\r
+\r
+(@) infix 8 \r
+(@) x y = x y\r
+\r
+mapSt f [] st = ([], st)\r
+mapSt f [x:xs] st\r
+       # (y, st) = f x st\r
+       # (ys, st) = mapSt f xs st\r
+       = ([y:ys], st)\r
+\r
+foldSt f []            = id \r
+foldSt f [x:xs]        = foldSt f xs o f x\r
+\r
+//-------------------------------------------------------------------------------------\r
+:: PrintState s =\r
+       { ps_output :: !s\r
+       , ps_context :: !Context\r
+       }\r
+:: Context \r
+       = CtxNone                                                                               // initial env\r
+       | CtxNullary                                                                    // nullary constructor\r
+       | CtxRecord                                                                             // record constructor   \r
+       | CtxTuple                                                                              // tuple constructor\r
+       | CtxNonfix                                                                             // normal nonfix constructor\r
+       | CtxInfix                                                                              // infix constructor\r
+               String                                                                          // name\r
+               GenConsAssoc                                                            // constructor's associativity  \r
+               Prio                                                                            // constructors priority        \r
+               GenConsAssoc                                                            // left or right argument\r
+:: Prio :== Int\r
+       \r
+instance == GenConsAssoc where\r
+       (==) GenConsAssocNone GenConsAssocNone = True\r
+       (==) GenConsAssocLeft GenConsAssocLeft = True\r
+       (==) GenConsAssocRight GenConsAssocRight = True\r
+       (==) _ _ = False\r
+\r
+mkContext :: GenericConsDescriptor -> Context\r
+mkContext {gcd_prio=GenConsNoPrio, gcd_fields, gcd_name, gcd_arity}\r
+       | isEmpty gcd_fields \r
+               | gcd_arity == 0\r
+                       = CtxNullary\r
+               | is_tuple gcd_name\r
+                       = CtxTuple\r
+               | otherwise\r
+                       = CtxNonfix\r
+       | otherwise     \r
+               = CtxRecord \r
+where\r
+       is_tuple name \r
+               #! size_name = size name\r
+               = (size_name == 7 || size_name == 8)\r
+               && name.[0] == '_'\r
+               && name.[1] == 'T'\r
+               && name.[2] == 'u'\r
+               && name.[3] == 'p'\r
+               && name.[4] == 'l'\r
+               && name.[5] == 'e'\r
+               && isDigit name.[6]\r
+               && (size_name == 7 || isDigit name.[7])\r
+       \r
+mkContext {gcd_prio=GenConsPrio assoc prio, gcd_name} \r
+       = CtxInfix gcd_name assoc prio GenConsAssocNone\r
+\r
+needParenthesis :: Context Context -> Bool\r
+needParenthesis CtxNone outer_ctx              = abort "needParenthesis: this_ctx = CtxNone"\r
+needParenthesis this_ctx CtxNullary            = abort "needParenthesis: outer_ctx = CtxNullary"\r
+needParenthesis CtxNullary outer_ctx   = False\r
+needParenthesis CtxTuple outer_ctx             = True          // the tuple parenthesis\r
+needParenthesis CtxRecord outer_ctx    = False\r
+needParenthesis CtxNonfix CtxNone              = False\r
+needParenthesis CtxNonfix CtxTuple             = False\r
+needParenthesis CtxNonfix CtxRecord            = False\r
+needParenthesis CtxNonfix CtxNonfix            = True\r
+needParenthesis CtxNonfix (CtxInfix _ _ _ _) = False\r
+needParenthesis (CtxInfix _ _ _ _) CtxNone = False\r
+needParenthesis (CtxInfix _ _ _ _) CtxNullary = True\r
+needParenthesis (CtxInfix _ _ _ _) CtxTuple = False\r
+needParenthesis (CtxInfix _ _ _ _) CtxRecord = False\r
+needParenthesis (CtxInfix _ _ _ _) CtxNonfix = True // False // PK\r
+needParenthesis (CtxInfix _ this_assoc this_prio _) (CtxInfix _ outer_assoc outer_prio branch) \r
+       =       outer_prio > this_prio \r
+       ||  (outer_prio == this_prio && not (this_assoc == outer_assoc && this_assoc == branch))\r
+\r
+//derive bimap PrintState\r
+\r
+//-------------------------------------------------------------------------------------\r
+\r
+\r
+printChar :: Char (PrintState *s) -> (PrintState *s) | PrintOutput s \r
+printChar ch s=:{ps_output}\r
+       # ps_output = printOutput ch ps_output\r
+       = {s & ps_output = ps_output}\r
+\r
+printCharLiteral '\\'  = printChar '\\' $ printChar '\\'\r
+printCharLiteral '\n'  = printChar '\\' $ printChar '\n'\r
+printCharLiteral '\t'  = printChar '\\' $ printChar '\t'\r
+printCharLiteral '\b'  = printChar '\\' $ printChar '\b'\r
+printCharLiteral '\''  = printChar '\\' $ printChar '\''\r
+printCharLiteral '\"'  = printChar '\\' $ printChar '\"'\r
+printCharLiteral '\0'  = printChar '\\' $ printChar '\0'\r
+printCharLiteral c             = printChar c\r
+\r
+printString str\r
+       #! size_str = size str\r
+       = do_it 0 size_str str\r
+where\r
+       do_it i n str\r
+               | i == n\r
+                       = id\r
+                       = printChar str.[i]\r
+                       $ do_it (inc i) n str \r
+\r
+printStringLiteral str\r
+       #! size_str = size str\r
+       = do_it 0 size_str str\r
+where\r
+       do_it i n str\r
+               | i == n\r
+                       = id\r
+                       = printCharLiteral str.[i]\r
+                       $ do_it (inc i) n str \r
+\r
+\r
+printList f xs ps=:{ps_context}\r
+       =       { print_list f xs { ps & ps_context = CtxNone} \r
+               & ps_context = ps_context \r
+               }\r
+where\r
+       print_list f [] = id\r
+       print_list f [x] = f x\r
+       print_list f [x:xs] \r
+               = f x                   \r
+               $ printString ", "\r
+               $ print_list f xs       \r
+\r
+//-------------------------------------------------------------------------------------\r
+generic gPrint a :: a (PrintState *s) -> (PrintState *s) | PrintOutput s\r
+gPrint{|Int|} x st \r
+       = printString (toString x) st\r
+gPrint{|Real|} x st \r
+       # str = toString x\r
+       | all isDigit [c\\c<-:str] // add .0 if needed\r
+               = printString (str +++ ".0") st \r
+       | str.[0] == '.'\r
+               = printString ("0" +++ str) st\r
+       | otherwise     \r
+               = printString str st\r
+gPrint{|Bool|} x st \r
+       = printString (toString x) st\r
+gPrint{|Char|} x st \r
+       = printChar '\'' $ printCharLiteral x $ printChar '\'' @ st \r
+gPrint{|String|} x st \r
+       = printChar '"'\r
+       $ printStringLiteral x \r
+       $ printChar '"'\r
+       @ st\r
+gPrint{|UNIT|} x st \r
+       = st\r
+       \r
+gPrint{|EITHER|} fl fr (LEFT x) st = fl x st\r
+gPrint{|EITHER|} fl fr (RIGHT x) st = fr x st\r
+\r
+gPrint{|PAIR|} fx fy (PAIR x y) st=:{ps_context = CtxNone}\r
+       = abort "gOutput{|PAIR|}: CtxNone\n" \r
+gPrint{|PAIR|} fx fy (PAIR x y) st=:{ps_context = CtxNullary}\r
+       = abort "gOutput{|PAIR|}: CtxNullary\n" \r
+gPrint{|PAIR|} fx fy (PAIR x y) st=:{ps_context = CtxTuple}\r
+       = fx x $ printString ", " $ fy y @ st\r
+gPrint{|PAIR|} fx fy (PAIR x y) st=:{ps_context = CtxRecord}\r
+       = fx x $ printString ", " $ fy y @ st\r
+gPrint{|PAIR|} fx fy (PAIR x y) st=:{ps_context = CtxNonfix}\r
+       = fx x $ printChar ' ' $ fy y @ st      \r
+gPrint{|PAIR|} fx fy (PAIR x y) st=:{ps_context = CtxInfix name assoc prio branch} \r
+       # st = fx x {st & ps_context = CtxInfix name assoc prio GenConsAssocLeft} \r
+       # st = printChar ' ' $ printStringLiteral name $ printChar ' ' @ st\r
+       # st = fy y {st & ps_context = CtxInfix name assoc prio GenConsAssocRight} \r
+       = {st & ps_context = CtxInfix name assoc prio branch} \r
+\r
+gPrint{|CONS of d|} print_arg (CONS x) st=:{ps_context}\r
+       #! ctx = mkContext d\r
+       #! st = { st & ps_context = ctx }\r
+       | needParenthesis ctx ps_context\r
+               =       { printChar '(' \r
+                       $ print print_arg ctx \r
+                       $ printChar ')' \r
+                       @ st \r
+                       & ps_context = ps_context \r
+                       }\r
+       | otherwise\r
+               = { print print_arg ctx st & ps_context = ps_context }\r
+where\r
+       print print_arg CtxNone                         \r
+               = abort "gOutput{|CONS|}: CtxNone\n"\r
+       print print_arg CtxNullary              \r
+               = printStringLiteral d.gcd_name \r
+       print print_arg CtxTuple\r
+               = print_arg x\r
+       print print_arg CtxRecord               \r
+               = printString "{ " \r
+               $ foldSt printChar (tl [c\\c<-:d.gcd_name]) //printStringLiteral d.gcd_name \r
+               $ printString " | "\r
+               $ print_arg x\r
+               $ printString " }"\r
+       print print_arg CtxNonfix               \r
+               = printStringLiteral d.gcd_name\r
+               $ printChar ' '\r
+               $ print_arg x \r
+       print print_arg (CtxInfix _ _ _ _)              \r
+               = print_arg x\r
+\r
+gPrint{|FIELD of d|} f (FIELD x) st\r
+       = printStringLiteral d.gfd_name\r
+       $ printString " = " \r
+       $ f x \r
+       @ st\r
+gPrint{|OBJECT|} f (OBJECT x) st\r
+       = f x st        \r
+       \r
+gPrint{|[]|} f xs st\r
+       = printChar '['\r
+       $ printList f xs \r
+       $ printChar ']'\r
+       @ st\r
+\r
+gPrint{|{}|} f xs st\r
+       = printChar '{'\r
+       $ printList f [ x \\ x <-: xs] \r
+       $ printChar '}'\r
+       @ st\r
+\r
+gPrint{|{!}|} f xs st\r
+       = printChar '{'\r
+       $ printList f [ x \\ x <-: xs] \r
+       $ printChar '}'\r
+       @ st\r
+\r
+//derive gOutput (,), (,,), (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+       \r
+//-------------------------------------------------------------------------------------\r
+(<<-) infixl 0 :: (PrintState *s) a -> *(PrintState *s) | gPrint{|*|} a & PrintOutput s\r
+(<<-) s x = gPrint{|*|} x s\r
+\r
+mkPrintState :: *s -> PrintState *s | PrintOutput s\r
+mkPrintState s =\r
+       { ps_output = s\r
+       , ps_context = CtxNone\r
+       } \r
+\r
+mkStringPrintState :: PrintState StringOutput\r
+mkStringPrintState = mkPrintState {so_pos = 0, so_str = createArray 16 '\0'}\r
+\r
+openFilePrintState :: String *fs -> (Maybe (PrintState *File), *fs) | FileSystem fs\r
+openFilePrintState name fs \r
+       # (ok, file, fs) = fopen name FWriteText fs\r
+       | ok    = (Just (mkPrintState file), fs)\r
+                       = (Nothing, fs)\r
+\r
+printToString :: a -> String | gPrint{|*|} a\r
+printToString x\r
+       # string_output = (mkStringPrintState <<- x).ps_output\r
+       = string_output.so_str % (0,string_output.so_pos-1)\r
+\r
+//-------------------------------------------------------------------------------------\r
+\r
+//Start = 1
\ No newline at end of file
diff --git a/a3/code/Generics/GenReduce.dcl b/a3/code/Generics/GenReduce.dcl
new file mode 100644 (file)
index 0000000..d968d2c
--- /dev/null
@@ -0,0 +1,17 @@
+definition module GenReduce\r
+\r
+import StdGeneric\r
+\r
+generic gReduce t :: (a a -> a) a  t -> a\r
+derive gReduce c, PAIR, EITHER, CONS, FIELD, OBJECT\r
+derive gReduce [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+generic gReduceRSt t :: .t .st -> .st\r
+derive gReduceRSt c, PAIR, EITHER, CONS, FIELD, OBJECT\r
+derive gReduceRSt [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+generic gReduceLSt t :: .t .st -> .st\r
+derive gReduceLSt c, PAIR, EITHER, CONS, FIELD, OBJECT\r
+derive gReduceLSt [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
\ No newline at end of file
diff --git a/a3/code/Generics/GenReduce.icl b/a3/code/Generics/GenReduce.icl
new file mode 100644 (file)
index 0000000..c4979c3
--- /dev/null
@@ -0,0 +1,43 @@
+implementation module GenReduce\r
+\r
+import StdGeneric, _Array\r
+\r
+// or crush\r
+generic gReduce t :: (a a -> a) a  t -> a\r
+gReduce{|c|} op e x                                    = e\r
+gReduce{|PAIR|} fx fy op e (PAIR x y)  = op (fx op e x) (fy op e y)\r
+gReduce{|EITHER|} fl fr op e (LEFT x)  = fl op e x\r
+gReduce{|EITHER|} fl fr op e (RIGHT x)         = fr op e x\r
+gReduce{|CONS|} f op e (CONS x)                = f op e x \r
+gReduce{|FIELD|} f op e (FIELD x)              = f op e x\r
+gReduce{|OBJECT|} f op e (OBJECT x)    = f op e x\r
+gReduce{|{}|} f op e x                                 = reduceArray f op e x\r
+gReduce{|{!}|} f op e x                                        = reduceArray f op e x\r
+derive gReduce [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+generic gReduceRSt t :: .t .st -> .st\r
+gReduceRSt{|c|} x st                                   = st\r
+gReduceRSt{|PAIR|} fx fy (PAIR x y) st         = fx x (fy y st)\r
+gReduceRSt{|EITHER|} fl fr x st                = reduceEITHER fl fr x st\r
+gReduceRSt{|CONS|} f (CONS x) st               = f x st\r
+gReduceRSt{|FIELD|} f (FIELD x) st             = f x st\r
+gReduceRSt{|OBJECT|} f (OBJECT x) st   = f x st\r
+gReduceRSt{|{}|} f xs st                               = reduceArrayRSt f xs st        \r
+gReduceRSt{|{!}|} f xs st                              = reduceArrayRSt f xs st        \r
+derive gReduceRSt [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+generic gReduceLSt t :: .t .st -> .st\r
+gReduceLSt{|c|} x st                                           = st\r
+gReduceLSt{|PAIR|} fx fy (PAIR x y) st         = fy y (fx x st)\r
+gReduceLSt{|EITHER|} fl fr x st                = reduceEITHER fl fr x st\r
+gReduceLSt{|CONS|} f (CONS x) st               = f x st\r
+gReduceLSt{|FIELD|} f (FIELD x) st             = f x st\r
+gReduceLSt{|OBJECT|} f (OBJECT x) st   = f x st\r
+gReduceLSt{|{}|} f xs st                               = reduceArrayLSt f xs st        \r
+gReduceLSt{|{!}|} f xs st                              = reduceArrayLSt f xs st        \r
+derive gReduceLSt [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+reduceEITHER fl fr (LEFT x) st                         = fl x st\r
+reduceEITHER fl fr (RIGHT x) st                = fr x st\r
+\r
+                 
\ No newline at end of file
diff --git a/a3/code/Generics/GenZip.dcl b/a3/code/Generics/GenZip.dcl
new file mode 100644 (file)
index 0000000..9170a69
--- /dev/null
@@ -0,0 +1,11 @@
+definition module GenZip\r
+\r
+import StdMaybe, StdGeneric\r
+\r
+generic gZip a b c :: .a .b -> .c\r
+derive gZip Int, Bool, Char, Real, String, UNIT, EITHER, PAIR, CONS, FIELD, OBJECT\r
+derive gZip [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+generic gMaybeZip a b c :: .a .b -> Maybe .c\r
+derive gMaybeZip Int, Char, Bool, Real, String, UNIT, EITHER, PAIR, CONS, FIELD, OBJECT\r
+derive gMaybeZip [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
diff --git a/a3/code/Generics/GenZip.icl b/a3/code/Generics/GenZip.icl
new file mode 100644 (file)
index 0000000..9f7d862
--- /dev/null
@@ -0,0 +1,44 @@
+implementation module GenZip\r
+\r
+import StdGeneric\r
+import StdEnv\r
+import StdMaybe\r
+\r
+derive bimap Maybe\r
+       \r
+generic gZip a b c :: .a .b -> .c\r
+gZip{|Int|} x y        = if (x == y) x (abort "zip Int failed\n")\r
+gZip{|Bool|} x y       = if (x == y) x (abort "zip Bool failed\n")\r
+gZip{|Char|} x y       = if (x == y) x (abort "zip Char failed\n")\r
+gZip{|Real|} x y       = if (x == y) x (abort "zip Real failed\n")\r
+gZip{|String|} x y     = if (x == y) x (abort "zip String failed\n")\r
+gZip{|UNIT|} UNIT UNIT                                         = UNIT\r
+gZip{|PAIR|} fx fy (PAIR x1 y1) (PAIR x2 y2) = PAIR (fx x1 x2) (fy y1 y2)\r
+gZip{|EITHER|} fl fr (LEFT x) (LEFT y)         = LEFT (fl x y) \r
+gZip{|EITHER|} fl fr (RIGHT x) (RIGHT y) = RIGHT (fr x y) \r
+gZip{|EITHER|} fl fr _ _                               = abort "gZip failed: EITHER does not match\n" \r
+gZip{|CONS|} f (CONS x) (CONS y)               = CONS (f x y)\r
+gZip{|FIELD|} f (FIELD x) (FIELD y)    = FIELD (f x y)\r
+gZip{|OBJECT|} f (OBJECT x) (OBJECT y)         = OBJECT (f x y)\r
+derive gZip [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
\r
+generic gMaybeZip a b c :: .a .b -> Maybe .c\r
+gMaybeZip{|Int|} x y = if (x == y) (Just x) Nothing\r
+gMaybeZip{|Bool|} x y = if (x == y) (Just x) Nothing\r
+gMaybeZip{|Char|} x y = if (x == y) (Just x) Nothing\r
+gMaybeZip{|Real|} x y = if (x == y) (Just x) Nothing\r
+gMaybeZip{|String|} x y = if (x == y) (Just x) Nothing\r
+gMaybeZip{|UNIT|} UNIT UNIT = Just UNIT\r
+gMaybeZip{|PAIR|} fx fy (PAIR x1 y1) (PAIR x2 y2) = zipMaybe PAIR (fx x1 x2) (fy y1 y2)\r
+gMaybeZip{|EITHER|} fl fr (LEFT x) (LEFT y)    = mapMaybe LEFT (fl x y)\r
+gMaybeZip{|EITHER|} fl fr (RIGHT x) (RIGHT y)          = mapMaybe RIGHT (fr x y)\r
+gMaybeZip{|EITHER|} fl fr _ _                                  = Nothing\r
+gMaybeZip{|CONS|} f (CONS x) (CONS y)                  = mapMaybe CONS (f x y)\r
+gMaybeZip{|FIELD|} f (FIELD x) (FIELD y)               = mapMaybe FIELD (f x y)\r
+gMaybeZip{|OBJECT|} f (OBJECT x) (OBJECT y)    = mapMaybe OBJECT (f x y)\r
+derive gMaybeZip [], (,), (,,),  (,,,), (,,,,), (,,,,,), (,,,,,,), (,,,,,,,)\r
+\r
+zipMaybe :: .(.a -> .(.b -> .c)) !(Maybe .a) (Maybe .b) -> (Maybe .c)\r
+zipMaybe f (Just x) (Just y)   = Just (f x y)\r
+zipMaybe f _ _                                         = Nothing\r
+\r
diff --git a/a3/code/Generics/_Array.dcl b/a3/code/Generics/_Array.dcl
new file mode 100644 (file)
index 0000000..46d25f6
--- /dev/null
@@ -0,0 +1,31 @@
+definition module _Array\r
+\r
+import StdArray\r
+\r
+createArrayUnsafe :: .Int -> u:(a v:b) | Array a b, [u <= v]\r
+\r
+\r
+/*\r
+class UnsafeArray a e | Array a e where\r
+       unsafeCreate                            :: !Int                         -> *(a .e)\r
+       unsafeUselect                           :: !u:(a .e) !Int       -> *(.e, !u:(a .e))\r
+\r
+instance UnsafeArray {} e, {!} e\r
+\r
+mapArray :: (u:a -> v:b) w:(c u:a) -> x:(d v:b) | UnsafeArray c a & UnsafeArray d b, [w <= u,x <= v]\r
+mapArrayLSt :: (u:a -> .(.b -> (v:c,.b))) w:(d u:a) .b -> (x:(e v:c),.b) | UnsafeArray d a & UnsafeArray e c, [w <= u,x <= v]\r
+mapArrayRSt :: (u:a -> .(.b -> (v:c,.b))) w:(d u:a) .b -> (x:(e v:c),.b) | UnsafeArray d a & UnsafeArray e c, [w <= u,x <= v]\r
+*/\r
+\r
+class UnsafeArray a where\r
+       unsafeCreate                            :: !Int                         -> *(a .e)\r
+       unsafeUselect                           :: !u:(a .e) !Int       -> *(.e, !u:(a .e))\r
+\r
+instance UnsafeArray {}, {!}\r
+\r
+mapArray :: (u:a -> v:b) w:(c u:a) -> x:(d v:b) | Array d b & UnsafeArray c & UnsafeArray d & Array c a, [w <= u,x <= v]\r
+mapArrayLSt :: (u:a -> .(.b -> (v:c,.b))) w:(d u:a) .b -> (x:(e v:c),.b) | Array e c & UnsafeArray d & UnsafeArray e & Array d a, [w <= u,x <= v]\r
+mapArrayRSt :: (u:a -> .(.b -> (v:c,.b))) w:(d u:a) .b -> (x:(e v:c),.b) | Array e c & UnsafeArray d & UnsafeArray e & Array d a, [w <= u,x <= v]\r
+reduceArray :: ((.a -> u:(b -> b)) -> .(b -> .(c -> .a))) (.a -> u:(b -> b)) b .(d c) -> b | Array d c\r
+reduceArrayLSt :: (u:a -> .(.b -> .b)) v:(c u:a) .b -> .b | UnsafeArray c & Array c a, [v <= u]\r
+reduceArrayRSt :: (u:a -> .(.b -> .b)) v:(c u:a) .b -> .b | UnsafeArray c & Array c a, [v <= u]\r
diff --git a/a3/code/Generics/_Array.icl b/a3/code/Generics/_Array.icl
new file mode 100644 (file)
index 0000000..dbff74a
--- /dev/null
@@ -0,0 +1,117 @@
+implementation module _Array\r
+\r
+import _SystemArray, StdInt, StdClass\r
+\r
+\r
+createArrayUnsafe :: .Int -> u:(a v:b) | Array a b, [u <= v]\r
+createArrayUnsafe n = _createArray n\r
+\r
+\r
+instance UnsafeArray {} where \r
+       unsafeCreate size =\r
+               code\r
+               {       \r
+                       create_array_ _ 1 0\r
+               }\r
+       unsafeUselect arr index =\r
+               code\r
+               {\r
+                       push_a 0\r
+                       select _ 1 0\r
+               }\r
+\r
+instance UnsafeArray {!} where \r
+       unsafeCreate size =\r
+               code\r
+               {       \r
+                       create_array_ _ 1 0\r
+               }\r
+       unsafeUselect arr index =\r
+               code\r
+               {\r
+                       push_a 0\r
+                       select _ 1 0\r
+               }\r
+\r
+//mapArray :: (u:a -> v:b) w:(c u:a) -> x:(d v:b) | UnsafeArray c a & UnsafeArray d b, [w <= u,x <= v]\r
+mapArray :: (u:a -> v:b) w:(c u:a) -> x:(d v:b) | Array d b & UnsafeArray c & UnsafeArray d & Array c a, [w <= u,x <= v]\r
+mapArray f xs\r
+       #! (size_xs, xs) = usize xs\r
+       #! (xs, ys) = map f 0 size_xs xs (unsafeCreate size_xs)\r
+       = ys\r
+where\r
+       map f i n xs ys\r
+               | i == n        \r
+                       = (xs, ys)\r
+               | otherwise\r
+                       #! (x, xs) = unsafeUselect xs i\r
+                       #! ys = update ys i (f x) \r
+                       = map f (inc i) n xs ys \r
+\r
+//mapArrayLSt :: (u:a -> .(.b -> (v:c,.b))) w:(d u:a) .b -> (x:(e v:c),.b) | UnsafeArray d a & UnsafeArray e c, [w <= u,x <= v]\r
+mapArrayLSt :: (u:a -> .(.b -> (v:c,.b))) w:(d u:a) .b -> (x:(e v:c),.b) | Array e c & UnsafeArray d & UnsafeArray e & Array d a, [w <= u,x <= v]\r
+mapArrayLSt f xs st\r
+       #! (size_xs, xs) = usize xs\r
+       #! (xs, ys, st) = map f 0 size_xs xs (unsafeCreate size_xs) st\r
+       = (ys, st)\r
+where\r
+       map f i n xs ys st\r
+               | i == n        \r
+                       = (xs, ys, st)\r
+               | otherwise\r
+                       #! (x, xs) = unsafeUselect xs i\r
+                       #! (y, st) = f x st\r
+                       #! ys = update ys i y \r
+                       = map f (inc i) n xs ys st\r
+\r
+//mapArrayRSt :: (u:a -> .(.b -> (v:c,.b))) w:(d u:a) .b -> (x:(e v:c),.b) | UnsafeArray d a & UnsafeArray e c, [w <= u,x <= v]\r
+mapArrayRSt :: (u:a -> .(.b -> (v:c,.b))) w:(d u:a) .b -> (x:(e v:c),.b) | Array e c & UnsafeArray d & UnsafeArray e & Array d a, [w <= u,x <= v]\r
+mapArrayRSt f xs st\r
+       #! (size_xs, xs) = usize xs\r
+       #! (xs, ys, st) = map f (size_xs - 1) xs (unsafeCreate size_xs) st\r
+       = (ys, st)\r
+where\r
+       map f i xs ys st\r
+               | i < 0 \r
+                       = (xs, ys, st)\r
+               | otherwise\r
+                       #! (x, xs) = unsafeUselect xs i\r
+                       #! (y, st) = f x st\r
+                       #! ys = update ys i y \r
+                       = map f (dec i) xs ys st\r
+\r
+reduceArray :: ((.a -> u:(b -> b)) -> .(b -> .(c -> .a))) (.a -> u:(b -> b)) b .(d c) -> b | Array d c\r
+reduceArray f op e xs \r
+       = reduce f 0 (size xs) op e xs\r
+where\r
+       reduce f i n op e xs\r
+               | i == n \r
+                       = e\r
+               | otherwise\r
+                       = op (f op e xs.[i]) (reduce f (inc i) n op e xs) \r
+\r
+reduceArrayLSt :: (u:a -> .(.b -> .b)) v:(c u:a) .b -> .b | UnsafeArray c & Array c a, [v <= u]\r
+reduceArrayLSt f xs st\r
+       #! (size_xs, xs) = usize xs\r
+       #! (xs, st) = reduce f 0 size_xs xs st\r
+       = st\r
+where\r
+       reduce f i n xs st\r
+               | i == n        \r
+                       = (xs, st)\r
+               | otherwise\r
+                       #! (x, xs) = unsafeUselect xs i\r
+                       = reduce f (inc i) n xs (f x st)\r
+\r
+reduceArrayRSt :: (u:a -> .(.b -> .b)) v:(c u:a) .b -> .b | UnsafeArray c & Array c a, [v <= u]\r
+reduceArrayRSt f xs st\r
+       #! (size_xs, xs) = usize xs\r
+       #! (xs, st) = reduce f (dec size_xs) xs st\r
+       = st\r
+where\r
+       reduce f i xs st\r
+               | i < 0\r
+                       = (xs, st)\r
+               | otherwise\r
+                       #! (x, xs) = unsafeUselect xs i\r
+                       = reduce f (dec i) xs (f x st)\r
diff --git a/a3/code/Generics/gentest.icl b/a3/code/Generics/gentest.icl
new file mode 100644 (file)
index 0000000..631d648
--- /dev/null
@@ -0,0 +1,242 @@
+module gentest\r
+\r
+import StdEnv, GenLib\r
+\r
+:: Tree a b = Tip a | Bin b (Tree a b) (Tree a b)\r
+:: Rose a = Rose a .[Rose a]\r
+:: Fork a = Fork a a\r
+:: Sequ a = SequEmpty | SequZero .(Sequ .(Fork a)) | SequOne a .(Sequ .(Fork a))\r
+:: InfCons \r
+       = :+: infixl 2 InfCons InfCons\r
+       | :-: infixl 2 InfCons InfCons\r
+       | :*: infixl 3 InfCons InfCons\r
+       | :->: infixr 4 InfCons InfCons\r
+       | U\r
+       | I Int \r
+:: Rec a b c = { rec_fst :: a, rec_snd :: b, rec_thd :: c }    \r
+:: Color = Red | Green | Blue\r
+\r
+derive bimap Tree, Rose, Fork, Sequ\r
+\r
+derive gEq                             Tree, Rose, Fork, Sequ, Color, InfCons, Rec, Maybe\r
+derive gLexOrd                         Tree, Rose, Fork, Sequ\r
+derive gMap                    Tree, Rose, Fork, Sequ\r
+derive gMapLSt                         Tree, Rose, Fork, Sequ\r
+derive gMapRSt                         Tree, Rose, Fork, Sequ\r
+derive gMapLM                  Tree, Rose, Fork, Sequ\r
+derive gMapRM                  Tree, Rose, Fork, Sequ\r
+derive gReduceLSt              Tree, Rose, Fork, Sequ\r
+derive gReduceRSt              Tree, Rose, Fork, Sequ\r
+derive gReduce                         Tree, Rose, Fork, Sequ\r
+derive gZip                            Tree, Rose, Fork, Sequ\r
+derive gMaybeZip               Tree, Rose, Fork, Sequ\r
+derive gPrint                  Tree, Rose, Fork, Sequ, Color, InfCons, Rec\r
+derive gParse                  Tree, Rose, Fork, Sequ, Color, InfCons, Rec\r
+derive gCompress               Tree, Rose, Fork, Sequ, Color\r
+derive gCompressedSize Tree, Rose, Fork, Sequ, Color\r
+derive gUncompress             Tree, Rose, Fork, Sequ, Color\r
+derive gLookupFMap             Tree, Rose, Fork, Sequ, Color\r
+derive gInsertFMap             Tree, Rose, Fork, Sequ, Color\r
+\r
+tree = Bin 1 (Bin 2 (Tip 1.1) (Tip 2.2)) (Bin 3 (Tip 3.3) (Tip 4.4)) \r
+rose = Rose 1 [Rose 2 [], Rose 3 [Rose 5 [], Rose 6 []], Rose 4[]]\r
+sequ = SequZero (SequOne (Fork 1 2) (SequOne (Fork (Fork 3 4) (Fork 5 6)) SequEmpty))\r
+\r
+testEq :: [Bool]\r
+testEq =       \r
+       [ [1,2,3] === [1,2,3]\r
+       , [1,2,3] =!= [1,2,3,4]\r
+       , [1,2,3] =!= [1,2,4] \r
+       , tree === tree\r
+       , rose === rose\r
+       , sequ === sequ\r
+       ]\r
+\r
+testLexOrd = \r
+       [ ([1,2,3] =?= [1,2,3]) === EQ \r
+       , ([1,2,3] =?= [1,2,3,4]) === LT\r
+       , ([1,2,4] =?= [1,2,3,4]) === GT\r
+       , (Rose 1 [Rose 2 [], Rose 3 []] =?= Rose 1 [Rose 2 [], Rose 3 []]) === EQ \r
+       , (Rose 1 [Rose 2 [], Rose 3 []] =?= Rose 1 [Rose 2 [], Rose 3 [], Rose 4 []]) === LT\r
+       , (Rose 1 [Rose 2 [], Rose 4 []] =?= Rose 1 [Rose 2 [], Rose 3 [], Rose 4 []]) === GT\r
+       ]\r
+       \r
+testMap =\r
+       [ gMap{|*->*|} inc [1,2,3] === [2,3,4]\r
+       , gMap{|*->*->*|} inc dec (Bin 1 (Tip 2.0) (Tip 3.0)) === Bin 0 (Tip 3.0) (Tip 4.0)\r
+       , gMap{|*->*|} inc (Rose 1 [Rose 2 [], Rose 3 []]) === Rose 2 [Rose 3 [], Rose 4 []] \r
+       , gMap{|*->*|} inc (SequZero (SequOne (Fork 1 2) (SequOne (Fork (Fork 3 4) (Fork 5 6)) SequEmpty)))\r
+               === SequZero (SequOne (Fork 2 3) (SequOne (Fork (Fork 4 5) (Fork 6 7)) SequEmpty))\r
+       ]\r
+\r
+testMapRSt =\r
+       [ gMapRSt{|*->*|} (\x st-> (dec x, [x:st])) [1,2,3] [] === ([0,1,2], [1,2,3]) \r
+       ]               \r
+\r
+testMapLSt =\r
+       [ gMapLSt{|*->*|} (\x st-> (dec x, [x:st])) [1,2,3] [] === ([0,1,2], [3,2,1]) \r
+       ]               \r
+\r
+testReduceRSt =\r
+       [ gReduceRSt{|*->*|} (\x st -> [x:st]) [1,2,3] [] === [1,2,3]\r
+       ]\r
+\r
+testReduceLSt =\r
+       [ gReduceLSt{|*->*|} (\x st -> [x:st]) [1,2,3] [] === [3,2,1]\r
+       ]\r
+\r
+testMapRM =\r
+       [ gMapRM{|*->*|} (Just o inc) [1,2,3] === (Just [2,3,4])\r
+       , (gMapRM{|*->*|} (\x -> {st_monad=(\xs -> (inc x, [x:xs]))}) [1,2,3]).st_monad [] === ([2,3,4], [1,2,3])  \r
+       ]\r
+\r
+testMapLM =\r
+       [ gMapLM{|*->*|} (Just o inc) [1,2,3] === (Just [2,3,4])\r
+       , (gMapLM{|*->*|} (\x -> {st_monad=(\xs -> (inc x, [x:xs]))}) [1,2,3]).st_monad [] === ([2,3,4], [3,2,1])  \r
+       ]               \r
+\r
+testParsePrint =\r
+       [ test 1 \r
+       , test 123\r
+       , test -123\r
+\r
+       , test 1.09\r
+       , test 0.123\r
+       , test -123.456\r
+       , test 1.23E-12\r
+       , test 1.23E+12\r
+       , test 1.23E5\r
+\r
+       , test True\r
+       , test False\r
+\r
+       , test 'a'\r
+       , test '\n'\r
+       , test '"'\r
+       , test '\''\r
+       , test "Hello"\r
+       , test "Hello\n"\r
+       , test "Hello \"string\""\r
+\r
+       , test nil\r
+       , test [1]\r
+       , test [1,2,3]\r
+\r
+       , test (arr nil)\r
+       , test (arr [1])\r
+       , test (arr [1,2,3])\r
+\r
+       , test Red\r
+       , test Green\r
+       , test Blue\r
+\r
+       , test {rec_fst=1, rec_snd='a', rec_thd=1.2}\r
+\r
+       , test (Bin 'a' (Tip 1) (Bin 'b' (Tip 2) (Bin 'c' (Tip 3) (Tip 4))))\r
+       , test (Rose 1 [Rose 2 [], Rose 3 [], Rose 4 [Rose 5 []]])\r
+\r
+       , test (U :+: U)\r
+       , test (U :+: U :+: U)\r
+       , test (U :->: U :->: U)\r
+       , test (U :+: U :*: U)\r
+       , test (U :*: U :->: U)\r
+       , test (I 1 :+: I 2 :+: I 3)\r
+       , test (I 1 :*: I 2 :+: I 3)\r
+       , test (I 1 :+: I 2 :*: I 3)\r
+       , test (I 1 :+: I 2 :*: I 3 :+: I 4)\r
+       , test (I 1 :+: (I 2 :+: I 3) :+: I 4)\r
+\r
+       , test [I 1 :+: I 2 :+: I 3, I 4 :->: I 5 :->: I 6]\r
+       , test (arr [I 1 :+: I 2 :+: I 3, I 4 :->: I 5 :->: I 6])\r
+       , test \r
+               {       rec_fst = I 1 :+: I 2 :+: I 3\r
+               ,       rec_snd = I 4 :->: I 5 :->: I 6\r
+               ,       rec_thd = I 7 :*: I 8 :+: I 9\r
+               }\r
+       ]\r
+where\r
+       test x = case parseString (printToString x) of\r
+               Nothing -> False\r
+               Just y -> x === y\r
+\r
+       nil :: [Int]\r
+       nil = []\r
+\r
+       arr :: [a] -> {a}\r
+       arr xs = {x\\x<-xs}\r
+\r
+\r
+testCompress =\r
+       [ test True\r
+       , test False\r
+       , test 12345\r
+       , test -2\r
+       , test 1.2345E20\r
+       , test [1 .. 100]\r
+       , test (flatten (repeatn 100 [Red, Green, Blue]))\r
+       //, test (flatten (repeatn 100000 [Red, Green, Blue]))\r
+       , test "hello"\r
+       , test 'a'\r
+       , test Green\r
+       , test Red\r
+       , test Blue     \r
+       , test rose\r
+       , test (Bin Red (Tip Green) (Bin Blue (Tip Red) (Tip Green))) \r
+       , test sequ\r
+       ]\r
+where  \r
+       test x = case uncompress (compress x) of\r
+               Nothing -> False\r
+               Just y -> x === y\r
+\r
+\r
+testFMap =\r
+       [ lookupFMap 1 fmap_int === Just 10\r
+       , lookupFMap 3 fmap_int === Just 30\r
+       , lookupFMap "two" fmap_str === Just 2\r
+       , lookupFMap "three" fmap_str === Just 3\r
+       , lookupFMap (Rose 1 [Rose 2 [], Rose 30 []]) fmap_rose === Just 3\r
+       , lookupFMap (Rose 1 [Rose 20 [], Rose 1 []]) fmap_rose === Just 100\r
+       ]\r
+where  \r
+       fmap_int = emptyFMap \r
+               <<= (1, 10) \r
+               <<= (2, 20) \r
+               <<= (3,30) \r
+               <<= (4,40) \r
+               <<= (5, 50)\r
+       fmap_str = emptyFMap \r
+               <<= ("one", 1) \r
+               <<= ("two", 2) \r
+               <<= ("three", 3) \r
+               <<= ("four",4) \r
+               <<= ("five", 5)\r
+       fmap_rose = emptyFMap \r
+               <<= (Rose 1 [Rose 2 [], Rose 10 []], 1)\r
+               <<= (Rose 1 [Rose 2 [], Rose 20 []], 2)\r
+               <<= (Rose 1 [Rose 2 [], Rose 30 []], 3)\r
+               <<= (Rose 1 [Rose 2 [], Rose 40 []], 4)\r
+               <<= (Rose 1 [Rose 2 [], Rose 50 []], 5)\r
+               <<= (Rose 1 [Rose 20 [], Rose 1 []], 100)\r
+\r
+Start :: [[Bool]]      \r
+Start\r
+       # result = foldr (&&) True (flatten tests)\r
+       | result\r
+               = [[result]]\r
+               = tests\r
+where\r
+       tests =\r
+               [ testEq\r
+               , testLexOrd\r
+               , testMap\r
+               , testMapRSt\r
+               , testMapLSt\r
+               , testMapRM\r
+               , testMapLM\r
+               , testReduceRSt\r
+               , testReduceLSt\r
+               , testParsePrint\r
+               , testCompress\r
+               , testFMap\r
+               ]\r