+includes = "#include <stdint.h>\n#include <stdbool.h>\n"
+
+genFiles :: String (Box GType a) *World -> *World | gType{|*|} a
+genFiles bn t w
+ # tds = map (map gTypeToType) $ map (filter (not o isBasic)) $ flattenGType $ unBox t
+ # (ok, h, w) = fopen (bn <.> "h") FWriteText w
+ | not ok = abort ("Couldn't open: " +++ bn <.> "h")
+ # (ok, c, w) = fopen (bn <.> "c") FWriteText w
+ | not ok = abort ("Couldn't open: " +++ bn <.> "c")
+ # h = h <<< "#ifndef " <<< toUpperCase bn <<< "_H\n"
+ <<< "#define " <<< toUpperCase bn <<< "_H\n"
+ <<< includes
+ # c = c <<< includes
+ <<< "#include \"" <<< (bn <.> "h") <<< "\"\n"
+ # h = case typedefs tds of
+ Left e = abort ("Couldn't generate typedef: " +++ e)
+ Right d = foldl (<<<) h d
+ # (h, c) = case parsers tds of
+ Left e = abort ("Couldn't generate parser: " +++ e)
+ Right (hd, cd) = (foldl (<<<) h hd, foldl (<<<) c cd)
+ # h = h <<< "\n#endif"
+ # (ok, w) = fclose h w
+ | not ok = abort ("Couldn't close: " +++ bn <.> "h")
+ # (ok, w) = fclose c w
+ | not ok = abort ("Couldn't close: " +++ bn <.> "c")
+ = w
+
+genFilesFlat :: String (Box GType a) *World -> *World | gType{|*|} a
+genFilesFlat bn t w
+ # ty = gTypeToType (unBox t)
+ # (ok, h, w) = fopen (bn <.> "h") FWriteText w
+ | not ok = abort ("Couldn't open: " +++ bn <.> "h")
+ # (ok, c, w) = fopen (bn <.> "c") FWriteText w
+ | not ok = abort ("Couldn't open: " +++ bn <.> "c")
+ # h = h <<< "#ifndef " <<< toUpperCase bn <<< "_H\n"
+ <<< "#define " <<< toUpperCase bn <<< "_H\n"
+ <<< includes
+ # c = c <<< includes
+ <<< "#include \"" <<< (bn <.> "h") <<< "\"\n"
+ # h = case flatTypedef ty of
+ Left e = abort ("Couldn't generate typedef: " +++ e)
+ Right d = foldl (<<<) h d
+ # (h, c) = case flatParser ty of
+ Left e = abort ("Couldn't generate parser: " +++ e)
+ Right (hd, cd) = (foldl (<<<) h hd, foldl (<<<) c cd)
+ # h = h <<< "\n#endif"
+ # (ok, w) = fclose h w
+ | not ok = abort ("Couldn't close: " +++ bn <.> "h")
+ # (ok, w) = fclose c w
+ | not ok = abort ("Couldn't close: " +++ bn <.> "c")
+ = w
+
+Start w = foldr ($) w
+ [ genFiles "maybeInt" maybeInt
+ , genFiles "eitherIntChar" eitherIntChar
+ , genFiles "eitherIntMaybeChar" eitherIntMaybeChar
+ ]
+// ( flatTypedef $ gTypeToType $ unBox t
+// , typedefs $ map (map gTypeToType) $ map (filter (not o isBasic)) $ flattenGType $ unBox t
+// , flatParser $ gTypeToType $ unBox t
+// , parsers $ map (map gTypeToType) $ map (filter (not o isBasic)) $ flattenGType $ unBox t
+where
+ maybeInt :: Box GType (?Int)
+ maybeInt = gType{|*|}
+
+ eitherIntChar :: Box GType (Either Int Char)
+ eitherIntChar = gType{|*|}
+
+ eitherIntMaybeChar :: Box GType (Either Int (?Char))
+ eitherIntMaybeChar = gType{|*|}