descript-lang-0.2.0.0: src/Descript/BasicInj/Read/Resolve/Subst/Global.hs
module Descript.BasicInj.Read.Resolve.Subst.Global
( globalSubstMany
) where
import Descript.BasicInj.Read.Resolve.Subst.Subst
import qualified Descript.BasicInj.Data.Value.In as In
import qualified Descript.BasicInj.Data.Value.Out as Out
import qualified Descript.BasicInj.Data.Type as RecordType
import Descript.BasicInj.Data
import Descript.Misc
import Data.Semigroup
import Core.Data.List
import Core.Data.List.Assoc
-- | Globally applies each substitution by modifying the top phase
-- and record declarations.
globalSubstMany :: (TaintAnn an)
=> [Subst]
-> AModule an
-> AModule an
globalSubstMany substs (AModule ann recCtx redCtx)
= AModule
{ amoduleAnn = ann
, recordCtx = globalSubstManyRecordCtx substs recCtx
, reduceCtx = globalSubstManyReduceCtx recCtx_ substs redCtx
}
where recCtx_ = remAnns recCtx
globalSubstManyRecordCtx :: (TaintAnn an)
=> [Subst]
-> RecordCtx an
-> RecordCtx an
globalSubstManyRecordCtx substs (RecordCtx ann decls)
= RecordCtx ann $ concatMap (globalSubstManyRecordDecl substs) decls
globalSubstManyRecordDecl :: (TaintAnn an)
=> [Subst]
-> RecordDecl an
-> [RecordDecl an]
globalSubstManyRecordDecl substs (RecordDecl ann typ)
= RecordDecl ann <$> globalSubstManyRecordType substs typ
globalSubstManyRecordType :: (TaintAnn an)
=> [Subst]
-> RecordType an
-> [RecordType an]
globalSubstManyRecordType substs (RecordType ann head' props)
= RecordType ann <$> globalSubstManyFSymbol substs head' <*> pure props
globalSubstManyFSymbol :: (TaintAnn an)
=> [Subst]
-> FSymbol an
-> [FSymbol an]
globalSubstManyFSymbol substs x = y ?: [x]
where y = (ann' <$) <$> y_
y_ = glookup x_ substs
x_ = remAnns x
ann' = getAnn x
globalSubstManyReduceCtx :: (TaintAnn an)
=> RecordCtx ()
-> [Subst]
-> ReduceCtx an
-> ReduceCtx an
globalSubstManyReduceCtx recCtx substs (ReduceCtx ann top lows)
= ReduceCtx ann top' lows
where top' = top <> extraTop
extraTop = substAnn <$ substManyPhase recCtx substs
substAnn = preInsertAnn ann
substManyPhase :: RecordCtx () -> [Subst] -> PhaseCtx ()
substManyPhase recCtx = PhaseCtx () . map (substToReducer recCtx)
substToReducer :: RecordCtx () -> Subst -> Reducer ()
substToReducer recCtx subst@(Subst _ from to) = Reducer () from' to'
where from'
= singletonValue
$ In.PartRecord
$ Record () from
$ map In.fullConsumeProp propKeys
to'
= singletonValue
$ Out.PartRecord
$ Record () to
$ map (Out.fullProduceProp from) propKeys
propKeys
= case lookupRecordType (substDeclHead subst) recCtx of
Nothing -> [undefinedSym]
Just rtype -> RecordType.properties rtype