{-# LANGUAGE QuasiQuotes, RecordWildCards, OverloadedStrings #-} module Language.MessagePack.IDL.CodeGen.Perl ( Config(..), generate, ) where import Data.Char import Data.List import qualified Data.Text as T import qualified Data.Text.Lazy as LT import qualified Data.Text.Lazy.IO as LT import System.FilePath import Text.Shakespeare.Text import Language.MessagePack.IDL.Syntax data Config = Config { configFilePath :: FilePath , configNameSpace :: String } deriving (Show, Eq) generate:: Config -> Spec -> IO () generate Config {..} spec = do let name = takeBaseName configFilePath once = map toUpper name ns = LT.splitOn "::" $ LT.pack configNameSpace -- types mapM_ writeType spec -- clients LT.writeFile (name ++ "_client.pm") [lt| package #{name}_client; use strict; use warnings; use AnyEvent::MPRPC::Client; #{LT.concat $ map genClient spec} |] writeType :: Decl -> IO () writeType MPMessage {..} = let fields = sortBy (\x y -> fldId x `compare` fldId y) msgFields fieldNames = map fldName fields :: [T.Text] packageName = msgName :: T.Text in LT.writeFile (T.unpack packageName ++ ".pm") [lt|package #{LT.pack $ T.unpack packageName}; sub new { return bless { #{LT.concat $ map f fieldNames} }; } 1; |] where f :: T.Text -> LT.Text f name = LT.append (LT.pack $ T.unpack name) $ LT.pack " => \"\"," writeType MPException {..} = let fields = sortBy (\x y -> fldId x `compare` fldId y) excFields fieldNames = map fldName fields :: [T.Text] packageName = excName :: T.Text in LT.writeFile (T.unpack packageName ++ ".pm") [lt|package #{LT.pack $ T.unpack packageName}; sub new { return bless { #{LT.concat $ map f fieldNames} }; } 1; |] where f :: T.Text -> LT.Text f name = LT.append (LT.pack $ T.unpack name) $ LT.pack " => \"\",\n" writeType _ = return () genClient :: Decl -> LT.Text genClient MPService {..} = [lt| sub new { my ($self, $host, $port) = @_; my $client = AnyEvent::MPRPC::Client->new( host => $host, port => $port ); bless { client => $client }, $self; }; sub bar { my ($self, $lang, $xs) = @_; $self->{'client'}->call(bar => [$xs, $lang])->recv; }; 1; |] genClient _ = "" templ :: FilePath -> String -> String -> LT.Text -> LT.Text templ filepath once name content = [lt| // This file is auto-generated from #{filepath} // *** DO NOT EDIT *** #{content} |]