Parse.hs 12 KB

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