packages feed

morloc-0.33.0: library/Morloc/CodeGenerator/Grammars/Macro.hs

{-|
Module      : Morloc.CodeGenerator.Grammars.Macro
Description : Expand parameters in concrete types
Copyright   : (c) Zebulun Arendsee, 2020
License     : GPL-3
Maintainer  : zbwrnz@gmail.com
Stability   : experimental
-}

module Morloc.CodeGenerator.Grammars.Macro
(   expandMacro
  , expandType
) where

import Morloc.CodeGenerator.Namespace
import Morloc.Data.Doc
import qualified Morloc.Data.Text as MT
import qualified Control.Monad.State as CMS
import Text.Megaparsec
import Text.Megaparsec.Char
import Data.Void (Void)
import qualified Text.Megaparsec.Char.Lexer as L

type Parser a = CMS.StateT ParserState (Parsec Void MT.Text) a

data ParserState = ParserState {
    stateParameters :: [MT.Text]
}

expandType
  :: (MDoc -> [MDoc] -> MDoc) -- ^ make function type
  -> (PVar -> [(PVar, MDoc)] -> MDoc) -- ^ make record type
  -> TypeP
  -> MDoc
expandType mkfun mkrec t0 = f t0 where
  f :: TypeP -> MDoc
  f (VarP (PV _ _ v)) = pretty v
  f t@(FunP t1 _) = mkfun (f t1) (map f (decomposeFull t))
  f (ArrP (PV _ _ v) ts) = pretty $ expandMacro v (map (render . f) ts)
  f (NamP _ v _ entries) = mkrec v [(k, f t) | (k, t) <- entries]
  f (UnkP _) = error "Cannot build unsolved type"

expandMacro :: MT.Text -> [MT.Text] -> MT.Text
expandMacro t [] = t
expandMacro t ps =
  case runParser
         (CMS.runStateT (pBase <* eof) (ParserState ps))
         "typemacro"
         t of
    Left err -> error (show err)
    Right (es, _) -> es

many1 :: Parser a -> Parser [a]
many1 p = do
  x <- p
  xs <- many p
  return (x : xs)

pBase :: Parser MT.Text
pBase = MT.concat <$> many1 (pChar <|> pMacro)

pChar :: Parser MT.Text
pChar = MT.pack <$> many1 (noneOf ['$'])

pMacro :: Parser MT.Text
pMacro = do
  xs <- CMS.gets stateParameters
  _ <- string "$"
  n <- L.decimal
  -- index is 1-based
  let i = n - 1
  return (xs !! i)