{-# Language FlexibleInstances #-} module Main where import Data.Either.Validation (Validation(..)) import Data.Functor.Identity (Identity(Identity)) import Data.List (isSuffixOf) import Data.List.NonEmpty (NonEmpty((:|)), toList) import Data.Text (Text, unpack) import Data.Text.IO (readFile) import Data.Text.Prettyprint.Doc (Pretty(pretty), layoutPretty, defaultLayoutOptions) import Data.Text.Prettyprint.Doc.Render.Text (renderStrict) import System.Directory (doesDirectoryExist, listDirectory) import System.FilePath.Posix (combine) import Test.Tasty (TestTree, defaultMain, testGroup) import Test.Tasty.HUnit (assertFailure, assertEqual, testCase) import qualified Transformation.Rank2 as Rank2 import Language.Oberon (parseAndResolveModule, LanguageVersion(Oberon2), Options(..), Placed) import Language.Oberon.AST (Language, Module) import Language.Oberon.Pretty () import qualified Language.Oberon.Resolver as Resolver import qualified Language.Oberon.TypeChecker as TypeChecker import qualified Language.Oberon.AST as AST import qualified Language.Oberon.Grammar as Grammar import qualified Language.Oberon.Reserializer as Reserializer import qualified Transformation.Deep as Deep import Prelude hiding (readFile) main = exampleTree "" "examples" >>= defaultMain . testGroup "Oberon" width = 80 contextLines = 3 exampleTree :: FilePath -> FilePath -> IO [TestTree] exampleTree ancestry path = do let fullPath = combine ancestry path isDir <- doesDirectoryExist fullPath if isDir then (:[]) . testGroup path . concat <$> (listDirectory fullPath >>= mapM (exampleTree fullPath)) else if ".Mod" `isSuffixOf` path then return . (:[]) . testCase path $ do moduleSource <- readFile fullPath prettyModule <- prettyFile ancestry moduleSource prettyModule' <- prettyFile ancestry prettyModule assertEqual "pretty" prettyModule prettyModule' else return [] prettyFile :: FilePath -> Text -> IO Text prettyFile dirPath source = do resolvedModule <- parseAndResolveModule Options{foldConstants= True, checkTypes= True, version= Oberon2} dirPath source case resolvedModule of Failure (Left (Resolver.UnparseableModule err :| [])) -> assertFailure (unpack err) Failure (Right errs) -> assertFailure $ show $ [(TypeChecker.errorModule err, TypeChecker.errorPosition err, TypeChecker.errorMessage $ TypeChecker.errorType err) | err <- toList errs] Success mod -> return (renderStrict $ layoutPretty defaultLayoutOptions $ pretty mod) instance {-# overlaps #-} Pretty (Placed (Module Language Language Placed Placed)) where pretty (_, m) = pretty ((Identity . snd) Rank2.<$> m)