Skip to content

Commit

Permalink
Merge pull request #2227 from ucsd-progsys/fd/test-case-desugaring
Browse files Browse the repository at this point in the history
Add a GHC API test for case desugaring
  • Loading branch information
facundominguez authored Sep 27, 2023
2 parents 79b339c + fbf68a6 commit c55c331
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 5 deletions.
87 changes: 82 additions & 5 deletions liquidhaskell-boot/ghc-api-tests/GhcApiTests.hs
Original file line number Diff line number Diff line change
@@ -1,29 +1,45 @@

import Control.Monad
import Data.List (find)
import Data.Time (getCurrentTime)
import Liquid.GHC.API
( ApiComment(ApiBlockComment)
, Expr(..)
, Alt(..)
, AltCon(..)
, apiCommentsParsedSource
, occNameString
, pAT_ERROR_ID
, showPprQualified
)
import Test.Tasty
import Test.Tasty.HUnit
import Test.Tasty.Runners.AntXML

import qualified GHC as GHC
import qualified GHC.Core as GHC
import qualified GHC.Data.EnumSet as EnumSet
import qualified GHC.Data.FastString as GHC
import qualified GHC.Data.StringBuffer as GHC
import qualified GHC.Parser as GHC
import qualified GHC.Parser as Parser
import qualified GHC.Parser.Lexer as GHC
import qualified GHC.Types.Name.Occurrence as GHC
import qualified GHC.Types.SrcLoc as GHC
import qualified GHC.Unit.Module.ModGuts as GHC

import GHC.Paths (libdir)


main :: IO ()
main =
defaultMainWithIngredients (antXMLRunner:defaultIngredients) testTree

testTree :: TestTree
testTree =
testGroup "GHC API" [
testCase "apiComments" testApiComments
]
testGroup "GHC API"
[ testCase "apiComments" testApiComments
, testCase "caseDesugaring" testCaseDesugaring
]

-- Tests that Liquid.GHC.API.Extra.apiComments can retrieve the comments in
-- the right order from an AST
Expand Down Expand Up @@ -64,6 +80,67 @@ testApiComments = do
buffer = GHC.stringToStringBuffer str
popts = GHC.mkParserOpts EnumSet.empty EnumSet.empty False True True True
parseState = GHC.initParserState popts buffer location
case GHC.unP GHC.parseModule parseState of
case GHC.unP Parser.parseModule parseState of
GHC.POk _ result -> return result
_ -> fail "Unexpected parser error"


-- | Tests that case expressions desugar as Liquid Haskell expects.
testCaseDesugaring :: IO ()
testCaseDesugaring = do
let inputSource = unlines
[ "module CaseDesugaring where"
, "f :: Bool -> ()"
, "f x = case x of"
, " True -> ()"
]

fBind (GHC.NonRec b _e) =
occNameString (GHC.occName b) == "f"
fBind _ = False

-- Expected desugaring:
--
-- CaseDesugaring.f
-- = \ (x :: GHC.Types.Bool) ->
-- case x of {
-- __DEFAULT ->
-- case Control.Exception.Base.patError ...
-- of {
-- };
-- GHC.Types.True -> GHC.Tuple.()
-- }
--
isExpectedDesugaring p = case find fBind p of
Just (GHC.NonRec _ e0)
| Lam x (Case (Var x') _ _ [alt0, _alt1]) <- e0
, x == x'
, Alt DEFAULT [] e1 <- alt0
, Case e2 _ _ [] <- e1
, (Var e3,_) <- GHC.collectArgs e2
-> e3 == pAT_ERROR_ID
_ -> False

coreProgram <- compileToCore inputSource
unless (isExpectedDesugaring coreProgram) $
fail $ unlines $
"Unexpected desugaring:" : map showPprQualified coreProgram
where
compileToCore inputSource = do
now <- getCurrentTime
GHC.runGhc (Just libdir) $ do
df1 <- GHC.getSessionDynFlags
GHC.setSessionDynFlags df1
let target = GHC.Target {
GHC.targetId = GHC.TargetFile "CaseDesugaring.hs" Nothing
, GHC.targetAllowObjCode = False
, GHC.targetContents = Just (GHC.stringToStringBuffer inputSource, now)
}
GHC.setTargets [target]
void $ GHC.load GHC.LoadAllTargets

dsMod <- GHC.getModSummary (GHC.mkModuleName "CaseDesugaring")
>>= GHC.parseModule
>>= GHC.typecheckModule
>>= GHC.desugarModule
return $ GHC.mg_binds $ GHC.dm_core_module dsMod
2 changes: 2 additions & 0 deletions liquidhaskell-boot/liquidhaskell-boot.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,12 @@ test-suite ghc-api-tests
hs-source-dirs: ghc-api-tests
build-depends: base
, ghc
, ghc-paths
, liquidhaskell-boot
, tasty
, tasty-ant-xml
, tasty-hunit
, time
default-language: Haskell2010
ghc-options: -W

Expand Down

0 comments on commit c55c331

Please sign in to comment.