module Symantic.Parser.Machine
  ( module Symantic.Parser.Machine
  , module Symantic.Parser.Machine.Generate
  , module Symantic.Parser.Machine.Input
  , module Symantic.Parser.Machine.Instructions
  , module Symantic.Parser.Machine.Optimize
  , module Symantic.Parser.Machine.Program
  , module Symantic.Parser.Machine.View
  ) where
import Data.Function ((.))
import Data.Ord (Ord)
import Text.Show (Show)
import qualified Language.Haskell.TH.Syntax as TH

import Symantic.Parser.Grammar
import Symantic.Parser.Machine.Generate
import Symantic.Parser.Machine.Input
import Symantic.Parser.Machine.Instructions
import Symantic.Parser.Machine.Optimize
import Symantic.Parser.Machine.Program
import Symantic.Parser.Machine.View

-- * Type 'Parser'
type Parser inp = ParserRepr Gen inp

-- | Like a 'Parser' but not bound to the 'Gen' interpreter.
type ParserRepr repr inp =
  ObserveSharing TH.Name
                 (OptimizeGrammar (Program repr inp))

-- | Build a 'Machine' able to 'generateCode' for the given 'Parser'.
machine :: forall inp repr a.
  Ord (InputToken inp) =>
  Show (InputToken inp) =>
  TH.Lift (InputToken inp) =>
  Grammar (InputToken inp) (Program repr inp) =>
  Machine (InputToken inp) repr =>
  ParserRepr repr inp a ->
  repr inp '[] ('Succ 'Zero) a
machine :: forall inp (repr :: ReprInstr) a.
(Ord (InputToken inp), Show (InputToken inp),
 Lift (InputToken inp), Grammar (InputToken inp) (Program repr inp),
 Machine (InputToken inp) repr) =>
ParserRepr repr inp a -> repr inp '[] ('Succ 'Zero) a
machine = Program repr inp a -> repr inp '[] ('Succ 'Zero) a
forall inp (es :: Peano) (repr :: ReprInstr) a.
Machine (InputToken inp) repr =>
Program repr inp a -> repr inp '[] ('Succ es) a
optimizeMachine (Program repr inp a -> repr inp '[] ('Succ 'Zero) a)
-> (ObserveSharing Name (OptimizeGrammar (Program repr inp)) a
    -> Program repr inp a)
-> ObserveSharing Name (OptimizeGrammar (Program repr inp)) a
-> repr inp '[] ('Succ 'Zero) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall tok (repr :: * -> *) a.
Grammar tok repr =>
ObserveSharing Name (OptimizeGrammar repr) a -> repr a
grammar @(InputToken inp)