spirv-reflect-yaml (empty) → 0.1
raw patch · 6 files changed
+433/−0 lines, 6 filesdep +HsYAMLdep +basedep +bytestring
Dependencies added: HsYAML, base, bytestring, directory, filepath, spirv-reflect-types, spirv-reflect-yaml, tasty, tasty-hunit, text, vector
Files
- ChangeLog.md +7/−0
- LICENSE +30/−0
- lib/Data/SpirV/Reflect/Yaml.hs +46/−0
- lib/Data/SpirV/Reflect/Yaml/Parsers.hs +202/−0
- spirv-reflect-yaml.cabal +91/−0
- test/Main.hs +57/−0
+ ChangeLog.md view
@@ -0,0 +1,7 @@+# Changelog for spirv-reflect-yaml++## [0.1] - 2022-06-11++* Initial release.++[0.1]: https://gitlab.com/dpwiz/spirv-reflect/-/tree/v0.1-yaml
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright IC Rainbow (c) 2022++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Author name here nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ lib/Data/SpirV/Reflect/Yaml.hs view
@@ -0,0 +1,46 @@+module Data.SpirV.Reflect.Yaml+ ( load+ , loadBytes++ , YamlError(..)+ , prettyYamlError+ , prettyYamlErrorBytes+ ) where++import Control.Exception (Exception, throwIO)+import Control.Monad.IO.Class (MonadIO(..))+import Data.ByteString.Lazy qualified as BSL+import Data.YAML qualified as YAML++import Data.SpirV.Reflect.Module (Module)+import Data.SpirV.Reflect.Yaml.Parsers (rootP)++data YamlError = YamlError+ { source :: FilePath+ , position :: YAML.Pos+ , message :: String+ }+ deriving (Show)++instance Exception YamlError++load :: MonadIO io => FilePath -> io Module+load file =+ liftIO (BSL.readFile file) >>= loadBytes file++loadBytes :: MonadIO io => FilePath -> BSL.ByteString -> io Module+loadBytes source bytes =+ case YAML.decode1 bytes >>= YAML.parseEither . rootP of+ Left (position, message) ->+ liftIO $ throwIO YamlError{..}+ Right res ->+ pure res++prettyYamlError :: MonadIO io => YamlError -> io String+prettyYamlError err = do+ bytes <- liftIO (BSL.readFile $ source err)+ pure $ prettyYamlErrorBytes err bytes++prettyYamlErrorBytes :: YamlError -> BSL.ByteString -> String+prettyYamlErrorBytes YamlError{..} bytes =+ YAML.prettyPosWithSource position bytes source ++ message
+ lib/Data/SpirV/Reflect/Yaml/Parsers.hs view
@@ -0,0 +1,202 @@+module Data.SpirV.Reflect.Yaml.Parsers where++import Prelude hiding (id)++import Data.Functor ((<&>))+import Data.Text (Text)+import Data.Vector (Vector)+import Data.Vector qualified as Vector+import Data.Vector.Storable qualified as Storable+import Data.YAML ((.:))+import Data.YAML qualified as YAML++import Data.SpirV.Reflect.BlockVariable (BlockVariable)+import Data.SpirV.Reflect.BlockVariable qualified as BlockVariable+import Data.SpirV.Reflect.DescriptorBinding (DescriptorBinding)+import Data.SpirV.Reflect.DescriptorBinding qualified as DescriptorBinding+import Data.SpirV.Reflect.DescriptorSet (DescriptorSet)+import Data.SpirV.Reflect.DescriptorSet qualified as DescriptorSet+import Data.SpirV.Reflect.Enums qualified as Enums+import Data.SpirV.Reflect.InterfaceVariable (InterfaceVariable)+import Data.SpirV.Reflect.InterfaceVariable qualified as InterfaceVariable+import Data.SpirV.Reflect.Module (Module)+import Data.SpirV.Reflect.Module qualified as Module+import Data.SpirV.Reflect.Traits qualified as Traits+import Data.SpirV.Reflect.TypeDescription (TypeDescription)+import Data.SpirV.Reflect.TypeDescription qualified as TypeDescription++rootP :: NodeParser Module+rootP = YAML.withMap "Root" \m ->+ -- XXX: Discarding all_XXX fields, assuming they got unrolled by YAML decoder.+ m .: "module" >>= moduleP++moduleP :: NodeParser Module+moduleP = YAML.withMap "Module" \m -> do+ generator <- m .: "generator" <&> Enums.Generator+ entry_point_name <- m .: "entry_point_name"+ entry_point_id <- m .: "entry_point_id"+ source_language <- m .: "source_language"+ source_language_version <- m .: "source_language_version"+ spirv_execution_model <- m .: "spirv_execution_model"+ shader_stage <- m .: "shader_stage"+ descriptor_bindings <- m .? "descriptor_bindings" `seqOf` descriptorBindingP+ descriptor_sets <- m .? "descriptor_sets" `seqOf` descriptorSetP+ input_variables <- m .? "input_variables" `seqOf` interfaceVariableP+ output_variables <- m .? "output_variables" `seqOf` interfaceVariableP+ push_constants <- m .? "push_constants" `seqOf` blockVariableP+ pure Module.Module{..}++descriptorBindingP :: NodeParser DescriptorBinding+descriptorBindingP = YAML.withMap "DescriptorBinding" \m -> do+ spirv_id <- m .? "spirv_id"+ name <- m .: "name"+ binding <- m .: "binding"+ input_attachment_index <- m .: "input_attachment_index"+ set <- m .: "set"+ descriptor_type <- m .: "descriptor_type" <&> Enums.DescriptorType+ resource_type <- m .: "resource_type" <&> Enums.ResourceFlagBits+ image <- m .: "image" >>= traitsImageP+ block <- m .: "block" >>= blockVariableP+ array <- m .: "array" >>= traitsArrayP+ count <- m .? "count"+ accessed <- m .: "accessed"+ uav_counter_id <- m .: "uav_counter_id"+ uav_counter_binding <- m .? "uav_counter_binding" >>= traverse descriptorBindingP+ type_description <- m .? "type_description" >>= traverse typeDescriptionP+ word_offset <- m .: "word_offset" >>= descriptorBindingWordOffsetP+ decoration_flags <- m .? "decoration_flags" <&> maybe Enums.DECORATION_NONE Enums.DecorationFlagBits+ pure DescriptorBinding.DescriptorBinding{..}++descriptorBindingWordOffsetP :: NodeParser DescriptorBinding.WordOffset+descriptorBindingWordOffsetP = YAML.withMap "DescriptorBinding.WordOffset" \m -> do+ binding <- m .: "binding"+ set <- m .: "set"+ pure DescriptorBinding.WordOffset{..}++typeDescriptionP :: NodeParser TypeDescription+typeDescriptionP = YAML.withMap "TypeDescription" \m -> do+ id <- m .? "id"+ op <- m .? "op" <&> fmap Enums.Op+ type_name <- m .? "type_name"+ struct_member_name <- m .? "struct_member_name"+ storage_class <- m .: "storage_class" <&> Enums.StorageClass+ type_flags <- m .? "type_flags" <&> maybe Enums.TYPE_FLAG_UNDEFINED Enums.TypeFlagBits+ traits <- m .? "traits" >>= traverse typeDescriptionTraitsP+ members <- m .? "members" `seqOf` typeDescriptionP+ pure TypeDescription.TypeDescription{..}++typeDescriptionTraitsP :: NodeParser TypeDescription.Traits+typeDescriptionTraitsP = YAML.withMap "TypeDescription.Traits" \m -> do+ numeric <- m .: "numeric" >>= traitsNumericP+ image <- m .: "image" >>= traitsImageP+ array <- m .: "array" >>= traitsArrayP+ pure TypeDescription.Traits{..}++descriptorSetP :: NodeParser DescriptorSet+descriptorSetP = YAML.withMap "DescriptorSet" \m -> do+ set <- m .: "set"+ bindings <- m .? "bindings" `seqOf` descriptorBindingP+ pure DescriptorSet.DescriptorSet{..}++interfaceVariableP :: NodeParser InterfaceVariable+interfaceVariableP = YAML.withMap "InterfaceVariable" \m -> do+ spirv_id <- m .? "spirv_id"+ name <- m .? "name"+ location <- m .: "location"+ storage_class <- m .: "storage_class" <&> Enums.StorageClass+ semantic <- m .: "semantic"+ decoration_flags <- m .: "decoration_flags" <&> Enums.DecorationFlagBits+ built_in <- m .: "built_in" <&> Enums.BuiltIn+ numeric <- m .: "numeric" >>= traitsNumericP+ array <- m .: "array" >>= traitsArrayP+ members <- m .? "members" `seqOf` typeDescriptionP+ format <- m .: "format" <&> Enums.Format+ type_description <- m .? "type_description" >>= traverse typeDescriptionP+ word_offset <- m .: "word_offset" >>= interfaceVariableWordOffsetP+ pure InterfaceVariable.InterfaceVariable{..}++interfaceVariableWordOffsetP :: NodeParser InterfaceVariable.WordOffset+interfaceVariableWordOffsetP = YAML.withMap "InterfaceVariable.WordOffset" \m -> do+ location <- m .: "location"+ pure InterfaceVariable.WordOffset{..}++blockVariableP :: NodeParser BlockVariable+blockVariableP = YAML.withMap "BlockVariable" \m -> do+ spirv_id <- m .? "spirv_id"+ name <- m .? "name"+ offset <- m .: "offset"+ absolute_offset <- m .: "absolute_offset"+ size <- m .: "size"+ padded_size <- m .: "padded_size"+ decorations <- m .: "decorations" <&> Enums.DecorationFlagBits+ numeric <- m .: "numeric" >>= traitsNumericP+ array <- m .: "array" >>= traitsArrayP+ members <- m .? "members" `seqOf` blockVariableP+ type_description <- m .? "type_description" >>= traverse typeDescriptionP+ pure BlockVariable.BlockVariable{..}++--------------++traitsNumericP :: NodeParser Traits.Numeric+traitsNumericP = YAML.withMap "Numeric" \m -> do+ scalar <- m .: "scalar" >>= traitsScalarP+ vector <- m .: "vector" >>= traitsVectorP+ matrix <- m .: "matrix" >>= traitsMatrixP+ pure Traits.Numeric{..}++traitsScalarP :: NodeParser Traits.Scalar+traitsScalarP = YAML.withMap "Scalar" \m -> do+ width <- m .: "width"+ signedness <- m .: "signedness"+ pure Traits.Scalar{..}++traitsVectorP :: NodeParser Traits.Vector+traitsVectorP = YAML.withMap "Vector" \m -> do+ component_count <- m .: "component_count"+ pure Traits.Vector{..}++traitsMatrixP :: NodeParser Traits.Matrix+traitsMatrixP = YAML.withMap "Matrix" \m -> do+ column_count <- m .: "column_count"+ row_count <- m .: "row_count"+ stride <- m .: "stride"+ pure Traits.Matrix{..}++traitsArrayP :: NodeParser Traits.Array+traitsArrayP = YAML.withMap "Array" \m -> do+ dims_count <- m .: "dims_count"+ dims <- m .: "dims" <&> Storable.fromList+ stride <- m .? "stride"+ pure Traits.Array{..}++traitsImageP :: NodeParser Traits.Image+traitsImageP = YAML.withMap "Image" \m -> do+ dim <- m .: "dim" <&> Enums.Dim+ depth <- m .: "depth"+ arrayed <- m .: "arrayed"+ ms <- m .: "ms"+ sampled <- m .: "sampled"+ image_format <- m .: "image_format" <&> Enums.ImageFormat+ pure Traits.Image{..}++type NodeParser a =+ YAML.Node YAML.Pos ->+ YAML.Parser a++(.?)+ :: YAML.FromYAML a+ => YAML.Mapping YAML.Pos+ -> Text+ -> YAML.Parser (Maybe a)+o .? v = o YAML..:? v++seqOf+ :: YAML.Parser (Maybe (YAML.Node YAML.Pos))+ -> NodeParser a+ -> YAML.Parser (Vector a)+seqOf mappingP nodeP =+ mappingP >>= \case+ Nothing ->+ pure mempty+ Just items ->+ YAML.withSeq "seqOf" (traverse nodeP . Vector.fromList) items
+ spirv-reflect-yaml.cabal view
@@ -0,0 +1,91 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.34.4.+--+-- see: https://github.com/sol/hpack++name: spirv-reflect-yaml+version: 0.1+synopsis: YAML loader for spirv-reflect tool.+category: Graphics+author: IC Rainbow+maintainer: ic.rbow@gmail.com+copyright: 2022 IC Rainbow+license: BSD3+license-file: LICENSE+build-type: Simple+extra-source-files:+ ChangeLog.md++source-repository head+ type: git+ location: https://gitlab.com/dpwiz/spirv-reflect++flag tests+ manual: True+ default: False++library+ exposed-modules:+ Data.SpirV.Reflect.Yaml+ Data.SpirV.Reflect.Yaml.Parsers+ other-modules:+ Paths_spirv_reflect_yaml+ hs-source-dirs:+ lib+ default-extensions:+ ApplicativeDo+ BlockArguments+ DeriveGeneric+ DerivingStrategies+ DuplicateRecordFields+ FlexibleContexts+ GeneralizedNewtypeDeriving+ ImportQualifiedPost+ LambdaCase+ OverloadedStrings+ PatternSynonyms+ RecordWildCards+ StrictData+ TypeApplications+ build-depends:+ HsYAML+ , base >=4.7 && <5+ , bytestring+ , spirv-reflect-types+ , text+ , vector+ default-language: Haskell2010++test-suite spirv-reflect-yaml-test+ type: exitcode-stdio-1.0+ main-is: Main.hs+ other-modules:+ Paths_spirv_reflect_yaml+ hs-source-dirs:+ test+ default-extensions:+ ApplicativeDo+ BlockArguments+ DeriveGeneric+ DerivingStrategies+ DuplicateRecordFields+ FlexibleContexts+ GeneralizedNewtypeDeriving+ ImportQualifiedPost+ LambdaCase+ OverloadedStrings+ PatternSynonyms+ RecordWildCards+ StrictData+ TypeApplications+ build-depends:+ base >=4.7 && <5+ , directory+ , filepath+ , spirv-reflect-yaml+ , tasty+ , tasty-hunit+ if !flag(tests)+ buildable: False+ default-language: Haskell2010
+ test/Main.hs view
@@ -0,0 +1,57 @@+module Main where++import Control.Exception (try)+import Control.Monad (guard)+import System.Directory (doesDirectoryExist, listDirectory)+import System.FilePath (splitExtensions, takeFileName, (</>))+import Test.Tasty (TestTree, defaultMain, testGroup)+import Test.Tasty.HUnit (testCase)++import Data.SpirV.Reflect.Yaml qualified as Yaml++main :: IO ()+main = discover >>= defaultMain++discover :: IO TestTree+discover = do+ groupDirs <- listDirectory UPSTREAM_PATH >>= traverse \path -> do+ let groupPath = UPSTREAM_PATH </> path+ isDir <- doesDirectoryExist groupPath+ if not isDir then+ pure mempty+ else do+ groupContents <- listDirectory groupPath+ let+ yamlFiles = do+ filePath <- groupContents+ case splitExtensions filePath of+ (name, ".spv.yaml") ->+ pure+ ( takeFileName name+ , groupPath </> filePath+ )+ _skip ->+ mempty+ pure (path, yamlFiles)++ let+ groups = do+ (name, yamls) <- groupDirs+ guard $ not (null yamls)+ pure $ testGroup name (map mkTest yamls)++ pure $ testGroup "upstream" groups++mkTest :: (String, FilePath) -> TestTree+mkTest (name, file) =+ testCase name do+ try (Yaml.load file) >>= \case+ Left err ->+ Yaml.prettyYamlError err >>= fail+ Right _res ->+ pure ()+ -- writeFile (file ++ ".hs") $+ -- show res++pattern UPSTREAM_PATH :: FilePath+pattern UPSTREAM_PATH = "../SPIRV-Reflect/tests/"