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

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

import Language.Symantic.Grammar

-- * Type 'View'

-- | Interpreter's data.
newtype View a
 =      View
 {    unView -- Inherited attribuctx:
             :: (Infix, Side)
             -> DepthLam
             -- Synthetised attribuctx:
             -> Text
 }
type DepthLam = Int
instance Show (View a) where
	show = Text.unpack . view

-- | Interpreter.
view :: View a -> Text
view r = unView r (infixN0, SideL) 0

-- ** Constructors
view0 :: Text -> View a
view0 name = View $ \_op _v -> name

view1 :: Text -> View a1 -> View a
view1 name (View a1) = View $ \po v ->
		parenInfix po op $
		Text.intercalate " "
		 [ name
		 , a1 (op, SideL) v
		 ]
	where op = infixN 10

view2 :: Text -> View a1 -> View a2 -> View a
view2 name (View a1) (View a2) =
	View $ \po v ->
		parenInfix po op $
		Text.intercalate " "
		 [ name
		 , a1 (op, SideL) v
		 , a2 (op, SideL) v
		 ]
	where op = infixN 10

view3 :: Text -> View a1 -> View a2 -> View a3 -> View a
view3 name (View a1) (View a2) (View a3) =
	View $ \po v ->
		parenInfix po op $
		Text.intercalate " "
		 [ name
		 , a1 (op, SideL) v
		 , a2 (op, SideL) v
		 , a3 (op, SideL) v
		 ]
	where op = infixN 10

viewInfix :: Text -> Infix -> View a1 -> View a2 -> View a
viewInfix name op (View a1) (View a2) =
	View $ \po v ->
		parenInfix po op $
		Text.intercalate " "
		 [ a1 (op, SideL) v
		 , name
		 , a2 (op, SideR) v
		 ]