packages feed

dataframe-3.0.0.0: tests/PrettyPrint.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}

{- | Golden tests pinning the format of 'prettyPrint'/'prettyPrintWidth': flat
@else if@ ladders, operator-precedence parenthesization, width-aware wrapping of
commutative chains, and short expressions staying on one line.
-}
module PrettyPrint (tests) where

import qualified Data.Text as T
import DataFrame.Internal.Expression (Expr, prettyPrint, prettyPrintWidth)
import DataFrame.Operators
import Test.HUnit

a, b, c :: Expr Double
a = col "a"
b = col "b"
c = col "c"

golden :: String -> String -> String -> Test
golden label want got =
    TestLabel label . TestCase $ assertEqual label want got

tests :: [Test]
tests =
    [ -- A short conditional stays compact; then/else still break onto own lines.
      golden
        "fits on one line"
        "if x .>=. 0.0\nthen \"pos\"\nelse \"neg\""
        ( prettyPrint
            (ifThenElse (col @Double "x" .>=. lit 0.0) (lit @T.Text "pos") (lit "neg"))
        )
    , -- Nested else-if forms a flat ladder (no staircase indentation).
      golden
        "flat else-if ladder"
        "if a .>. 1.0\nthen \"x\"\nelse if b .>. 2.0\nthen \"y\"\nelse \"z\""
        ( prettyPrint
            ( ifThenElse
                (col @Double "a" .>. lit 1.0)
                (lit @T.Text "x")
                (ifThenElse (col @Double "b" .>. lit 2.0) (lit "y") (lit "z"))
            )
        )
    , -- A lower-precedence operand is parenthesized under a higher one.
      golden "precedence: (a + b) * c" "(a + b) * c" (prettyPrint ((a + b) * c))
    , -- No spurious parens when precedence already disambiguates.
      golden "precedence: a + b * c" "a + b * c" (prettyPrint (a + b * c))
    , -- Non-commutative operators are not flattened/reordered.
      golden "left-assoc subtraction" "a - b - c" (prettyPrint (a - b - c))
    , -- A commutative chain stays on one line when it fits the width.
      golden
        "commutative chain fits"
        "alpha + beta + gamma"
        (prettyPrintWidth 80 (col @Double "alpha" + col "beta" + col "gamma"))
    , -- The same chain wraps at the operator with a hanging indent when narrow.
      golden
        "commutative chain wraps"
        "alpha\n  + beta\n  + gamma"
        (prettyPrintWidth 12 (col @Double "alpha" + col "beta" + col "gamma"))
    , -- A comparison/logical chain that fits stays free of grouping parens.
      golden
        "boolean chain fits: no paren noise"
        "a + b .>=. c .&&. a .>. b"
        (prettyPrintWidth 80 ((a + b .>=. c) .&&. (a .>. b)))
    , -- When a nested operand wraps, parens delimit it; flat operands stay bare.
      golden
        "wrapped operand gets parens"
        "(a + b + c\n  .>=. 0.0)\n  .&&. a .>. b"
        (prettyPrintWidth 16 ((a + b + c .>=. lit 0.0) .&&. (a .>. b)))
    ]