Server.hs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. module Gidl.Backend.Tower.Server where
  2. import Data.Monoid
  3. import Data.List (intercalate, nub)
  4. import Gidl.Interface
  5. import Gidl.Schema
  6. import Gidl.Backend.Ivory.Types
  7. import Gidl.Backend.Ivory.Schema (ifModuleName)
  8. import Ivory.Artifact
  9. import Text.PrettyPrint.Mainland
  10. umbrellaModule :: [String] -> Interface -> Artifact
  11. umbrellaModule modulepath i =
  12. artifactPath (intercalate "/" modulepath) $
  13. artifactText (ifModuleName i ++ ".hs") $
  14. prettyLazyText 1000 $
  15. stack
  16. [ text "module" <+> mname
  17. , indent 2 $ encloseStack lparen (rparen <+> text "where") comma
  18. [ text "module" <+> im "Producer"
  19. , text "module" <+> im "Consumer"
  20. , text "module" <+> im "Server"
  21. ]
  22. , text "import" <+> im "Producer"
  23. , text "import" <+> im "Consumer"
  24. , text "import" <+> im "Server"
  25. ]
  26. where
  27. modAt path = mconcat (punctuate dot (map text path))
  28. mname = modAt (modulepath ++ [ifModuleName i])
  29. im m = modAt (modulepath ++ [ifModuleName i, m])
  30. serverModule :: [String] -> Interface -> Artifact
  31. serverModule modulepath i =
  32. artifactPath (intercalate "/" (modulepath ++ [ifModuleName i])) $
  33. artifactText "Server.hs" $
  34. prettyLazyText 1000 $
  35. stack
  36. [ text "{-# LANGUAGE DataKinds #-}"
  37. , text "{-# LANGUAGE RankNTypes #-}"
  38. , text "{-# LANGUAGE ScopedTypeVariables #-}"
  39. , text "{-# LANGUAGE KindSignatures #-}"
  40. , text "{-# LANGUAGE RecordWildCards #-}"
  41. , text "{-# OPTIONS_GHC -fno-warn-unused-imports #-}"
  42. , text "{-# OPTIONS_GHC -fno-warn-unused-matches #-}"
  43. , empty
  44. , text "module"
  45. <+> im "Server"
  46. <+> text "where"
  47. , empty
  48. , stack imports
  49. , empty
  50. , attrsDataType i
  51. , empty
  52. , attrsTowerConstructor i
  53. , empty
  54. , attrsInitializer i
  55. , empty
  56. , streamsDataType i
  57. , empty
  58. , streamsTowerConstructor i
  59. , empty
  60. , interfaceServer i
  61. ]
  62. where
  63. rootpath = reverse . drop 2 . reverse
  64. modAt path = mconcat (punctuate dot (map text path))
  65. im mname = modAt (modulepath ++ [ifModuleName i, mname])
  66. tm mname = modAt (rootpath modulepath ++ ["Ivory","Types", mname])
  67. imports =
  68. [ text "import" <+> modAt (rootpath modulepath ++ ["Tower", "Attr"])
  69. , text "import" <+> im "Producer"
  70. , text "import" <+> im "Consumer"
  71. , text "import Ivory.Language"
  72. , text "import Ivory.Tower"
  73. ] ++ typeimports
  74. typeimports = map (importDecl tm)
  75. $ nub
  76. $ map importType
  77. $ interfaceTypes i
  78. attrsDataType :: Interface -> Doc
  79. attrsDataType i = text "data" <+> constructor <+> text "(p :: Area * -> *) ="
  80. </> indent 2 constructor
  81. </> indent 4 body
  82. where
  83. constructor = text (ifModuleName i) <> text "Attrs"
  84. body = encloseStack lbrace rbrace comma
  85. [ text n <+> colon <> colon <+> text "p"
  86. <+> typeIvoryArea t
  87. | (aname, AttrMethod _ t) <- interfaceMethods i
  88. , let n = userEnumValueName aname
  89. ]
  90. attrsTowerConstructor :: Interface -> Doc
  91. attrsTowerConstructor i = typesig </> decl </> indent 2 body </> indent 2 ret
  92. where
  93. constructor = text (ifModuleName i) <> text "Attrs"
  94. typesig = text "tower" <> constructor <+> colon <> colon
  95. <+> constructor <+> text "Init"
  96. <+> text "->"
  97. <+> text "Tower e" <+> parens (constructor <+> text "Attr")
  98. decl = text "tower" <> constructor <+> text "ivals = do"
  99. body = stack
  100. [ text n <> text "_p <- towerAttr"
  101. <+> dquotes (text (aname ++ "_attr"))
  102. <+> parens (text n <+> text "ivals")
  103. | (aname, AttrMethod _ _) <- interfaceMethods i
  104. , let n = userEnumValueName aname
  105. ]
  106. ret = text "return" <+> constructor <+> encloseStack lbrace rbrace comma
  107. [ text n <+> equals <+> text n <> text "_p"
  108. | (aname, AttrMethod _ _) <- interfaceMethods i
  109. , let n = userEnumValueName aname
  110. ]
  111. attrsInitializer :: Interface -> Doc
  112. attrsInitializer i = typesig </> decl </> indent 2 body
  113. where
  114. constructor = text (ifModuleName i) <> text "Attrs"
  115. typesig = text "init" <> constructor <+> colon <> colon
  116. <+> constructor <+> text "Init"
  117. decl = text "init" <> constructor <+> equals <+> constructor
  118. body = encloseStack lbrace rbrace comma
  119. [ text n <+> equals <+> text "izero"
  120. | (aname, AttrMethod _ _) <- interfaceMethods i
  121. , let n = userEnumValueName aname
  122. ]
  123. streamsDataType :: Interface -> Doc
  124. streamsDataType i = text "data" <+> constructor <+> text "(p :: Area * -> *) ="
  125. </> indent 2 constructor
  126. </> indent 4 body
  127. where
  128. constructor = text (ifModuleName i) <> text "Streams"
  129. body = encloseStack lbrace rbrace comma
  130. [ text n <+> colon <> colon <+> text "p"
  131. <+> parens (text (typeIvoryType t))
  132. | (aname, StreamMethod _ t) <- interfaceMethods i
  133. , let n = userEnumValueName aname
  134. ]
  135. streamsTowerConstructor :: Interface -> Doc
  136. streamsTowerConstructor i = typesig </> decl </> indent 2 body </> indent 2 ret
  137. where
  138. constructor = text (ifModuleName i) <> text "Streams"
  139. typesig = text "tower" <> constructor <+> colon <> colon
  140. <+> text "Tower e"
  141. <+> parens (constructor <+> text "ChanInput" <> comma
  142. <+> constructor <+> text "ChanOutput")
  143. decl = text "tower" <> constructor <+> text "= do"
  144. body = stack
  145. [ text n <> text "_c <- channel"
  146. | (aname, StreamMethod _ _) <- interfaceMethods i
  147. , let n = userEnumValueName aname
  148. ]
  149. ret = text "return" <+> encloseStack lparen rparen comma
  150. [ mkstream "fst", mkstream "snd"]
  151. mkstream acc = constructor </> indent 2 (encloseStack lbrace rbrace comma
  152. [ text n <+> equals <+> text acc <+> text n <> text "_c"
  153. | (aname, StreamMethod _ _) <- interfaceMethods i
  154. , let n = userEnumValueName aname
  155. ])
  156. interfaceServer :: Interface -> Doc
  157. interfaceServer i =
  158. stack [typedef, decl, indent 2 body, indent 2 ret]
  159. where
  160. constructor postfix = text (ifModuleName i) <> text postfix
  161. fname = text "tower" <> constructor "Server"
  162. typedef = fname <+> align (stack
  163. [ guardEmptySchema (consumerSchema i)
  164. (text "::" <+> constructor "Consumer")
  165. (text ":: -- no consumer schema")
  166. , guardEmptySchema (consumerSchema i) (text "->") (text " ")
  167. <+> constructor "Attrs Attr"
  168. , text "->" <+> constructor "Streams ChanOutput"
  169. , text "->" <+> text "Tower e"
  170. <+> guardEmptySchema (producerSchema i)
  171. (constructor "Producer")
  172. (text "()")
  173. ])
  174. decl = fname <+> guardEmptySchema (consumerSchema i)
  175. (constructor "Consumer{..}")
  176. empty
  177. <+> constructor "Attrs{..}"
  178. <+> constructor "Streams{..}"
  179. <+> equals <+> text "do"
  180. body = stack [ methodBody (text (userEnumValueName n)) m
  181. | (n,m) <- interfaceMethods i ]
  182. ret = text "return" <+> guardEmptySchema (producerSchema i)
  183. (constructor "Producer{..}")
  184. (text "()")
  185. methodBody n (StreamMethod _ _) =
  186. text "let" <+> n <> text "Producer" <+> equals <+> n
  187. methodBody n (AttrMethod Read t) =
  188. n <> text "GetRespProducer" <+> text "<- readableAttrServer"
  189. <+> seqnumGetter t "val" <+> seqnumGetter t "seqnum"
  190. <+> n <+> n <> text "GetReqConsumer"
  191. methodBody n (AttrMethod Write t) =
  192. n <> text "SetRespProducer" <+> text "<- writableAttrServer"
  193. <+> seqnumGetter t "val" <+> seqnumGetter t "seqnum"
  194. <+> n <+> n <> text "SetReqConsumer"
  195. methodBody n (AttrMethod ReadWrite t) =
  196. parens (n <> text "GetRespProducer" <> comma
  197. <+> n <> text "SetRespProducer")
  198. <+> text "<- readwritableAttrServer"
  199. <+> seqnumGetter t "val" <+> seqnumGetter t "seqnum"
  200. <+> n <+> n <> text "GetReqConsumer" <+> n <> text "SetReqConsumer"
  201. seqnumGetter t s = importPrefix (importType (sequenceNumStruct t)) <> dot <> text s
  202. guardEmptySchema :: Schema -> Doc -> Doc -> Doc
  203. guardEmptySchema (Schema _ []) _ d = d
  204. guardEmptySchema (Schema _ _) d _ = d