alms 0.4.12 → 0.5.0
raw patch · 29 files changed
+475/−278 lines, 29 filesdep ~parsec
Dependency ranges changed: parsec
Files
- Makefile +1/−1
- alms.cabal +12/−3
- examples/echoServer.alms +2/−2
- examples/ex03-poly-blame-error.alms +1/−1
- examples/ex27-focusing-and-adoption.alms +40/−41
- examples/ex28-focusing-and-adoption.alms +2/−2
- examples/ex63-popl-CapArray.alms +2/−2
- lib/libbasis.alms +1/−0
- src/Basis.hs +5/−5
- src/Basis/Channel/Haskell.hs +38/−51
- src/Coercion.hs +1/−1
- src/Compat.hs +39/−0
- src/ErrorST.hs +3/−2
- src/Lexer.hs +24/−6
- src/Makefile +4/−1
- src/Message/Quasi.hs +2/−3
- src/Meta/Quasi.hs +17/−15
- src/Meta/THHelpers.hs +5/−3
- src/Parser.hs +18/−18
- src/Ppr.hs +6/−6
- src/Rename.hs +11/−7
- src/Statics.hs +38/−29
- src/Syntax/Decl.hs-boot +3/−1
- src/Syntax/Ident.hs-boot +3/−1
- src/Syntax/POClass.hs +11/−10
- src/Syntax/Type.hs +7/−5
- src/Type.hs +117/−13
- src/TypeRel.hs +49/−42
- src/Util.hs +13/−7
Makefile view
@@ -50,7 +50,7 @@ $(RM) html -VERSION = 0.4.12+VERSION = 0.5.0 DISTDIR = alms-$(VERSION) TARBALL = $(DISTDIR).tar.gz
alms.cabal view
@@ -1,5 +1,5 @@ Name: alms-Version: 0.4.12+Version: 0.5.0 Copyright: 2010, Jesse A. Tov Cabal-Version: >= 1.8 License: BSD3@@ -31,8 +31,10 @@ Flag editline Description: Enable line editing using the editline package- Default: True +Flag parsec3+ Description: Use version 3 of the parsec package+ Flag readline Description: Enable line editing using the readline package Default: False@@ -47,7 +49,6 @@ syb >= 0.1, pretty >= 1, containers >= 0.1,- parsec == 2.*, mtl >= 1.1, filepath >= 1.1, network >= 2.2,@@ -69,6 +70,7 @@ Basis.Thread, BasisUtils, Coercion,+ Compat, Dynamics, Env, ErrorMessage,@@ -121,4 +123,11 @@ if flag(editline) Build-Depends: editline >= 0.2.1 CPP-Options: -DUSE_READLINE=System.Console.Editline.Readline++ if flag(parsec3)+ Build-Depends: parsec == 3.*+ CPP-Options: -DPARSEC_VERSION=3+ else+ Build-Depends: parsec == 2.*+ CPP-Options: -DPARSEC_VERSION=2
examples/echoServer.alms view
@@ -19,7 +19,7 @@ let rec acceptLoop['t] (sock: 't socket) (f: string -> string) (cap: 't listening) : unit =- let (Pack('s, clientsock, clientcap), cap) = accept sock cap in+ let (('s, clientsock, clientcap), cap) = accept sock cap in putStrLn "Opened connection"; (Thread.fork :> (unit -o unit) -> Thread.thread) (fun () -> handleClient clientsock f clientcap;@@ -27,7 +27,7 @@ acceptLoop sock f cap let serve (port: int) (f: string -> string) =- let Pack('t, sock, cap) = socket () in+ let ('t, sock, cap) = socket () in let cap = bind sock port cap in let cap = listen sock cap in acceptLoop sock f cap
examples/ex03-poly-blame-error.alms view
@@ -5,7 +5,7 @@ let inc2 = fun y: int ->- let g = (ap :> all 'a 'b. ('a -o 'b) -> 'a -> 'b)+ let g = (ap :> all 'a 'b. ('a -A> 'b) -> 'a -U> 'b) (fun z: int -> z + 1) in g (g y) (* g is used twice here *)
examples/ex27-focusing-and-adoption.alms view
@@ -23,12 +23,12 @@ (n + 1, Cons (x, xs))) (0, Nil[`a]) xs -let snoc[`a] (x: `a) | (xs: `a list) : `a list =+let snoc[`a] (x: `a) |[a] (xs: `a list) : `a list = foldr (fun (x: `a) (xs: `a list) -> Cons (x, xs)) (Cons (x, Nil[`a])) xs let revAppN =- let rec loop[`a] (n: int) (xs: `a list) | (acc: `a list)+ let rec loop[`a] (n: int) (xs: `a list) |[a] (acc: `a list) : `a list * `a list = match n with | 0 -> (acc, xs)@@ -41,55 +41,54 @@ let (_, acc) = revAppN (-1) xs Nil[`a] in acc -let swapN[`a] (ix: int) (y: `a) | (xs: `a list)+let swapN[`a] (ix: int) (y: `a) |[a] (xs: `a list) : `a * `a list = let (Cons(x, xs), acc) = revAppN ix xs Nil[`a] in let (xs, _) = revAppN (-1) acc (Cons (y, xs)) in (x, xs) -abstype ('t, `a) region qualifier A = Rgn of `a list- and ('t, `a) region1 qualifier A = Rgn1 of `a- and 't ptr qualifier U = Ptr of int-with- let newRgn[`a] () =- Pack[ex 't. ('t, `a) region] (unit, Rgn[unit] (Nil[`a]))- let freeRgn[`a,'t] (_: ('t, `a) region) = ()+module Region : sig+ type ('t, `a) region : A+ type ('t, `a) region1 : A+ type 't ptr - let mallocIn[`a,'t] (Rgn xs: ('t, `a) region) | (a: `a)- : 't ptr * ('t, `a) region =+ val newRgn : unit -> ex 't. ('t,`a) region+ val mallocIn : ('t,`a) region -> `a -o 't ptr * ('t,`a) region+ val swap : ('t,`a) region -> 't ptr -o `a -o `a * ('t,`a) region+ val malloc : unit -> ex 't. ('t,unit) region1 * 't ptr+ val free : ('t,`a) region1 -> unit+ val adopt : ('t1,`a) region -> ('t2,`a) region1 -o 't2 ptr -o+ 't1 ptr * ('t1,`a) region+ val focus : ('t,`a) region -> 't ptr -o+ ex 't1. ('t1,`a) region1 * 't1 ptr *+ (('t1,`a) region1 -o ('t,`a) region)+end = struct+ type ('t, `a) region = `a list+ type ('t, `a) region1 = `a+ type 't ptr = int++ let newRgn () = Nil++ let freeRgn _ = ()++ let mallocIn (xs: `a list) (a: `a) = let (ix, xs) = length xs in- (Ptr['t] ix, Rgn['t] (snoc a xs))- let swap[`a,'t] (Rgn xs: ('t, `a) region) |- (Ptr ix: 't ptr) (x: `a)- : `a * ('t, `a) region =+ (ix, snoc a xs)++ let swap (xs: `a list) (ix: 't ptr) (x: `a) = let (y, xs) = swapN ix x xs in- (y, Rgn['t] xs)+ (y, xs) - let malloc () =- Pack[ex 't. ('t, unit) region1 * 't ptr]- (unit, Rgn1[unit] (), Ptr[unit] 0)- let swap1[`a,`b,'t] (Rgn1 x: ('t, `a) region1) |- (_: 't ptr) (y: `b)- : `a * ('t, `b) region1 =- (x, Rgn1['t] y)- let free[`a, 't] (_: ('t, `a) region1) = ()+ let malloc () = ((), 0) - let adopt[`a,'t1,'t2] (rgn: ('t1, `a) region) |- (Rgn1 x: ('t2, `a) region1)- (_: 't2 ptr)- : 't1 ptr * ('t1, `a) region =+ let swap1 (x: `a) _ (y: `b) = (x, y)++ let free _ = ()++ let adopt (rgn: `a list) (x: `a) _ = mallocIn rgn x - let focus[`a,'t]- (Rgn xs: ('t, `a) region) |- (Ptr ix: 't ptr)- : ex 't1. ('t1, `a) region1 * 't1 ptr *- (('t1, `a) region1 -o ('t, `a) region) =- let (Cons (x, xs), acc) = revAppN ix xs Nil[`a] in- Pack[ex 't1. ('t1, `a) region1 * 't1 ptr *- (('t1, `a) region1 -o ('t, `a) region)]- (unit, Rgn1[unit] x, Ptr[unit] 0,- fun (Rgn1 y: (unit, `a) region1) ->- let (xs, _) = revAppN (-1) acc (Cons (y, xs)) in- Rgn['t] xs)+ let focus (xs: `a list) (ix: 't ptr) =+ let (Cons (x, xs), acc) = revAppN ix xs Nil in+ (x, 0, fun (y: `a) -> fst (revAppN (-1) acc (Cons (y, xs)))) end
examples/ex28-focusing-and-adoption.alms view
@@ -11,7 +11,7 @@ (n + 1, Cons (x, xs))) (0, Nil[`a]) xs -let snoc[`a] (x: `a) | (xs: `a list) : `a list =+let snoc[`a] (x: `a) |[a] (xs: `a list) : `a list = foldr (fun (x: `a) (xs: `a list) -> Cons (x, xs)) (Cons (x, Nil[`a])) xs @@ -25,7 +25,7 @@ | xs -> (acc, xs) in loop -let swapN[`a] (ix: int) (y: `a) | (xs: `a list)+let swapN[`a] (ix: int) (y: `a) |[a] (xs: `a list) : `a * `a list = let (Cons(x, xs), acc) = revAppN ix xs Nil[`a] in let (xs, _) = revAppN (-1) acc (Cons (y, xs)) in
examples/ex63-popl-CapArray.alms view
@@ -4,9 +4,9 @@ type ('a,'b) array type 'b cap : A - val new : int → 'a → ∃'b. ('a,'b) array * 'b cap+ val new : int → 'a → ∃'b. ('a,'b) array × 'b cap val set : ('a,'b) array → int → 'a → 'b cap → 'b cap- val get : ('a,'b) array → int → 'b cap → 'a * 'b cap+ val get : ('a,'b) array → int → 'b cap → 'a × 'b cap val dirtyGet : ('a,'b) array → int → 'a val size : ('a,'b) array → int
lib/libbasis.alms view
@@ -142,6 +142,7 @@ | Some y -> Cons(y, xs') | None -> xs') Nil+ xs let revApp[`c] (xs : `c list) (ys : `c list) = let cons (x : `c) (acc : `c list) = Cons (x, acc) in foldl cons ys xs
src/Basis.hs view
@@ -113,9 +113,9 @@ -= (read :: String -> Double), -- Strings- fun "explode" -: [$ty| string -> int list |]+ fun "explode" -: [$ty| string -> char list |] -= map char2integer,- fun "implode" -: [$ty| int list -> string |]+ fun "implode" -: [$ty| char list -> string |] -= map integer2char, fun "^" -: [$ty| string -> string -> string |] -= ((++) :: String -> String -> String),@@ -131,9 +131,9 @@ -= (print :: Value -> IO ()), -- I/O- fun "putChar" -: [$ty| int -> unit |]+ fun "putChar" -: [$ty| char -> unit |] -= putChar . integer2char,- fun "getChar" -: [$ty| unit -> int |]+ fun "getChar" -: [$ty| unit -> char |] -= \() -> fmap char2integer getChar, fun "flush" -: [$ty| unit -> unit |] -= \() -> IO.hFlush IO.stdout,@@ -168,7 +168,7 @@ -= (\r -> do v <- readIORef (unRef r) return (r, v)),- fun "<-" -: [$ty| all `a. `a ref -> `a -o `a |]+ fun "<-" -: [$ty| all `a. `a ref -> `a -> `a |] -= (\r v -> do atomicModifyIORef (unRef r) (\v' -> (v, v'))), fun "<-!" -: [$ty| all `a `b. `a aref ->
src/Basis/Channel/Haskell.hs view
@@ -6,7 +6,7 @@ -- -- Maintainer : tov@ccs.neu.edu -- Stability : experimental--- Portability : somewhat portable?+-- Portability : GHC 6-7 -- -- This module provides synchronous channels. Unlike the channels in -- 'Control.Concurrent.Chan', which are unbounded queues on which@@ -45,7 +45,7 @@ -- with another. In particular, we can write code like this: -- -- @- -- 'Control.Exception.block' $ do+ -- 'Control.Exception.mask_' $ do -- msg <- 'readChan' c -- 'writeIORef' r msg -- @@@ -113,11 +113,13 @@ ) where import Control.Concurrent.MVar hiding ( modifyMVar )-import Control.Exception import Control.Monad import Data.IORef import System.IO.Unsafe ( unsafeInterleaveIO ) +import Control.Exception ( finally, onException )+import Compat ( mask )+ --- --- Amortized O(1) queues ---@@ -196,7 +198,7 @@ getWriters (WQ q) = dequeue empty q clear :: IO a -> IORef (Maybe b) -> IO a-clear io r = block $ io `finally` writeIORef r Nothing+clear io r = mask $ \_ -> io `finally` writeIORef r Nothing -- | Make a new channel. newChan :: IO (Chan a)@@ -355,7 +357,7 @@ Just a -> do r' <- newIORef (Just a') confirm' <- newEmptyMVar- _ <- block $ do+ _ <- mask $ \_ -> do putMVar confirm () commit (WQ ((r', confirm') <| writers)) return $ do@@ -585,7 +587,7 @@ loop [] e = return (e, Success (Success (), [])) loop (a:as) e = do case getReaders e of- r :< readers -> block $ do+ r :< readers -> mask $ \_ -> do maybereader <- readIORef r case maybereader of Just reader -> do@@ -609,64 +611,49 @@ --- Helpful MVar stuff --- -saveBlock :: IO (IO a -> IO a)-saveBlock = do- b <- blocked- case b of- True -> return block- False -> return unblock- modifyMVar :: MVar a -> (a -> IO (a, b)) -> IO b-modifyMVar m io = do- restore <- saveBlock- block $ do- a <- takeMVar m- (a',b) <- restore (io a)- `onException` putMVar m a- putMVar m a'- return b+modifyMVar m io = mask $ \restore -> do+ a <- takeMVar m+ (a',b) <- restore (io a)+ `onException` putMVar m a+ putMVar m a'+ return b -- Control.Concurrent.MVar doesn't have this, but it's pretty useful -- for implementing non-blocking operations. tryModifyMVar :: MVar a -> (a -> IO (a, TryResult b)) -> IO (TryResult b)-tryModifyMVar m io = do- restore <- saveBlock- block $ do- maybea <- tryTakeMVar m- case maybea of- Just a -> do- (a',b) <- restore (io a)- `onException` putMVar m a- putMVar m a'- return b- Nothing ->- return WouldBlock+tryModifyMVar m io = mask $ \restore -> do+ maybea <- tryTakeMVar m+ case maybea of+ Just a -> do+ (a',b) <- restore (io a)+ `onException` putMVar m a+ putMVar m a'+ return b+ Nothing ->+ return WouldBlock transactMVar :: MVar a -> (a -> (a -> IO ()) -> IO b) -> IO b-transactMVar m io = do- restore <- saveBlock- block $ do- a <- takeMVar m- r <- newIORef a- restore (io a (writeIORef r))- `finally` (readIORef r >>= putMVar m)+transactMVar m io = mask $ \restore -> do+ a <- takeMVar m+ r <- newIORef a+ restore (io a (writeIORef r))+ `finally` (readIORef r >>= putMVar m) {- tryTransactMVar :: MVar a -> (a -> (a -> IO ()) -> IO (TryResult b)) -> IO (TryResult b)-tryTransactMVar m io = do- restore <- saveBlock- block $ do- maybea <- tryTakeMVar m- case maybea of- Just a -> do- r <- newIORef a- restore (io a (writeIORef r))- `finally` (readIORef r >>= putMVar m)- Nothing ->- return WouldBlock+tryTransactMVar m io = mask $ \restore -> do+ maybea <- tryTakeMVar m+ case maybea of+ Just a -> do+ r <- newIORef a+ restore (io a (writeIORef r))+ `finally` (readIORef r >>= putMVar m)+ Nothing ->+ return WouldBlock -}
src/Coercion.hs view
@@ -87,7 +87,7 @@ exBVar (lid "x") build b recs (view -> TyQu Exists tv t) (view -> TyQu Exists tv' t') = do let recs' = M.insert (tv, tv') Nothing (shadow [tv] [tv'] recs)- body <- build b recs' t t' >>! instContract+ body <- instContract `liftM` build b recs' t t' let tv'' = freshTyVar tv (ftv (tv, tv')) tstx = typeToStx' t tstx' = typeToStx' t'
+ src/Compat.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE+ TemplateHaskell #-}+-- | Compatibility layer for different GHC and library versions+module Compat (+ mask, newQuasi,+) where++import Language.Haskell.TH++import Language.Haskell.TH.Quote+import qualified Control.Exception++mask :: ((IO a -> IO a) -> IO b) -> IO b+mask = $(do+ let name s = mkName ("Control.Exception." ++ s)+ var = varE . name+ recover+ [| \action -> do+ b <- $(var "blocked")+ let restore = if b then $(var "block")+ else $(var "unblock")+ $(var "block") (action restore) |]+ (do reify (name "mask")+ [| \action -> $(var "mask") (\restore -> action restore) |]))++newQuasi :: String -> QuasiQuoter+newQuasi name = $(do+ let quasiQuoter = conE 'QuasiQuoter+ arity (AppT (AppT ArrowT _) t') = 1 + arity t'+ arity _ = 0 :: Int+ DataConI _ ty _ _ <- reify 'QuasiQuoter+ [| let qf cat _ = fail $ "Quasiquoter ‘" ++ name +++ "’ does not support " ++ cat+ q2 = $quasiQuoter (qf "expressions") (qf "patterns") in+ $(if arity ty == 4+ then [| q2 (qf "types") (qf "declarations") |]+ else [| q2 |]) |])++
src/ErrorST.hs view
@@ -51,9 +51,10 @@ liftST_ newUndo unST (handler e) -runST :: Error e => (forall s. ST s e a) -> Either e a+runST :: (Error e, MonadError e m) => (forall s. ST s e a) -> m a runST block =- Super.runST (evalStateT (runErrorT (unST (transaction block))) (return ()))+ either throwError return $+ Super.runST (evalStateT (runErrorT (unST (transaction block))) (return ())) -- | Run something directly in the underlying ST monad liftST :: Error e => Super.ST s a -> ST s e a
src/Lexer.hs view
@@ -11,7 +11,7 @@ lolli, arrow, funbraces, lambda, forall, exists, mu, qualbox,- qualU, qualA,+ qualU, qualA, qdisj, qconj, opP, -- * Token parsers from Parsec@@ -23,6 +23,7 @@ ) where import Prec+import Util import Data.Char import Text.ParserCombinators.Parsec@@ -182,16 +183,25 @@ arrow :: T.TokenEnd st => CharParser st () arrow = reservedOp "->" <|> reservedOp "→" --- | The left part of the $-[_]>$ operator+-- | The left part of the $-_>$ operator funbraceLeft :: T.TokenEnd st => CharParser st ()-funbraceLeft = try (symbol "-[") >> return ()+funbraceLeft = try (symbol "-") >> return () --- | The right part of the $-[_]>$ operator+-- | The right part of the $-_>$ operator funbraceRight :: T.TokenEnd st => CharParser st ()-funbraceRight = try (symbol "]>") >> return ()+funbraceRight = try (symbol ">") >> return () +-- | The left part of the $-[_]>$ operator+oldFunbraceLeft :: T.TokenEnd st => CharParser st ()+oldFunbraceLeft = try (symbol "-[") >> return ()++-- | The right part of the $-[_]>$ operator+oldFunbraceRight :: T.TokenEnd st => CharParser st ()+oldFunbraceRight = try (symbol "]>") >> return ()+ funbraces :: T.TokenEnd st => CharParser st a -> CharParser st a-funbraces = between funbraceLeft funbraceRight+funbraces = liftM2 (<|>) (between oldFunbraceLeft oldFunbraceRight)+ (between funbraceLeft funbraceRight) -- | The left part of the $|[_]$ annotation qualboxLeft :: T.TokenEnd st => CharParser st ()@@ -242,6 +252,14 @@ -- | Qualifier @A@ (not reserved) qualA :: T.TokenEnd st => CharParser st () qualA = reserved "A"++-- | Infix operator for qualifier disjunction+qdisj :: T.TokenEnd st => CharParser st ()+qdisj = reservedOp "," <|> reservedOp "\\/" <|> reservedOp "⋁"++-- | Infix operator for qualifier conjunction+qconj :: T.TokenEnd st => CharParser st ()+qconj = reservedOp "/\\" <|> reservedOp "⋀" -- | Is the string an uppercase identifier? (Special case: @true@ and -- @false@ are consider uppercase.)
src/Makefile view
@@ -9,8 +9,10 @@ Message/*.hs Meta/*.hs HSBOOT_SRC = Syntax/*.hs-boot -HCOPTS = -W -Wall -O0 $(EDITING) $(NOWARN)+HCOPTS = -W -Wall -O0 $(EDITING) $(PARSEC) $(NOWARN) $(IMPARR) EDITING = -DUSE_READLINE=System.Console.Editline.Readline+PARSEC = -DPARSEC_VERSION=3+# IMPARR = -DANNOTATION_PRINTING_RULE=Rule0 NOWARN = -fno-warn-unused-do-bind -fno-warn-orphans $(EXE) $(EXE)-%: $(SRC)@@ -18,6 +20,7 @@ $(EXE)-%: GHC = ghc-$* $(EXE)-6.8.%: EDITING = -DUSE_READLINE=System.Console.Readline+$(EXE)-6.%: PARSEC = -DPARSEC_VERSION=2 clean: $(RM) $(HS_SRC:.hs=.hi) $(HS_SRC:.hs=.o)
src/Message/Quasi.hs view
@@ -12,6 +12,7 @@ import Message.AST import Message.Parser+import Meta.THHelpers import PprClass import Util @@ -21,9 +22,7 @@ import Language.Haskell.TH.Syntax (lift) msg :: QuasiQuoter-msg = QuasiQuoter qexp qpat where- qexp s = parseMessageQ s >>= msgAstToExpQ- qpat _ = fail "Quasiquoter ‘msg’ does not support patterns"+msg = (newQuasi "msg") { quoteExp = parseMessageQ >=> msgAstToExpQ } msgAstToExpQ :: Message d -> ExpQ msgAstToExpQ msg0 = do
src/Meta/Quasi.hs view
@@ -73,29 +73,31 @@ pa, ty, ex, dc, me, prQ, tdQ, atQ, caQ, bnQ, qeQ, tpQ, seQ, sgQ :: QuasiQuoter -ex = mkQuasi parseExpr-dc = mkQuasi parseDecl-ty = mkQuasi parseType-me = mkQuasi parseModExp-pa = mkQuasi parsePatt-prQ = mkQuasi parseProg-tdQ = mkQuasi parseTyDec-atQ = mkQuasi parseAbsTy-caQ = mkQuasi parseCaseAlt-bnQ = mkQuasi parseBinding-qeQ = mkQuasi parseQExp-tpQ = mkQuasi parseTyPat-seQ = mkQuasi parseSigExp-sgQ = mkQuasi parseSigItem+ex = mkQuasi "ex" parseExpr+dc = mkQuasi "dc" parseDecl+ty = mkQuasi "ty" parseType+me = mkQuasi "me" parseModExp+pa = mkQuasi "pa" parsePatt+prQ = mkQuasi "prQ" parseProg+tdQ = mkQuasi "tdQ" parseTyDec+atQ = mkQuasi "atQ" parseAbsTy+caQ = mkQuasi "caQ" parseCaseAlt+bnQ = mkQuasi "bnQ" parseBinding+qeQ = mkQuasi "qeQ" parseQExp+tpQ = mkQuasi "tpQ" parseTyPat+seQ = mkQuasi "seQ" parseSigExp+sgQ = mkQuasi "sgQ" parseSigItem mkQuasi :: forall stx note. (Data (note Raw), Data (stx Raw), LocAst (N (note Raw) (stx Raw)), Data (note Renamed), Data (stx Renamed), LocAst (N (note Renamed) (stx Renamed))) =>+ String -> (forall i. Id i => P (N (note i) (stx i))) -> QuasiQuoter-mkQuasi parser = QuasiQuoter qast qast where+mkQuasi name parser = (newQuasi name) { quoteExp = qast, quotePat = qast }+ where qast s = join $ parseQuasi s $ \iflag lflag ->
src/Meta/THHelpers.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE+ CPP, DeriveDataTypeable, RankNTypes, TemplateHaskell,@@ -6,6 +7,8 @@ module Meta.THHelpers ( -- * Simplified TH quasiquote th,+ -- * For initializing quasiquoters+ newQuasi, -- * Generic expression/pattern AST construction ToSyntax(..), -- * Miscellany@@ -14,6 +17,7 @@ import Lexer (lid, uid) import Util+import Compat (newQuasi) import Data.Generics (Typeable, Data, everything, mkQ) import Language.Haskell.TH@@ -36,9 +40,7 @@ -- | The quasiquoter for building TH expressions th :: QuasiQuoter-th = QuasiQuoter qexp qpat where- qexp s = parseHs s >>= hsToExpQ- qpat _ = fail "Quasiquoter `hs' does not support patterns"+th = (newQuasi "th") { quoteExp = parseHs >=> hsToExpQ } -- | Don't allow HsOr to the left of HsApp: hsApp :: HsAst -> HsAst -> HsAst
src/Parser.hs view
@@ -397,7 +397,7 @@ (choice [ tyArr <$ arrow, tyLol <$ lolli,- funbraces (tyFun <$> qExpp),+ funbraces (tyFun <$> (antiblep <|> Just <$> qExpp)), tybinopp (Right precArr) ]) (typepP precStart) | p == precSemi@@ -801,8 +801,8 @@ qExpp :: Id i => P (QExp i) qExpp = "qualifier expression" @@ qexp where- qexp = addLoc $ qeDisj <$> sepBy1 qterm (reservedOp "\\/")- qterm = addLoc $ qeConj <$> sepBy1 qfact (reservedOp "/\\")+ qexp = addLoc $ qeDisj <$> sepBy1 qterm qdisj+ qterm = addLoc $ qeConj <$> sepBy1 qfact qconj qfact = addLoc $ parens qexp <|> qatom qatom = addLoc $ qeLit Qu <$ qualU@@ -1007,24 +1007,24 @@ -- Zero or more of (pat:typ, ...), (), or tyvar, recognizing '|' -- to introduce affine arrows afargsp :: Id i => P (Bool, Type i -> Type i, Expr i -> Expr i)-afargsp = loop tyArr where- loop arrcon0 = do- arrcon <- option arrcon0 $ choice- [ tyFun <$> qualbox qExpp,+afargsp = choice+ [ do (tvt, tve) <- tyargp+ (b, ft, fe) <- afargsp+ return (b, tvt . ft, tve . fe),+ do arrcon <- arrconp+ (b, ft, fe) <- vargp arrcon+ if b+ then return (b, ft, fe)+ else do+ (b', fts, fes) <- afargsp+ return (b', ft . fts, fe . fes),+ return (False, id, id) ]+ where+ arrconp = option tyArr $ choice+ [ tyFun . Just <$> qualbox qExpp, do reservedOp "|" return tyLol ]- choice- [ do (tvt, tve) <- tyargp- (b, ft, fe) <- loop arrcon- return (b, tvt . ft, tve . fe),- do (b, ft, fe) <- vargp arrcon- if b- then return (b, ft, fe)- else do- (b', fts, fes) <- loop arrcon- return (b', ft . fts, fe . fes),- return (False, id, id) ] -- One or more of (pat:typ, ...), (), tyvar argsp1 :: Id i => P (Bool, Expr i -> Expr i)
src/Ppr.hs view
@@ -75,13 +75,13 @@ instance Ppr (Type i) where -- pprPrec p (TyFun q t1 t2)+ ppr [$ty| $t1 -> $t2 |]+ = prec precArr $+ sep [ ppr1 t1, text "->" <+> pprRight t2 ] ppr [$ty| $t1 -[$q]> $t2 |] = prec precArr $ sep [ ppr1 t1,- pprArr (view q) <+> pprRight t2 ]- where pprArr (QeLit Qu) = text "->"- pprArr (QeLit Qa) = text "-o"- pprArr _ = text "-[" <> ppr0 q <> text "]>"+ text "-" <> ppr0 q <> text ">" <+> pprRight t2 ] ppr t@[$ty| ($list:ts) $qlid:n |] | Just doc <- pprInfix unfoldType t = doc@@ -131,8 +131,8 @@ [] -> ppr Qu [qe] -> ppr qe _ -> prec precPlus $- fsep $- intersperse (text "\\/") $+ hcat $+ intersperse (text ",") $ map ppr1 qes ppr [$qeQ| $qconj:qes |] = case qes of [] -> ppr Qa
src/Rename.hs view
@@ -80,6 +80,10 @@ m >>= k = R (unR m >>= unR . k) fail = renameError . [$msg| $words:1 |] +instance Applicative Renaming where+ pure = return+ (<*>) = ap+ instance MonadWriter Module Renaming where listen = R . listen . unR tell = R . tell@@ -755,11 +759,11 @@ [$ty| '$tv |] -> do tv' <- getTyvar tv return [$ty|+ '$tv' |]- [$ty| $t1 -[$qe]> $t2 |] -> do- t1' <- renameType t1- qe' <- renameQExp qe- t2' <- renameType t2- return [$ty|+ $t1' -[$qe']> $t2' |]+ [$ty| $t1 -[$opt:mqe]> $t2 |] -> do+ t1' <- renameType t1+ mqe' <- gmapM renameQExp mqe+ t2' <- renameType t2+ return [$ty|+ $t1' -[$opt:mqe']> $t2' |] [$ty| $quant:u '$tv. $t |] -> do (tv', md) <- steal $ bindTyvar tv t' <- inModule md $ renameType t@@ -902,8 +906,8 @@ ftvList t0 = case t0 of [$ty| ($list:ts) $qlid:_ |] -> ftvList ts [$ty| '$tv |] -> [tv]- [$ty| $t1 -[$qe]> $t2 |] ->- ftvList t1 `List.union` ftvList qe `List.union` ftvList t2+ [$ty| $t1 -[$opt:mqe]> $t2 |] ->+ ftvList t1 `List.union` ftvList mqe `List.union` ftvList t2 [$ty| $quant:_ '$tv. $t |] -> List.delete tv (ftvList t) [$ty| mu '$tv. $t |] -> List.delete tv (ftvList t) [$ty| $anti:a |] -> $antierror
src/Statics.hs view
@@ -3,7 +3,6 @@ DeriveDataTypeable, FlexibleContexts, FlexibleInstances,- GeneralizedNewtypeDeriving, ImplicitParams, MultiParamTypeClasses, ParallelListComp,@@ -51,6 +50,7 @@ import Control.Monad.RWS as RWS import Control.Monad.Error as Error+import System.IO (hPutStrLn, stderr) import Data.Data (Typeable, Data) import Data.Generics (everywhere, mkT) import Data.List (transpose, tails)@@ -63,6 +63,8 @@ pP a b = unsafePerformIO (print a) `seq` b pM :: (Show a, Monad m) => a -> m () pM a = if pP a True then return () else fail "wibble"+ioM :: Monad m => IO a -> m ()+ioM a = if unsafePerformIO a `seq` True then return () else fail "wibble" -- The kind of names we're using. type R = Renamed@@ -198,13 +200,16 @@ -- and keeps track of a gensym counter (currently unused). newtype TC m a = TC { unTC :: RWST Context Module Int (ErrorT AlmsException m) a-} deriving Functor+} instance Monad m => Monad (TC m) where return = TC . return m >>= k = TC (unTC m >>= unTC . k) fail = let ?loc = bogus in typeError . [$msg| $words:1 |] +instance Monad m => Functor (TC m) where+ fmap = liftM+ instance Monad m => Applicative (TC m) where pure = return (<*>) = ap@@ -395,17 +400,21 @@ -- | Check type for closed-ness and and defined-ness, and add info tcType :: (?loc :: Loc, Monad m) => Syntax.Type R -> TC m Type-tcType = tc where- tc :: Monad m => Syntax.Type R -> TC m Type- tc [$ty| '$tv |] = do+tcType stxtype0 = do+ t <- tc iaeInit stxtype0+ return t+ where+ tc :: Monad m => CurrentImpArrRule -> Syntax.Type R -> TC m Type+ tc iae [$ty| '$tv |] = do return (TyVar tv)- tc [$ty| $t1 -[$q]> $t2 |] = do- TyFun <$> qInterpretM q- <*> tcType t1- <*> tcType t2- tc [$ty| ($list:ts) $qlid:n |] = do- ts' <- mapM tc ts+ tc iae [$ty| $t1 -[$opt:mq]> $t2 |] = do+ qd <- iaeInterpret iae mq+ t1' <- tc (iaeLeft iae) t1+ t2' <- tc (iaeRight iae qd t1') t2+ return (TyFun qd t1' t2')+ tc iae [$ty| ($list:ts) $qlid:n |] = do tc' <- find n+ ts' <- zipWithM (tc . iaeUnder iae) (tcArity tc') ts checkLength (length (tcArity tc')) checkBound (tcBounds tc') ts' return (tyApp tc' ts')@@ -422,14 +431,14 @@ qualifiers than permitted: |] ([$msg| $1 |] (map (qRepresent . qualifier) ts')) [$msg| $quals (or less) |]- tc [$ty| $quant:u '$tv . $t |] =- TyQu u tv <$> tc t- tc t0@[$ty| mu '$tv . $t |] = do+ tc iae [$ty| $quant:u '$tv . $t |] =+ TyQu u tv <$> tc iae t+ tc iae t0@[$ty| mu '$tv . $t |] = do case unfoldTyMu t of (_, N _ (Syntax.TyVar tv')) | tv == tv' -> typeError [$msg| Recursive type is not contractive: $t0 |] _ -> return ()- t' <- tc t+ t' <- tc iae t let actqual = qualConst t' expqual = tvqual tv tassert (actqual == expqual)@@ -441,7 +450,7 @@ <dt>in type: <dd>$5:t0 </dl> |] return (TyMu tv t')- tc [$ty| $anti:a |] = $antifail+ tc _ [$ty| $anti:a |] = $antifail -- | Type check an A expression tcExpr :: Monad m => Expr R -> TC m (Type, Expr R)@@ -465,8 +474,8 @@ checkSharing "match or let" (caexpr ca) md return (ti, caClause xi' ei' <<@ note) tr <- foldM (\ti' ti -> case ti' \/? ti of- Just tr' -> return tr'- Nothing -> typeError [$msg|+ Right tr' -> return tr'+ Left (_ :: String) -> typeError [$msg| Mismatch in branches of match or let. Cannot unify: <ul> <li>$ti@@ -842,16 +851,15 @@ if or changed then loop md' else return (tcs, md')- in do- (tcs, md') <- loop stub- forM_ tcs $ \tc -> do- case tcNext tc of- Nothing -> return ()- Just clauses -> forM_ clauses $ \(tps, rhs) ->- tassert (rhs /= tyPatToType (TpApp tc {tcNext = Nothing} tps)) $- "Recursive type synonym is not contractive:" !:: tc- tell (replaceTyCons tcs md')- return tds0+ (tcs, md') <- loop stub+ forM_ tcs $ \tc -> do+ case tcNext tc of+ Nothing -> return ()+ Just clauses -> forM_ clauses $ \(tps, rhs) -> do+ tassert (rhs /= tyPatToType (TpApp tc {tcNext = Nothing} tps)) $+ "Recursive type synonym is not contractive:" !:: tc+ tell (replaceTyCons tcs md')+ return tds0 where allocStub name params = do ix <- newIndex@@ -1001,7 +1009,7 @@ _ -> S.empty `S.union` S.unions (map tyConsOfType ts) tyConsOfType [$ty| '$_ |] = S.empty-tyConsOfType [$ty| $t1 -[$_]> $t2 |] =+tyConsOfType [$ty| $t1 -[$opt:_]> $t2 |] = tyConsOfType t1 `S.union` tyConsOfType t2 tyConsOfType [$ty| $quant:_ '$_. $t |] = tyConsOfType t tyConsOfType [$ty| mu '$_. $t |] = tyConsOfType t@@ -1138,6 +1146,7 @@ </dl> |] (qRepresent (qualifier te)) return te x' <- tcPatt t' x+ -- ioM (hPutStrLn stderr (show te)) return (x', Just (typeToStx' t'), e') -- | Run a computation in the context of a module open declaration
src/Syntax/Decl.hs-boot view
@@ -10,12 +10,14 @@ import Syntax.Notable import Syntax.Ident (Id, Fv, Dv) -import Data.Data (Data)+import Data.Data (Data, Typeable1) data DeclNote i data Decl' i type Decl i = N (DeclNote i) (Decl' i) +instance Typeable1 DeclNote+instance Typeable1 Decl' instance Id i => Data (DeclNote i) instance Id i => Data (Decl' i) instance Locatable (DeclNote i)
src/Syntax/Ident.hs-boot view
@@ -1,10 +1,12 @@ module Syntax.Ident where -import Data.Data (Data)+import Data.Data (Data, Typeable1) class Id i data TyVar i +instance Typeable1 TyVar instance Data i => Data (TyVar i) instance Id i => Ord (TyVar i)+instance Id i => Eq (TyVar i)
src/Syntax/POClass.hs view
@@ -5,6 +5,7 @@ import Util +import Control.Monad.Error import qualified Data.Set as S -- | Partial orders.@@ -19,29 +20,29 @@ -- | Takes a boolean parameter, and does join if true -- and meet if false. This sometimes allows us to exploit duality -- to define both at once.- ifMJ :: Monad m => Bool -> a -> a -> m a+ ifMJ :: (Error e, MonadError e m) => Bool -> a -> a -> m a ifMJ True x y = return (x \/ y) ifMJ False x y = return (x /\ y) -- | Partial join returns in a monad, in case join DNE- (\/?) :: Monad m => a -> a -> m a+ (\/?) :: (Error e, MonadError e m) => a -> a -> m a (\/?) = ifMJ True -- | Partial meet returns in a monad, in case meet DNE- (/\?) :: Monad m => a -> a -> m a+ (/\?) :: (Error e, MonadError e m) => a -> a -> m a (/\?) = ifMJ False -- | Total join (\/) :: a -> a -> a -- | Total meet (/\) :: a -> a -> a- x \/ y = fromJust (x \/? y)- x /\ y = fromJust (x /\? y)+ x \/ y = either error id (x \/? y)+ x /\ y = either error id (x /\? y) -- | The order relation (derived) (<:) :: a -> a -> Bool- x <: y = Just x == (x /\? y)- || Just y == (x \/? y)+ x <: y = either (const False :: String -> Bool) ((==) x) (x /\? y)+ || either (const False :: String -> Bool) ((==) y) (x \/? y) -- | The complement of the order relation (derived) (/<:) :: a -> a -> Bool@@ -54,13 +55,13 @@ bigVee :: (Bounded a, PO a) => [a] -> a bigVee = foldr (\/) minBound -bigVeeM :: (Monad m, Bounded a, PO a) => [a] -> m a+bigVeeM :: (Error e, MonadError e m, Bounded a, PO a) => [a] -> m a bigVeeM = foldrM (\/?) minBound bigWedge :: (Bounded a, PO a) => [a] -> a bigWedge = foldr (/\) maxBound -bigWedgeM :: (Monad m, Bounded a, PO a) => [a] -> m a+bigWedgeM :: (Error e, MonadError e m, Bounded a, PO a) => [a] -> m a bigWedgeM = foldrM (/\?) maxBound instance Ord a => PO (S.Set a) where@@ -72,7 +73,7 @@ Nothing \/? b = return b a \/? Nothing = return a - Just a /\? Just b = return (a /\? b)+ Just a /\? Just b = liftM Just (a /\? b) Nothing /\? _ = return Nothing _ /\? Nothing = return Nothing
src/Syntax/Type.hs view
@@ -42,7 +42,7 @@ data Type' i = TyApp (QLid i) [Type i] | TyVar (TyVar i)- | TyFun (QExp i) (Type i) (Type i)+ | TyFun (Maybe (QExp i)) (Type i) (Type i) | TyQu Quant (TyVar i) (Type i) | TyMu (TyVar i) (Type i) | TyAnti Anti@@ -99,10 +99,10 @@ tyAf = tyNulOp "A" tyArr :: Type i -> Type i -> Type i-tyArr = tyFun minBound+tyArr = tyFun Nothing tyLol :: Type i -> Type i -> Type i-tyLol = tyFun maxBound+tyLol = tyFun (Just maxBound) infixr 8 `tyArr`, `tyLol` @@ -115,8 +115,10 @@ putStrLn $ show n ++ " {" mapM_ (dumpType (i + 2)) ps putStrLn (replicate i ' ' ++ "}")- TyFun q dom cod -> do- putStrLn $ "-[" ++ maybe "ANTI" show (qInterpretM q) ++ "]> {"+ TyFun mq dom cod -> do+ putStrLn $ case mq of+ Just q -> "-[" ++ maybe "ANTI" show (qInterpretM q) ++ "]> {"+ Nothing -> "-> {" dumpType (i + 2) dom dumpType (i + 2) cod putStrLn (replicate i ' ' ++ "}")
src/Type.hs view
@@ -1,6 +1,7 @@ -- | The internal representation of types, created by the type checker -- from the syntactic types in 'Syntax.Type'. {-# LANGUAGE+ CPP, DeriveDataTypeable, DeriveFunctor, ViewPatterns,@@ -47,6 +48,8 @@ vtAppTc, isBotType, -- ** Unfolds vtFuns, vtQus,+ -- * Implicit arrow annotations+ CurrentImpArrRule, ImpArrRule(..), -- * Re-exports module Syntax.Ident, module Syntax.Kind,@@ -692,24 +695,58 @@ typeToStx' = typeToStx tyNames0 -- | Represent a type value as a syntactic type, for printing; renames--- so that scope is apparent, since internal renaming may result int+-- so that scope is apparent, since internal renaming may result in -- different identifiers that print the same typeToStx :: TyNames -> Type -> Stx.Type Renamed-typeToStx f = loop (S.empty, M.empty) where- loop ren t0 = case t0 of+typeToStx tns = typeToStxRule tns (iaeInit :: CurrentImpArrPrintingRule)++#ifdef ANNOTATION_RULE+type CurrentImpArrRule = ANNOTATION_RULE+#else+type CurrentImpArrRule = Rule4+#endif++#ifdef ANNOTATION_PRINTING_RULE+type CurrentImpArrPrintingRule = ANNOTATION_PRINTING_RULE+#else+type CurrentImpArrPrintingRule = CurrentImpArrRule+#endif++class ImpArrRule a where+ iaeInit :: a+ iaeLeft :: a -> a+ iaeRight :: a -> QDen (TyVar Renamed) -> Type -> a+ iaeImplied :: a -> QDen (TyVar Renamed)+ iaeInterpret :: Monad m =>+ a -> Maybe (QExp Renamed) -> m (QDen (TyVar Renamed))+ iaeRepresent :: a -> QDen (TyVar Renamed) -> Maybe (QExp Renamed)+ iaeUnder :: a -> Variance -> a+ --+ iaeLeft _ = iaeInit+ iaeRight iae _ _ = iae+ iaeImplied _ = minBound+ iaeInterpret iae = maybe (return (iaeImplied iae)) qInterpretM+ iaeRepresent iae actual+ | actual == iaeImplied iae = Nothing+ | otherwise = Just (qRepresent actual)+ iaeUnder _ _ = iaeInit++-- | Turns annotated arrows into implicit arrows where possible+typeToStxRule :: ImpArrRule iae => TyNames -> iae -> Type -> Stx.Type Renamed+typeToStxRule f iae0 = loop (S.empty, M.empty) iae0 where+ loop ren iae t0 = case t0 of TyVar tv -> Stx.tyVar (maybe tv id (M.lookup tv (snd ren)))- TyFun q t1 t2 -> Stx.tyFun (qRepresent q) (loop ren t1) (loop ren t2)- TyApp tc ts _ -> Stx.tyApp (bestName f tc) (map (loop ren) ts)- {-- (fmap (\ql -> lid ("[" ++ show (tcId tc) ++ "]" ++ unLid ql))- (tcName tc)) - (map (loop ren) ts)- -}- TyQu qu tv t1 -> Stx.tyQu qu tv' (loop ren' t1)+ TyFun q t1 t2 -> Stx.tyFun (iaeRepresent iae q)+ (loop ren (iaeLeft iae) t1)+ (loop ren (iaeRight iae q t1) t2)+ TyApp tc ts _ -> Stx.tyApp+ (bestName f tc)+ (zipWith (loop ren . iaeUnder iae) (tcArity tc) ts)+ TyQu qu tv t1 -> Stx.tyQu qu tv' (loop ren' iae t1) where (tv', ren') = fresh tv ren- TyMu tv t1 -> Stx.tyMu tv' (loop ren' t1)+ TyMu tv t1 -> Stx.tyMu tv' (loop ren' iae t1) where (tv', ren') = fresh tv ren- fresh tv (seen, remap) = + fresh tv (seen, remap) = let tv' = if S.member (unLid (tvname tv)) seen then freshTyVar tv $ M.keysSet remap `S.union`@@ -718,6 +755,72 @@ in (tv', (S.insert (unLid (tvname tv')) seen, M.insert tv tv' remap)) +-- | Print all arrow annotations explicitly+data Rule0 = Rule0++instance ImpArrRule Rule0 where+ iaeInit = Rule0+ iaeRepresent _ actual = Just (qRepresent actual)++-- | Annotation ‘U’ is implicit for unlabeled arrows.+data Rule1 = Rule1++instance ImpArrRule Rule1 where+ iaeInit = Rule1++newtype Rule2 = Rule2 { unRule2 :: QDen (TyVar Renamed) }++-- | Implicit annotation is lub of qualifiers of prior curried+-- arguments. Explicit annotations have no effect on subsequent+-- arrows.+instance ImpArrRule Rule2 where+ iaeInit = Rule2 minBound+ iaeRight iae _ t = Rule2 (unRule2 iae \/ qualifier t)+ iaeImplied = unRule2++-- | Like 'Rule2', but explicit annotations reset the qualifier to+-- themselves for subsequent arrows.+newtype Rule3 = Rule3 { unRule3 :: QDen (TyVar Renamed) }++instance ImpArrRule Rule3 where+ iaeInit = Rule3 minBound+ iaeRight iae actual t+ | unRule3 iae == actual = Rule3 (unRule3 iae \/ qualifier t)+ | otherwise = Rule3 (actual \/ qualifier t)+ iaeImplied = unRule3++-- | Like 'Rule3', but we arrow the implicit qualifer into covariant+-- type constructors.+newtype Rule4 = Rule4 { unRule4 :: QDen (TyVar Renamed) }++instance ImpArrRule Rule4 where+ iaeInit = Rule4 minBound+ iaeRight iae actual t+ | unRule4 iae == actual = Rule4 (unRule4 iae \/ qualifier t)+ | otherwise = Rule4 (actual \/ qualifier t)+ iaeImplied = unRule4+ iaeUnder iae Covariant = iae+ iaeUnder _ _ = iaeInit++-- | Like 'Rule4', but we carry the implicit quantifier into ALL type+-- constructors and only use it when we arrive at an arrow in a+-- positive position wrt the surrounding arrow.+data Rule5+ = Rule5 {+ unRule5 :: !(QDen (TyVar Renamed)),+ r4Var :: !Variance+ }++instance ImpArrRule Rule5 where+ iaeInit = Rule5 minBound 1+ iaeRight iae actual t+ | unRule5 iae == actual = Rule5 (unRule5 iae \/ qualifier t) 1+ | otherwise = Rule5 (actual \/ qualifier t) 1+ iaeImplied iae+ | r4Var iae == 1 = unRule5 iae+ | otherwise = minBound+ iaeUnder iae var = Rule5 (unRule5 iae) (var * r4Var iae)+ tyPatToStx' :: TyPat -> Stx.TyPat Renamed tyPatToStx' = tyPatToStx tyNames0 @@ -957,6 +1060,7 @@ ppr (qRepresent (denumberQDen (map qDenOfTyVar tvs) (tcQual tc)))+ ps :: Ppr a => [a] -> [Doc] ps tvs = [ ppr var <> pprPrec (precApp + 1) tv | tv <- tvs | var <- tcArity tc ]
src/TypeRel.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE+ FlexibleContexts, GeneralizedNewtypeDeriving, ParallelListComp, PatternGuards,@@ -27,6 +28,7 @@ import Viewable import qualified Control.Monad.Reader as CMR+import Control.Monad.Error import Data.Generics (Data, everywhere, mkT, extT) import Data.Monoid import qualified Data.Map as M@@ -171,25 +173,21 @@ env1 = Field tcsEnv1 (\tcs e -> tcs { tcsEnv1 = e }) env2 = Field tcsEnv2 (\tcs e -> tcs { tcsEnv2 = e }) -lift :: (CMR.MonadTrans t, Monad m) => m a -> t m a-lift = CMR.lift--runUT :: forall s a m. Monad m =>+runUT :: forall s a m. MonadError String m => (forall t. UT s t a) -> S.Set TyVarR -> m a runUT m set =- either fail return $- runST $ do- seen <- newTransSTRef M.empty- supply <- newSTRef [ f | f <- tvalphabet- , f Qu `S.notMember` set- , f Qa `S.notMember` set ]- CMR.runReaderT m TCS {- tcsSeen = seen,- tcsSupply = supply,- tcsLevel = 1,- tcsEnv1 = M.empty,- tcsEnv2 = M.empty- }+ runST $ do+ seen <- newTransSTRef M.empty+ supply <- newSTRef [ f | f <- tvalphabet+ , f Qu `S.notMember` set+ , f Qa `S.notMember` set ]+ CMR.runReaderT m TCS {+ tcsSeen = seen,+ tcsSupply = supply,+ tcsLevel = 1,+ tcsEnv1 = M.empty,+ tcsEnv2 = M.empty+ } getVar :: TyVarR -> Field s t -> UT s t (Maybe (UVar t)) getVar tv field = CMR.asks (M.lookup tv . get field)@@ -221,7 +219,7 @@ if isBotType lower then if upper == tyUn || upper == tyAf then lower else upper else lower- else fail $+ else throwError $ "Unification cannot solve:\n" ++ show lower ++ " <: " ++ show upper | (_, (_, ref)) <- refs ]@@ -292,7 +290,7 @@ -- pM = lift . unsafeIOToST . print -- pM = const $ return () -subtype :: Monad m =>+subtype :: MonadError String m => Int -> [TyVarR] -> Type -> [TyVarR] -> Type -> m ([Type], [Type]) subtype limit uvars1 t1i uvars2 t2i =@@ -388,7 +386,7 @@ _ -> giveUp t u -- giveUp t u = - fail $+ throwError $ "Got type `" ++ show t ++ "' where type `" ++ show u ++ "' expected" --@@ -406,6 +404,7 @@ | tj <- ts | uj <- us ] --+ -- XXX This is woefully insufficient subkind qd1 qd2 orElse = if qd1 <: qd2 then return () else do (m1, m2) <- getUVars@@ -423,7 +422,7 @@ -> lowerBoundUVar ref (tyTop qlit) _ -> orElse -jointype :: Monad m => Int -> Bool -> Type -> Type -> m Type+jointype :: MonadError String m => Int -> Bool -> Type -> Type -> m Type jointype limit b t1i t2i = liftM clean $ runUT (cmp (b, True) t1i t2i) (alltv (t1i, t2i)) where@@ -485,7 +484,7 @@ cmp m t (tysubst tvu u u1) -- Failure _ ->- fail $+ throwError $ "Could not " ++ (if direction then "join" else "meet") ++ " types `" ++ show t ++ "' and `" ++ show u ++ "'"@@ -499,7 +498,7 @@ -1 -> revCmp m tj uj _ -> if tj == uj then return tj- else fail $+ else throwError $ "Could not unify types `" ++ show tj ++ "' and `" ++ show uj ++ "'" | var <- arity@@ -546,7 +545,8 @@ instance PO Type where t1 <: t2 = runEither (const False) (const True) (subtype 100 [] t1 [] t2)- ifMJ b t1 t2 = jointype 100 b t1 t2+ ifMJ b t1 t2 = runEither (throwError . strMsg) return+ (jointype 100 b t1 t2) subtypeTests, joinTests, uvarsTests :: T.Test @@ -915,14 +915,14 @@ t1 \/! t2 = Left (t1, t2) t1 /\! t2 = Right (t1, t2) Left (t1, t2) ==! t =- T.assertEqual (show t1 ++ " \\/ " ++ show t2 ++ " = " ++ show t)- (Just t) (t1 \/? t2)+ tassertSuccess (show t1 ++ " \\/ " ++ show t2 ++ " = " ++ show t)+ t (t1 \/? t2) Right (t1, t2) ==! t =- T.assertEqual (show t1 ++ " /\\ " ++ show t2 ++ " = " ++ show t)- (Just t) (t1 /\? t2)+ tassertSuccess (show t1 ++ " /\\ " ++ show t2 ++ " = " ++ show t)+ t (t1 /\? t2) t1 !/\ t2 =- T.assertEqual (show t1 ++ " /\\ " ++ show t2 ++ " DNE")- Nothing (t1 /\? t2)+ tassertFailure (show t1 ++ " /\\ " ++ show t2 ++ " DNE")+ (t1 /\? t2) infix 2 ==! infix 4 \/!, /\!, !/\ a = tvUn "a"; b = tvUn "b"; c = tvAf "c"; d = tvAf "d"@@ -997,8 +997,8 @@ ==! (noU, noU, TyVar e, noA) , tyRecv (TyVar c) .*. tyRecv (TyVar c) !>: tyRecv (TyVar e) .*. tyRecv (TyVar f)- , T.assertEqual "'<c `supertype` '<d = ERROR"- Nothing (subtype 100 [c] (TyVar c) [d] (TyVar d))+ , tassertFailure "'<c `supertype` '<d = ERROR"+ (subtype 100 [c] (TyVar c) [d] (TyVar d)) , tyFollow (TyVar a) (TyVar b) >:! tyFollow tyUnit (tyRecv tyInt .:. TyMu e (tyFollow tyUnit (tyRecv tyInt .:.@@ -1016,25 +1016,32 @@ t1 <:! t2 = Left (t1, t2) t1 >:! t2 = Right (t1, t2) Left (t1, t2) ==! (ta, tb, tc, td) =- T.assertEqual (show t1 ++ " `subtype` " ++ show t2)- (Right ([ta, tb, tc, td], []))- (runEither Left Right $ subtype 100 set t1 [] t2)+ tassertSuccess (show t1 ++ " `subtype` " ++ show t2)+ ([ta, tb, tc, td], [])+ (subtype 100 set t1 [] t2) Right (t1, t2) ==! (ta, tb, tc, td) =- T.assertEqual (show t1 ++ " `supertype` " ++ show t2)- (Right ([], [ta, tb, tc, td]))- (runEither Left Right $ subtype 100 [] t2 set t1)+ tassertSuccess (show t1 ++ " `supertype` " ++ show t2)+ ([], [ta, tb, tc, td])+ (subtype 100 [] t2 set t1) t1 !<: t2 =- T.assertEqual (show t1 ++ " `subtype` " ++ show t2 ++ " = ERROR")- Nothing (subtype 100 set t1 [] t2)+ tassertFailure (show t1 ++ " `subtype` " ++ show t2 ++ " = ERROR")+ (subtype 100 set t1 [] t2) t1 !>: t2 =- T.assertEqual (show t1 ++ " `supertype` " ++ show t2 ++ " = ERROR")- Nothing (subtype 100 [] t2 set t1)+ tassertFailure (show t1 ++ " `supertype` " ++ show t2 ++ " = ERROR")+ (subtype 100 [] t2 set t1) infix 2 ==! infix 4 <:!, !<:, >:!, !>: noU = tyBot; noA = tyBot set = [a, b, c, d] a = tvUn "a"; b = tvUn "b"; c = tvAf "c"; d = tvAf "d" e = tvAf "e"; f = tvAf "f"++tassertSuccess :: (Eq a, Show a) =>+ String -> a -> Either String a -> T.Assertion+tassertSuccess msg = T.assertEqual msg . Right++tassertFailure :: String -> Either String a -> T.Assertion+tassertFailure msg = either (\_ -> return ()) (\_ -> T.assertFailure msg) tests :: IO () tests = do
src/Util.hs view
@@ -1,5 +1,8 @@ -- | Utility functions-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE+ CPP,+ FlexibleContexts+ #-} module Util ( -- * List combinators -- ** Shallow mapping@@ -45,7 +48,16 @@ import Control.Arrow hiding (loop, (<+>)) import Control.Monad import Control.Applicative (Applicative(..), (<$>), (<$), (<**>))++#if PARSEC_VERSION == 2+ import Text.ParserCombinators.Parsec (GenParser)+-- | Parsec parsers are Applicatives, which lets us write slightly+-- more pleasant, non-monadic-looking parsers+instance Applicative (GenParser a b) where+ pure = return+ (<*>) = ap+#endif -- | Right-associative monadic fold foldrM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a@@ -221,9 +233,3 @@ instance GSequence Maybe where gsequence = maybe (return Nothing) (liftM return) gsequence_ = maybe (return ()) (>> return ())---- | Parsec parsers are Applicatives, which lets us write slightly--- more pleasant, non-monadic-looking parsers-instance Applicative (GenParser a b) where- pure = return- (<*>) = ap