{-# LANGUAGE UndecidableInstances #-}
-- | Interpreter to serialize an expression into a 'Text'.
module Language.Symantic.Interpreting.Text where

import Data.Text (Text)
import qualified Data.Text as Text
import Prelude hiding (Integral(..))

import Language.Symantic.Grammar

-- * Type 'TextI'

-- | Interpreter's data.
newtype TextI h
 =      TextI
 {    unTextI -- Inherited attributes:
              :: (Infix, LR)
              -> TextI_Lambda_Depth
              -- Synthetised attributes:
              -> Text
 }
type TextI_Lambda_Depth = Int
instance Show (TextI h) where
	show = Text.unpack . text_from_term

-- | Interpreter.
text_from_term :: TextI h -> Text
text_from_term r = unTextI r (infixN0, L) 0

-- * Helpers

-- ** Helpers for lambda applications
textI0 :: Text -> TextI h
textI0 name = TextI $ \_op _v -> name
textI1 :: Text -> TextI a1 -> TextI h
textI1 name (TextI a1) = TextI $ \po v ->
		infix_paren po op $
		Text.intercalate " "
		 [ name
		 , a1 (op, L) v
		 ]
	where op = infixN 10
textI2 :: Text -> TextI a1 -> TextI a2 -> TextI h
textI2 name (TextI a1) (TextI a2) =
	TextI $ \po v ->
		infix_paren po op $
		Text.intercalate " "
		 [ name
		 , a1 (op, L) v
		 , a2 (op, L) v
		 ]
	where op = infixN 10
textI3 :: Text -> TextI a1 -> TextI a2 -> TextI a3 -> TextI h
textI3 name (TextI a1) (TextI a2) (TextI a3) =
	TextI $ \po v ->
		infix_paren po op $
		Text.intercalate " "
		 [ name
		 , a1 (op, L) v
		 , a2 (op, L) v
		 , a3 (op, L) v
		 ]
	where op = infixN 10

textI_infix :: Text -> Infix -> TextI a1 -> TextI a2 -> TextI h
textI_infix name op (TextI a1) (TextI a2) =
	TextI $ \po v ->
		infix_paren po op $
		Text.intercalate " "
		 [ a1 (op, L) v
		 , name
		 , a2 (op, R) v
		 ]