packages feed

ddc-tools-0.3.2.1: src/ddci-core/DDCI/Core/Rewrite.hs

module DDCI.Core.Rewrite
        ( SetRuleCommand(..)
        , parseFirstWord
	, parseRewrite
	, showRule )
where
import DDC.Base.Pretty
import DDC.Build.Language
import DDC.Core.Lexer
import DDC.Core.Fragment                hiding (Error)
import DDC.Core.Transform.Rewrite.Rule  hiding (Error)
import DDC.Core.Transform.Rewrite.Parser
import DDCI.Core.State
import DDCI.Core.Output
import Data.Char
import qualified DDC.Core.Check         as C
import qualified DDC.Core.Parser        as C
import qualified DDC.Base.Parser        as BP

import DDC.Core.Module
import Data.Map                         (Map)


-- | :set rule command
data SetRuleCommand a n
        = SetAdd    
                { setRuleName   :: String 
                , setRuleRule   :: RewriteRule a n }

        | SetRemove 
                { setRuleName   :: String }

	| SetList
        deriving (Eq, Show)

type Error = String


-- | Return first word and remainder of string
parseFirstWord :: String -> (String,String)
parseFirstWord s = break isSpace $ dropWhile isSpace s


-- | Parse a :set rule command
--   +name rule, name rule:  add rewrite rule
--   -name                   remove rule
parseRewrite 
        :: (Ord n, Show n, Pretty n)
        => Fragment n err 
	-> Map ModuleName (Module (C.AnTEC () n) n)
        -> String 
        -> Either Error (SetRuleCommand (C.AnTEC BP.SourcePos n) n)

parseRewrite fragment modules str
 = case dropWhile isSpace str of
	[]		-> Right SetList
	('+':rest)	-> parseAdd fragment modules rest

	('-':rest)	
         -> let (name,_) = parseFirstWord rest 
            in Right $ SetRemove name

	rest            -> parseAdd fragment modules rest


-- | Parse add rule
parseAdd
        :: (Ord n, Show n, Pretty n)
        => Fragment n err
	-> Map ModuleName (Module (C.AnTEC () n) n)
        -> String 
        -> Either Error (SetRuleCommand (C.AnTEC BP.SourcePos n) n)

parseAdd fragment modules str
 | (name, rest) <- parseFirstWord str
 = case BP.runTokenParser describeTok "<interactive>" 
        (pRule (C.contextOfProfile (fragmentProfile fragment)))
          (fragmentLexExp fragment "interactive" 0 rest) of
                Left err -> Left $ renderIndent $ ppr err
                Right rule ->
                  case checkRewriteRule config kinds' types' rule of
                    Left err    -> Left  $ renderIndent $ ppr err
                    Right rule' -> Right $ SetAdd name rule'
 where
        config   = C.configOfProfile (fragmentProfile fragment)
	kinds	 = profilePrimKinds  (fragmentProfile fragment)
	types	 = profilePrimTypes  (fragmentProfile fragment)

	kinds'	 = modulesExportKinds modules kinds
	types'	 = modulesExportTypes modules types


-- | Display rule
showRule :: (Eq n, Pretty n)
         => State -> Int -> String -> RewriteRule a n -> IO ()

showRule state indentBy name rule
 = do	putStr $ (take indentBy $ repeat '\t') ++ name ++ " "
	outDocLn state
	 $  ppr rule