Added the pshowCode function that uses the ShowOccam and ShowRain classes to print out applicable parts of an AST

This commit is contained in:
Neil Brown 2007-09-17 10:38:30 +00:00
parent 3e342a621c
commit 1172bfd2a0
2 changed files with 48 additions and 22 deletions

View File

@ -20,16 +20,19 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
-- This ought to use a class (like show does), so that it can be extended
-- properly without me needing to have Tock-specific cases in here -- see the
-- appropriate SYB paper.
module PrettyShow (pshow) where
module PrettyShow (pshow, pshowCode) where
import Control.Monad.State
import Data.Generics
import qualified Data.Map as Map
import qualified Data.Set as Set
import Text.PrettyPrint.HughesPJ
import qualified AST as A
import CompState
import Metadata
import Pattern
import ShowCode
-- This is ugly -- but it looks like you can't easily define a generic function
-- even for a single tuple type, since it has to parameterise over multiple Data
@ -42,8 +45,8 @@ isTupleCtr ('(':cs) = checkRest cs
checkRest _ = False
isTupleCtr _ = False
doGeneral :: Data a => a -> Doc
doGeneral t =
doGeneral :: Data a => GenericQ Doc -> a -> Doc
doGeneral anyFunc t =
if isTupleCtr cn then
parens $ sep $ punctuate (text ",") l
else case l of
@ -52,10 +55,10 @@ doGeneral t =
where
cn = showConstr (toConstr t)
con = text $ cn
l = gmapQ doAny t
l = gmapQ anyFunc t
doList :: Data a => [a] -> Doc
doList t = brackets $ sep $ punctuate (text ",") (map doAny t)
doList :: Data a => GenericQ Doc -> [a] -> Doc
doList anyFunc t = brackets $ sep $ punctuate (text ",") (map anyFunc t)
doString :: String -> Doc
doString s = text $ show s
@ -63,12 +66,12 @@ doString s = text $ show s
doMeta :: Meta -> Doc
doMeta m = text $ show m
doMap :: (Data a, Data b) => Map.Map a b -> Doc
doMap map = braces $ sep $ punctuate (text ",") [doAny k <+> text ":" <+> doAny v
| (k, v) <- Map.toAscList map]
doMap :: (Data a, Data b) => GenericQ Doc -> Map.Map a b -> Doc
doMap anyFunc map = braces $ sep $ punctuate (text ",") [anyFunc k <+> text ":" <+> anyFunc v
| (k, v) <- Map.toAscList map]
doSet :: Data a => Set.Set a -> Doc
doSet set = brackets $ sep $ punctuate (text ",") (map doAny $ Set.toList set)
doSet :: Data a => GenericQ Doc -> Set.Set a -> Doc
doSet anyFunc set = brackets $ sep $ punctuate (text ",") (map anyFunc $ Set.toList set)
foldPatternList :: Pattern -> [Pattern]
foldPatternList (Match con patList)
@ -113,25 +116,39 @@ doPattern p@(Match c ps) =
--It's a string:
then doString (showStringPattern folded)
--It's some other kind of list:
else doList folded
else doList (mkQ empty doPattern) folded
--It's neither a list nor a tuple:
else parens $ (text (showConstr c)) $+$ (sep items)
where
items = map doPattern ps
folded = foldPatternList p
doAny :: Data a => a -> Doc
doAny = doGeneral `ext1Q` doList `extQ` doString `extQ` doMeta `extQ` doPattern
`extQ` (doMap :: Map.Map String String -> Doc)
`extQ` (doMap :: Map.Map String A.NameDef -> Doc)
`extQ` (doMap :: Map.Map String [A.Type] -> Doc)
`extQ` (doMap :: Map.Map String [A.Actual] -> Doc)
`extQ` (doSet :: Set.Set String -> Doc)
`extQ` (doSet :: Set.Set A.Name -> Doc)
doAny :: (forall a. Typeable a => (a -> Doc) -> (a -> Doc)) -> GenericQ Doc
doAny extFunc = extFunc (
(doGeneral anyFunc) `ext1Q` (doList anyFunc) `extQ` doString `extQ` doMeta `extQ` doPattern
`extQ` (doMap anyFunc :: Map.Map String String -> Doc)
`extQ` (doMap anyFunc :: Map.Map String A.NameDef -> Doc)
`extQ` (doMap anyFunc :: Map.Map String [A.Type] -> Doc)
`extQ` (doMap anyFunc :: Map.Map String [A.Actual] -> Doc)
`extQ` (doSet anyFunc :: Set.Set String -> Doc)
`extQ` (doSet anyFunc :: Set.Set A.Name -> Doc)
)
where
anyFunc :: GenericQ Doc
anyFunc = doAny extFunc
-- | Convert an arbitrary data structure to a string in a reasonably pretty way.
-- This is currently rather slow.
pshow :: Data a => a -> String
pshow x = render $ doAny x
pshow x = render $ doAny id x
pshowCode :: (Data a, CSM m) => a -> m String
pshowCode c = do st <- get
case csFrontend st of
FrontendOccam -> return $ render $ (extOccam $ doAny extOccam) c
FrontendRain -> return $ render $ (extRain $ doAny extRain) c
where
extOccam :: forall a. Typeable a => (a -> Doc) -> (a -> Doc)
extOccam f = extCode f showOccam
extRain :: forall a. Typeable a => (a -> Doc) -> (a -> Doc)
extRain f = extCode f showRain

View File

@ -22,6 +22,9 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
module ShowCode where
import Control.Monad.State
import Data.Generics
import Data.List
import Text.PrettyPrint.HughesPJ
import Text.Regex
import qualified AST as A
import CompState
@ -171,3 +174,9 @@ instance ShowRain A.Variable where
showRain (A.DirectedVariable _ A.DirInput v) = "?" ++ showRain v
showRain (A.DirectedVariable _ A.DirOutput v) = "!" ++ showRain v
showRain x = "<invalid Rain variable: " ++ show x ++ ">"
-- | Extends an existing (probably generic) function with cases for everything that has a specific ShowOccam and ShowRain instance
extCode :: Typeable b => (b -> Doc) -> (forall a. (ShowOccam a, ShowRain a) => a -> String) -> (b -> Doc)
extCode q f = q `extQ` (text . (f :: A.Type -> String))
`extQ` (text . (f :: A.DyadicOp -> String))
`extQ` (text . (f :: A.Variable -> String))