parsley-core-1.5.0.0: src/ghc/Parsley/Internal/Core/Identifiers.hs
{-# OPTIONS_GHC -Wno-incomplete-patterns #-}
{-# LANGUAGE DerivingStrategies,
GeneralizedNewtypeDeriving #-}
{-|
Module : Parsley.Internal.Backend.Machine.Identifiers
Description : frontend specific identifiers.
License : BSD-3-Clause
Maintainer : Jamie Willis
Stability : experimental
This module defines "identifiers", which are used to uniquely identify different
nodes in the combinator tree (and abstract machine).
@since 1.0.0.0
-}
module Parsley.Internal.Core.Identifiers (
MVar(..), IMVar,
ΣVar(..), IΣVar, SomeΣVar(..), getIΣVar
) where
import Data.Array (Ix)
import Data.Function (on)
import Data.GADT.Compare (GEq, GCompare, gcompare, geq, GOrdering(..))
import Data.Kind (Type)
import Data.Typeable ((:~:)(Refl))
import Data.Word (Word64)
import Unsafe.Coerce (unsafeCoerce)
{-|
An identifier representing concrete registers and mutable state.
@since 0.1.0.0
-}
newtype ΣVar (a :: Type) = ΣVar IΣVar
{-|
An identifier representing let-bound parsers, recursion, and iteration.
@since 0.1.0.0
-}
newtype MVar (a :: Type) = MVar IMVar
{-|
Underlying untyped identifier, which is numeric but otherwise opaque.
@since 0.1.0.0
-}
newtype IMVar = IMVar Word64 deriving newtype (Ord, Eq, Num, Enum, Show, Ix)
{-|
Underlying untyped identifier, which is numeric but otherwise opaque.
@since 0.1.0.0
-}
newtype IΣVar = IΣVar Word64 deriving newtype (Ord, Eq, Num, Enum, Show, Ix)
instance Show (MVar a) where show (MVar μ) = "μ" ++ show μ
instance Show (ΣVar a) where show (ΣVar σ) = "σ" ++ show σ
instance GEq ΣVar where
geq (ΣVar u) (ΣVar v)
| u == v = Just (unsafeCoerce Refl)
| otherwise = Nothing
instance GCompare ΣVar where
gcompare σ1@(ΣVar u) σ2@(ΣVar v) = case compare u v of
LT -> GLT
EQ -> case geq σ1 σ2 of Just Refl -> GEQ
GT -> GGT
{-|
An identifier representing some concrete register, but where the type is existential.
@since 0.1.0.0
-}
data SomeΣVar = forall r. SomeΣVar (ΣVar r)
instance Eq SomeΣVar where (==) = (==) `on` getIΣVar
instance Ord SomeΣVar where compare = compare `on` getIΣVar
instance Show SomeΣVar where show (SomeΣVar σ) = show σ
{-|
Fetch the untyped identifier from under the existential.
@since 0.1.0.0
-}
getIΣVar :: SomeΣVar -> IΣVar
getIΣVar (SomeΣVar (ΣVar σ)) = σ
instance GEq MVar where
geq (MVar u) (MVar v)
| u == v = Just (unsafeCoerce Refl)
| otherwise = Nothing
instance GCompare MVar where
gcompare μ1@(MVar u) μ2@(MVar v) = case compare u v of
LT -> GLT
EQ -> case geq μ1 μ2 of Just Refl -> GEQ
GT -> GGT