packages feed

symantic-parser-0.1.0.20210201: src/Symantic/Parser/Haskell/View.hs

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Symantic.Parser.Haskell.View where

import Data.Bool
import Data.Function (($), (.))
import Data.Int (Int)
import Data.Semigroup (Semigroup(..))
import Data.String (IsString(..), String)
import Prelude ((+))
import Text.Show (Show(..), ShowS, shows, showParen, showString)
import qualified Data.Function as Fun

import Symantic.Parser.Grammar.Fixity
import qualified Symantic.Parser.Haskell.Optimize as H

-- * Type 'ViewTerm'
newtype ViewTerm a = ViewTerm { unViewTerm :: ViewTermInh -> ShowS }

instance IsString (ViewTerm a) where
  fromString s = ViewTerm $ \_inh -> showString s

-- ** Type 'ViewTermInh'
data ViewTermInh
 =   ViewTermInh
 {   viewTermInh_op :: (Infix, Side)
 ,   viewTermInh_pair :: Pair
 ,   viewTermInh_lamDepth :: Int
 }

pairViewTerm :: ViewTermInh -> Infix -> ShowS -> ShowS
pairViewTerm inh op s =
  if isPairNeeded (viewTermInh_op inh) op
  then showString o . s . showString c
  else s
  where (o,c) = viewTermInh_pair inh

instance Show (ViewTerm a) where
  showsPrec p v = unViewTerm v ViewTermInh
    { viewTermInh_op = (infixN p, SideL)
    , viewTermInh_pair = pairParen
    , viewTermInh_lamDepth = 1
    }
instance Show (H.Term repr a) where
  showsPrec p = showsPrec p . go
    where
    go :: forall b. H.Term repr b -> ViewTerm b
    go = \case
      H.Term{} -> "Term"
      {-
      (H.:.) H.:@ f H.:@ g -> ViewTerm $ \inh ->
        pairViewTerm inh op Fun.$
          unViewTerm (go f) inh{viewTermInh_op=op} Fun..
          showString " . " Fun..
          unViewTerm (go g) inh{viewTermInh_op=op}
        where op = infixR 9
      (H.:.) -> "(.)"
      -}
      {-
      H.Char t -> ViewTerm $ \_inh ->
        showString "(char " .
        shows t .
        showString ")"
      -}
      H.Char t -> ViewTerm $ \_inh -> shows t
      H.Cons H.:@ x H.:@ xs -> ViewTerm $ \inh ->
        pairViewTerm inh op Fun.$
          unViewTerm (go x) inh{viewTermInh_op=(op, SideL)} Fun..
          showString " : " Fun..
          unViewTerm (go xs) inh{viewTermInh_op=(op, SideR)}
        where op = infixN 5
      H.Cons -> "cons"
      H.Eq H.:@ x H.:@ y -> ViewTerm $ \inh ->
        pairViewTerm inh op Fun.$
          unViewTerm (go x) inh{viewTermInh_op=(op, SideL)} Fun..
          showString " == " Fun..
          unViewTerm (go y) inh{viewTermInh_op=(op, SideR)}
        where op = infixN 4
      H.Eq H.:@ x -> ViewTerm $ \inh ->
        showParen True Fun.$
          unViewTerm (go x) inh{viewTermInh_op=(op, SideL)} Fun..
          showString " =="
          where op = infixN 4
      H.Eq -> "(==)"
      H.Var v -> fromString v
      H.Lam1 f -> viewLam "u" f
      H.Lam f -> viewLam "x" f
      f H.:@ x -> ViewTerm $ \inh ->
        pairViewTerm inh op $
          unViewTerm (go f) inh{viewTermInh_op = (op, SideL) } .
          -- showString " :@ " .
          showString " " .
          unViewTerm (go x) inh{viewTermInh_op = (op, SideR) }
        where op = infixN 10
      {-
      H.Const -> "const"
      H.Flip -> "flip"
      H.Id -> "id"
      (H.:$) -> "($)"
      -}
    viewLam :: forall b c. String -> (H.Term repr b -> H.Term repr c) -> ViewTerm (b -> c)
    viewLam v f = ViewTerm $ \inh ->
      pairViewTerm inh op $
        let x = v<>show (viewTermInh_lamDepth inh) in
        -- showString "Lam1 (" .
        showString "\\" . showString x . showString " -> " .
        (unViewTerm (go (f (H.Var x))) inh
          { viewTermInh_op = (op, SideL)
          , viewTermInh_lamDepth = viewTermInh_lamDepth inh + 1
          })
        -- . showString ")"
      where op = infixN 0