module YesodDsl.ExpandMacros (expandMacros) where
import YesodDsl.AST
import Data.List
import Data.Generics
expandMacros :: Module -> Module
expandMacros m = everywhere (mkT f) m 
    where
        f (ApplyExpr fn ps) = expandApplyExpr fn ps
        f x = x
        expandApplyExpr fn ps = case find (\d -> defineName d == fn) (modDefines m) of
            Just d -> if length (defineParams d) == length ps
                then case defineContent d of
                    (DefineSubQuery sq) -> SubQueryExpr (expandSubQuery sq $ zip (defineParams d) ps)
                else error $ "Expected " ++ show (length $ defineParams d)
                             ++ " parameters for macro " ++ fn ++ " got " ++
                             show (length ps)
            _ -> error $ "Reference to undefined macro " ++ fn
                        
        expandSubQuery sq subs = foldl repSubQuery sq subs
        repSubQuery sq sub = everywhere ((mkT $ repFr sub) . (mkT $ repSf sub)) sq 
        repSf (pn,pv) spf@(SelectParamField vn pn' mvn) 
            | pn == pn' = SelectField vn pv mvn
            | otherwise = spf
        repSf _ x = x    
        repFr (pn,pv) fr@(FieldRefParamField vn pn') 
            | pn == pn' = FieldRefNormal vn pv
            | otherwise = fr
        repFr _ x  =x