{-# LANGUAGE OverloadedStrings #-}

module Unison.PrettyPrintEnv.Util (declarationPPE, declarationPPEDecl) where

import Unison.PrettyPrintEnv (PrettyPrintEnv (..))
import Unison.PrettyPrintEnv qualified as PPE
import Unison.PrettyPrintEnvDecl (PrettyPrintEnvDecl (suffixifiedPPE, unsuffixifiedPPE))
import Unison.Reference (Reference)
import Unison.Reference qualified as Reference
import Unison.Referent qualified as Referent

-- declarationPPE uses the full name for references that are
-- part the same cycle as the input reference, used to ensures
-- recursive definitions are printed properly, for instance:
--
-- foo.bar x = foo.bar x
-- and not
-- foo.bar x = bar x
declarationPPE :: PrettyPrintEnvDecl -> Reference -> PrettyPrintEnv
declarationPPE :: PrettyPrintEnvDecl -> Reference -> PrettyPrintEnv
declarationPPE PrettyPrintEnvDecl
ppe Reference
ref = (Referent -> [(HashQualified Name, HashQualified Name)])
-> (Reference -> [(HashQualified Name, HashQualified Name)])
-> PrettyPrintEnv
PrettyPrintEnv Referent -> [(HashQualified Name, HashQualified Name)]
tm Reference -> [(HashQualified Name, HashQualified Name)]
ty
  where
    rootH :: Maybe Hash
rootH = Reference -> Maybe Hash
forall {t} {a}. Reference' t a -> Maybe a
hash Reference
ref
    hash :: Reference' t a -> Maybe a
hash Reference.Builtin {} = Maybe a
forall a. Maybe a
Nothing
    hash (Reference.Derived a
h Pos
_) = a -> Maybe a
forall a. a -> Maybe a
Just a
h
    tm :: Referent -> [(HashQualified Name, HashQualified Name)]
tm r0 :: Referent
r0@(Referent.Ref Reference
r)
      | Reference -> Maybe Hash
forall {t} {a}. Reference' t a -> Maybe a
hash Reference
r Maybe Hash -> Maybe Hash -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Hash
rootH = PrettyPrintEnv
-> Referent -> [(HashQualified Name, HashQualified Name)]
PPE.termNames (PrettyPrintEnvDecl -> PrettyPrintEnv
unsuffixifiedPPE PrettyPrintEnvDecl
ppe) Referent
r0
      | Bool
otherwise = PrettyPrintEnv
-> Referent -> [(HashQualified Name, HashQualified Name)]
PPE.termNames (PrettyPrintEnvDecl -> PrettyPrintEnv
suffixifiedPPE PrettyPrintEnvDecl
ppe) Referent
r0
    tm Referent
r = PrettyPrintEnv
-> Referent -> [(HashQualified Name, HashQualified Name)]
PPE.termNames (PrettyPrintEnvDecl -> PrettyPrintEnv
suffixifiedPPE PrettyPrintEnvDecl
ppe) Referent
r
    ty :: Reference -> [(HashQualified Name, HashQualified Name)]
ty Reference
r
      | Reference -> Maybe Hash
forall {t} {a}. Reference' t a -> Maybe a
hash Reference
r Maybe Hash -> Maybe Hash -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Hash
rootH = PrettyPrintEnv
-> Reference -> [(HashQualified Name, HashQualified Name)]
PPE.typeNames (PrettyPrintEnvDecl -> PrettyPrintEnv
unsuffixifiedPPE PrettyPrintEnvDecl
ppe) Reference
r
      | Bool
otherwise = PrettyPrintEnv
-> Reference -> [(HashQualified Name, HashQualified Name)]
PPE.typeNames (PrettyPrintEnvDecl -> PrettyPrintEnv
suffixifiedPPE PrettyPrintEnvDecl
ppe) Reference
r

-- The suffixed names uses the fully-qualified name for `r`
declarationPPEDecl :: PrettyPrintEnvDecl -> Reference -> PrettyPrintEnvDecl
declarationPPEDecl :: PrettyPrintEnvDecl -> Reference -> PrettyPrintEnvDecl
declarationPPEDecl PrettyPrintEnvDecl
ppe Reference
r =
  PrettyPrintEnvDecl
ppe {suffixifiedPPE = declarationPPE ppe r}