egison-4.1.0: hs-src/Language/Egison/Desugar.hs
{-# LANGUAGE TupleSections #-}
{- |
Module : Language.Egison.Desugar
Licence : MIT
This module provides desugar functions.
-}
module Language.Egison.Desugar
( desugarTopExpr
, desugarTopExprs
, desugarExpr
) where
import Control.Monad.Except (throwError)
import Data.Char (toUpper)
import Data.Foldable (foldrM)
import Data.List (union)
import Language.Egison.AST
import Language.Egison.Data
import Language.Egison.IExpr
import Language.Egison.RState
desugarTopExpr :: TopExpr -> EvalM (Maybe ITopExpr)
desugarTopExpr (Define (VarWithIndices name []) expr) = do
expr' <- desugar expr
case expr' of
ILambdaExpr Nothing args body -> return . Just $ IDefine (Var name []) (ILambdaExpr (Just name) args body)
_ -> return . Just $ IDefine (Var name []) expr'
desugarTopExpr (Define vwi expr) = do
(var, iexpr) <- desugarDefineWithIndices vwi expr
return . Just $ IDefine var iexpr
desugarTopExpr (Test expr) = Just . ITest <$> desugar expr
desugarTopExpr (Execute expr) = Just . IExecute <$> desugar expr
desugarTopExpr (Load file) = return . Just $ ILoad file
desugarTopExpr (LoadFile file) = return . Just $ ILoadFile file
desugarTopExpr _ = return Nothing
desugarTopExprs :: [TopExpr] -> EvalM [ITopExpr]
desugarTopExprs [] = return []
desugarTopExprs (expr : exprs) = do
expr' <- desugarTopExpr expr
case expr' of
Nothing -> desugarTopExprs exprs
Just expr' -> (expr' :) <$> desugarTopExprs exprs
desugarExpr :: Expr -> EvalM IExpr
desugarExpr = desugar
desugar :: Expr -> EvalM IExpr
desugar (ConstantExpr c) = return $ IConstantExpr c
desugar (VarExpr var) = return $ IVarExpr var
desugar (AlgebraicDataMatcherExpr patterns) = do
matcherName <- fresh
let matcherRef = IVarExpr matcherName
matcher <- genMatcherClauses patterns matcherRef
return $ ILetRecExpr [(PDPatVar (stringToVar matcherName), matcher)] matcherRef
where
genMatcherClauses :: [(String, [Expr])] -> IExpr -> EvalM IExpr
genMatcherClauses patterns matcher = do
main <- genMainClause patterns matcher
body <- mapM genMatcherClause patterns
footer <- genSomethingClause
let clauses = [main] ++ body ++ [footer]
return $ IMatcherExpr clauses
genMainClause :: [(String, [Expr])] -> IExpr -> EvalM (PrimitivePatPattern, IExpr, [(IPrimitiveDataPattern, IExpr)])
genMainClause patterns matcher = do
clauses <- genClauses patterns
return (PPValuePat "val", ITupleExpr [],
[(PDPatVar (stringToVar "tgt"),
IMatchExpr BFSMode
(ITupleExpr [IVarExpr "val", IVarExpr "tgt"])
(ITupleExpr [matcher, matcher])
clauses)])
where
genClauses :: [(String, [Expr])] -> EvalM [IMatchClause]
genClauses patterns = (++) <$> mapM genClause patterns
<*> pure [(ITuplePat [IWildCard, IWildCard], matchingFailure)]
genClause :: (String, [Expr]) -> EvalM IMatchClause
genClause pattern = do
(pat0, pat1) <- genMatchingPattern pattern
return (ITuplePat [pat0, pat1], matchingSuccess)
genMatchingPattern :: (String, [Expr]) -> EvalM (IPattern, IPattern)
genMatchingPattern (name, patterns) = do
names <- mapM (const fresh) patterns
return (IInductivePat name (map IPatVar names),
IInductivePat name (map (IValuePat . IVarExpr) names))
genMatcherClause :: (String, [Expr]) -> EvalM (PrimitivePatPattern, IExpr, [(IPrimitiveDataPattern, IExpr)])
genMatcherClause pattern = do
(ppat, matchers) <- genPrimitivePatPat pattern
(dpat, body) <- genPrimitiveDataPat pattern
return (ppat, ITupleExpr matchers, [(dpat, ICollectionExpr [ITupleExpr body]), (PDWildCard, matchingFailure)])
where
genPrimitivePatPat :: (String, [Expr]) -> EvalM (PrimitivePatPattern, [IExpr])
genPrimitivePatPat (name, matchers) = do
patterns' <- mapM (const $ return PPPatVar) matchers
matchers' <- mapM desugar matchers
return (PPInductivePat name patterns', matchers')
genPrimitiveDataPat :: (String, [Expr]) -> EvalM (IPrimitiveDataPattern, [IExpr])
genPrimitiveDataPat (name, patterns) = do
patterns' <- mapM (const fresh) patterns
return (PDInductivePat (capitalize name) $ map (PDPatVar . stringToVar) patterns', map IVarExpr patterns')
capitalize :: String -> String
capitalize (x:xs) = toUpper x : xs
genSomethingClause :: EvalM (PrimitivePatPattern, IExpr, [(IPrimitiveDataPattern, IExpr)])
genSomethingClause =
return (PPPatVar, ITupleExpr [IConstantExpr SomethingExpr], [(PDPatVar (stringToVar "tgt"), ICollectionExpr [IVarExpr "tgt"])])
matchingSuccess :: IExpr
matchingSuccess = ICollectionExpr [ITupleExpr []]
matchingFailure :: IExpr
matchingFailure = ICollectionExpr []
desugar (MatchAllLambdaExpr matcher clauses) = do
name <- fresh
ILambdaExpr Nothing [name] <$>
desugar (MatchAllExpr BFSMode (VarExpr name) matcher clauses)
desugar (MatchLambdaExpr matcher clauses) = do
name <- fresh
ILambdaExpr Nothing [name] <$>
desugar (MatchExpr BFSMode (VarExpr name) matcher clauses)
-- TODO: Allow nested MultiSubscript and MultiSuperscript
desugar (IndexedExpr b expr indices) =
case indices of
[MultiSubscript x y] ->
case (x, y) of
(IndexedExpr b1 e1 [n1], IndexedExpr _ _ [n2]) ->
desugarMultiScript ISubrefsExpr b1 e1 n1 n2
_ -> throwError $ Default "Index should be IndexedExpr for multi subscript"
[MultiSuperscript x y] ->
case (x, y) of
(IndexedExpr b1 e1 [n1], IndexedExpr _ _ [n2]) ->
desugarMultiScript ISuprefsExpr b1 e1 n1 n2
_ -> throwError $ Default "Index should be IndexedExpr for multi superscript"
_ -> IIndexedExpr b <$> desugar expr <*> mapM desugarIndex indices
where
desugarMultiScript refExpr b1 e1 n1 n2 = do
k <- fresh
n1' <- desugar (extractIndexExpr n1)
n2' <- desugar (extractIndexExpr n2)
e1' <- desugar e1
expr' <- desugar expr
return $ refExpr b expr' (makeIApply "map"
[ILambdaExpr Nothing [k] (IIndexedExpr b1 e1' [Sub (IVarExpr k)]),
makeIApply "between" [n1', n2']])
desugar (SubrefsExpr bool expr1 expr2) =
ISubrefsExpr bool <$> desugar expr1 <*> desugar expr2
desugar (SuprefsExpr bool expr1 expr2) =
ISuprefsExpr bool <$> desugar expr1 <*> desugar expr2
desugar (UserrefsExpr bool expr1 expr2) =
IUserrefsExpr bool <$> desugar expr1 <*> desugar expr2
desugar (TupleExpr exprs) = ITupleExpr <$> mapM desugar exprs
desugar (CollectionExpr xs) = ICollectionExpr <$> mapM desugar xs
desugar (ConsExpr x xs) = IConsExpr <$> desugar x <*> desugar xs
desugar (JoinExpr x xs) = IJoinExpr <$> desugar x <*> desugar xs
desugar (HashExpr exprPairs) =
IHashExpr <$> mapM (\(expr1, expr2) -> (,) <$> desugar expr1 <*> desugar expr2) exprPairs
desugar (VectorExpr exprs) =
IVectorExpr <$> mapM desugar exprs
desugar (TensorExpr nsExpr xsExpr) =
ITensorExpr <$> desugar nsExpr <*> desugar xsExpr
-- Desugar of LambdaExpr takes place in 2 stages.
-- * LambdaExpr -> LambdaExpr' : Desugar pattern matches at the arg positions
-- * LambdaExpr' -> ILambdaExpr : Desugar ScalarArg and InvertedScalarArg
desugar (LambdaExpr args expr) = do
(args', expr') <- foldrM desugarArg ([], expr) args
desugar $ LambdaExpr' args' expr'
where
desugarArg :: Arg ArgPattern -> ([Arg String], Expr) -> EvalM ([Arg String], Expr)
desugarArg (TensorArg x) (args, expr) = do
(var, expr') <- desugarArgPat x expr
return (TensorArg var : args, expr')
desugarArg (ScalarArg x) (args, expr) = do
(var, expr') <- desugarArgPat x expr
return (ScalarArg var : args, expr')
desugarArg (InvertedScalarArg x) (args, expr) = do
(var, expr') <- desugarArgPat x expr
return (InvertedScalarArg var : args, expr')
-- Desugar argument patterns. Examples:
-- \$(%x, %y) -> expr ==> \$tmp -> let (tmp1, tmp2) := tmp in (\%x %y -> expr) tmp1 tmp2
-- \(x, (y, z)) -> expr ==> \tmp -> let (tmp1, tmp2) := tmp in (\x (y, z) -> expr) tmp1 tmp2
desugarArgPat :: ArgPattern -> Expr -> EvalM (String, Expr)
desugarArgPat APWildCard expr = do
tmp <- fresh
return (tmp, LetExpr [Bind PDWildCard (VarExpr tmp)] expr)
desugarArgPat (APPatVar var) expr = return (var, expr)
desugarArgPat (APTuplePat args) expr = do
tmp <- fresh
tmps <- mapM (const fresh) args
return (tmp, LetExpr [Bind (PDTuplePat (map PDPatVar tmps)) (VarExpr tmp)]
(ApplyExpr (LambdaExpr args expr) (map VarExpr tmps)))
desugarArgPat (APInductivePat ctor args) expr = do
tmp <- fresh
tmps <- mapM (const fresh) args
return (tmp, LetExpr [Bind (PDInductivePat ctor (map PDPatVar tmps)) (VarExpr tmp)]
(ApplyExpr (LambdaExpr args expr) (map VarExpr tmps)))
desugarArgPat APEmptyPat expr = do
tmp <- fresh
return (tmp, LetExpr [Bind PDEmptyPat (VarExpr tmp)] expr)
desugarArgPat (APConsPat arg1 arg2) expr = do
tmp <- fresh
tmp1 <- fresh
tmp2 <- fresh
return (tmp, LetExpr [Bind (PDConsPat (PDPatVar tmp1) (PDPatVar tmp2)) (VarExpr tmp)]
(ApplyExpr (LambdaExpr [arg1, arg2] expr) [VarExpr tmp1, VarExpr tmp2]))
desugarArgPat (APSnocPat arg1 arg2) expr = do
tmp <- fresh
tmp1 <- fresh
tmp2 <- fresh
return (tmp, LetExpr [Bind (PDSnocPat (PDPatVar tmp1) (PDPatVar tmp2)) (VarExpr tmp)]
(ApplyExpr (LambdaExpr [arg1, arg2] expr) [VarExpr tmp1, VarExpr tmp2]))
desugar (LambdaExpr' names expr) = do
let (args', expr') = foldr desugarInvertedArgs ([], expr) names
expr' <- desugar expr'
return $ ILambdaExpr Nothing args' expr'
where
desugarInvertedArgs :: Arg String -> ([String], Expr) -> ([String], Expr)
desugarInvertedArgs (TensorArg x) (args, expr) = (x : args, expr)
desugarInvertedArgs (ScalarArg x) (args, expr) =
(x : args,
TensorMapExpr (LambdaExpr' [TensorArg x] expr) (VarExpr x))
desugarInvertedArgs (InvertedScalarArg x) (args, expr) =
(x : args,
TensorMapExpr (LambdaExpr' [TensorArg x] expr) (FlipIndicesExpr (VarExpr x)))
desugar (MemoizedLambdaExpr names expr) =
IMemoizedLambdaExpr names <$> desugar expr
desugar (CambdaExpr name expr) =
ICambdaExpr name <$> desugar expr
desugar (PatternFunctionExpr names pattern) =
IPatternFunctionExpr names <$> desugarPattern pattern
desugar (IfExpr expr0 expr1 expr2) =
IIfExpr <$> desugar expr0 <*> desugar expr1 <*> desugar expr2
desugar (LetExpr binds expr) =
ILetExpr <$> desugarBindings binds <*> desugar expr
desugar (LetRecExpr binds expr) =
ILetRecExpr <$> desugarBindings binds <*> desugar expr
desugar (WithSymbolsExpr vars expr) =
IWithSymbolsExpr vars <$> desugar expr
desugar (MatchExpr pmmode expr0 expr1 clauses) =
IMatchExpr pmmode <$> desugar expr0 <*> desugar expr1 <*> desugarMatchClauses clauses
desugar (MatchAllExpr pmmode expr0 expr1 clauses) =
IMatchAllExpr pmmode <$> desugar expr0 <*> desugar expr1 <*> desugarMatchClauses clauses
desugar (DoExpr binds expr) =
IDoExpr <$> desugarBindings binds <*> desugar expr
desugar (PrefixExpr "-" expr) = do
expr' <- desugar expr
return $ makeIApply "*" [IConstantExpr (IntegerExpr (-1)), expr']
desugar (PrefixExpr "!" (ApplyExpr expr args)) =
IWedgeApplyExpr <$> desugar expr <*> mapM desugar args
desugar (PrefixExpr "'" expr) = IQuoteExpr <$> desugar expr
desugar (PrefixExpr "`" expr) = IQuoteSymbolExpr <$> desugar expr
desugar (PrefixExpr op _) = fail ("Unknown prefix " ++ op)
desugar (InfixExpr op expr1 expr2) | isWedge op =
(\x y -> IWedgeApplyExpr (IVarExpr (repr op)) [x, y])
<$> desugar expr1 <*> desugar expr2
desugar (InfixExpr op expr1 expr2) | repr op == "::" =
IConsExpr <$> desugar expr1 <*> desugar expr2
desugar (InfixExpr op expr1 expr2) | repr op == "++" =
IJoinExpr <$> desugar expr1 <*> desugar expr2
desugar (InfixExpr op expr1 expr2) =
(\x y -> makeIApply (repr op) [x, y]) <$> desugar expr1 <*> desugar expr2
-- section
--
-- If `op` is not a cambda, simply desugar it into the function
desugar (SectionExpr op Nothing Nothing)
| not (isWedge op || repr op `elem` ["::", "++"]) =
desugar (VarExpr (repr op))
desugar (SectionExpr op Nothing Nothing) = do
x <- fresh
y <- fresh
ILambdaExpr Nothing [x, y] <$> desugar (InfixExpr op (VarExpr x) (VarExpr y))
desugar (SectionExpr op Nothing (Just expr2)) = do
x <- fresh
ILambdaExpr Nothing [x] <$> desugar (InfixExpr op (VarExpr x) expr2)
desugar (SectionExpr op (Just expr1) Nothing) = do
y <- fresh
ILambdaExpr Nothing [y] <$> desugar (InfixExpr op expr1 (VarExpr y))
desugar SectionExpr{} = throwError $ Default "Cannot reach here: section with both arguments"
desugar (SeqExpr expr0 expr1) =
ISeqExpr <$> desugar expr0 <*> desugar expr1
desugar (GenerateTensorExpr fnExpr sizeExpr) =
IGenerateTensorExpr <$> desugar fnExpr <*> desugar sizeExpr
desugar (TensorContractExpr tExpr) =
ITensorContractExpr <$> desugar tExpr
desugar (TensorMapExpr (LambdaExpr' [x] (TensorMapExpr (LambdaExpr' [y] expr) b)) a) =
desugar (TensorMap2Expr (LambdaExpr' [x, y] expr) a b)
desugar (TensorMapExpr (LambdaExpr [x] (TensorMapExpr (LambdaExpr [y] expr) b)) a) =
desugar (TensorMap2Expr (LambdaExpr [x, y] expr) a b)
desugar (TensorMapExpr fnExpr tExpr) =
ITensorMapExpr <$> desugar fnExpr <*> desugar tExpr
desugar (TensorMap2Expr fnExpr t1Expr t2Expr) =
ITensorMap2Expr <$> desugar fnExpr <*> desugar t1Expr <*> desugar t2Expr
desugar (TransposeExpr vars expr) =
ITransposeExpr <$> desugar vars <*> desugar expr
desugar (FlipIndicesExpr expr) =
IFlipIndicesExpr <$> desugar expr
desugar (ApplyExpr expr args) =
IApplyExpr <$> desugar expr <*> mapM desugar args
desugar (CApplyExpr expr0 expr1) =
ICApplyExpr <$> desugar expr0 <*> desugar expr1
desugar FreshVarExpr = do
id <- fresh
return $ IVarExpr (":::" ++ id)
desugar (MatcherExpr patternDefs) =
IMatcherExpr <$> mapM desugarPatternDef patternDefs
desugar (AnonParamExpr n) = return $ IVarExpr ('%' : show n)
desugar (AnonParamFuncExpr n expr) = do
expr' <- desugar expr
let lambda = ILambdaExpr Nothing (map (\n -> '%' : show n) [1..n]) expr'
return $ ILetRecExpr [(PDPatVar (stringToVar "%0"), lambda)] (IVarExpr "%0")
desugar (QuoteExpr expr) =
IQuoteExpr <$> desugar expr
desugar (QuoteSymbolExpr expr) =
IQuoteSymbolExpr <$> desugar expr
desugar (WedgeApplyExpr expr args) =
IWedgeApplyExpr <$> desugar expr <*> mapM desugar args
desugar (FunctionExpr args) = return $ IFunctionExpr args
desugarIndex :: IndexExpr Expr -> EvalM (Index IExpr)
desugarIndex (Subscript e) = Sub <$> desugar e
desugarIndex (Superscript e) = Sup <$> desugar e
desugarIndex (SupSubscript e) = SupSub <$> desugar e
desugarIndex (Userscript e) = User <$> desugar e
desugarIndex _ = undefined
desugarPattern :: Pattern -> EvalM IPattern
desugarPattern pat =
case collectName pat of
[] -> desugarPattern' pat
names -> ILetPat (map makeBinding names) <$> desugarPattern' pat
where
collectNames :: [Pattern] -> [String]
collectNames pats = foldl union [] (map collectName pats)
collectName :: Pattern -> [String]
collectName (ForallPat pat1 pat2) = collectName pat1 `union` collectName pat2
collectName (InfixPat _ pat1 pat2) = collectName pat1 `union` collectName pat2
collectName (NotPat pat) = collectName pat
collectName (AndPat pat1 pat2) = collectName pat1 `union` collectName pat2
collectName (OrPat pat1 pat2) = collectName pat1 `union` collectName pat2
collectName (TuplePat pats) = collectNames pats
collectName (InductiveOrPApplyPat _ pats) = collectNames pats
collectName (InductivePat _ pats) = collectNames pats
collectName (PApplyPat _ pats) = collectNames pats
collectName (DApplyPat _ pats) = collectNames pats
collectName (LoopPat _ (LoopRange _ _ endNumPat) pat1 pat2) = collectName endNumPat `union` collectName pat1 `union` collectName pat2
collectName (LetPat _ pat) = collectName pat
collectName (IndexedPat (PatVar var) _) = [var]
collectName _ = []
makeBinding :: String -> IBindingExpr
makeBinding var = (PDPatVar (stringToVar var), IHashExpr [])
desugarPattern' :: Pattern -> EvalM IPattern
desugarPattern' WildCard = return IWildCard
desugarPattern' ContPat = return IContPat
desugarPattern' SeqNilPat = return ISeqNilPat
desugarPattern' LaterPatVar = return ILaterPatVar
desugarPattern' (VarPat v) = return (IVarPat v)
desugarPattern' (PatVar var) = return (IPatVar var)
desugarPattern' (ValuePat expr) = IValuePat <$> desugar expr
desugarPattern' (PredPat expr) = IPredPat <$> desugar expr
desugarPattern' (NotPat pat) = INotPat <$> desugarPattern' pat
desugarPattern' (AndPat pat1 pat2) = IAndPat <$> desugarPattern' pat1 <*> desugarPattern' pat2
desugarPattern' (OrPat pat1 pat2) = IOrPat <$> desugarPattern' pat1 <*> desugarPattern' pat2
desugarPattern' (ForallPat pat1 pat2) = IForallPat <$> desugarPattern' pat1 <*> desugarPattern' pat2
desugarPattern' (InfixPat Op{ repr = "&" } pat1 pat2) =
IAndPat <$> desugarPattern' pat1 <*> desugarPattern' pat2
desugarPattern' (InfixPat Op{ repr = "|" } pat1 pat2) =
IOrPat <$> desugarPattern' pat1 <*> desugarPattern' pat2
desugarPattern' (InfixPat Op{ repr = f } pat1 pat2) =
(\x y -> IInductivePat f [x, y]) <$> desugarPattern' pat1 <*> desugarPattern' pat2
desugarPattern' (TuplePat pats) = ITuplePat <$> mapM desugarPattern' pats
desugarPattern' (InductiveOrPApplyPat name pats) = IInductiveOrPApplyPat name <$> mapM desugarPattern' pats
desugarPattern' (InductivePat name pats) = IInductivePat name <$> mapM desugarPattern' pats
desugarPattern' (IndexedPat pat exprs) = IIndexedPat <$> desugarPattern' pat <*> mapM desugar exprs
desugarPattern' (PApplyPat expr pats) = IPApplyPat <$> desugar expr <*> mapM desugarPattern' pats
desugarPattern' (DApplyPat pat pats) = IDApplyPat <$> desugarPattern' pat <*> mapM desugarPattern' pats
desugarPattern' (LoopPat name range pat1 pat2) = ILoopPat name <$> desugarLoopRange range <*> desugarPattern' pat1 <*> desugarPattern' pat2
desugarPattern' (LetPat binds pat) = ILetPat <$> desugarBindings binds <*> desugarPattern' pat
desugarPattern' (SeqConsPat pat1 pat2) = ISeqConsPat <$> desugarPattern' pat1 <*> desugarPattern' pat2
desugarLoopRange :: LoopRange -> EvalM ILoopRange
desugarLoopRange (LoopRange sExpr eExpr pat) =
ILoopRange <$> desugar sExpr <*> desugar eExpr <*> desugarPattern' pat
desugarBindings :: [BindingExpr] -> EvalM [IBindingExpr]
desugarBindings = mapM desugarBinding
where
desugarBinding (Bind name expr) = do
let name' = fmap stringToVar name
expr' <- desugar expr
case (name, expr') of
(PDPatVar var, ILambdaExpr Nothing args body) ->
return (name', ILambdaExpr (Just var) args body)
_ -> return (name', expr')
desugarBinding (BindWithIndices vwi expr) = do
(var, iexpr) <- desugarDefineWithIndices vwi expr
return (PDPatVar var, iexpr)
desugarMatchClauses :: [MatchClause] -> EvalM [IMatchClause]
desugarMatchClauses = mapM (\(pat, expr) -> (,) <$> desugarPattern pat <*> desugar expr)
desugarPatternDef :: PatternDef -> EvalM IPatternDef
desugarPatternDef (pp, matcher, pds) =
(pp,,) <$> desugar matcher <*> desugarPrimitiveDataMatchClauses pds
desugarPrimitiveDataMatchClauses :: [(PrimitiveDataPattern, Expr)] -> EvalM [(IPrimitiveDataPattern, IExpr)]
desugarPrimitiveDataMatchClauses = mapM (\(pd, expr) -> (fmap stringToVar pd,) <$> desugar expr)
desugarDefineWithIndices :: VarWithIndices -> Expr -> EvalM (Var, IExpr)
desugarDefineWithIndices (VarWithIndices name is) expr = do
let (isSubs, indexNames) = unzip $ concatMap extractSubSupIndex is
expr <- if any isExtendedIndice is
then desugarExtendedIndices is isSubs indexNames expr
else return expr
body <- desugar expr
let indexNamesCollection = ICollectionExpr (map IVarExpr indexNames)
let is' = map (\b -> if b then Sub () else Sup ()) isSubs
return (Var name is', IWithSymbolsExpr indexNames (ITransposeExpr indexNamesCollection body))
extractSubSupIndex :: VarIndex -> [(Bool, String)]
extractSubSupIndex (VSubscript x) = [(True, x)]
extractSubSupIndex (VSuperscript x) = [(False, x)]
extractSubSupIndex (VGroupScripts xs) = concatMap extractSubSupIndex xs
extractSubSupIndex (VSymmScripts xs) = concatMap extractSubSupIndex xs
extractSubSupIndex (VAntiSymmScripts xs) = concatMap extractSubSupIndex xs
desugarExtendedIndices :: [VarIndex] -> [Bool] -> [String] -> Expr -> EvalM Expr
desugarExtendedIndices indices isSubs indexNames tensorBody = do
tensorName <- fresh
tensorGenExpr <- f indices (VarExpr tensorName) [] []
let indexFunctionExpr = LambdaExpr' (map TensorArg indexNames) tensorGenExpr
let genTensorExpr = GenerateTensorExpr indexFunctionExpr (makeApply "tensorShape" [VarExpr tensorName])
let tensorIndices = zipWith (\isSub name -> if isSub then Subscript (VarExpr name) else Superscript (VarExpr name)) isSubs indexNames
return $ LetExpr [Bind (PDPatVar tensorName) tensorBody] (IndexedExpr True genTensorExpr tensorIndices)
where
f :: [VarIndex] -> Expr -> [String] -> [BindingExpr] -> EvalM Expr
f [] expr [] [] = return expr
f [] expr [] bindings = return $ LetRecExpr bindings expr
f [] expr signs bindings =
return $ LetRecExpr bindings (makeApply "product" [CollectionExpr (map VarExpr signs ++ [expr])])
f (index:indices) expr signs bindings = do
(indices', signs', bindings') <- genBindings index
let isSubs = subOrSupScripts index
symbols <- mapM (const fresh) isSubs
let is = zipWith (\x isSub -> (if isSub then Subscript else Superscript) (VarExpr x)) symbols isSubs
f indices (IndexedExpr True expr is)
(signs ++ signs') (bindings ++ bindings' ++ [Bind (foldr PDConsPat PDEmptyPat (map PDPatVar symbols)) indices'])
subOrSupScripts :: VarIndex -> [Bool]
subOrSupScripts VSubscript{} = [True]
subOrSupScripts VSuperscript{} = [False]
subOrSupScripts (VGroupScripts xs) = concatMap subOrSupScripts xs
subOrSupScripts (VSymmScripts xs) = concatMap subOrSupScripts xs
subOrSupScripts (VAntiSymmScripts xs) = concatMap subOrSupScripts xs
genBindings :: VarIndex -> EvalM (Expr, [String], [BindingExpr])
genBindings (VSubscript x) = return (CollectionExpr [VarExpr x], [], [])
genBindings (VSuperscript x) = return (CollectionExpr [VarExpr x], [], [])
genBindings (VGroupScripts xs) = do
(indices, signss, bindingss) <- unzip3 <$> mapM genBindings xs
let newIndices =
-- If indices are all CollectionExpr, we can calculate the concatenated result of them
case allCollections indices of
Just xs -> CollectionExpr xs
Nothing -> makeApply "concat" [CollectionExpr indices]
return (newIndices, concat signss, concat bindingss)
where
allCollections [] = Just []
allCollections (CollectionExpr xs : exprs) = (xs ++) <$> allCollections exprs
allCollections _ = Nothing
genBindings (VSymmScripts xs) = do
(indices, signss, bindingss) <- unzip3 <$> mapM genBindings xs
let signs = concat signss
let bindings = concat bindingss
sortedCollectionName <- fresh
let newBindings = bindings ++ [Bind (PDTuplePat [PDWildCard, PDPatVar sortedCollectionName]) (makeApply "sortWithSign" [CollectionExpr indices])]
return (VarExpr sortedCollectionName, signs, newBindings)
genBindings (VAntiSymmScripts xs) = do
(indices, signss, bindingss) <- unzip3 <$> mapM genBindings xs
let signs = concat signss
let bindings = concat bindingss
sortedCollectionName <- fresh
signName <- fresh
let newBindings = bindings ++ [Bind (PDTuplePat [PDPatVar signName, PDPatVar sortedCollectionName]) (makeApply "sortWithSign" [CollectionExpr indices])]
return (VarExpr sortedCollectionName, signName : signs, newBindings)
--
-- Utils
--
extractIndexExpr :: IndexExpr a -> a
extractIndexExpr (Subscript x) = x
extractIndexExpr (Superscript x) = x
extractIndexExpr (SupSubscript x) = x
extractIndexExpr (Userscript x) = x
extractIndexExpr _ = error "extractIndexExpr: Not supported"
isExtendedIndice :: VarIndex -> Bool
isExtendedIndice VSubscript{} = False
isExtendedIndice VSuperscript{} = False
isExtendedIndice (VGroupScripts xs) = isExtendedIndice (head xs)
isExtendedIndice _ = True