Parse.hs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-# LANGUAGE PatternSynonyms #-}
  3. module Gidl.Parse (parseDecls) where
  4. import Control.Applicative ((<$>), (<*>))
  5. import Control.Monad ((>=>), guard)
  6. import Data.List (nub, partition)
  7. import Data.SCargot.Comments (withHaskellComments)
  8. import Data.SCargot.General ( SExprSpec
  9. , convertSpec
  10. , decode
  11. , asWellFormed
  12. )
  13. import Data.SCargot.HaskLike (HaskLikeAtom(..), haskLikeSpec)
  14. import Data.SCargot.Repr.WellFormed
  15. import Data.Text (unpack, pack)
  16. import Gidl.Types
  17. import Gidl.Interface
  18. -- We parse into this abstract structure before converting it to the
  19. -- structures Gidl uses elsewhere. That way, we can separate our
  20. -- parsing and our checking.
  21. data Decl
  22. = NewtypeDecl Identifier Identifier
  23. | EnumDecl (Identifier, Bits) [(Identifier, Integer)]
  24. | StructDecl Identifier [(Identifier, Identifier)]
  25. | InterfaceDecl Identifier [Identifier] [(Identifier, MethodDecl)]
  26. deriving (Eq, Show)
  27. data MethodDecl
  28. = AttrDecl Perm Identifier
  29. | StreamDecl Integer Identifier
  30. deriving (Eq, Show)
  31. check :: Bool -> String -> Either String ()
  32. check True _ = return ()
  33. check _ msg = throw msg
  34. -- Here's a function to convert those decls.
  35. toEnv :: [Decl] -> Either String (TypeEnv, InterfaceEnv)
  36. toEnv decls = do
  37. check (unique typeNames) "duplicate type names"
  38. check (unique interfaceNames) "duplicate interface names"
  39. typs <- mapM getTypePair typeNames
  40. ifcs <- mapM getIfacePair interfaceNames
  41. return (TypeEnv typs, InterfaceEnv ifcs)
  42. where (typDs, ifcDs) = partition isTypeDecl decls
  43. builtins = let TypeEnv bs = baseTypeEnv in bs
  44. typeNames = map fst builtins ++ map getName typDs
  45. interfaceNames = map getName ifcDs
  46. typMap = [(getName d, toType d) | d <- typDs] ++
  47. [(n, return (n, t)) | (n, t) <- builtins ]
  48. ifcMap = [(getName i, toInterface i) | i <- ifcDs]
  49. -- this is gross because I'm trying to make sure declarations
  50. -- can happen in any order. XXX: prevent recursion!
  51. getType n = snd `fmap` getTypePair n
  52. getTypePair n = case lookup n typMap of
  53. Just (Right t) -> return t
  54. Just (Left l) -> Left l
  55. Nothing -> throw ("Unknown primitive type: " ++ n)
  56. getIface n = snd `fmap` getIfacePair n
  57. getIfacePair n = case lookup n ifcMap of
  58. Just (Right i) -> return i
  59. Just (Left l) -> Left l
  60. Nothing -> throw ("Unknown interface: " ++ n)
  61. getPrimType n = do
  62. t <- getType n
  63. case t of
  64. PrimType t' -> return t'
  65. _ -> throw ("Expected primitive type but got " ++ show t)
  66. -- converts a decl to an actual type
  67. toType (NewtypeDecl n t) = do
  68. t' <- getPrimType t
  69. return (n, PrimType (Newtype n t'))
  70. toType (EnumDecl (n, s) ts) = do
  71. guard (unique (map fst ts)) /?/ "baz"
  72. return (n, PrimType (EnumType n s ts))
  73. toType (StructDecl n ss) = do
  74. ps <- mapM (getPrimType . snd) ss
  75. return (n, StructType n (zip (map fst ss) ps))
  76. toType _ = error "[unreachable]"
  77. toMethod (n, AttrDecl perm t) = do
  78. t' <- getType t
  79. return (n, AttrMethod perm t')
  80. toMethod (n, StreamDecl rate t) = do
  81. t' <- getType t
  82. return (n, StreamMethod rate t')
  83. toInterface (InterfaceDecl n is ms) = do
  84. ms' <- mapM toMethod ms
  85. is' <- mapM getIface is
  86. return (n, Interface n is' ms')
  87. toInterface _ = error "[unreachable]"
  88. getName (NewtypeDecl n _) = n
  89. getName (EnumDecl (n, _) _) = n
  90. getName (StructDecl n _) = n
  91. getName (InterfaceDecl n _ _) = n
  92. isTypeDecl InterfaceDecl {} = False
  93. isTypeDecl _ = True
  94. unique l = nub l == l
  95. parseDecls :: String -> Either String (TypeEnv, InterfaceEnv)
  96. parseDecls = return . pack >=> decode gidlSpec >=> toEnv
  97. gidlSpec :: SExprSpec HaskLikeAtom Decl
  98. gidlSpec
  99. = withHaskellComments
  100. $ convertSpec tDecl ppDecl
  101. $ asWellFormed haskLikeSpec
  102. -- utility aliases and helpers
  103. type Parse a = WellFormedSExpr HaskLikeAtom -> Either String a
  104. throw :: String -> Either String a
  105. throw = Left
  106. infix 9 /?/
  107. (/?/) :: Either String a -> String -> Either String a
  108. Left msg /?/ ctx = throw (msg ++ "\n in parsing " ++ ctx)
  109. r /?/ _ = r
  110. -- basic parsing of things (these might show up in s-cargot
  111. -- proper eventually?)
  112. tSymbol :: Parse String
  113. tSymbol = asAtom go
  114. where go (HSIdent i) = return (unpack i)
  115. go sx = throw ("Expected identifier; got " ++ show sx)
  116. tType :: Parse String
  117. tType = tSymbol
  118. tInteger :: Parse Integer
  119. tInteger = asAtom go
  120. where go (HSInt n) = return n
  121. go sx = throw ("Expected integer; got " ++ show sx)
  122. -- some parsing of gidl-specific types
  123. tBits :: Parse Bits
  124. tBits = tInteger >=> tWidth
  125. tWidth :: Integer -> Either String Bits
  126. tWidth 8 = return Bits8
  127. tWidth 16 = return Bits16
  128. tWidth 32 = return Bits32
  129. tWidth 64 = return Bits64
  130. tWidth _ = throw "Expected enum bit size to be 8, 16, 32, or 64"
  131. tPermission :: Parse Perm
  132. tPermission = asAtom go
  133. where go token
  134. | token == "read" || token == "r" = return Read
  135. | token == "write" || token == "w" = return Write
  136. | token == "readwrite" || token == "rw" = return ReadWrite
  137. | otherwise = throw ("unknown permission: " ++ show token)
  138. -- newtypes
  139. tNewtypeDecl :: Parse Decl
  140. tNewtypeDecl = asList $ \ls -> do
  141. car (isAtom "def-newtype") ls
  142. name <- cdr (car tSymbol) ls /?/ "newtype name"
  143. typ <- cdr (cdr (car tSymbol)) ls /?/ "newtype type"
  144. return (NewtypeDecl name typ)
  145. -- structs
  146. tStructDecl :: Parse Decl
  147. tStructDecl = asList go
  148. where go ("def-struct":name:body) =
  149. StructDecl <$> (tSymbol name /?/ "structure name")
  150. <*> (mapM tStructRow body /?/ "structure body")
  151. go _ = throw "invalid struct decl"
  152. tStructRow :: Parse (Identifier, Identifier)
  153. tStructRow = fromPair tSymbol tType
  154. -- enums
  155. tEnumDecl :: Parse Decl
  156. tEnumDecl = asList go
  157. where go ("def-enum" : name : body) =
  158. EnumDecl <$> tEnumName name /?/ "enum name"
  159. <*> mapM tEnumBody body /?/ "enum body"
  160. go _ = throw "invalid enum decl"
  161. tEnumName :: Parse (Identifier, Bits)
  162. tEnumName (L [name, size]) = (,) <$> tSymbol name <*> tBits size
  163. tEnumName name = (,) <$> tSymbol name <*> return Bits32
  164. tEnumBody :: Parse (Identifier, Integer)
  165. tEnumBody = fromPair tSymbol tInteger
  166. -- interface declarations
  167. tInterfaceDecl :: Parse Decl
  168. tInterfaceDecl = asList go
  169. where go ("def-interface":name:parents:body) =
  170. InterfaceDecl
  171. <$> tSymbol name /?/ "interface name"
  172. <*> asList (mapM tSymbol) parents /?/ "interface supers"
  173. <*> mapM tInterfaceMethod body /?/ "interface methods"
  174. go _ = throw "invalid interface decl"
  175. tInterfaceMethod :: Parse (Identifier, MethodDecl)
  176. tInterfaceMethod = fromPair tSymbol (asList go)
  177. where go ["attr", p, t] = AttrDecl <$> tPermission p <*> tType t
  178. go ["stream", n, t] = StreamDecl <$> tInteger n <*> tType t
  179. go (x:_) = throw ("unknown interface type: " ++ show x)
  180. go [] = throw "empty interface decl"
  181. -- declarations in general
  182. tDecl :: Parse Decl
  183. tDecl ls@(L ("def-struct" : _)) = tStructDecl ls /?/ "struct"
  184. tDecl ls@(L ("def-newtype" : _)) = tNewtypeDecl ls /?/ "newtype"
  185. tDecl ls@(L ("def-enum" : _)) = tEnumDecl ls /?/ "enum"
  186. tDecl ls@(L ("def-interface" : _)) = tInterfaceDecl ls /?/ "interface"
  187. tDecl (L (A name : _)) =
  188. throw ("unknown declaration type: " ++ show name)
  189. tDecl item = do
  190. throw ("invalid top-level item " ++ show item)
  191. -- For now, no pretty-printing (but it will come soon!)
  192. ppDecl :: Decl -> WellFormedSExpr HaskLikeAtom
  193. ppDecl = const "<unimplemented>"