packages feed

indigo-0.4: src/Indigo/Internal/SIS.hs

-- SPDX-FileCopyrightText: 2020 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-TQ

module Indigo.Internal.SIS
  ( SomeIndigoState (..)
  , SomeGenCode (..)
  , toSIS
  , runSIS
  , thenSIS
  , overSIS
  ) where

import Indigo.Prelude

import Indigo.Internal.State

-- | 'GenCode' with hidden output stack
data SomeGenCode inp where
  SomeGenCode :: GenCode inp out -> SomeGenCode inp

-- | 'IndigoState' with hidden output stack,
-- necessary to generate typed Lorentz code from untyped Indigo frontend.
newtype SomeIndigoState inp = SomeIndigoState
  { unSIS :: MetaData inp -> SomeGenCode inp
  }

-- | To run 'SomeIndigoState' you need to pass an handler of 'GenCode' with any
-- output stack and initial 'MetaData'.
runSIS :: SomeIndigoState inp -> MetaData inp -> (forall out . GenCode inp out -> r) -> r
runSIS (SomeIndigoState act) md f = case act md of
  SomeGenCode gc -> f gc

-- | Convert 'IndigoState' to 'SomeIndigoState'
toSIS :: IndigoState inp out -> SomeIndigoState inp
toSIS is = SomeIndigoState $ \md -> SomeGenCode $ runIndigoState is md

-- | Similar to a @>>@ for 'SomeIndigoState'.
thenSIS :: SomeIndigoState inp -> (forall out . SomeIndigoState out) -> SomeIndigoState inp
thenSIS m f = SomeIndigoState $ \md ->
  case unSIS m md of
    (SomeGenCode (GenCode st1 cd1 cl1 :: GenCode inp out)) ->
      case unSIS (f @out) (replStkMd md st1) of
        SomeGenCode (GenCode st2 cd2 cl2) ->
          SomeGenCode (GenCode st2 (cd1 ## cd2) (cl2 ## cl1))

-- | Modify the 'GenCode' inside a 'SomeIndigoState' by passing an handler of
-- 'GenCode' that returns a 'SomeGenCode'.
-- Useful in some cases to "wrap" or update and exising 'SomeGenCode'.
overSIS
  :: (forall out. GenCode inp out -> SomeGenCode inp)
  -> SomeIndigoState inp
  -> SomeIndigoState inp
overSIS f si = SomeIndigoState $ \md -> runSIS si md f