123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- module Gidl.Backend.Tower.Interface where
- import Data.Monoid
- import Data.List (intercalate, nub)
- import Gidl.Types
- import Gidl.Interface
- import Gidl.Schema
- import Gidl.Backend.Ivory.Types
- import Gidl.Backend.Ivory.Interface (ifModuleName, parserName, senderName)
- import Ivory.Artifact
- import Text.PrettyPrint.Mainland
- interfaceModule :: [String] -> Interface -> Schema -> Artifact
- interfaceModule modulepath ir schema =
- artifactPath (intercalate "/" (modulepath ++ [ifModuleName ir])) $
- artifactText (schemaName ++ ".hs") $
- prettyLazyText 80 $
- stack
- [ text "{-# LANGUAGE DataKinds #-}"
- , text "{-# LANGUAGE RankNTypes #-}"
- , text "{-# LANGUAGE ScopedTypeVariables #-}"
- , text "{-# OPTIONS_GHC -fno-warn-unused-imports #-}"
- , empty
- , text "module"
- <+> im (ifModuleName ir) <> dot <> text schemaName
- <+> text "where"
- , empty
- , stack $ typeimports ++ extraimports
- , empty
- , schemaDoc (ifModuleName ir) schema
- ]
- where
- (Schema schemaName _) = schema
- rootpath = reverse . drop 3 . reverse
- modAt path = mconcat (punctuate dot (map text path))
- im mname = modAt (modulepath ++ [mname])
- tm mname = modAt (rootpath modulepath ++ ["Ivory","Types", mname])
- ivoryIFMod = modAt (rootpath modulepath
- ++ ["Ivory","Interface", ifModuleName ir, schemaName])
- typeimports = map (importDecl tm)
- $ nub
- $ map importType
- $ interfaceTypes ir
- extraimports = [ text "import qualified" <+> ivoryIFMod <+> text "as I"
- , text "import Ivory.Language"
- , text "import Ivory.Stdlib"
- , text "import Ivory.Tower"
- , text "import Ivory.Serialize"
- ]
- schemaDoc :: String -> Schema -> Doc
- schemaDoc interfaceName (Schema schemaName []) =
- text "-- Cannot define" <+> text schemaName <+> text "schema for"
- <+> text interfaceName <+> text "interface: schema is empty"
- schemaDoc interfaceName (Schema schemaName schema) = stack
- [ text "-- Define" <+> text schemaName <+> text "schema for"
- <+> text interfaceName <+> text "interface"
- , empty
- , text "data" <+> constructor <+> text "c" <+> equals <+> constructor
- , indent 2 $ encloseStack lbrace rbrace comma
- [ case t of
- PrimType VoidType -> accessorName n <+> colon <> colon
- <+> text "c (Stored IBool)"
- _ -> accessorName n <+> colon <> colon
- <+> text "c"
- <+> parens (text (typeIvoryType t))
- | (_, (Message n t)) <- schema
- ]
- , empty
- , text (inputFuncName typeName) <+> align
- (stack [ text ":: (ANat n)"
- , text "=> ChanOutput (Array n (Stored Uint8))"
- , text "-> Tower e" <+> parens (constructor <+> text "ChanOutput")
- ])
- , text (inputFuncName typeName) <+> text "frame_ch" <+> equals <+> text "do"
- , indent 2 $ stack
- [ stack [ chanName n <+> text "<- channel"
- | (_, Message n _) <- schema ]
- , empty
- , text "monitor" <+> dquotes (text (outputFuncName typeName))
- <+> text "$ do"
- , indent 2 $ stack
- [ text "handler frame_ch \"parse_frame\" $ do"
- , indent 2 $ stack
- [ stack [ emitterName n <+> text "<- emitter"
- <+> parens (text "fst" <+> chanName n)
- <+> text "1"
- | (_, Message n _) <- schema
- ]
- , text "callback $ \\f -> do"
- , indent 2 $ stack
- [ text "offs <- local izero"
- , text "_ <- I." <> text (parserName typeName)
- <+> text "f offs $ I." <> constructor
- , indent 2 $ encloseStack lbrace rbrace comma
- [ case t of
- PrimType VoidType ->
- text "I." <> accessorName n <+> equals
- <+> text "emitV" <+> emitterName n
- <+> text "true >> return true"
- _ -> text "I." <> accessorName n <+> equals
- <+> text "\\v -> emit" <+> emitterName n
- <+> text "v >> return true"
- | (_, Message n t) <- schema
- ]
- , text "return ()"
- ]
- ]
- ]
- , empty
- , text "return" <+> constructor <+> encloseStack lbrace rbrace comma
- [ accessorName n <+> equals
- <+> parens (text "snd" <+> chanName n)
- | (_, Message n _) <- schema
- ]
- ]
- , empty
- , text (outputFuncName typeName) <> align
- (stack [ text ":: (ANat n)"
- , text "=>" <+> constructor <+> text "ChanOutput"
- , text "-> Tower e (ChanOutput (Array n (Stored Uint8)))"
- ])
- , text (outputFuncName typeName) <+> text "a" <+> equals <+> text "do"
- , indent 2 $ stack
- [ text "frame_ch <- channel"
- , text "monitor" <+> dquotes (text (outputFuncName typeName))
- <+> text "$ do"
- , indent 2 $ stack
- [ text "handler" <+> parens (accessorName n <+> text "a")
- <+> dquotes (accessorName n) <+> text "$ do"
- </> indent 2 (parseEmitBody n t)
- </> empty
- | (_, Message n t) <- schema
- ]
- , text "return (snd frame_ch)"
- ]
- ]
- where
- constructor = text typeName
- accessorName n = text (userEnumValueName n ++ schemaName)
- typeName = interfaceName ++ schemaName
- inputFuncName tn = userEnumValueName tn ++ "Input"
- outputFuncName tn = userEnumValueName tn ++ "Output"
- chanName s = text "ch_" <> text s
- emitterName s = text "emitter_" <> text s
- parseEmitBody n (PrimType VoidType) = stack
- [ text "e <- emitter (fst frame_ch) 1"
- , text "callback $ \\_ -> do"
- , indent 2 $ stack
- [ text "f <- local izero"
- , text "o <- local izero"
- , text "ok <-" <+> text "I." <> accessorName n
- <+> parens (text "I." <> text (senderName typeName)
- <+> text "f o")
- , text "ifte_ ok (emit e (constRef f)) (return ())"
- ]
- ]
- parseEmitBody n _ = stack
- [ text "e <- emitter (fst frame_ch) 1"
- , text "callback $ \\w -> do"
- , indent 2 $ stack
- [ text "f <- local izero"
- , text "o <- local izero"
- , text "ok <-" <+> text "I." <> accessorName n
- <+> parens (text "I." <> text (senderName typeName)
- <+> text "f o")
- <+> text "w"
- , text "ifte_ ok (emit e (constRef f)) (return ())"
- ]
- ]
|