phino-0.0.95: test/RewriterSpec.hs
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE LambdaCase #-}
{-# OPTIONS_GHC -Wno-orphans #-}
-- SPDX-FileCopyrightText: Copyright (c) 2025 Objectionary.com
-- SPDX-License-Identifier: MIT
module RewriterSpec where
import AST (Expression (ExRoot))
import Control.Monad (forM_, unless)
import Data.Aeson
import Data.Char (isSpace)
import Data.List.NonEmpty qualified as NE
import Data.Yaml qualified as Yaml
import Deps (dontSaveStep)
import Files (allPathsIn, ensuredFile)
import Functions (buildTerm)
import GHC.Generics
import Must (Must (..))
import Parser (parseProgramThrows)
import Printer (printProgram)
import Rewriter (RewriteContext (RewriteContext), rewrite)
import System.FilePath (makeRelative, replaceExtension, (</>))
import Tau (seedTaus)
import Test.Hspec (Spec, describe, expectationFailure, it, pending, runIO)
import Yaml (normalizationRules)
import Yaml qualified as Y
data Rules = Rules
{ basic :: Maybe [String]
, custom :: Maybe [Y.Rule]
}
deriving (Generic, FromJSON, Show)
data YamlPack = YamlPack
{ input :: String
, output :: String
, rules :: Maybe Rules
, skip :: Maybe Bool
, repeat_ :: Maybe Int
, must :: Maybe Int
, normalize :: Maybe Bool
}
deriving (Generic, Show)
instance FromJSON YamlPack where
parseJSON =
genericParseJSON
defaultOptions
{ fieldLabelModifier = \case
"repeat_" -> "repeat"
other -> other
}
yamlPack :: FilePath -> IO YamlPack
yamlPack = Yaml.decodeFileThrow
noSpaces :: String -> String
noSpaces = filter (not . isSpace)
spec :: Spec
spec =
describe "rewrite packs" $ do
let resources = "test-resources/rewriter-packs"
packs <- runIO (allPathsIn resources)
forM_
packs
( \pth -> it (makeRelative resources pth) $ do
pack <- yamlPack pth
let normalize' = case normalize pack of
Just _ -> True
_ -> False
repeat' =
if normalize'
then 50
else case repeat_ pack of
Just num -> num
_ -> 1
must' = case must pack of
Just num -> MtExact num
_ -> MtDisabled
case skip pack of
Just True -> pending
_ -> do
prog <- parseProgramThrows (input pack)
seedTaus prog
rules' <- case rules pack of
Just _rules -> case custom _rules of
Just custom' -> pure custom'
_ -> case basic _rules of
Just basic' ->
mapM
( \name -> do
yaml <- ensuredFile ("resources/normalize" </> replaceExtension name ".yaml")
Y.yamlRule yaml
)
basic'
_ -> pure []
Nothing ->
if normalize'
then pure normalizationRules
else pure []
(rewrittens, _) <-
rewrite
prog
rules'
( RewriteContext
ExRoot
repeat'
repeat'
False
buildTerm
must'
Nothing
dontSaveStep
)
let (program, _) = NE.last rewrittens
result' <- parseProgramThrows (output pack)
unless (program == result') $
expectationFailure
( "Wrong rewritten program. Expected:\n"
++ printProgram result'
++ "\nGot:\n"
++ printProgram program
)
)