packages feed

ychr-0.1.0.0: src/YCHR/Internal/Runtime/Types.hs

-- | Shared types for the CHR Haskell runtime.
module YCHR.Internal.Runtime.Types
  ( SuspensionId (..),
    VarId (..),
    Var (..),
    VarState (..),
    Value (..),
    CallVal (..),
    Suspension (..),
  )
where

import Data.IORef
import Data.Text (Text)
import YCHR.Internal.Types (ConstraintType)

-- | Unique identifier for a constraint suspension. Also serves as the
-- observer key on variables for selective reactivation.
newtype SuspensionId = SuspensionId Int
  deriving (Eq, Ord, Show)

-- | Unique identifier for a logical variable.
newtype VarId = VarId Int
  deriving (Eq, Ord, Show)

-- | A logical variable, backed by a mutable cell.
newtype Var = Var (IORef VarState)

-- | The state of a logical variable.
data VarState
  = -- | Not yet bound. Carries a unique ID and a list of observer IDs
    -- (constraints watching this variable for reactivation).
    Unbound !VarId ![SuspensionId]
  | -- | Bound to a value (possibly another variable, forming a chain).
    Bound !Value

-- | Runtime values that flow through the VM. Constraint identifiers
-- are a separate runtime kind ('SuspensionId'); they never inhabit
-- this type.
data Value
  = -- | A logical variable (possibly unbound, possibly bound).
    -- 'YCHR.Run.deref' follows the chain to what it stands for.
    VVar !Var
  | -- | Arbitrary-precision integer.
    VInt !Integer
  | -- | Floating-point number.
    VFloat !Double
  | -- | Atom: a symbolic constant. Zero-arity compounds collapse to
    -- this form at run time, unlike in the AST.
    VAtom !Text
  | -- | String.
    VText !Text
  | -- | Boolean. Guards and the prelude's comparisons produce these.
    VBool !Bool
  | -- | Compound term: functor and arguments.
    VTerm !Text ![Value]
  | -- | Wildcard: unifies with anything without binding.
    VWildcard

-- | Procedure-call argument at runtime. Procedures take a heterogeneous
-- mix of value and id parameters; this wrapper carries the kind across
-- the call boundary so the callee can bind each parameter into the right
-- environment slot. Mirrors 'YCHR.Internal.VM.Types.CallArg' on the IR side.
data CallVal
  = CVal !Value
  | CId !SuspensionId

-- | A constraint suspension in the store. The 'alive' flag is mutable so
-- that 'killConstraint' is O(1) and copies of the suspension obtained
-- before the kill see the updated state without an explicit lookup.
data Suspension = Suspension
  { suspId :: !SuspensionId,
    suspType :: !ConstraintType,
    args :: ![Value],
    alive :: !(IORef Bool)
  }