module Lang.LamIf.Stamp where
import FP
import Lang.LamIf.Syntax
import Lang.LamIf.Parser
data Name = Name
{ nameID ∷ ℕ
, nameSource ∷ 𝕊
}
instance Eq Name where (==) = (≟) `on` nameID
instance Ord Name where compare = compare `on` nameID
instance Pretty Name where pretty = ppBdr ∘ nameSource
data Exp = Exp
{ expID ∷ ℕ
, expContext ∷ SourceContext Token
, expRawExp ∷ PreExp Name Exp
}
type Atom = PreAtom Name Exp
stripStampedPreExp ∷ PreExp Name Exp → PreExp 𝕊 (Fixed (PreExp 𝕊))
stripStampedPreExp = mapExp nameSource nameSource stripStampedExp
stripStampedExp ∷ Exp → Fixed (PreExp 𝕊)
stripStampedExp = Fixed ∘ stripStampedPreExp ∘ expRawExp
instance Eq Exp where (==) = (≟) `on` expID
instance Ord Exp where compare = (⋚) `on` expID
instance POrd Exp where (⊑⊒) = discretePO
instance Pretty Exp where
pretty e = ppVertical
[ pretty $ expContext e
]
data StampState = StampState
{ stampNameID ∷ ℕ
, stampExpID ∷ ℕ
, stampBinderMap ∷ 𝕊 ⇰ ℕ
}
makeLenses ''StampState
stampState₀ ∷ StampState
stampState₀ = StampState bot bot emptyDict
data StampEnv = StampEnv
{ stampContext ∷ SourceContext Token
}
makeLenses ''StampEnv
stampEnv₀ ∷ StampEnv
stampEnv₀ = StampEnv null
newtype StampM a = StampM { runStampM ∷ ReaderT StampEnv (StateT StampState (Error Doc)) a }
deriving
(Functor,Monad
,MonadError Doc
,MonadState StampState
,MonadReader StampEnv
)
runStampM₀ ∷ StampM a → Doc ⨄ a
runStampM₀ xM = runError $ evalStateTWith stampState₀ $ runReaderTWith stampEnv₀ $ runStampM xM
stampExp ∷ SourceExp → StampM Exp
stampExp (SourceExp ctx e) = do
i ← nextL stampExpIDL
ei ← local (update stampContextL ctx) $ mapExpM stampVar stampBinder stampExp e
return $ Exp i ctx ei
stampVar ∷ 𝕊 → StampM Name
stampVar x = do
binderMap ← getL stampBinderMapL
case binderMap # x of
Nothing → do
fc ← askL stampContextL
throw $ ppVertical
[ ppHeader "Bad Syntax: Unbound variable"
, errorSourceContext fc
]
Just n → return $ Name n x
stampBinder ∷ 𝕊 → StampM Name
stampBinder x = do
i ← nextL stampNameIDL
modifyL stampBinderMapL $ insertDict x i
return $ Name i x
stamp ∷ SourceExp → Doc ⨄ Exp
stamp = runStampM₀ ∘ stampExp