@@ -29,6 +29,7 @@ main = do
2929 let extModules = extensionModules api registry
3030 CM. forM_ extModules printExtensionModule
3131 printReExports extModules
32+ printExtensionSupport extModules
3233 CM. forM_ (openGLVersions api) $ \ v ->
3334 CM. forM_ (supportedProfiles api v) $ \ p ->
3435 printFeature api v p registry
@@ -63,7 +64,7 @@ profileToReExport = last . latestProfiles
6364
6465printFeature :: API -> Version -> Maybe ProfileName -> Registry -> IO ()
6566printFeature api version mbProfile registry =
66- printExtension [featureName version mbProfile] [] $
67+ printExtension [featureName version mbProfile] Nothing $
6768 fixedReplay api version mbProfile registry
6869
6970featureName :: Version -> Maybe ProfileName -> String
@@ -139,22 +140,22 @@ groupHeader es = case sortUnique (map enumType es) of
139140 [] -> " There are no values defined for this enumeration group."
140141 [t] | isMask t -> " A bitwise combination of several of the following values:"
141142 | otherwise -> " One of the following values:"
142- types -> error $ " Contradicting enumerant types " ++ show types
143+ tys -> error $ " Contradicting enumerant types " ++ show tys
143144
144145-- Calulate a map from compact signature to short names.
145146signatureMap :: Registry -> M. Map String String
146- signatureMap registry = fst $ M. foldl' step (M. empty, 0 ) (commands registry)
147+ signatureMap registry = fst $ M. foldl' step (M. empty, 0 :: Integer ) (commands registry)
147148 where step (m,n) command = memberAndInsert (n+ 1 ) n (sig command) (dyn n) m
148149 sig = flip (showSignatureFromCommand registry) False
149150 dyn n = " dyn" ++ show n
150- memberAndInsert notFound found key value map =
151+ memberAndInsert notFound found key value theMap =
151152 (newMap, maybe notFound (const found) maybeValue)
152- where (maybeValue, newMap) = M. insertLookupWithKey (\ _ _ s -> s) key value map
153+ where (maybeValue, newMap) = M. insertLookupWithKey (\ _ _ s -> s) key value theMap
153154
154155printForeign :: M. Map String String -> IO ()
155156printForeign sigMap = do
156157 let comment = [" All foreign imports." ]
157- startModule [" Foreign" ] (Just " {-# LANGUAGE CPP #-}" ) comment $ \ moduleName h -> do
158+ startModule [" Foreign" ] (Just " {-# LANGUAGE CPP #-}\n {-# OPTIONS_HADDOCK hide #-} " ) comment $ \ moduleName h -> do
158159 SI. hPutStrLn h $ " module " ++ moduleName ++ " where"
159160 SI. hPutStrLn h " "
160161 SI. hPutStrLn h " import Foreign.C.Types"
@@ -191,10 +192,13 @@ printFunctions api registry sigMap = do
191192 SI. hPutStrLn h " "
192193 mapM_ (SI. hPutStrLn h . showCommand api registry sigMap) (M. elems (commands registry))
193194
194- printExtensionModule :: (ExtensionName , ExtensionName , ([TypeName ], [Enum' ], [Command ])) -> IO ()
195+ type ExtensionParts = ([TypeName ], [Enum' ], [Command ])
196+ type ExtensionModule = (ExtensionName , ExtensionName , ExtensionParts )
197+
198+ printExtensionModule :: ExtensionModule -> IO ()
195199printExtensionModule (extName, mangledExtName, extensionParts) =
196200 printExtension [extensionNameCategory mangledExtName, extensionNameName mangledExtName]
197- (commentForExension extName)
201+ (Just extName)
198202 extensionParts
199203
200204extendWithProfile :: ExtensionName -> Maybe ProfileName -> ExtensionName
@@ -204,7 +208,7 @@ extendWithProfile extName =
204208mangleExtensionName :: ExtensionName -> ExtensionName
205209mangleExtensionName extName = extName {
206210 extensionNameCategory = fixCategory $ extensionNameCategory extName,
207- extensionNameName = zip (splitWords (extensionNameName extName)) [0 .. ] >>= fixExtensionWord }
211+ extensionNameName = zip (splitWords (extensionNameName extName)) [0 :: Integer .. ] >>= fixExtensionWord }
208212 where fixCategory c = case c of
209213 " 3DFX" -> " ThreeDFX"
210214 _ -> c
@@ -247,7 +251,7 @@ mangleExtensionName extName = extName {
247251 " ycrcba" -> " YCrCbA"
248252 _ -> capitalize w
249253
250- extensionModules :: API -> Registry -> [( ExtensionName , ExtensionName , ([ TypeName ], [ Enum' ], [ Command ])) ]
254+ extensionModules :: API -> Registry -> [ExtensionModule ]
251255extensionModules api registry =
252256 [ (extName, mangledExtName, executeModifications api mbProfile registry mods)
253257 | (extName, mods) <- supportedExtensions api registry
@@ -265,21 +269,21 @@ supportedExtensions api registry =
265269 [ nameAndMods
266270 | ext <- extensions registry
267271 , api `supports` extensionSupported ext
268- , nameAndMods@ (_,(_: _)) <- [nameAndModifications api ext] ]
269- where nameAndModifications :: API -> Extension -> (ExtensionName , [Modification ])
270- nameAndModifications api e =
272+ , nameAndMods@ (_,(_: _)) <- [nameAndModifications ext] ]
273+ where nameAndModifications :: Extension -> (ExtensionName , [Modification ])
274+ nameAndModifications e =
271275 (extensionName e,
272276 [ conditionalModificationModification cm
273277 | cm <- extensionsRequireRemove e
274278 , api `matches` conditionalModificationAPI cm
275279 -- ARB_compatibility has an empty "require" element only
276280 , not . null . modificationInterfaceElements . conditionalModificationModification $ cm ])
277281
278- commentForExension :: ExtensionName -> [ String ]
279- commentForExension n = [
280- " The <https://www.opengl.org/registry/specs/" ++
282+ extensionHyperlink :: ExtensionName -> String
283+ extensionHyperlink n =
284+ " <https://www.opengl.org/registry/specs/" ++
281285 fixRegistryPath (extensionNameCategory n ++ " /" ++ extensionNameName n) ++ " .txt " ++
282- joinWords [extensionNameCategory n, extensionNameName n] ++ " > extension. " ]
286+ joinWords [extensionNameCategory n, extensionNameName n] ++ " >"
283287 where fixRegistryPath :: String -> String
284288 fixRegistryPath path = case path of
285289 " 3DFX/multisample" -> " 3DFX/3dfx_multisample"
@@ -305,7 +309,7 @@ commentForExension n = [
305309 " SGIX/texture_add_env" -> " SGIX/texture_env_add"
306310 _ -> path
307311
308- printReExports :: [( ExtensionName , ExtensionName , ([ TypeName ], [ Enum' ], [ Command ])) ] -> IO ()
312+ printReExports :: [ExtensionModule ] -> IO ()
309313printReExports extModules = do
310314 let extMap = M. fromListWith (++) [((extensionNameCategory extName, extensionNameCategory mangledExtName), [mangledExtName])
311315 | (extName, mangledExtName, _) <- extModules ]
@@ -321,6 +325,37 @@ printReExports extModules = do
321325 CM. forM_ mangledExtNames $ \ mangledExtName ->
322326 SI. hPutStrLn h $ " import " ++ extensionNameFor mangledExtName
323327
328+ printExtensionSupport :: [ExtensionModule ] -> IO ()
329+ printExtensionSupport extModules = do
330+ let comment = [" Extension support predicates." ]
331+ startModule [" ExtensionPredicates" ] (Just " {-# LANGUAGE CPP #-}\n {-# OPTIONS_HADDOCK hide #-}" ) comment $ \ moduleName h -> do
332+ SI. hPutStrLn h $ " module " ++ moduleName ++ " where"
333+ SI. hPutStrLn h $ " "
334+ SI. hPutStrLn h " #if !MIN_VERSION_base(4,8,0)"
335+ SI. hPutStrLn h " import Data.Functor( (<$>) )"
336+ SI. hPutStrLn h " #endif"
337+ SI. hPutStrLn h $ " import Control.Monad.IO.Class ( MonadIO(..) )"
338+ SI. hPutStrLn h $ " import Data.Set ( member )"
339+ SI. hPutStrLn h $ " import " ++ moduleNameFor [" GetProcAddress" ] ++ " ( getExtensions, extensions )"
340+ let names = sortUnique [ extName | (extName, _, _) <- extModules]
341+ CM. forM_ names $ \ extName -> do
342+ let predNameMonad = extensionPredicateNameMonad extName
343+ predName = extensionPredicateName extName
344+ extString = joinWords [ extensionNameAPI extName
345+ , extensionNameCategory extName
346+ , extensionNameName extName ]
347+ SI. hPutStrLn h $ " "
348+ SI. hPutStrLn h $ " -- | Is the " ++ extensionHyperlink extName ++ " extension supported?"
349+ SI. hPutStrLn h $ predNameMonad ++ " :: MonadIO m => m Bool"
350+ SI. hPutStrLn h $ predNameMonad ++ " = member " ++ show extString ++ " <$> getExtensions"
351+ SI. hPutStrLn h $ " "
352+ SI. hPutStrLn h $ " -- | Is the " ++ extensionHyperlink extName ++ " extension supported?"
353+ SI. hPutStrLn h $ " -- Note that in the presence of multiple contexts with different capabilities,"
354+ SI. hPutStrLn h $ " -- this might be wrong. Use '" ++ predNameMonad ++ " ' in those cases instead."
355+ SI. hPutStrLn h $ predName ++ " :: Bool"
356+ SI. hPutStrLn h $ predName ++ " = member " ++ show extString ++ " extensions"
357+ SI. hPutStrLn h $ " {-# NOINLINE " ++ predName ++ " #-}"
358+
324359extensionNameFor :: ExtensionName -> String
325360extensionNameFor mangledExtName = moduleNameFor [extensionNameCategory mangledExtName, extensionNameName mangledExtName]
326361
@@ -335,10 +370,14 @@ separate :: (a -> String) -> [a] -> String
335370separate f = L. intercalate " ,\n " . map (" " ++ ) . map f
336371
337372-- Note that we handle features just like extensions.
338- printExtension :: [String ] -> [ String ] -> ([ TypeName ], [ Enum' ], [ Command ]) -> IO ()
339- printExtension moduleNameSuffix comment (ts, es, cs) =
340- startModule moduleNameSuffix Nothing comment $ \ moduleName h -> do
373+ printExtension :: [String ] -> Maybe ExtensionName -> ExtensionParts -> IO ()
374+ printExtension moduleNameSuffix mbExtName (ts, es, cs) =
375+ startModule moduleNameSuffix Nothing [] $ \ moduleName h -> do
341376 SI. hPutStrLn h $ " module " ++ moduleName ++ " ("
377+ flip (maybe (return () )) mbExtName $ \ extName -> do
378+ SI. hPutStrLn h " -- * Extension Support"
379+ SI. hPutStrLn h $ separate id [ extensionPredicateNameMonad extName
380+ , extensionPredicateName extName ] ++ " ,"
342381 CM. unless (null ts) $ do
343382 SI. hPutStrLn h " -- * Types"
344383 SI. hPutStr h $ separate unTypeName ts
@@ -353,14 +392,30 @@ printExtension moduleNameSuffix comment (ts, es, cs) =
353392 SI. hPutStrLn h " "
354393 SI. hPutStrLn h " ) where"
355394 SI. hPutStrLn h " "
395+ CM. when (DM. isJust mbExtName) $
396+ SI. hPutStrLn h $ " import " ++ moduleNameFor [" ExtensionPredicates" ]
356397 CM. unless (null ts) $
357398 SI. hPutStrLn h $ " import " ++ moduleNameFor [" Types" ]
358399 CM. unless (null es) $
359400 SI. hPutStrLn h $ " import " ++ moduleNameFor [" Tokens" ]
360401 CM. unless (null cs) $
361402 SI. hPutStrLn h $ " import " ++ moduleNameFor [" Functions" ]
362403
363- printTopLevel :: API -> [(ExtensionName , ExtensionName , ([TypeName ], [Enum' ], [Command ]))] -> IO ()
404+ extensionPredicateName :: ExtensionName -> String
405+ extensionPredicateName extName =
406+ joinWords [ map C. toLower (extensionNameAPI extName)
407+ , extensionNameCategory extName
408+ , extensionNameName extName ]
409+
410+ extensionPredicateNameMonad :: ExtensionName -> String
411+ extensionPredicateNameMonad extName =
412+ map C. toLower (extensionNameAPI mangledExtName) ++
413+ " Get" ++
414+ extensionNameCategory mangledExtName ++
415+ extensionNameName mangledExtName
416+ where mangledExtName = mangleExtensionName extName
417+
418+ printTopLevel :: API -> [ExtensionModule ] -> IO ()
364419printTopLevel api extModules = do
365420 let mangledCategories = sortUnique [ extensionNameCategory mangledExtName
366421 | (_, mangledExtName, _) <- extModules ]
@@ -378,8 +433,8 @@ printTopLevel api extModules = do
378433 SI. hPutStrLn h $ separate (\ m -> " module " ++ m) moduleNames
379434 SI. hPutStrLn h " ) where"
380435 SI. hPutStrLn h " "
381- CM. forM_ moduleNames $ \ moduleName ->
382- SI. hPutStrLn h $ " import " ++ moduleName
436+ CM. forM_ moduleNames $ \ theModuleName ->
437+ SI. hPutStrLn h $ " import " ++ theModuleName
383438
384439apiName :: API -> String
385440apiName api = case unAPI api of
@@ -431,7 +486,7 @@ printModuleHeader h mbPragma moduleName comments = do
431486-- Annoyingly enough, the OpenGL registry doesn't contain any enums for
432487-- OpenGL 1.0, so let's just use the OpenGL 1.1 ones. Furthermore, features
433488-- don't explicitly list the types referenced by commands, so we add them.
434- fixedReplay :: API -> Version -> Maybe ProfileName -> Registry -> ([ TypeName ], [ Enum' ], [ Command ])
489+ fixedReplay :: API -> Version -> Maybe ProfileName -> Registry -> ExtensionParts
435490fixedReplay api version mbProfile registry
436491 | api == API " gl" && version == read " 1.0" = (ts', es11, cs)
437492 | otherwise = (ts', es, cs)
@@ -454,7 +509,7 @@ addFuncsAndMakes =
454509
455510-- Here is the heart of the feature construction logic: Chronologically replay
456511-- the whole version history for the given API/version/profile triple.
457- replay :: API -> Version -> Maybe ProfileName -> Registry -> ([ TypeName ], [ Enum' ], [ Command ])
512+ replay :: API -> Version -> Maybe ProfileName -> Registry -> ExtensionParts
458513replay api version mbProfile registry =
459514 executeModifications api mbProfile registry modifications
460515 where modifications = history >>= flip lookup' (features registry)
@@ -463,7 +518,7 @@ replay api version mbProfile registry =
463518 , a == api
464519 , v <= version ]
465520
466- executeModifications :: API -> Maybe ProfileName -> Registry -> [Modification ] -> ([ TypeName ], [ Enum' ], [ Command ])
521+ executeModifications :: API -> Maybe ProfileName -> Registry -> [Modification ] -> ExtensionParts
467522executeModifications api mbProfile registry modifications = (ts, es, cs)
468523 where ts = [ n | TypeElement n <- lst ]
469524 es = [ e | EnumElement n <- lst
0 commit comments