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

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