Simple polymorphic and monomorphic functions properly morphed in test demo.

This commit is contained in:
Rakarake 2023-03-07 18:49:21 +01:00
parent 887c3b8391
commit 63f9689f38
3 changed files with 67 additions and 38 deletions

View file

@ -81,6 +81,7 @@ Test-suite language-testsuite
, extra , extra
, array , array
, QuickCheck , QuickCheck
, hspec
default-language: GHC2021 default-language: GHC2021

View file

@ -1,56 +1,84 @@
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} {-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
{-# HLINT ignore "Use <$>" #-} {-# HLINT ignore "Use <$>" #-}
module Main where module Main where
import Grammar.Abs (Ident (Ident), Literal (LInt))
import Control.Monad.Except
import Grammar.Abs
import Test.QuickCheck
import TypeChecker.TypeChecker
import qualified TypeChecker.TypeCheckerIr as T import qualified TypeChecker.TypeCheckerIr as T
import Monomorpher.Monomorpher (monomorphize)
import Grammar.Print (printTree)
import System.IO (stderr)
import GHC.IO.Handle.Text (hPutStrLn)
import Test.Hspec
printToErr :: String -> IO ()
printToErr = hPutStrLn stderr
-- A simple demo
simpleDemo = do
printToErr "# Monomorphic function f"
printToErr "-- Lifted Tree --"
printToErr $ printTree example1
printToErr "-- Monomorphized Tree --"
printToErr $ printTree (monomorphize example1)
printToErr "# Polymorphic function p"
printToErr "-- Lifted Tree --"
printToErr $ printTree example2
printToErr "-- Monomorphized Tree --"
printToErr $ printTree (monomorphize example2)
main :: IO () main :: IO ()
main = do main = do
quickCheck prop_isInt return ()
quickCheck prop_idAbs_generic
newtype AbsExp = AE Exp deriving Show -- | Reusable test constructs for Monomorpher.
newtype EIntExp = EI Exp deriving Show typeInt :: T.Type
typeInt = T.TMono $ Ident "Int"
instance Arbitrary EIntExp where typeIntToInt :: T.Type
arbitrary = genInt typeIntToInt = T.TArr typeInt typeInt
instance Arbitrary AbsExp where typeA :: T.Type
arbitrary = genLambda typeA = T.TPol $ Ident "a"
getType :: Infer (Type, T.Exp) -> Either Error Type typeAToA :: T.Type
getType ie = case run ie of typeAToA = T.TArr typeA typeA
Left err -> Left err
Right (t,e) -> return t
genInt :: Gen EIntExp -- f :: Int -> Int
genInt = EI . ELit . LInt <$> arbitrary -- f x = x + x
fName = (Ident "f", typeIntToInt)
fArg1 = (Ident "x", typeInt)
fArgs = [fArg1]
fExp :: T.Exp
fExp = T.EAdd typeInt (T.EId (Ident "x", typeInt)) (T.EId (Ident "x", typeInt))
f :: T.Bind
f = T.Bind fName fArgs fExp
genLambda :: Gen AbsExp -- f :: a -> a
genLambda = do -- f x = x + x
str <- arbitrary @String pName = (Ident "p", typeAToA)
let str' = Ident str pArg1 = (Ident "x", typeA)
return $ AE $ EAbs str' (EId str') pArgs = [pArg1]
pExp :: T.Exp
pExp = T.EAdd typeA (T.EId (Ident "x", typeA)) (T.EId (Ident "x", typeA))
p :: T.Bind
p = T.Bind pName pArgs pExp
prop_idAbs_generic :: AbsExp -> Bool
prop_idAbs_generic (AE e) = case getType (inferExp e) of
Left _ -> False
Right t -> isGenericArr t
prop_isInt :: EIntExp -> Bool -- | Examples
prop_isInt (EI e) = case getType (inferExp e) of
Left _ -> False
Right t -> t == int
int :: Type -- main = f 5
int = TMono "Int" example1Name = (Ident "main", typeInt)
example1Exp :: T.Exp
example1Exp = T.EApp typeInt (T.EId (Ident "f", typeIntToInt)) (T.ELit typeInt $ LInt 5)
example1 :: T.Program
example1 = T.Program [T.Bind example1Name [] example1Exp, f]
-- main = p 5
example2Name = (Ident "main", typeInt)
example2Exp :: T.Exp
example2Exp = T.EApp typeInt (T.EId (Ident "p", typeIntToInt)) (T.ELit typeInt $ LInt 5)
example2 :: T.Program
example2 = T.Program [T.Bind example2Name [] example2Exp, p]
isGenericArr :: Type -> Bool
isGenericArr (TArr (TPol a) (TPol b)) = a == b
isGenericArr _ = False