{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE UndecidableInstances #-}
module Language.Symantic.Grammar.Meta where

import Data.Either (Either)
import Data.Function (($), const)
import Data.Functor (Functor, (<$>))

import Language.Symantic.Grammar.Source

-- * Type 'Gram_Reader'
class Gram_Reader st g where
        askBefore :: g (st -> a) -> g a
        askAfter  :: g (st -> a) -> g a

-- * Type 'Gram_State'
class Gram_State st g where
        stateBefore :: g (st -> (st, a)) -> g a
        stateAfter  :: g (st -> (st, a)) -> g a
        getBefore   :: g (st -> a) -> g a
        getAfter    :: g (st -> a) -> g a
        put         :: g (st, a) -> g a
        default getBefore :: Functor g => g (st -> a) -> g a
        default getAfter  :: Functor g => g (st -> a) -> g a
        default put       :: Functor g => g (st, a) -> g a
        getBefore g = stateBefore ((\f st -> (st, f st)) <$> g)
        getAfter  g = stateAfter ((\f st -> (st, f st)) <$> g)
        put       g = stateAfter ((\(st, a) -> const (st, a)) <$> g)

-- * Class 'Gram_Error'
-- | Symantics for handling errors at the semantic level (not the syntaxic one).
class Gram_Error err g where
        catch :: g (Either err a) -> g a

-- * Class 'Gram_Source'
class
 ( Gram_Reader (Source_Input src) g
 , SourceInj (Span (Source_Input src)) src
 ) => Gram_Source src g where
        source :: Functor g => g (src -> a) -> g a
        source g =
                askAfter $ askBefore $
                 (\f (beg::Source_Input src) (end::Source_Input src) ->
                        f (sourceInj $ Span beg end::src))
                 <$> g
instance
 ( Gram_Reader (Source_Input src) g
 , SourceInj (Span (Source_Input src)) src
 ) => Gram_Source src g