packages feed

kempe 0.2.0.9 → 0.2.0.10

raw patch · 14 files changed

+94/−52 lines, 14 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,10 @@ # kempe +## 0.2.0.10++  * Fix bug in typechecking against inferred signatures.+  * Fix bug in prelude+ ## 0.2.0.9    * Add `armabi` method of exporting Kempe functions, so that `kc` generates
docs/manual.pdf view

binary file changed (217165 → 217165 bytes)

golden/CDecl.hs view
@@ -5,7 +5,7 @@ import           Data.Text.Lazy.Encoding   (encodeUtf8) import           Kempe.File import           Language.C.AST-import           Prettyprinter             (Doc, LayoutOptions (..), PageWidth (..), layoutSmart)+import           Prettyprinter             (Doc, layoutSmart) import           Prettyprinter.Render.Text (renderLazy) import           Test.Tasty                (TestTree) import           Test.Tasty.Golden         (goldenVsString)
golden/Golden.hs view
@@ -20,7 +20,9 @@     _         -> error "Test suite must be run on x86_64 or aarch64"  headerGoldens :: [(FilePath, FilePath)]-headerGoldens = [ ("test/examples/splitmix.kmp", "test/include/splitmix.h") ]+headerGoldens = [ ("test/examples/splitmix.kmp", "test/include/splitmix.h")+                , ("lib/numbertheory.kmp", "test/include/num.h")+                ]  allGoldens :: [(FilePath, FilePath, FilePath)] allGoldens =
kempe.cabal view
@@ -1,6 +1,6 @@ cabal-version:   3.0 name:            kempe-version:         0.2.0.9+version:         0.2.0.10 license:         BSD-3-Clause license-file:    LICENSE copyright:       Copyright: (c) 2020-2021 Vanessa McHale
prelude/fn.kmp view
@@ -10,7 +10,11 @@      =: [ swap dip(swap) ]  rotl : a b c -- c b a-     =: [ dip(swap) swap ]+     =: [ rotr swap ]++; from https://docs.factorcode.org/content/word-pick%2Ckernel.html+pick : a b c -- a b c a+     =: [ dip(dip(dup)) dip(swap) swap ]  over : a b -- a b a      =: [ dip(dup) swap ]
src/Kempe/Check/Lint.hs view
@@ -33,7 +33,7 @@ lintAtoms ((Dip l [AtBuiltin _ WordTimes]):a@(AtBuiltin _ WordTimes):_) = Just (DipAssoc l a) lintAtoms ((Dip l [AtBuiltin _ And]):a@(AtBuiltin _ And):_)             = Just (DipAssoc l a) lintAtoms ((Dip l [AtBuiltin _ Or]):a@(AtBuiltin _ Or):_)               = Just (DipAssoc l a)-lintAtoms ((Dip l [AtBuiltin _ IntEq]):a@(AtBuiltin _ IntEq):_)         = Just (DipAssoc l a)+-- lintAtoms ((Dip l [AtBuiltin _ IntEq]):a@(AtBuiltin _ IntEq):_)         = Just (DipAssoc l a) lintAtoms ((AtBuiltin l Swap):(AtBuiltin _ Swap):_)                     = Just (DoubleSwap l) lintAtoms ((AtBuiltin l Dup):a@(AtBuiltin _ And):_)                     = Just (Identity l a) lintAtoms ((AtBuiltin l Dup):a@(AtBuiltin _ Or):_)                      = Just (Identity l a)
src/Kempe/Error.hs view
@@ -43,7 +43,7 @@     pretty (UnificationFailed _ ty ty')  = "could not unify type" <+> squotes (pretty ty) <+> "with" <+> squotes (pretty ty')     pretty (TyVarExt _ n)                = "Error in function" <+> pretty n <> ": type variables may not occur in external or exported functions."     pretty (MonoFailed _)                = "Monomorphization step failed"-    pretty (LessGeneral _ sty sty')      = "Type" <+> pretty sty' <+> "is not as general as type" <+> pretty sty+    pretty (LessGeneral _ sty sty')      = "Type" <+> pretty sty' <+> "is not as general as type" <+> pretty sty <+> "or does not match."     pretty (InvalidCExport _ n)          = "C export" <+> pretty n <+> "has more than one return value"     pretty (InvalidCImport _ n)          = pretty n <+> "imported functions can have at most one return value"     pretty (IllKinded _ ty)              = "Ill-kinded type:" <+> squotes (pretty ty) <> ". Note that type variables have kind ⭑ in Kempe."
src/Kempe/TyAssign.hs view
@@ -11,12 +11,11 @@ import           Control.Composition        (thread, (.$)) import           Control.Monad              (foldM, replicateM, unless, when, zipWithM_) import           Control.Monad.Except       (throwError)-import           Control.Monad.State.Strict (StateT, get, gets, modify, put, runStateT)+import           Control.Monad.State.Strict (State, StateT, evalState, get, gets, modify, put, runStateT) import           Data.Bifunctor             (bimap, second) import           Data.Foldable              (traverse_) import           Data.Functor               (void, ($>)) import qualified Data.IntMap                as IM-import           Data.List                  (foldl') import           Data.List.NonEmpty         (NonEmpty (..)) import           Data.Semigroup             ((<>)) import qualified Data.Set                   as S@@ -294,14 +293,22 @@     where dropFst (_, y, z) = (y, z)  assignAtoms :: [Atom b a] -> TypeM () ([Atom (StackType ()) (StackType ())], StackType ())-assignAtoms = foldM-    (\seed a -> do { (ty, r) <- assignAtom a ; (fst seed ++ [r] ,) <$> catTypes (snd seed) ty })-    ([], emptyStackType)+assignAtoms []  = pure ([], emptyStackType)+assignAtoms [a] = do+    (ty, a') <- assignAtom a+    pure ([a'], ty)+assignAtoms (a:as) = do+    (ty, a') <- assignAtom a+    (as', ty') <- assignAtoms as+    (a':as' ,) <$> catTypes ty ty'  tyAtoms :: [Atom b a] -> TypeM () (StackType ())-tyAtoms = foldM-    (\seed a -> do { tys' <- tyAtom a ; catTypes seed tys' })-    emptyStackType+tyAtoms [] = pure emptyStackType+tyAtoms [a] = tyAtom a+tyAtoms (a:as) = do+    ty <- tyAtom a+    tys <- tyAtoms as+    catTypes ty tys  -- from size, mkHKT :: Int -> Kind@@ -334,7 +341,7 @@     (tn $> ty, fmap void ins)  app :: KempeTy a -> [Name a] -> KempeTy a-app = foldl' (\ty n -> TyApp undefined ty (TyVar undefined n))+app = foldr (\n ty -> TyApp undefined ty (TyVar undefined n))  kindLookup :: TyName a -> TypeM a Kind kindLookup n@(Name _ (Unique i) l) = do@@ -361,14 +368,14 @@     sig <- renameStack $ voidStackType $ StackType (freeVars (ins ++ os)) ins os     (as, inferred) <- assignAtoms a     reconcile <- mergeStackTypes sig inferred-    -- assign comes after tyInsert+    when (inferred `lessGeneral` sig) $+        throwError $ LessGeneral () sig inferred     pure $ FunDecl reconcile (n $> reconcile) (void <$> ins) (void <$> os) as assignDecl (ExtFnDecl _ n ins os cn) = do     traverse_ kindOf (void <$> ins ++ os)     unless (length os <= 1) $         throwError $ InvalidCImport () (void n)     let sig = voidStackType $ StackType S.empty ins os-    -- assign always comes after tyInsert     pure $ ExtFnDecl sig (n $> sig) (void <$> ins) (void <$> os) cn assignDecl (Export _ abi n) = do     ty@(StackType _ _ os) <- tyLookup (void n)@@ -394,18 +401,56 @@     modifying tyEnvLens (IM.insert i sig) tyHeader TyDecl{} = pure () -lessGeneral :: StackType a -> StackType a -> Bool-lessGeneral (StackType _ is os) (StackType _ is' os') = lessGenerals (is ++ os) (is' ++ os')-    where lessGeneralAtom :: KempeTy a -> KempeTy a -> Bool-          lessGeneralAtom TyBuiltin{} TyVar{}                   = True-          lessGeneralAtom TyApp{} TyVar{}                       = True-          lessGeneralAtom (TyApp _ ty ty') (TyApp _ ty'' ty''') = lessGeneralAtom ty ty'' || lessGeneralAtom ty' ty''' -- lazy pattern match?-          lessGeneralAtom _ _                                   = False-          lessGenerals :: [KempeTy a] -> [KempeTy a] -> Bool-          lessGenerals [] []               = False-          lessGenerals (ty:tys) (ty':tys') = lessGeneralAtom ty ty' || lessGenerals tys tys'-          lessGenerals _ []                = False -- shouldn't happen; will be caught later-          lessGenerals [] _                = False+type Vars a = IM.IntMap (Name a)++-- TODO: do we want strict or lazy?+type EqState a = State (Vars a)++-- FIXME: this is too simple-minded.+-- a -- a b+-- checks against+-- dup+-- because it results in the constraint a = b...+--+-- NEED to check stack types are equivalent up to "alpha-equivalence"+-- (implicit binding with every space/new var!)+lessGeneral :: StackType a -- ^ Inferred type+            -> StackType a -- ^ Type from signature+            -> Bool+lessGeneral (StackType _ is os) (StackType _ is' os') =+    flip evalState mempty $+        if il > il' || ol > ol'+            then (||) <$> lessGenerals trimIs is' <*> lessGenerals trimOs os'+            else (||) <$> lessGenerals is trimIs' <*> lessGenerals os trimOs'+    where il = length is+          il' = length is'+          ol = length os+          ol' = length os'+          trimIs = drop (il-il') is+          trimIs' = drop (il'-il) is'+          trimOs = drop (ol-ol') os+          trimOs' = drop (ol'-ol) os'++          lessGeneralAtom :: KempeTy a -> KempeTy a -> EqState a Bool+          lessGeneralAtom TyBuiltin{} TyVar{}                   = pure True+          lessGeneralAtom TyApp{} TyVar{}                       = pure True+          -- FIXME: Type a_13 (Maybe_1 a_10) -- a_12 is not as general as type a_9 (Maybe_1 a_9) -- a_9+          --+          -- FIXME Type a_38 b_39 a_40 -- b_39 b_42 a_41 is not as general as type a_35 b_36 c_37 -- c_37 b_36 a_35+          lessGeneralAtom (TyApp _ ty ty') (TyApp _ ty'' ty''') = (||) <$> lessGeneralAtom ty ty'' <*> lessGeneralAtom ty' ty''' -- lazy pattern match?+          lessGeneralAtom _ _                                   = pure False+          lessGenerals :: [KempeTy a] -> [KempeTy a] -> EqState a Bool+          lessGenerals [] []                                 = pure False+          lessGenerals ((TyVar _ n):tys) ((TyVar _ n'):tys') = do+                st <- get+                let i = unUnique $ unique n+                case IM.lookup i st of+                    Nothing ->+                        modify (IM.insert i n') *>+                        lessGenerals tys tys' -- we can skip checking ty `lessGeneral` ty' at the first site+                    Just n'' ->+                        (n'' /= n' ||) <$> lessGenerals tys tys'+          lessGenerals (ty:tys) (ty':tys')                  = (||) <$> lessGeneralAtom ty ty' <*> lessGenerals tys tys'  tyInsert :: KempeDecl a c b -> TypeM () () tyInsert (TyDecl _ tn ns ls) = traverse_ (tyInsertLeaf tn (S.fromList ns)) ls
test/Parser.hs view
@@ -2,19 +2,11 @@               ) where  import qualified Data.ByteString.Lazy as BSL-import           Kempe.Lexer import           Kempe.Parser import           Prettyprinter        (pretty) import           Test.Tasty import           Test.Tasty.HUnit -lexNoError :: FilePath -> TestTree-lexNoError fp = testCase ("Lexing doesn't fail (" ++ fp ++ ")") $ do-    contents <- BSL.readFile fp-    case lexKempe contents of-        Left err -> assertFailure err-        Right{}  -> assertBool "Doesn't fail lexing" True- parseNoError :: FilePath -> TestTree parseNoError fp = testCase ("Parsing doesn't fail (" ++ fp ++ ")") $ do     contents <- BSL.readFile fp@@ -26,8 +18,6 @@ parserTests :: TestTree parserTests =     testGroup "Parser golden tests"-        [ lexNoError "test/data/lex.kmp"-        , lexNoError "examples/splitmix.kmp"-        , parseNoError "test/data/lex.kmp"+        [ parseNoError "test/data/lex.kmp"         , parseNoError "examples/splitmix.kmp"         ]
test/Type.hs view
@@ -27,11 +27,10 @@         , tyInfer "lib/gaussian.kmp"         , tyInfer "test/data/transitive.kmp"         , tyInfer "lib/tuple.kmp"-        , badType "test/err/merge.kmp" "Type a_5 -- Int a_4 is not as general as type a_3 -- a_3 a_3"+        , badType "test/err/merge.kmp" "Type a_4 -- Int a_4 is not as general as type a_3 -- a_3 a_3 or does not match."         , badType "test/err/kind.kmp" "Ill-kinded type: '(Maybe_1 Maybe_1)'. Note that type variables have kind \11089 in Kempe."         , badType "test/err/patternMatch.kmp" "Inexhaustive pattern match."-        , detectsWarn "test/err/stupid.kmp" "4:1 'rand_1' is defined more than once."-        , detectsWarn "test/err/questionable.kmp" "3:19 'Some_3' is defined more than once."+        , badType "test/err/typecheck.kmp" "Type a_8 a_9 a_10 -- a_8 a_8 a_9 a_10 is not as general as type a_5\nb_6\nc_7 -- a_5 b_6 c_7 a_5 or does not match."         , testAssignment "test/data/ty.kmp"         , testAssignment "lib/either.kmp"         , testAssignment "prelude/fn.kmp"@@ -57,13 +56,6 @@     case res of         Left err -> assertFailure (show $ pretty err)         Right{}  -> assertBool "Doesn't fail type-checking" True--detectsWarn :: FilePath -> String -> TestTree-detectsWarn fp msg = testCase ("Warns (" ++ fp ++ ")") $ do-    res <- warnFile fp-    case res of-        Just err -> show (pretty err) @?= msg-        Nothing  -> assertFailure "Failed to warn!"  badType :: FilePath -> String -> TestTree badType fp msg = testCase ("Detects error (" ++ fp ++ ")") $ do
test/data/mutual.kmp view
@@ -1,5 +1,3 @@-import "lib/bool.kmp"- odd : Int -- Bool     =: [ dup 0 =             if( drop False
+ test/err/typecheck.kmp view
@@ -0,0 +1,3 @@+; FIXME: should not typecheck (just generates constraint b = c, which should not be allowed+pick : a b c -- a b c a+     =: [ dip(dip(dup)) ]
+ test/include/num.h view
@@ -0,0 +1,3 @@+#include <stdbool.h>+extern int k_gcd (void*, int, int);+extern bool is_prime (void*, int);