packages feed

HaRe-0.6: tools/property/parse/extras/ParseUtil.hs

-- $Id: ParseUtil.hs,v 1.7 2001/11/06 06:33:37 hallgren Exp $

{-

Utilities for the parser.

Author(s): Simon Marlow 1997, 1998;
           Emir Pasalic, Bill Harrison, Andrew Moran 2001

-}

module ParseUtil (--setInfix,        -- HsInfixDecl -> PM ()
		  splitTyConApp,   -- HsType -> PM (HsName, [HsType])
                  mkQuant,         -- HsQuantifier -> [HsPat] -> HsExp -> HsExp
		  mkValDef,        -- HsExp -> SrcLoc -> HsRhs HsExp
		                   --   -> [HsDecl] -> PM HsDecl
                  mkFunDef,        -- HsExp -> SrcLoc -> HsRhs HsExp
                                   --   -> [HsDecl] -> PM HsDecl
                  expToPat)        -- HsExp -> PM HsPat
where

import ParseMonad
--import Rewrite
--import HsAssoc
import PropSyntax
import PropSyntaxUtil(isConE)
import PrettyPrint

{-
-- Update the infix environment with infix information from declaration.
setInfix (HsInfixDecl sl (HsFixity prec assoc) names) = 
  mapM (addToEnv prec assoc) names
  where 
      addToEnv prec HsAssocNone  n =
	  do { s <- getInfixEnv ;
	       setInfixEnv $ extend s (HsInfix HsAssocNone  prec n)
	     }
      addToEnv prec HsAssocRight n =
	  do { s <- getInfixEnv ;
	       setInfixEnv $ extend s (HsInfix HsAssocLeft  prec n)
	     }
      addToEnv prec HsAssocLeft  n =
	  do { s <- getInfixEnv ;
	       setInfixEnv $ extend s (HsInfix HsAssocRight prec n)
	     }
-}

splitTyConApp :: HsType -> PM (HsName, [HsType])
splitTyConApp t = split t []
    where
    split :: HsType -> [HsType] -> PM (HsName, [HsType])
    split (Typ (HsTyApp t u)) ts = split t (u:ts)
    split (Typ (HsTyCon t))   ts = return (t, ts)
    split _                   _
        = parseError "illegal data/newtype declaration"

mkQuant :: HsQuantifier -> [HsPat] -> HsExp -> HsExp
mkQuant q ps (e @ (Exp (Prop (HsQuant q' ps' e'))))
    | q == q'   = hsQuant q (ps ++ ps') e'
    | otherwise = hsQuant q ps e
mkQuant q ps e  = hsQuant q ps e

mkValDef :: HsExp -> SrcLoc -> HsRhs HsExp -> [HsDecl] -> PM HsDecl
mkValDef lhs sloc (HsBody b) wheres = 
    do { lpat <- expToPat lhs ;
	 return $ hsPatBind sloc lpat (HsBody b) wheres
       }
mkValDef lhs sloc (HsGuard gds) wheres = 
    do { lpat <- expToPat lhs ;
	 return $ hsPatBind sloc lpat (HsGuard gds) wheres
       }

mkFunDef :: HsExp -> SrcLoc -> HsRhs HsExp -> [HsDecl] -> PM HsDecl
mkFunDef lhs sloc rhs wheres = 
    do { (fnamePat, ps) <- getFundefPats lhs ; 
	 case fnamePat of 
         Pat (Base (HsPId (HsVar nm))) ->
              return $ hsFunBind sloc [HsMatch sloc nm ps rhs  wheres]
         _                      ->
              parseError $ "invalid function name in:\n\n" ++ pp lhs
       }


getFundefPats :: HsExp -> PM (HsPat, [HsPat])
getFundefPats (Exp (Base pexp)) = 
    case pexp of 
    HsId (HsVar nm) -> return (hsPVar nm, [])
    HsApp l r ->  
        do { (pv, ps) <- getFundefPats l ;
             p        <- expToPat r ;
             return (pv, ps ++ [p])
	   }
    HsInfixApp l (HsVar n) r -> 
        do { lp  <- expToPat l ;
             rp  <- expToPat r ;
             return (hsPVar n, [lp, rp])
	   }
    HsInfixApp l (HsCon n) r -> 
        do { lp  <- expToPat l ;
             rp  <- expToPat r ;
             return (hsPCon n, [lp, rp])
	   }
    HsParen e -> getFundefPats e
    _     -> parseError $
	     "cannot use\n\n" ++ pp pexp ++
	     "\n\nas a function definition pattern."
getFundefPats p =
    parseError $
    "cannot use\n\n" ++ pp p ++
    "\n\nas a function definition pattern."


expToPat :: HsExp -> PM HsPat
expToPat l@(Exp (Base lhexp))  = 
    case lhexp of 
      HsId (HsVar n) -> return $ hsPVar n
      HsId (HsCon n) -> return $ hsPCon n
      HsLit literal  -> return $ hsPLit literal
      HsNegApp  e    -> do { p <- expToPat e ; return $ hsPNeg p }
      HsLambda _ _   -> parseError "lambdas not allowed in patterns."
      HsList es      -> do { ps <- sequence (map expToPat es) ;
			     return $ hsPList ps
			   }
      HsTuple es     -> do { ps <- sequence (map expToPat es) ;
			     return $ hsPTuple ps
			   }
      HsWildCard     -> return hsPWildCard
      HsIrrPat e     -> do { p <- expToPat e ; return $ hsPIrrPat p }
      HsAsPat nm e   -> do { p <- expToPat e ; return $ hsPAsPat nm p}
      HsApp l r | isConE l  -> 
                        do { let { Exp (Base (HsId (HsCon n))) = l } ;
			     rp <- expToPat r ;
			     return $ hsPApp n [rp]
			   }
                | otherwise ->
                        do { lp <- expToPat l ;
                             rp <- expToPat r ;
                             case lp of 
                             Pat (Base (HsPApp n ps)) ->
			         return $ hsPApp n (ps ++ [rp])
                             _                 ->
			         parseError $
			         "Cannot use:\n\n" ++
			         pp lhexp ++
			         "\n\n as a pattern."
                           }
      HsInfixApp l (HsCon n) r -> 
                        do { lp <- expToPat l ;
                             rp <- expToPat r ;
                             return $ hsPInfixApp lp (HsCon n) rp 
			   }
      HsParen e                -> expToPat e
      HsRecConstr con fields   ->
                        do { pfs <- mapM fieldToPat fields ;
			     return $ hsPRec con pfs
			   }
      HsExpTypeSig _ e c t     ->
                        do { p <- expToPat e ;
                             return $ hsPatTypeSig p c t
                           }
      _                        ->
          parseError $ "ParseUtil.expToPat: not a valid/supported pattern:\n\n"
                       ++ pp lhexp
    where --fieldToPat (HsFieldBind f)     = return $ HsPFieldPun f
	  fieldToPat (HsFieldUpdate f e) = do { p <- expToPat e ;
						return $ HsPFieldPat f p
					      }
expToPat e  =
    parseError $ "ParseUtil.expToPat: not a valid/supported pattern:\n\n"
                 ++ pp e