@@ -29,6 +29,7 @@ main = do
29
29
let extModules = extensionModules api registry
30
30
CM. forM_ extModules printExtensionModule
31
31
printReExports extModules
32
+ printExtensionSupport extModules
32
33
CM. forM_ (openGLVersions api) $ \ v ->
33
34
CM. forM_ (supportedProfiles api v) $ \ p ->
34
35
printFeature api v p registry
@@ -63,7 +64,7 @@ profileToReExport = last . latestProfiles
63
64
64
65
printFeature :: API -> Version -> Maybe ProfileName -> Registry -> IO ()
65
66
printFeature api version mbProfile registry =
66
- printExtension [featureName version mbProfile] [] $
67
+ printExtension [featureName version mbProfile] Nothing $
67
68
fixedReplay api version mbProfile registry
68
69
69
70
featureName :: Version -> Maybe ProfileName -> String
@@ -139,22 +140,22 @@ groupHeader es = case sortUnique (map enumType es) of
139
140
[] -> " There are no values defined for this enumeration group."
140
141
[t] | isMask t -> " A bitwise combination of several of the following values:"
141
142
| otherwise -> " One of the following values:"
142
- types -> error $ " Contradicting enumerant types " ++ show types
143
+ tys -> error $ " Contradicting enumerant types " ++ show tys
143
144
144
145
-- Calulate a map from compact signature to short names.
145
146
signatureMap :: 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)
147
148
where step (m,n) command = memberAndInsert (n+ 1 ) n (sig command) (dyn n) m
148
149
sig = flip (showSignatureFromCommand registry) False
149
150
dyn n = " dyn" ++ show n
150
- memberAndInsert notFound found key value map =
151
+ memberAndInsert notFound found key value theMap =
151
152
(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
153
154
154
155
printForeign :: M. Map String String -> IO ()
155
156
printForeign sigMap = do
156
157
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
158
159
SI. hPutStrLn h $ " module " ++ moduleName ++ " where"
159
160
SI. hPutStrLn h " "
160
161
SI. hPutStrLn h " import Foreign.C.Types"
@@ -191,10 +192,13 @@ printFunctions api registry sigMap = do
191
192
SI. hPutStrLn h " "
192
193
mapM_ (SI. hPutStrLn h . showCommand api registry sigMap) (M. elems (commands registry))
193
194
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 ()
195
199
printExtensionModule (extName, mangledExtName, extensionParts) =
196
200
printExtension [extensionNameCategory mangledExtName, extensionNameName mangledExtName]
197
- (commentForExension extName)
201
+ (Just extName)
198
202
extensionParts
199
203
200
204
extendWithProfile :: ExtensionName -> Maybe ProfileName -> ExtensionName
@@ -204,7 +208,7 @@ extendWithProfile extName =
204
208
mangleExtensionName :: ExtensionName -> ExtensionName
205
209
mangleExtensionName extName = extName {
206
210
extensionNameCategory = fixCategory $ extensionNameCategory extName,
207
- extensionNameName = zip (splitWords (extensionNameName extName)) [0 .. ] >>= fixExtensionWord }
211
+ extensionNameName = zip (splitWords (extensionNameName extName)) [0 :: Integer .. ] >>= fixExtensionWord }
208
212
where fixCategory c = case c of
209
213
" 3DFX" -> " ThreeDFX"
210
214
_ -> c
@@ -247,7 +251,7 @@ mangleExtensionName extName = extName {
247
251
" ycrcba" -> " YCrCbA"
248
252
_ -> capitalize w
249
253
250
- extensionModules :: API -> Registry -> [( ExtensionName , ExtensionName , ([ TypeName ], [ Enum' ], [ Command ])) ]
254
+ extensionModules :: API -> Registry -> [ExtensionModule ]
251
255
extensionModules api registry =
252
256
[ (extName, mangledExtName, executeModifications api mbProfile registry mods)
253
257
| (extName, mods) <- supportedExtensions api registry
@@ -265,21 +269,21 @@ supportedExtensions api registry =
265
269
[ nameAndMods
266
270
| ext <- extensions registry
267
271
, 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 =
271
275
(extensionName e,
272
276
[ conditionalModificationModification cm
273
277
| cm <- extensionsRequireRemove e
274
278
, api `matches` conditionalModificationAPI cm
275
279
-- ARB_compatibility has an empty "require" element only
276
280
, not . null . modificationInterfaceElements . conditionalModificationModification $ cm ])
277
281
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/" ++
281
285
fixRegistryPath (extensionNameCategory n ++ " /" ++ extensionNameName n) ++ " .txt " ++
282
- joinWords [extensionNameCategory n, extensionNameName n] ++ " > extension. " ]
286
+ joinWords [extensionNameCategory n, extensionNameName n] ++ " >"
283
287
where fixRegistryPath :: String -> String
284
288
fixRegistryPath path = case path of
285
289
" 3DFX/multisample" -> " 3DFX/3dfx_multisample"
@@ -305,7 +309,7 @@ commentForExension n = [
305
309
" SGIX/texture_add_env" -> " SGIX/texture_env_add"
306
310
_ -> path
307
311
308
- printReExports :: [( ExtensionName , ExtensionName , ([ TypeName ], [ Enum' ], [ Command ])) ] -> IO ()
312
+ printReExports :: [ExtensionModule ] -> IO ()
309
313
printReExports extModules = do
310
314
let extMap = M. fromListWith (++) [((extensionNameCategory extName, extensionNameCategory mangledExtName), [mangledExtName])
311
315
| (extName, mangledExtName, _) <- extModules ]
@@ -321,6 +325,37 @@ printReExports extModules = do
321
325
CM. forM_ mangledExtNames $ \ mangledExtName ->
322
326
SI. hPutStrLn h $ " import " ++ extensionNameFor mangledExtName
323
327
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
+
324
359
extensionNameFor :: ExtensionName -> String
325
360
extensionNameFor mangledExtName = moduleNameFor [extensionNameCategory mangledExtName, extensionNameName mangledExtName]
326
361
@@ -335,10 +370,14 @@ separate :: (a -> String) -> [a] -> String
335
370
separate f = L. intercalate " ,\n " . map (" " ++ ) . map f
336
371
337
372
-- 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
341
376
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 ] ++ " ,"
342
381
CM. unless (null ts) $ do
343
382
SI. hPutStrLn h " -- * Types"
344
383
SI. hPutStr h $ separate unTypeName ts
@@ -353,14 +392,30 @@ printExtension moduleNameSuffix comment (ts, es, cs) =
353
392
SI. hPutStrLn h " "
354
393
SI. hPutStrLn h " ) where"
355
394
SI. hPutStrLn h " "
395
+ CM. when (DM. isJust mbExtName) $
396
+ SI. hPutStrLn h $ " import " ++ moduleNameFor [" ExtensionPredicates" ]
356
397
CM. unless (null ts) $
357
398
SI. hPutStrLn h $ " import " ++ moduleNameFor [" Types" ]
358
399
CM. unless (null es) $
359
400
SI. hPutStrLn h $ " import " ++ moduleNameFor [" Tokens" ]
360
401
CM. unless (null cs) $
361
402
SI. hPutStrLn h $ " import " ++ moduleNameFor [" Functions" ]
362
403
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 ()
364
419
printTopLevel api extModules = do
365
420
let mangledCategories = sortUnique [ extensionNameCategory mangledExtName
366
421
| (_, mangledExtName, _) <- extModules ]
@@ -378,8 +433,8 @@ printTopLevel api extModules = do
378
433
SI. hPutStrLn h $ separate (\ m -> " module " ++ m) moduleNames
379
434
SI. hPutStrLn h " ) where"
380
435
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
383
438
384
439
apiName :: API -> String
385
440
apiName api = case unAPI api of
@@ -431,7 +486,7 @@ printModuleHeader h mbPragma moduleName comments = do
431
486
-- Annoyingly enough, the OpenGL registry doesn't contain any enums for
432
487
-- OpenGL 1.0, so let's just use the OpenGL 1.1 ones. Furthermore, features
433
488
-- 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
435
490
fixedReplay api version mbProfile registry
436
491
| api == API " gl" && version == read " 1.0" = (ts', es11, cs)
437
492
| otherwise = (ts', es, cs)
@@ -454,7 +509,7 @@ addFuncsAndMakes =
454
509
455
510
-- Here is the heart of the feature construction logic: Chronologically replay
456
511
-- 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
458
513
replay api version mbProfile registry =
459
514
executeModifications api mbProfile registry modifications
460
515
where modifications = history >>= flip lookup' (features registry)
@@ -463,7 +518,7 @@ replay api version mbProfile registry =
463
518
, a == api
464
519
, v <= version ]
465
520
466
- executeModifications :: API -> Maybe ProfileName -> Registry -> [Modification ] -> ([ TypeName ], [ Enum' ], [ Command ])
521
+ executeModifications :: API -> Maybe ProfileName -> Registry -> [Modification ] -> ExtensionParts
467
522
executeModifications api mbProfile registry modifications = (ts, es, cs)
468
523
where ts = [ n | TypeElement n <- lst ]
469
524
es = [ e | EnumElement n <- lst
0 commit comments