Subversion

ptable

[/] [InOut.hs] - Rev 1

Compare with Previous - Blame


-- Generates in's and out's for given data types
module InOut where

import Data.Transform.TwoLevel ((><),(/\))
import Language.Haskell.Parser
import Language.Haskell.Syntax
import Language.Haskell.Pretty (prettyPrint)

import Language.Pointwise.Syntax hiding (swap)
import Language.Pointwise.Pretty (pw2hs)

-- In
makeIn :: [HsConDecl] -> Term
makeIn = makeIn2 . makeIn1
        where
                makeIn1 :: [HsConDecl] -> [(String, Int)] -- (Name, arity)
		makeIn1 lcons = map removeRecs lcons
                -- 'Strict' or not, doesn't really matter
		removeRecs :: HsConDecl -> (String, Int)
		removeRecs (HsConDecl loc (HsIdent name) l)  = (name, length l)
                removeRecs (HsConDecl loc (HsSymbol name) l) = (name, length l)
                removeRecs (HsRecDecl loc name l) = error "makeIn: record constructors not supported"

                makeIn2 :: [(String, Int)] -> Term
		makeIn2 [x] = handle x
                makeIn2 (h:t) = (Const "either" :@: handle h) :@: makeIn2 t

                handle :: (String, Int) -> Term
		handle (s,0) = Const "const" :@: Const s
                handle (s,1) = Const s
                handle (s,n) = (foldr1 (:@:) (replicate (pred n) (Const "uncurry"))) :@: Const s
                
-- Out
makeOut :: [HsConDecl] -> Term
makeOut = Match (Var "x") . (uncurry zip) . (makeLhs /\ makeRhs) . makeOut1
        where
                makeOut1 :: [HsConDecl] -> [(String, Int)] -- (Name, arity)
		makeOut1 lcons = map removeRecs lcons
                -- 'Strict' or not, doesn't really matter
		removeRecs :: HsConDecl -> (String, Int)
		removeRecs (HsConDecl loc (HsIdent name) l)  = (name, length l)
                removeRecs (HsConDecl loc (HsSymbol name) l) = (name, length l)
                removeRecs (HsRecDecl loc name l) = error "makeOut: record constructors not supported"

                makeLhs :: [(String, Int)] -> [Term]
		makeLhs = map (\(s,a) -> getVars s a)
                        where
                                getVars s 0 = Var s
                                getVars s 1 = Var s :@: (Var $ head vars)
                                -- getVars s n = Var s :@: (foldr1 (:@:) $ map Var (take n vars)) -- :@: is not right
				getVars s n = Var s :@: (Const (foldr1 (\a b -> a++" "++b) (take n vars))) -- awful solution

                makeRhs :: [(String, Int)] -> [Term]
		makeRhs l = map (\((s,a),(i,n)) -> handle (i,n) a) l2 
                        where l2 = zip l [(i, length l) | i <- [1..]]

                handle :: (Int,Int) -> Int -> Term
		handle (i,1) a = getVars a
                handle (i,n) a = (getPlace i n) $ getVars a
                getVars 0 = Unit
                getVars 1 = Var $ head vars
                getVars n = foldr1 (:&:) $ map Var (take n vars)
                
                getPlace :: Int -> Int -> (Term -> Term)
		getPlace i n 
                        | i == 1 = Inl
                        | i > 1 && i < n = ini . Inl
                        | i == n = ini
                        | otherwise = error "getPlace: not enough constructors"
                        where
                                ini :: Term -> Term
				ini t = foldr ($) t (replicate (pred i) (Inr))
                
                vars :: [String]
		vars = map (\(a,b) -> a : show b) $ zip (repeat 'x') [1..]

{-
-- Tests, stuff to remove
pppw :: Term -> String
pppw = prettyPrint . pw2hs 

testIns = do
        let 
                tests =
                        [
                                "data A = Empty", 
                                "data B = Empty1 | Empty2 ()",
                                "data C = Cons1 Int Bool | Cons2 (Int,Bool)",
                                "data D = Lister [Maybe Int]",
                                "data E = Leaf | Node E",
                                "data F = Nil | Cons Int X",
                                "data G = Fun (Int -> Bool)",
                                "data H = Rose [H] | A | B | C Int Int Int Int",
                                "data I = Use H"
                        ]
        mapM putStrLn $ map (pppw . makeIn . parse) tests
        
testOuts = do
        let 
                tests =
                        [
                                "data A = Empty", 
                                "data B = Empty1 | Empty2 ()",
                                "data C = Cons1 Int Bool | Cons2 (Int,Bool)",
                                "data D = Lister [Maybe Int]",
                                "data E = Leaf | Node E",
                                "data F = Nil | Cons Int X",
                                "data G = Fun (Int -> Bool)",
                                "data H = Rose [H] | A | B | C Int Int Int Int",
                                "data I = Use H"
                        ]
        mapM putStrLn $ map (pppw . makeOut . parse) tests
  
parse s =
        case (parseModule s) of
           ParseOk (HsModule _ _ _ _ [HsDataDecl _ _ _ _ x _]) -> x
-}

Theme by Vikram Singh | Powered by WebSVN v1.61