egison-5.1.0: hs-src/Language/Egison/EvalState.hs
{-# LANGUAGE FlexibleInstances #-}
{- |
Module : Language.Egison.EvalState
Licence : MIT
This module defines the state during the evaluation.
-}
module Language.Egison.EvalState
( EvalState(..)
, initialEvalState
, MonadEval(..)
, mLabelFuncName
, InstanceEnv
, MethodDict
, ConstructorEnv
, ConstructorInfo(..)
, PatternConstructorEnv
) where
import Control.Monad.Except
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.State.Strict
import qualified Data.HashMap.Strict as HashMap
import Data.HashMap.Strict (HashMap)
import qualified Data.Set as Set
import Language.Egison.IExpr
import Language.Egison.Type.Types (Type, TypeScheme)
import Language.Egison.Type.Env (TypeEnv, ClassEnv, PatternTypeEnv, emptyEnv, emptyClassEnv, emptyPatternEnv, extendEnv)
-- | Instance environment: maps class name -> method name -> type -> implementation
-- The implementation is stored as a function reference (Var name)
type MethodDict = HashMap Type String -- Type -> implementation function name
type InstanceEnv = HashMap String (HashMap String MethodDict) -- ClassName -> MethodName -> Dict
-- | Constructor environment: maps constructor name -> constructor info
-- Used for type inference and pattern matching
data ConstructorInfo = ConstructorInfo
{ ctorTypeName :: String -- ^ The inductive type name, e.g., "Maybe"
, ctorArgTypes :: [Type] -- ^ Constructor argument types
, ctorTypeParams :: [String] -- ^ Type parameters of the inductive type, e.g., ["a"]
} deriving (Show, Eq)
type ConstructorEnv = HashMap String ConstructorInfo
-- | Pattern constructor environment: maps pattern constructor name -> type scheme
-- This uses the same format as PatternTypeEnv for consistency
type PatternConstructorEnv = PatternTypeEnv
data EvalState = EvalState
{ funcNameStack :: [Var] -- ^ Names of called functions for improved error message
, instanceEnv :: InstanceEnv -- ^ Type class instance environment (runtime dispatch)
, constructorEnv :: ConstructorEnv -- ^ Inductive data constructor environment
, typeEnv :: TypeEnv -- ^ Type environment (for type inference)
, classEnv :: ClassEnv -- ^ Class environment (for type inference)
, patternEnv :: PatternTypeEnv -- ^ Pattern constructor environment (for type inference)
, patternFuncEnv :: PatternTypeEnv -- ^ Pattern function environment (for disambiguation)
, patternFuncStructEnv :: PatternTypeEnv -- ^ Pattern function structural signatures (paper PATFUN-DEF):
-- for each pattern function, the scheme of
-- beta_1 -> ... -> beta_k -> tau_p_body, where beta_i is the
-- structural index of parameter i and tau_p_body is the body's
-- structural index. Instantiated at application sites (PAT-APP)
-- to propagate the arguments' structural indices into the result.
, reductionRulesCount :: Int -- ^ Phase 7.4/7.5: number of `declare rule` declarations seen
, derivativeRulesCount :: Int -- ^ Phase 6.3: number of `declare derivative` declarations seen
, reductionRuleNames :: [String] -- ^ Names of named rules ("auto" rules are excluded)
, derivativeRuleNames :: [String] -- ^ Names of declared derivatives (the function names)
, autoRuleVarNames :: [String] -- ^ Phase 7.5: full var names of auto rules (e.g. "autoRule.0").
-- Accumulated as `declare rule auto` declarations are desugared,
-- used to rebuild `mathNormalize` to apply each rule in sequence.
, autoRuleTriggers :: [Set.Set String] -- ^ Trigger-symbol set per auto rule (parallel to autoRuleVarNames).
-- Each entry is the set of literal symbols/functions referenced by
-- the rule's LHS. Empty set means "no specific trigger" -> always run.
-- Stored as Set already (not [String]) so iterateRulesCAS can read
-- it once per call without per-call Set construction.
, derivativesDesugared :: [String] -- ^ Phase 6.3: derivative names desugared so far (in declaration order).
-- Each `declare derivative` redefines `chainPartialDiff` using only
-- the names *up to and including* itself, avoiding forward references
-- to derivatives declared later (which would emit warnings).
, casTypeAliasEnv :: HashMap String Type -- ^ Phase alpha (extensible CAS tower):
-- `declare cas-type` transparent aliases, name -> fully
-- expanded Type. Persists across load batches so aliases
-- declared in a library apply to later files.
, casSubtypeEdges :: [(Type, Type)] -- ^ Phase beta: `declare cas-subtype` edges (alias-expanded,
-- declaration order, redundant edges included for node
-- bookkeeping). Persists across load batches.
, declaredSymbolOrder :: [String] -- ^ G3 (cas-simplification): CAS symbols in `declare symbol`
-- declaration order (deduplicated). DG1: symbols declared
-- earlier rank lower in the monomial order used by
-- `declare ideal`, i.e. they survive in normal forms.
}
initialEvalState :: EvalState
initialEvalState = EvalState
{ funcNameStack = []
, instanceEnv = HashMap.empty
, constructorEnv = HashMap.empty
, typeEnv = emptyEnv
, classEnv = emptyClassEnv
, patternEnv = emptyPatternEnv
, patternFuncEnv = emptyPatternEnv
, patternFuncStructEnv = emptyPatternEnv
, reductionRulesCount = 0
, derivativeRulesCount = 0
, reductionRuleNames = []
, derivativeRuleNames = []
, autoRuleVarNames = []
, autoRuleTriggers = []
, derivativesDesugared = []
, casTypeAliasEnv = HashMap.empty
, casSubtypeEdges = []
, declaredSymbolOrder = []
}
class (Applicative m, Monad m) => MonadEval m where
pushFuncName :: Var -> m ()
topFuncName :: m Var
popFuncName :: m ()
getFuncNameStack :: m [Var]
-- Instance environment operations
getInstanceEnv :: m InstanceEnv
registerInstance :: String -> String -> Type -> String -> m ()
lookupInstance :: String -> String -> Type -> m (Maybe String)
-- Constructor environment operations
getConstructorEnv :: m ConstructorEnv
registerConstructor :: String -> ConstructorInfo -> m ()
lookupConstructor :: String -> m (Maybe ConstructorInfo)
-- Type environment operations
getTypeEnv :: m TypeEnv
setTypeEnv :: TypeEnv -> m ()
extendTypeEnv :: Var -> TypeScheme -> m ()
-- Class environment operations
getClassEnv :: m ClassEnv
setClassEnv :: ClassEnv -> m ()
-- Pattern environment operations
getPatternEnv :: m PatternTypeEnv
setPatternEnv :: PatternTypeEnv -> m ()
-- Pattern function environment operations
getPatternFuncEnv :: m PatternTypeEnv
setPatternFuncEnv :: PatternTypeEnv -> m ()
-- Pattern function structural-signature environment operations (paper PATFUN-DEF/PAT-APP)
getPatternFuncStructEnv :: m PatternTypeEnv
setPatternFuncStructEnv :: PatternTypeEnv -> m ()
-- Phase 7.4/7.5: reduction-rule and derivative-rule registration counts.
-- Counts only — full data is held by EnvBuildResult during build phase
-- and isn't currently threaded into the runtime state.
getReductionRulesCount :: m Int
setReductionRulesCount :: Int -> m ()
getDerivativeRulesCount :: m Int
setDerivativeRulesCount :: Int -> m ()
getReductionRuleNames :: m [String]
setReductionRuleNames :: [String] -> m ()
getDerivativeRuleNames :: m [String]
setDerivativeRuleNames :: [String] -> m ()
-- Phase 7.5: auto-rule full var names (e.g. "autoRule.0", "autoRule.1").
-- Used to rebuild `mathNormalize` per `declare rule auto`.
getAutoRuleVarNames :: m [String]
setAutoRuleVarNames :: [String] -> m ()
appendAutoRuleVarName :: String -> m ()
-- Trigger-symbol set per auto rule, parallel to autoRuleVarNames.
-- Read by iterateRulesCAS via getAutoRuleTriggers (returns the cached
-- Set list directly; no per-call construction).
getAutoRuleTriggers :: m [Set.Set String]
appendAutoRuleTriggers :: [String] -> m ()
-- Phase 6.3: derivative names already desugared (in declaration order).
-- Lets each `declare derivative` see only the derivatives that come at or
-- before it, avoiding forward references in the generated chainPartialDiff.
getDerivativesDesugared :: m [String]
setDerivativesDesugared :: [String] -> m ()
appendDerivativeDesugared :: String -> m ()
-- G3 (cas-simplification): `declare symbol` declaration order for the
-- `declare ideal` priority list.
getDeclaredSymbolOrder :: m [String]
appendDeclaredSymbols :: [String] -> m ()
-- Phase alpha (extensible CAS tower): `declare cas-type` alias environment.
getCasTypeAliasEnv :: m (HashMap String Type)
setCasTypeAliasEnv :: HashMap String Type -> m ()
-- Phase beta: `declare cas-subtype` edges.
getCasSubtypeEdges :: m [(Type, Type)]
setCasSubtypeEdges :: [(Type, Type)] -> m ()
instance Monad m => MonadEval (StateT EvalState m) where
pushFuncName name = do
st <- get
put $ st { funcNameStack = name : funcNameStack st }
return ()
topFuncName = do
stack <- funcNameStack <$> get
case stack of
(x:_) -> return x
[] -> error "topFuncName: function name stack is empty"
popFuncName = do
st <- get
case funcNameStack st of
(_:rest) -> put st { funcNameStack = rest }
[] -> error "popFuncName: function name stack is empty"
getFuncNameStack = funcNameStack <$> get
getInstanceEnv = instanceEnv <$> get
registerInstance className methodName ty implName = do
st <- get
let env = instanceEnv st
classDict = HashMap.lookupDefault HashMap.empty className env
methodDict = HashMap.lookupDefault HashMap.empty methodName classDict
methodDict' = HashMap.insert ty implName methodDict
classDict' = HashMap.insert methodName methodDict' classDict
env' = HashMap.insert className classDict' env
put $ st { instanceEnv = env' }
lookupInstance className methodName ty = do
env <- instanceEnv <$> get
return $ do
classDict <- HashMap.lookup className env
methodDict <- HashMap.lookup methodName classDict
HashMap.lookup ty methodDict
getConstructorEnv = constructorEnv <$> get
registerConstructor ctorName info = do
st <- get
let env = constructorEnv st
env' = HashMap.insert ctorName info env
put $ st { constructorEnv = env' }
lookupConstructor ctorName = do
env <- constructorEnv <$> get
return $ HashMap.lookup ctorName env
getTypeEnv = typeEnv <$> get
setTypeEnv env = do
st <- get
put $ st { typeEnv = env }
extendTypeEnv name scheme = do
st <- get
let env' = extendEnv name scheme (typeEnv st)
put $ st { typeEnv = env' }
getClassEnv = classEnv <$> get
setClassEnv env = do
st <- get
put $ st { classEnv = env }
getPatternEnv = patternEnv <$> get
setPatternEnv env = do
st <- get
put $ st { patternEnv = env }
getPatternFuncEnv = patternFuncEnv <$> get
setPatternFuncEnv env = do
st <- get
put $ st { patternFuncEnv = env }
getPatternFuncStructEnv = patternFuncStructEnv <$> get
setPatternFuncStructEnv env = do
st <- get
put $ st { patternFuncStructEnv = env }
getReductionRulesCount = reductionRulesCount <$> get
setReductionRulesCount n = do
st <- get
put $ st { reductionRulesCount = n }
getDerivativeRulesCount = derivativeRulesCount <$> get
setDerivativeRulesCount n = do
st <- get
put $ st { derivativeRulesCount = n }
getReductionRuleNames = reductionRuleNames <$> get
setReductionRuleNames ns = do
st <- get
put $ st { reductionRuleNames = ns }
getDerivativeRuleNames = derivativeRuleNames <$> get
setDerivativeRuleNames ns = do
st <- get
put $ st { derivativeRuleNames = ns }
getAutoRuleVarNames = autoRuleVarNames <$> get
setAutoRuleVarNames ns = do
st <- get
put $ st { autoRuleVarNames = ns }
appendAutoRuleVarName n = do
st <- get
put $ st { autoRuleVarNames = autoRuleVarNames st ++ [n] }
getAutoRuleTriggers = autoRuleTriggers <$> get
appendAutoRuleTriggers ts = do
st <- get
put $ st { autoRuleTriggers = autoRuleTriggers st ++ [Set.fromList ts] }
getDerivativesDesugared = derivativesDesugared <$> get
setDerivativesDesugared ns = do
st <- get
put $ st { derivativesDesugared = ns }
appendDerivativeDesugared n = do
st <- get
put $ st { derivativesDesugared = derivativesDesugared st ++ [n] }
getDeclaredSymbolOrder = declaredSymbolOrder <$> get
appendDeclaredSymbols names = do
st <- get
let existing = declaredSymbolOrder st
newNames = filter (`notElem` existing) names
put $ st { declaredSymbolOrder = existing ++ newNames }
getCasTypeAliasEnv = casTypeAliasEnv <$> get
setCasTypeAliasEnv env = do
st <- get
put $ st { casTypeAliasEnv = env }
getCasSubtypeEdges = casSubtypeEdges <$> get
setCasSubtypeEdges es = do
st <- get
put $ st { casSubtypeEdges = es }
instance (MonadEval m) => MonadEval (ExceptT e m) where
pushFuncName name = lift $ pushFuncName name
topFuncName = lift topFuncName
popFuncName = lift popFuncName
getFuncNameStack = lift getFuncNameStack
getInstanceEnv = lift getInstanceEnv
registerInstance cn mn t i = lift $ registerInstance cn mn t i
lookupInstance cn mn t = lift $ lookupInstance cn mn t
getConstructorEnv = lift getConstructorEnv
registerConstructor cn info = lift $ registerConstructor cn info
lookupConstructor cn = lift $ lookupConstructor cn
getTypeEnv = lift getTypeEnv
setTypeEnv = lift . setTypeEnv
extendTypeEnv name scheme = lift $ extendTypeEnv name scheme
getClassEnv = lift getClassEnv
setClassEnv = lift . setClassEnv
getPatternEnv = lift getPatternEnv
setPatternEnv = lift . setPatternEnv
getPatternFuncEnv = lift getPatternFuncEnv
setPatternFuncEnv = lift . setPatternFuncEnv
getPatternFuncStructEnv = lift getPatternFuncStructEnv
setPatternFuncStructEnv = lift . setPatternFuncStructEnv
getReductionRulesCount = lift getReductionRulesCount
setReductionRulesCount = lift . setReductionRulesCount
getDerivativeRulesCount = lift getDerivativeRulesCount
setDerivativeRulesCount = lift . setDerivativeRulesCount
getReductionRuleNames = lift getReductionRuleNames
setReductionRuleNames = lift . setReductionRuleNames
getDerivativeRuleNames = lift getDerivativeRuleNames
setDerivativeRuleNames = lift . setDerivativeRuleNames
getAutoRuleVarNames = lift getAutoRuleVarNames
setAutoRuleVarNames = lift . setAutoRuleVarNames
appendAutoRuleVarName = lift . appendAutoRuleVarName
getAutoRuleTriggers = lift getAutoRuleTriggers
appendAutoRuleTriggers = lift . appendAutoRuleTriggers
getDerivativesDesugared = lift getDerivativesDesugared
setDerivativesDesugared = lift . setDerivativesDesugared
appendDerivativeDesugared = lift . appendDerivativeDesugared
getDeclaredSymbolOrder = lift getDeclaredSymbolOrder
appendDeclaredSymbols = lift . appendDeclaredSymbols
getCasTypeAliasEnv = lift getCasTypeAliasEnv
setCasTypeAliasEnv = lift . setCasTypeAliasEnv
getCasSubtypeEdges = lift getCasSubtypeEdges
setCasSubtypeEdges = lift . setCasSubtypeEdges
mLabelFuncName :: MonadEval m => Maybe Var -> m a -> m a
mLabelFuncName Nothing m = m
mLabelFuncName (Just name) m = do
pushFuncName name
v <- m
popFuncName
return v