Skip to content

Commit b987e4e

Browse files
committed
Start describing Haskell source abstractly and pretty print it later.
This disentangles the pure calculation of the Haskell source from doing IO, just as it should be. Not finished yet, just a start...
1 parent 3017c93 commit b987e4e

File tree

2 files changed

+84
-76
lines changed

2 files changed

+84
-76
lines changed

RegistryProcessor/RegistryProcessor.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ executable RegistryProcessor
2121
containers >= 0.3 && < 0.6,
2222
hxt >= 9.3 && < 9.4,
2323
directory >= 1.0 && < 1.3,
24-
filepath >= 1.0 && < 1.5
24+
filepath >= 1.0 && < 1.5,
25+
pretty >= 1.1 && < 1.2
2526
hs-source-dirs: src
2627
default-language: Haskell2010
2728
ghc-options: -Wall

RegistryProcessor/src/Main.hs

Lines changed: 82 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import qualified Data.List as L
66
import qualified Data.Map.Strict as M
77
import qualified Data.Maybe as DM
88
import qualified Data.Set as S
9+
import qualified Text.PrettyPrint.HughesPJClass as P
910
import qualified System.Directory as D
1011
import qualified System.Environment as E
1112
import qualified System.FilePath as F
@@ -78,9 +79,8 @@ printTokens api registry = do
7879
["All enumeration tokens from the",
7980
"<http://www.opengl.org/registry/ OpenGL registry>."]
8081
startModule ["Tokens"] (Just "{-# LANGUAGE CPP, PatternSynonyms, ScopedTypeVariables #-}\n#if __GLASGOW_HASKELL__ >= 800\n{-# OPTIONS_GHC -Wno-missing-pattern-synonym-signatures #-}\n#endif") comment $ \moduleName h -> do
81-
SI.hPutStrLn h $ "module " ++ moduleName ++ " where"
82-
SI.hPutStrLn h ""
83-
SI.hPutStrLn h $ "import " ++ moduleNameFor ["Types"]
82+
hRender h $ Module moduleName P.empty
83+
hRender h $ Import (moduleNameFor ["Types"]) P.empty
8484
SI.hPutStrLn h ""
8585
mapM_ (SI.hPutStrLn h . unlines . convertEnum)
8686
[ e
@@ -94,10 +94,7 @@ printGroups api registry = do
9494
["All enumeration groups from the",
9595
"<http://www.opengl.org/registry/ OpenGL registry>."]
9696
startModule ["Groups"] Nothing comment $ \moduleName h -> do
97-
SI.hPutStrLn h $ "module " ++ moduleName ++ " ("
98-
SI.hPutStrLn h $ " -- $EnumerantGroups"
99-
SI.hPutStrLn h $ ") where"
100-
SI.hPutStrLn h ""
97+
hRender h $ Module moduleName (P.text "(\n -- $EnumerantGroups\n)")
10198
SI.hPutStrLn h $ "-- $EnumerantGroups"
10299
SI.hPutStrLn h $ "-- Note that the actual set of valid values depend on the OpenGL version, the"
103100
SI.hPutStrLn h $ "-- chosen profile and the supported extensions. Therefore, the groups mentioned"
@@ -123,7 +120,7 @@ printGroups api registry = do
123120
| otherwise = "aliases")
124121

125122
linkToToken :: Enum' -> String
126-
linkToToken e = "'" ++ moduleNameFor ["Tokens"] ++ "." ++ (unEnumName . enumName) e ++ "'"
123+
linkToToken e = "'" ++ (case moduleNameFor ["Tokens"] of ModuleName mn -> mn) ++ "." ++ (unEnumName . enumName) e ++ "'"
127124

128125
-- There are several enums which are mentioned in groups, but commented out in
129126
-- enums (12 GL_*_ICC_SGIX enumerants). These are implicitly filtered out below.
@@ -156,15 +153,14 @@ printForeign :: M.Map String String -> IO ()
156153
printForeign sigMap = do
157154
let comment = ["All foreign imports."]
158155
startModule ["Foreign"] (Just "{-# LANGUAGE CPP #-}\n{-# OPTIONS_HADDOCK hide #-}") comment $ \moduleName h -> do
159-
SI.hPutStrLn h $ "module " ++ moduleName ++ " where"
160-
SI.hPutStrLn h ""
161-
SI.hPutStrLn h "import Foreign.C.Types"
162-
SI.hPutStrLn h "import Foreign.Marshal.Error ( throwIf )"
163-
SI.hPutStrLn h "import Foreign.Ptr"
164-
SI.hPutStrLn h $ "import " ++ moduleNameFor ["GetProcAddress"] ++ " ( getProcAddress )"
165-
SI.hPutStrLn h $ "import " ++ moduleNameFor ["Types"]
166-
SI.hPutStrLn h "import Numeric.Fixed"
167-
SI.hPutStrLn h "import Numeric.Half"
156+
hRender h $ Module moduleName P.empty
157+
hRender h $ Import (ModuleName "Foreign.C.Types") P.empty
158+
hRender h $ Import (ModuleName "Foreign.Marshal.Error") (P.text "( throwIf )")
159+
hRender h $ Import (ModuleName "Foreign.Ptr") P.empty
160+
hRender h $ Import (moduleNameFor ["GetProcAddress"]) (P.text "( getProcAddress )")
161+
hRender h $ Import (moduleNameFor ["Types"]) P.empty
162+
hRender h $ Import (ModuleName "Numeric.Fixed") P.empty
163+
hRender h $ Import (ModuleName "Numeric.Half") P.empty
168164
SI.hPutStrLn h ""
169165
SI.hPutStrLn h "getCommand :: String -> IO (FunPtr a)"
170166
SI.hPutStrLn h "getCommand cmd ="
@@ -189,11 +185,9 @@ printFunctions api registry sigMap = do
189185
mnames = [ [ "Functions", "F" ++ justifyRight 2 '0' (show i) ] |
190186
i <- [ 1 .. length cmds ] ]
191187
startModule ["Functions"] Nothing comment $ \moduleName h -> do
192-
SI.hPutStrLn h $ "module " ++ moduleName ++ " ("
193-
SI.hPutStrLn h . separate (("module " ++) . moduleNameFor) $ mnames
194-
SI.hPutStrLn h ") where"
195-
SI.hPutStrLn h ""
196-
mapM_ (SI.hPutStrLn h . ("import " ++) . moduleNameFor) mnames
188+
hRender h $ Module moduleName (P.text ("(\n" ++ separate (\x -> "module " ++ (case moduleNameFor x of ModuleName mn -> mn)) mnames ++ "\n)"))
189+
CM.forM_ mnames $ \mname ->
190+
hRender h $ Import (moduleNameFor mname) P.empty
197191
CM.zipWithM_ (printSubFunctions api registry sigMap) mnames cmds
198192

199193
printSubFunctions :: API -> Registry -> M.Map String String ->
@@ -203,15 +197,12 @@ printSubFunctions api registry sigMap mname cmds = do
203197
["Raw functions from the",
204198
"<http://www.opengl.org/registry/ OpenGL registry>."]
205199
startModule mname (Just "{-# OPTIONS_HADDOCK hide #-}") comment $ \moduleName h -> do
206-
SI.hPutStrLn h $ "module " ++ moduleName ++ " ("
207-
SI.hPutStrLn h . separate unCommandName . map fst $ cmds
208-
SI.hPutStrLn h ") where"
209-
SI.hPutStrLn h ""
210-
SI.hPutStrLn h "import Control.Monad.IO.Class ( MonadIO(..) )"
211-
SI.hPutStrLn h "import Foreign.Ptr"
212-
SI.hPutStrLn h $ "import " ++ moduleNameFor ["Foreign"]
213-
SI.hPutStrLn h $ "import " ++ moduleNameFor ["Types"]
214-
SI.hPutStrLn h "import System.IO.Unsafe ( unsafePerformIO )"
200+
hRender h $ Module moduleName (P.text ("(\n" ++ separate unCommandName (map fst cmds) ++ "\n)"))
201+
hRender h $ Import (ModuleName "Control.Monad.IO.Class") (P.text "( MonadIO(..) )")
202+
hRender h $ Import (ModuleName "Foreign.Ptr") P.empty
203+
hRender h $ Import (moduleNameFor ["Foreign"]) P.empty
204+
hRender h $ Import (moduleNameFor ["Types"]) P.empty
205+
hRender h $ Import (ModuleName "System.IO.Unsafe") (P.text "( unsafePerformIO )")
215206
SI.hPutStrLn h ""
216207
mapM_ (SI.hPutStrLn h . showCommand api registry sigMap . snd) cmds
217208

@@ -341,22 +332,18 @@ printReExports extModules = do
341332
CM.forM_ reExports $ \((category, mangledCategory), mangledExtNames) -> do
342333
let comment = ["A convenience module, combining all raw modules containing " ++ category ++ " extensions."]
343334
startModule [mangledCategory] Nothing comment $ \moduleName h -> do
344-
SI.hPutStrLn h $ "module "++ moduleName ++ " ("
345-
SI.hPutStrLn h $ separate (\mangledExtName -> "module " ++ extensionNameFor mangledExtName) mangledExtNames
346-
SI.hPutStrLn h ") where"
347-
SI.hPutStrLn h ""
335+
hRender h $ Module moduleName (P.text ("(\n" ++ separate (\mangledExtName -> "module " ++ (case extensionNameFor mangledExtName of ModuleName mn -> mn)) mangledExtNames ++ "\n)"))
348336
CM.forM_ mangledExtNames $ \mangledExtName ->
349-
SI.hPutStrLn h $ "import " ++ extensionNameFor mangledExtName
337+
hRender h $ Import (extensionNameFor mangledExtName) P.empty
350338

351339
printExtensionSupport :: [ExtensionModule] -> IO ()
352340
printExtensionSupport extModules = do
353341
let comment = ["Extension support predicates."]
354342
startModule ["ExtensionPredicates"] (Just "{-# OPTIONS_HADDOCK hide #-}") comment $ \moduleName h -> do
355-
SI.hPutStrLn h $ "module "++ moduleName ++ " where"
356-
SI.hPutStrLn h $ ""
357-
SI.hPutStrLn h $ "import Control.Monad.IO.Class ( MonadIO(..) )"
358-
SI.hPutStrLn h $ "import Data.Set ( member )"
359-
SI.hPutStrLn h $ "import " ++ moduleNameFor ["GetProcAddress"] ++ " ( getExtensions, extensions )"
343+
hRender h $ Module moduleName P.empty
344+
hRender h $ Import (ModuleName "Control.Monad.IO.Class") (P.text "( MonadIO(..) )")
345+
hRender h $ Import (ModuleName "Data.Set") (P.text "( member )")
346+
hRender h $ Import (moduleNameFor ["GetProcAddress"]) (P.text "( getExtensions, extensions )")
360347
let names = sortUnique [ extName | (extName, _, _) <- extModules]
361348
CM.forM_ names $ \extName -> do
362349
let predNameMonad = extensionPredicateNameMonad extName
@@ -376,7 +363,7 @@ printExtensionSupport extModules = do
376363
SI.hPutStrLn h $ predName ++ " = member " ++ show extString ++ " extensions"
377364
SI.hPutStrLn h $ "{-# NOINLINE " ++ predName ++ " #-}"
378365

379-
extensionNameFor :: ExtensionName -> String
366+
extensionNameFor :: ExtensionName -> ModuleName
380367
extensionNameFor mangledExtName = moduleNameFor [extensionNameCategory mangledExtName, extensionNameName mangledExtName]
381368

382369
supports :: API -> Maybe [API] -> Bool
@@ -394,33 +381,32 @@ printExtension :: [String] -> Maybe ExtensionName -> ExtensionParts -> IO ()
394381
printExtension moduleNameSuffix mbExtName (ts, es, cs) = do
395382
let pragma = if null es then Nothing else Just "{-# LANGUAGE PatternSynonyms #-}"
396383
startModule moduleNameSuffix pragma [] $ \moduleName h -> do
397-
SI.hPutStrLn h $ "module "++ moduleName ++ " ("
398-
flip (maybe (return ())) mbExtName $ \extName -> do
399-
SI.hPutStrLn h " -- * Extension Support"
400-
SI.hPutStrLn h $ separate id [ extensionPredicateNameMonad extName
401-
, extensionPredicateName extName ] ++ ","
402-
CM.unless (null ts) $ do
403-
SI.hPutStrLn h " -- * Types"
404-
SI.hPutStr h $ separate unTypeName ts
405-
SI.hPutStrLn h $ if null es && null cs then "" else ","
406-
CM.unless (null es) $ do
407-
SI.hPutStrLn h " -- * Enums"
408-
SI.hPutStr h $ separate (("pattern " ++) . unEnumName . enumName) es
409-
SI.hPutStrLn h $ if null cs then "" else ","
410-
CM.unless (null cs) $ do
411-
SI.hPutStrLn h " -- * Functions"
412-
SI.hPutStr h $ separate (unCommandName . commandName) cs
413-
SI.hPutStrLn h ""
414-
SI.hPutStrLn h ") where"
415-
SI.hPutStrLn h ""
384+
let extStr = flip (maybe "") mbExtName $ \extName ->
385+
" -- * Extension Support\n" ++
386+
separate id [ extensionPredicateNameMonad extName
387+
, extensionPredicateName extName ] ++ ",\n"
388+
typeStr | null ts = ""
389+
| otherwise = " -- * Types\n" ++
390+
separate unTypeName ts ++
391+
if null es && null cs then "\n" else ",\n"
392+
enumStr | null es = ""
393+
| otherwise = " -- * Enums\n" ++
394+
separate (("pattern " ++) . unEnumName . enumName) es ++
395+
if null cs then "\n" else ",\n"
396+
funcStr | null cs = ""
397+
| otherwise = " -- * Functions\n" ++
398+
separate (unCommandName . commandName) cs ++
399+
"\n"
400+
401+
hRender h $ Module moduleName (P.text ("(\n" ++ extStr ++ typeStr ++ enumStr ++ funcStr ++ ")"))
416402
CM.when (DM.isJust mbExtName) $
417-
SI.hPutStrLn h $ "import " ++ moduleNameFor ["ExtensionPredicates"]
403+
hRender h $ Import (moduleNameFor ["ExtensionPredicates"]) P.empty
418404
CM.unless (null ts) $
419-
SI.hPutStrLn h $ "import " ++ moduleNameFor ["Types"]
405+
hRender h $ Import (moduleNameFor ["Types"]) P.empty
420406
CM.unless (null es) $
421-
SI.hPutStrLn h $ "import " ++ moduleNameFor ["Tokens"]
407+
hRender h $ Import (moduleNameFor ["Tokens"]) P.empty
422408
CM.unless (null cs) $
423-
SI.hPutStrLn h $ "import " ++ moduleNameFor ["Functions"]
409+
hRender h $ Import (moduleNameFor ["Functions"]) P.empty
424410

425411
extensionPredicateName :: ExtensionName -> String
426412
extensionPredicateName extName =
@@ -450,12 +436,9 @@ printTopLevel api extModules = do
450436
, "plus" ]
451437
, "all extensions." ]
452438
startModule [] Nothing comment $ \moduleName h -> do
453-
SI.hPutStrLn h $ "module "++ moduleName ++ " ("
454-
SI.hPutStrLn h $ separate (\m -> "module " ++ m) moduleNames
455-
SI.hPutStrLn h ") where"
456-
SI.hPutStrLn h ""
439+
hRender h $ Module moduleName (P.text ("(\n" ++ separate (\(ModuleName m) -> "module " ++ m) moduleNames ++ "\n)"))
457440
CM.forM_ moduleNames $ \theModuleName ->
458-
SI.hPutStrLn h $ "import " ++ theModuleName
441+
hRender h $ Import theModuleName P.empty
459442

460443
apiName :: API -> String
461444
apiName api = case unAPI api of
@@ -467,7 +450,7 @@ apiName api = case unAPI api of
467450
sortUnique :: Ord a => [a] -> [a]
468451
sortUnique = S.toList . S.fromList
469452

470-
startModule :: [String] -> Maybe String -> [String] -> (String -> SI.Handle -> IO ()) -> IO ()
453+
startModule :: [String] -> Maybe String -> [String] -> (ModuleName -> SI.Handle -> IO ()) -> IO ()
471454
startModule moduleNameSuffix mbPragma comments action = do
472455
let path = modulePathFor moduleNameSuffix
473456
moduleName = moduleNameFor moduleNameSuffix
@@ -476,17 +459,17 @@ startModule moduleNameSuffix mbPragma comments action = do
476459
printModuleHeader h mbPragma moduleName comments
477460
action moduleName h
478461

479-
moduleNameFor :: [String] -> String
480-
moduleNameFor = L.intercalate "." . moduleNameParts
462+
moduleNameFor :: [String] -> ModuleName
463+
moduleNameFor = ModuleName . L.intercalate "." . moduleNameParts
481464

482465
modulePathFor :: [String] -> FilePath
483466
modulePathFor moduleNameSuffix = F.joinPath (moduleNameParts moduleNameSuffix) `F.addExtension` "hs"
484467

485468
moduleNameParts :: [String] -> [String]
486469
moduleNameParts = (["Graphics", "GL"] ++)
487470

488-
printModuleHeader :: SI.Handle -> Maybe String -> String -> [String] -> IO ()
489-
printModuleHeader h mbPragma moduleName comments = do
471+
printModuleHeader :: SI.Handle -> Maybe String -> ModuleName -> [String] -> IO ()
472+
printModuleHeader h mbPragma (ModuleName moduleName) comments = do
490473
maybe (return ()) (SI.hPutStrLn h) mbPragma
491474
SI.hPutStrLn h "--------------------------------------------------------------------------------"
492475
SI.hPutStrLn h "-- |"
@@ -720,3 +703,27 @@ toEnumType eNamespace eGroup eType suffix eName = TypeName $
720703

721704
isMask :: TypeName -> Bool
722705
isMask = (== TypeName "GLbitfield")
706+
707+
--------------------------------------------------------------------------------
708+
709+
data Module = Module ModuleName Exports
710+
711+
instance P.Pretty Module where
712+
pPrint (Module mn ex) = P.text "module" P.<+> P.pPrint mn P.<+> ex P.<+> P.text "where\n"
713+
714+
type Exports = P.Doc
715+
716+
data Import = Import ModuleName ImportSpecs
717+
718+
instance P.Pretty Import where
719+
pPrint (Import mn im) = P.text "import" P.<+> P.pPrint mn P.<+> im
720+
721+
type ImportSpecs = P.Doc
722+
723+
newtype ModuleName = ModuleName String
724+
725+
instance P.Pretty ModuleName where
726+
pPrint (ModuleName m) = P.text m
727+
728+
hRender :: P.Pretty a => SI.Handle -> a -> IO ()
729+
hRender h = SI.hPutStrLn h . P.render . P.pPrint

0 commit comments

Comments
 (0)