packages feed

disco-0.2: src/Disco/Pretty/Prec.hs

-----------------------------------------------------------------------------

-----------------------------------------------------------------------------

-- |
-- Module      :  Disco.Pretty.Prec
-- Copyright   :  disco team and contributors
-- Maintainer  :  byorgey@gmail.com
--
-- SPDX-License-Identifier: BSD-3-Clause
--
-- Precedence and associativity for pretty-printing.
module Disco.Pretty.Prec where

import Disco.Syntax.Operators

-- Types for storing precedence + associativity together

type Prec = Int

data PA = PA Prec BFixity
  deriving (Show, Eq) -- Do NOT derive Ord, see note below.

lowerPrec :: PA -> PA -> Bool
lowerPrec (PA p1 a1) (PA p2 a2) = p1 < p2 || (p1 == p2 && a1 /= a2)

-- Note re: lowerPrec: we used to have an unlawful Ord instance defined by
--
--   compare (PA p1 a1) (PA p2 a2) = compare p1 p2 `mappend` (if a1 == a2 then EQ else LT)
--
-- with the idea that we could test whether one precedence was lower
-- than another simply using (<).
--
-- However, this was unlawful since e.g. it does not satisfy x < y ==
-- y > x: If x and y have the same Prec value but different BFixity
-- values, we would have both x < y and y < x.
--
-- In base-4.18 apparently something in the default implementations of
-- Ord methods changed so that e.g. not (PA 2 InR < PA 2 InL).  Hence
-- the 'mparens' method in such cases of nested same-precedence
-- operators was not emitting parentheses in cases where it should.

-- Standard precedence levels

initPA :: PA
initPA = PA 0 InL

ascrPA :: PA
ascrPA = PA 1 InL

funPA :: PA
funPA = PA funPrec InL

rPA :: Int -> PA
rPA n = PA n InR

tarrPA, taddPA, tmulPA, tfunPA :: PA
tarrPA = rPA 1
taddPA = rPA 6
tmulPA = rPA 7
tfunPA = PA 9 InL

-- Converting UOp and BOp

ugetPA :: UOp -> PA
ugetPA op = PA (uPrec op) In

getPA :: BOp -> PA
getPA op = PA (bPrec op) (assoc op)