Eq-1.0: EqManips/Algorithm/Inject.hs
{-# LANGUAGE ScopedTypeVariables #-}
module EqManips.Algorithm.Inject( inject ) where
import Control.Applicative
import EqManips.Types
import EqManips.FormulaIterator
import EqManips.EvaluationContext
import EqManips.Algorithm.Utils
-- | Replace all variables that get a definition by
-- their definition if there is one. Otherwise let
-- the variable like that.
inject :: Formula ListForm -> EqContext (Formula ListForm)
inject (Formula f) = do
#ifdef _DEBUG
addTrace ("Injection:", Formula $ f)
#endif
Formula <$> depthPrimTraversal scopePreserver injectIntern f
-- | This function perform a sort of alpha
-- renaming on subScope, it's called when arriving
-- on a node, to prevent wrong replacements.
scopePreserver :: FormulaPrim -> EqContext ()
scopePreserver f = keepSafe $ reBoundVar f
where keepSafe Nothing = return ()
keepSafe (Just v) = do
pushContext
mapM_ delSymbol v
injectIntern :: FormulaPrim -> EqContext FormulaPrim
injectIntern f@(Variable v) =
maybe f unTagFormula <$> symbolLookup v
injectIntern f = scope $ reBoundVar f
where scope Nothing = return f
scope _ = popContext >> return f
-- | Tell if a node change the scope.
-- The pattern is explicitely exaustive to be sure
-- to get the compiler shout if a change is made.
reBoundVar :: FormulaPrim -> Maybe [String]
reBoundVar (Product _ (BinOp _ OpEq (Variable v:_)) _ _) = Just [v]
reBoundVar (Sum _ (BinOp _ OpEq (Variable v: _)) _ _) = Just [v]
reBoundVar (Lambda _ clauses) = Just $
concat [concatMap collectSymbols args | (args, _) <- clauses]
reBoundVar (Indexes _ _ _) = Nothing
reBoundVar (List _ _) = Nothing
reBoundVar (Complex _ _) = Nothing
reBoundVar (Fraction _) = Nothing
reBoundVar (Poly _ _) = Nothing
reBoundVar (Variable _) = Nothing
reBoundVar (NumEntity _) = Nothing
reBoundVar (CInteger _) = Nothing
reBoundVar (CFloat _) = Nothing
reBoundVar (App _ _ _) = Nothing
reBoundVar (Derivate _ _ _) = Nothing
reBoundVar (Integrate _ _ _ _ _) = Nothing
reBoundVar (UnOp _ _ _) = Nothing
reBoundVar (BinOp _ _ _) = Nothing
reBoundVar (Matrix _ _ _ _) = Nothing
reBoundVar (Block _ _ _) = Nothing
reBoundVar (Product _ _ _ _) = Nothing
reBoundVar (Sum _ _ _ _) = Nothing
reBoundVar (Truth _) = Nothing
-- Nothing preserved during evaluation normaly.
reBoundVar (Meta _ _ _) = Nothing