{-# LANGUAGE DerivingStrategies, PatternSynonyms #-} {-| Module : Parsley.Internal.Backend.Machine.Types.Coins Description : Meta-data associated with input consumption optimisations. License : BSD-3-Clause Maintainer : Jamie Willis Stability : unstable This module exposes `Coins` and the relevant operations. These are used by constant input analysis to side-step unnecessary length checks and character reads (in the case of lookahead). @since 1.5.0.0 -} module Parsley.Internal.Backend.Machine.Types.Coins ( Coins(..), minCoins, plus1, minus, canReclaim, pattern Zero, one, items ) where import Control.Applicative (liftA2) import Parsley.Internal.Core.CharPred (CharPred, mergePreds) {-| Packages together the known input that can be consumed after a length-check with the number of characters that can be rewound on a lookahead backtrack. @since 1.5.0.0 -} data Coins = Coins { -- | The number of tokens we know must be consumed along the path to succeed. willConsume :: {-# UNPACK #-} !Int, willCache :: {-# UNPACK #-} !Int, knownPreds :: !(Maybe CharPred) } deriving stock Show canReclaim :: Coins -> Int canReclaim = willConsume {-| Makes a `Coins` value of 0. @since 1.5.0.0 -} pattern Zero :: Coins pattern Zero = Coins 0 0 Nothing one :: CharPred -> Coins one p = Coins 1 1 (Just p) items :: Int -> Coins items n = Coins n 0 Nothing zipCoins :: (Int -> Int -> Int) -> (Int -> Int -> Int) -> (Maybe CharPred -> Maybe CharPred -> Maybe CharPred) -> Coins -> Coins -> Coins zipCoins f g h (Coins k1 c1 cs1) (Coins k2 c2 cs2) = Coins k' c' cs' where k' = f k1 k2 c' = g c1 c2 cs' = h cs1 cs2 {-| Takes the pairwise min of two `Coins` values. @since 1.5.0.0 -} minCoins :: Coins -> Coins -> Coins minCoins = zipCoins min min (liftA2 mergePreds) {-| Adds 1 to all the `Coins` values. @since 1.5.0.0 -} plus1 :: CharPred -> Coins -> Coins plus1 p = zipCoins (+) (+) const (one p) {-| @since 1.5.0.0 -} minus :: Coins -> Int -> Coins minus c 0 = c minus (Coins n c _) m = Coins (max (n - m) 0) (max (c - m) 0) Nothing