Parse.hs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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. , encodeOne
  12. , asWellFormed
  13. )
  14. import Data.SCargot.HaskLike (HaskLikeAtom(..), haskLikeSpec)
  15. import Data.SCargot.Repr.WellFormed
  16. import Data.Text (unpack, pack)
  17. import Gidl.Types
  18. import Gidl.Interface
  19. -- We parse into this abstract structure before converting it to the
  20. -- structures Gidl uses elsewhere. That way, we can separate our
  21. -- parsing and our checking.
  22. data Decl
  23. = NewtypeDecl Identifier Identifier
  24. | EnumDecl (Identifier, Bits) [(Identifier, Integer)]
  25. | StructDecl Identifier [(Identifier, Identifier)]
  26. | InterfaceDecl Identifier [Identifier] [(Identifier, MethodDecl)]
  27. deriving (Eq, Show)
  28. data MethodDecl
  29. = AttrDecl Perm Identifier
  30. | StreamDecl Integer Identifier
  31. deriving (Eq, Show)
  32. check :: Bool -> String -> Either String ()
  33. check True _ = return ()
  34. check _ msg = throw msg
  35. -- Here's a function to convert those decls.
  36. toEnv :: [Decl] -> Either String (TypeEnv, InterfaceEnv)
  37. toEnv decls = do
  38. check (unique typeNames) "duplicate type names"
  39. check (unique interfaceNames) "duplicate interface names"
  40. typs <- mapM getTypePair typeNames
  41. ifcs <- mapM getIfacePair interfaceNames
  42. return (TypeEnv typs, InterfaceEnv ifcs)
  43. where (typDs, ifcDs) = partition isTypeDecl decls
  44. builtins = let TypeEnv bs = baseTypeEnv in bs
  45. typeNames = map fst builtins ++ map getName typDs
  46. interfaceNames = map getName ifcDs
  47. typMap = [(getName d, toType d) | d <- typDs] ++
  48. [(n, return (n, t)) | (n, t) <- builtins ]
  49. ifcMap = [(getName i, toInterface i) | i <- ifcDs]
  50. -- this is gross because I'm trying to make sure declarations
  51. -- can happen in any order. XXX: prevent recursion!
  52. getType n = snd `fmap` getTypePair n
  53. getTypePair n = case lookup n typMap of
  54. Just (Right t) -> return t
  55. Just (Left l) -> Left l
  56. Nothing -> throw ("Unknown primitive type: " ++ n)
  57. getIface n = snd `fmap` getIfacePair n
  58. getIfacePair n = case lookup n ifcMap of
  59. Just (Right i) -> return i
  60. Just (Left l) -> Left l
  61. Nothing -> throw ("Unknown interface: " ++ n)
  62. getPrimType n = do
  63. t <- getType n
  64. case t of
  65. PrimType t' -> return t'
  66. _ -> throw ("Expected primitive type but got " ++ show t)
  67. -- converts a decl to an actual type
  68. toType (NewtypeDecl n t) = do
  69. t' <- getPrimType t
  70. return (n, PrimType (Newtype n t'))
  71. toType (EnumDecl (n, s) ts) = do
  72. guard (unique (map fst ts)) /?/ "baz"
  73. return (n, PrimType (EnumType n s ts))
  74. toType (StructDecl n ss) = do
  75. ps <- mapM (getPrimType . snd) ss
  76. return (n, StructType n (zip (map fst ss) ps))
  77. toType _ = error "[unreachable]"
  78. toMethod (n, AttrDecl perm t) = do
  79. t' <- getType t
  80. return (n, AttrMethod perm t')
  81. toMethod (n, StreamDecl rate t) = do
  82. t' <- getType t
  83. return (n, StreamMethod rate t')
  84. toInterface (InterfaceDecl n is ms) = do
  85. ms' <- mapM toMethod ms
  86. is' <- mapM getIface is
  87. return (n, Interface n is' ms')
  88. toInterface _ = error "[unreachable]"
  89. getName (NewtypeDecl n _) = n
  90. getName (EnumDecl (n, _) _) = n
  91. getName (StructDecl n _) = n
  92. getName (InterfaceDecl n _ _) = n
  93. isTypeDecl InterfaceDecl {} = False
  94. isTypeDecl _ = True
  95. unique l = nub l == l
  96. parseDecls :: String -> Either String (TypeEnv, InterfaceEnv)
  97. parseDecls = return . pack >=> decode gidlSpec >=> toEnv
  98. gidlSpec :: SExprSpec HaskLikeAtom Decl
  99. gidlSpec
  100. = withHaskellComments
  101. $ convertSpec tDecl ppDecl
  102. $ asWellFormed haskLikeSpec
  103. -- utility aliases and helpers
  104. type Parse a = WellFormedSExpr HaskLikeAtom -> Either String a
  105. throw :: String -> Either String a
  106. throw = Left
  107. infix 9 /?/
  108. (/?/) :: Either String a -> String -> Either String a
  109. Left msg /?/ ctx = throw (msg ++ "\n in parsing " ++ ctx)
  110. r /?/ _ = r
  111. infix 9 `asErr`
  112. asErr :: Either String a -> String -> Either String a
  113. Left _ `asErr` msg = throw msg
  114. r `asErr` _ = r
  115. seShow :: WellFormedSExpr HaskLikeAtom -> String
  116. seShow sx = "`" ++ unpack (encodeOne (asWellFormed haskLikeSpec) sx) ++ "`"
  117. atShow :: WellFormedSExpr HaskLikeAtom -> String
  118. atShow e = go e ++ " " ++ seShow e
  119. where
  120. go (A (HSInt _)) = "int"
  121. go (A (HSString _)) = "string"
  122. go (A (HSIdent _)) = "identifier"
  123. go (A (HSFloat _)) = "float"
  124. go (L _) = "list"
  125. go _ = "??"
  126. -- basic parsing of things (these might show up in s-cargot
  127. -- proper eventually?)
  128. tSymbol :: Parse String
  129. tSymbol e = asAtom go e `asErr`
  130. ("Expected identifier; got " ++ atShow e)
  131. where go (HSIdent i) = return (unpack i)
  132. go sx = throw ("Expected identifier; got " ++ atShow (A sx))
  133. tType :: Parse String
  134. tType = tSymbol
  135. tInteger :: Parse Integer
  136. tInteger e = asAtom go e `asErr` ("Expected integer; got " ++ atShow e)
  137. where go (HSInt n) = return n
  138. go sx = throw ("Expected integer; got " ++ atShow (A sx))
  139. -- some parsing of gidl-specific types
  140. tBits :: Parse Bits
  141. tBits = tInteger >=> tWidth
  142. tWidth :: Integer -> Either String Bits
  143. tWidth 8 = return Bits8
  144. tWidth 16 = return Bits16
  145. tWidth 32 = return Bits32
  146. tWidth 64 = return Bits64
  147. tWidth _ = throw "Expected enum bit size to be 8, 16, 32, or 64"
  148. tPermission :: Parse Perm
  149. tPermission e = asAtom go e `asErr` ("unknown permission: " ++ seShow e)
  150. where go token
  151. | token == "read" || token == "r" = return Read
  152. | token == "write" || token == "w" = return Write
  153. | token == "readwrite" || token == "rw" = return ReadWrite
  154. | otherwise = throw "error"
  155. -- newtypes
  156. tNewtypeDecl :: Parse Decl
  157. tNewtypeDecl = asList go
  158. where go ["def-newtype",name,typ] =
  159. NewtypeDecl <$> tSymbol name /?/ "newtype name"
  160. <*> tSymbol typ /?/ "newtype type"
  161. go _ = throw "wrong number of elements"
  162. -- structs
  163. tStructDecl :: Parse Decl
  164. tStructDecl = asList go
  165. where go ("def-struct":name:body) =
  166. StructDecl
  167. <$> (tSymbol name /?/ "struct name")
  168. <*> (mapM tStructRow body /?/
  169. ("struct body " ++ seShow (L (A "..." : body))))
  170. go _ = throw "invalid struct decl"
  171. tStructRow :: Parse (Identifier, Identifier)
  172. tStructRow sx =
  173. fromPair tSymbol tType sx /?/ ("struct row " ++ seShow sx)
  174. -- enums
  175. tEnumDecl :: Parse Decl
  176. tEnumDecl = asList go
  177. where go ("def-enum" : name : body) =
  178. EnumDecl <$> tEnumName name /?/ "enum name"
  179. <*> mapM tEnumBody body
  180. go _ = throw "invalid enum decl"
  181. tEnumName :: Parse (Identifier, Bits)
  182. tEnumName (L [name, size]) = (,) <$> tSymbol name <*> tBits size
  183. tEnumName name = (,) <$> tSymbol name <*> return Bits32
  184. tEnumBody :: Parse (Identifier, Integer)
  185. tEnumBody e =
  186. fromPair tSymbol tInteger e /?/ ("enum constructor " ++ seShow e)
  187. -- interface declarations
  188. tInterfaceDecl :: Parse Decl
  189. tInterfaceDecl = asList go
  190. where go ("def-interface":name:parents:body) =
  191. InterfaceDecl
  192. <$> tSymbol name /?/ "interface name"
  193. <*> asList (mapM tSymbol) parents
  194. /?/ ("interface parents " ++ seShow parents)
  195. <*> mapM tInterfaceMethod body
  196. go _ = throw "invalid interface decl"
  197. tInterfaceMethod :: Parse (Identifier, MethodDecl)
  198. tInterfaceMethod e =
  199. fromPair tSymbol (asList go) e /?/ ("interface method " ++ seShow e)
  200. where go ["attr", p, t] = AttrDecl <$> tPermission p <*> tType t
  201. go ["stream", n, t] = StreamDecl <$> tInteger n <*> tType t
  202. go (x:_) = throw ("unknown interface type: " ++ seShow x)
  203. go [] = throw "empty interface decl"
  204. -- declarations in general
  205. tDecl :: Parse Decl
  206. tDecl ls@(L ("def-struct" : _)) =
  207. tStructDecl ls /?/ ("struct " ++ showHead ls)
  208. tDecl ls@(L ("def-newtype" : _)) =
  209. tNewtypeDecl ls /?/ ("newtype " ++ showHead ls)
  210. tDecl ls@(L ("def-enum" : _)) =
  211. tEnumDecl ls /?/ ("enum " ++ showHead ls)
  212. tDecl ls@(L ("def-interface" : _)) =
  213. tInterfaceDecl ls /?/ ("interface " ++ showHead ls)
  214. tDecl (L (A name : _)) =
  215. throw ("unknown declaration type: " ++ seShow (A name))
  216. tDecl item = do
  217. throw ("invalid top-level item " ++ seShow item)
  218. showHead :: WellFormedSExpr HaskLikeAtom -> String
  219. showHead (L (a:b:_)) = seShow (L [a,b,"..."])
  220. showHead sx = seShow sx
  221. -- For now, no pretty-printing (but it will come soon!)
  222. ident :: Identifier -> WellFormedSExpr HaskLikeAtom
  223. ident = A . HSIdent . pack
  224. int :: Integer -> WellFormedSExpr HaskLikeAtom
  225. int = A . HSInt
  226. ppBits :: Bits -> WellFormedSExpr HaskLikeAtom
  227. ppBits Bits8 = A (HSInt 8)
  228. ppBits Bits16 = A (HSInt 16)
  229. ppBits Bits32 = A (HSInt 32)
  230. ppBits Bits64 = A (HSInt 64)
  231. ppDecl :: Decl -> WellFormedSExpr HaskLikeAtom
  232. ppDecl (NewtypeDecl name typ) =
  233. L ["def-newtype", ident name, ident typ ]
  234. ppDecl (EnumDecl (name, Bits32) fields) =
  235. L ( "def-enum"
  236. : ident name
  237. : [ L [ ident a, int b ]
  238. | (a, b) <- fields
  239. ]
  240. )
  241. ppDecl (EnumDecl (name, bits) fields) =
  242. L ( "def-enum"
  243. : L [ ident name, ppBits bits ]
  244. : [ L [ ident a, int b ]
  245. | (a, b) <- fields
  246. ]
  247. )
  248. ppDecl (StructDecl name fields) =
  249. L ( "def-struct"
  250. : ident name
  251. : [ L [ident a, ident b ]
  252. | (a, b) <- fields
  253. ]
  254. )
  255. ppDecl (InterfaceDecl name parents methods) =
  256. L ( "def-interface"
  257. : ident name
  258. : L (map ident parents)
  259. : map go methods
  260. ) where go (n, m) = L [ ident n, ppMethod m ]
  261. ppMethod :: MethodDecl -> WellFormedSExpr HaskLikeAtom
  262. ppMethod (StreamDecl rate name) = L [ "stream", int rate, ident name ]
  263. ppMethod (AttrDecl perm name) = L [ "attr", ppPerm perm, ident name ]
  264. where ppPerm Read = "r"
  265. ppPerm Write = "w"
  266. ppPerm ReadWrite = "rw"