on master help sign in
Merge remote-tracking branch 'upstream/master' into pretty-warnings
commit117a8ecb54f785ecf9cf0772471b67ae4979430c authorJason Felice <jason.m.felice@gmail.com> dateThu 21 Dec 2017, 08:33 (9 years ago) parenteb4c2351e4133b
48 files changed+945−122
CHANGELOG.md+6−1 docs/reference/syntax-guide.rst−1 idris.cabal+2−2 libs/contrib/Control/ST/File.idr+247 libs/contrib/contrib.ipkg+1 libs/prelude/IO.idr+1−1 libs/prelude/Prelude/Interfaces.idr+2 libs/prelude/Prelude/List.idr+12−12 samples/tutorial/BTreeMod.idr+5−5 src/IRTS/CodegenC.hs+7−1 src/IRTS/JavaScript/Codegen.hs+1−4 src/IRTS/JavaScript/PrimOp.hs−2 src/IRTS/Lang.hs+95−32 src/IRTS/LangOpts.hs+163−7 src/Idris/Parser.hs+13−5 src/Idris/Parser/Expr.hs−3 src/Idris/Parser/Helpers.hs+5−21 stack-nightly.yaml−17 stack.yaml+2−5 test/README.md+1 test/TestData.hs+8 test/st001/expected+8 test/st001/run+6 test/st001/test001.idr+66 test/st001/testFile+2 test/st002/expected+8 test/st002/run+6 test/st002/test002.idr+66 test/st002/testFile+2 test/st003/expected+8 test/st003/run+6 test/st003/test003.idr+25 test/st003/testFile+2 test/st004/expected+6 test/st004/run+6 test/st004/test004.idr+24 test/st005/expected+6 test/st005/run+7 test/st005/test005.idr+33 test/st006/expected+5 test/st006/run+6 test/st006/test006.idr+37 test/st007/expected+6 test/st007/run+6 test/st007/test007.idr+24 test/views001/views001.idr+1−1 test/views001/views001a.idr+1−1 test/views002/views002.idr+1−1
CHANGELOG.md+6−1
@@ -31,7 +31,10 @@
3131 intMax : IO Int
3232 intMax = foreign FFI_C "#INT_MAX" (IO Int)
3333 ```
34−
34++ The deprecated keywords `%assert_total`, `abstract`, and `[static]` have
35+ been removed as well as the use of "public" instead of "public export" to
36+ expose a symbol.
37+
3538## Library Updates
3639
3740+ Removed `oldeffects` library from `libs` folder, use `effects` or `Control.ST` instead.
@@ -68,6 +71,8 @@
6871+ Removed several deprecated items from the libraries shipped with Idris.
6972+ Moved `abs` from the `Neg` interface into its own `Abs` interface. `Nat`
7073 implements `Abs` with `abs = id`.
74++ Added `Control.ST.File`, an ST based implementation of the same behaviour
75+ implemented by `Effect.File` in the effects package.
7176
7277## Tool Updates
7378
docs/reference/syntax-guide.rst−1
@@ -407,7 +407,6 @@ Options
407407 %no_implicit
408408 %error_handler
409409 %error_reverse
410− %assert_total
411410 %reflection
412411 %specialise [<name list>]
413412
idris.cabal+2−2
@@ -270,7 +270,7 @@ Library
270270 Build-depends: base >=4 && <5
271271 , aeson >= 0.6 && < 1.3
272272 , annotated-wl-pprint >= 0.7 && < 0.8
273− , ansi-terminal < 0.7
273+ , ansi-terminal < 0.8
274274 , ansi-wl-pprint < 0.7
275275 , array >= 0.4.0.1 && < 0.6
276276 , base64-bytestring < 1.1
@@ -287,7 +287,7 @@ Library
287287 , fingertree >= 0.1 && < 0.2
288288 , haskeline >= 0.7 && < 0.8
289289 , ieee754 >= 0.7 && < 0.9
290− , megaparsec >= 6.2 && <6.3
290+ , megaparsec >= 6.2
291291 , mtl >= 2.1 && < 2.3
292292 , network < 2.7
293293 , optparse-applicative >= 0.13 && < 0.15
libs/contrib/Control/ST/File.idrnew file+247
@@ -0,0 +1,247 @@
1+module Control.ST.File
2+
3+import Control.ST
4+import Control.IOExcept
5+
6+%default total
7+
8+||| A record of the file modes that can read from a file.
9+public export
10+data ValidModeRead : Mode -> Type where
11+ VMRRead : ValidModeRead Read
12+ VMRReadW : ValidModeRead ReadWrite
13+ VMRReadWT : ValidModeRead ReadWriteTruncate
14+ VMRReadA : ValidModeRead ReadAppend
15+
16+||| A record of the file modes that can write from a file.
17+public export
18+data ValidModeWrite : Mode -> Type where
19+ VMWWrite : ValidModeWrite WriteTruncate
20+ VMWAppend : ValidModeWrite Append
21+ VMWReadW : ValidModeWrite ReadWrite
22+ VMWReadWT : ValidModeWrite ReadWriteTruncate
23+
24+||| The file handle which will be used as a State Transition
25+||| resource in the `IO` and `IOExcept` implementations of `File`.
26+|||
27+||| @mode The `Mode` that the handle was generated under.
28+|||
29+public export
30+data FileHandle : (mode : Mode) -> Type where
31+ FH : File -> FileHandle mode
32+
33+||| Description of state transition operations on a file.
34+|||
35+||| +------------+-------------+----------------+----------------+----------------+
36+||| | Operation | State in | Mode in | State out | Mode out |
37+||| +------------+-------------+----------------+----------------+----------------+
38+||| | open | - | - | file handle | input paramater|
39+||| | close | file handle | any | - | - |
40+||| | eof | file handle | ValidModeRead | file handle | ValidModeRead |
41+||| | flush | file handle | any | file handle | unchanged |
42+||| | readLine | file handle | ValidModeRead | file handle | ValidModeRead |
43+||| | readChar | file handle | ValidModeRead | file handle | ValidModeRead |
44+||| | readFile | - | - | - | - |
45+||| | writeString| file handle | ValidModeWrite | file handle | ValidModeWrite |
46+||| | writeLine | file handle | ValidModeWrite | file handle | ValidModeWrite |
47+||| | writeFile | - | - | - | - |
48+||| +------------+-------------+----------------+----------------+----------------+
49+|||
50+public export
51+interface File (m : Type -> Type) where
52+ FileHandleI : Mode -> Type
53+
54+ ||| Open a file.
55+ |||
56+ ||| @fname the filename.
57+ ||| @mode the mode; either Read, WriteTruncate, Append, ReadWrite,
58+ ||| ReadWriteTruncate, or ReadAppend
59+ |||
60+ open : (fname : String)
61+ -> (mode : Mode)
62+ -> ST m (Either FileError Var) [ addIfRight (FileHandleI mode) ]
63+
64+ ||| Close a file.
65+ close : (fileHandle : Var)
66+ -> ST m () [ remove fileHandle (FileHandleI mode) ]
67+
68+ ||| Have we reached the end of the file.
69+ eof : (fileHandle : Var)
70+ -> {auto prf : ValidModeRead mode}
71+ -> ST m Bool [ fileHandle ::: (FileHandleI mode) ]
72+
73+ ||| Flush
74+ flush : (fileHandle : Var)
75+ -> ST m () [ fileHandle ::: (FileHandleI mode) ]
76+
77+ ||| Read a complete line.
78+ readLine : (fileHandle : Var)
79+ -> {auto prf : ValidModeRead mode}
80+ -> ST m (Either FileError String) [ fileHandle ::: (FileHandleI mode) ]
81+
82+ ||| Read a `Char`.
83+ readChar : (fileHandle : Var)
84+ -> {auto prf : ValidModeRead mode}
85+ -> ST m (Either FileError Char) [ fileHandle ::: (FileHandleI mode) ]
86+
87+ ||| Read the contents of a file into a string.
88+ |||
89+ ||| This checks the size of
90+ ||| the file before beginning to read, and only reads that many bytes,
91+ ||| to ensure that it remains a total function if the file is appended
92+ ||| to while being read.
93+ |||
94+ ||| Returns an error if fname is not a normal file.
95+ |||
96+ readFile : (fileName : String)
97+ -> ST m (Either FileError String) []
98+
99+ ||| Write a complete line to the file.
100+ |||
101+ ||| @string The string to be written to file.
102+ |||
103+ writeString : (fileHandle : Var)
104+ -> (string : String)
105+ -> {auto prf : ValidModeWrite mode}
106+ -> ST m (Either FileError ()) [ fileHandle ::: (FileHandleI mode) ]
107+
108+ ||| Write a complete line to the file.
109+ |||
110+ ||| @string The text to be written to file.
111+ |||
112+ writeLine : (fileHandle : Var)
113+ -> (string : String)
114+ -> {auto prf : ValidModeWrite mode}
115+ -> ST m (Either FileError ()) [ fileHandle ::: (FileHandleI mode) ]
116+
117+ ||| Create a file and write contents to the file.
118+ |||
119+ ||| @fname The fileName of the file.
120+ ||| @string The text to be written to file.
121+ |||
122+ writeFile : (fname : String)
123+ -> (string : String)
124+ -> ST m (Either FileError ()) []
125+
126+public export
127+File IO where
128+ FileHandleI mode = State (FileHandle mode)
129+
130+ open fname mode = do
131+ (Right file) <- lift ( openFile fname mode )
132+ | (Left error ) => pure (Left error)
133+ let fh = FH file
134+ var <- new fh
135+ pure (Right var)
136+
137+ close fh = do
138+ (FH file) <- read fh
139+ lift (closeFile file)
140+ delete fh
141+ pure ()
142+
143+ eof fh = do
144+ (FH file) <- read fh
145+ isEof <- lift (fEOF file)
146+ pure (isEof)
147+
148+ flush fh = do
149+ (FH file) <- read fh
150+ lift (fEOF file)
151+ pure ()
152+
153+ readLine fh = do
154+ (FH file) <- read fh
155+ (Right string) <- lift (fGetLine file)
156+ | (Left error ) => pure (Left error)
157+ pure (Right string)
158+
159+ readChar fh = do
160+ (FH file) <- read fh
161+ (Right chr) <- lift (fgetc file)
162+ | (Left error ) => pure (Left error)
163+ pure (Right chr)
164+
165+ readFile fname = do
166+ (Right content) <- lift ( readFile fname )
167+ | (Left error ) => pure (Left error)
168+ pure (Right content)
169+
170+ writeString fh str = do
171+ (FH file) <- read fh
172+ Right x <- lift (fPutStr file str)
173+ | (Left error ) => pure (Left error)
174+ pure (Right x)
175+
176+ writeLine fh str = do
177+ (FH file) <- read fh
178+ Right x <- lift (fPutStrLn file str)
179+ | (Left error ) => pure (Left error)
180+ pure (Right x)
181+
182+ writeFile fname str = do
183+ Right x <- lift (writeFile fname str)
184+ | (Left error ) => pure (Left error)
185+ pure (Right x)
186+
187+public export
188+File (IOExcept a) where
189+ FileHandleI mode = State (FileHandle mode)
190+
191+ open fname mode = do
192+ (Right file) <- lift (ioe_lift (openFile fname mode))
193+ | (Left error ) => pure (Left error)
194+ let fh = FH file
195+ var <- new fh
196+ pure (Right var)
197+
198+ close fh = do
199+ (FH file) <- read fh
200+ lift (ioe_lift (closeFile file))
201+ delete fh
202+ pure ()
203+
204+ eof fh = do
205+ (FH file) <- read fh
206+ isEof <- lift (ioe_lift (fEOF file))
207+ pure (isEof)
208+
209+ flush fh = do
210+ (FH file) <- read fh
211+ lift (ioe_lift (fEOF file))
212+ pure ()
213+
214+ readLine fh = do
215+ (FH file) <- read fh
216+ (Right string) <- lift (ioe_lift (fGetLine file))
217+ | (Left error ) => pure (Left error)
218+ pure (Right string)
219+
220+ readChar fh = do
221+ (FH file) <- read fh
222+ (Right chr) <- lift (ioe_lift (fgetc file))
223+ | (Left error ) => pure (Left error)
224+ pure (Right chr)
225+
226+ readFile fname = do
227+ (Right content) <- lift (ioe_lift (readFile fname))
228+ | (Left error ) => pure (Left error)
229+ pure (Right content)
230+
231+ writeString fh str = do
232+ (FH file) <- read fh
233+ Right x <- lift (ioe_lift (fPutStr file str))
234+ | (Left error ) => pure (Left error)
235+ pure (Right x)
236+
237+ writeLine fh str = do
238+ (FH file) <- read fh
239+ Right x <- lift (ioe_lift (fPutStrLn file str))
240+ | (Left error ) => pure (Left error)
241+ pure (Right x)
242+
243+ writeFile fname str = do
244+ Right x <- lift (ioe_lift (writeFile fname str))
245+ | (Left error ) => pure (Left error)
246+ pure (Right x)
247+--- EOF -------------------------------------------------------------------------
libs/contrib/contrib.ipkg+1
@@ -20,6 +20,7 @@ modules = CFFI
2020 , Control.ST.Exception
2121 , Control.ST.ImplicitCall
2222 , Control.ST.Random
23+ , Control.ST.File
2324
2425 , Data.Bool.Extra
2526 , Data.BoundedList
libs/prelude/IO.idr+1−1
@@ -101,7 +101,7 @@ unsafePerformPrimIO : PrimIO a -> a
101101prim_io_pure : a -> PrimIO a
102102prim_io_pure x = Prim__IO x
103103
104−-- %inline
104+-- Don't %inline; the compiler treats it specially
105105io_bind : IO' l a -> (a -> IO' l b) -> IO' l b
106106io_bind (MkIO fn)
107107 = \k => MkIO (\w => prim_io_bind (fn w)
libs/prelude/Prelude/Interfaces.idr+2
@@ -12,6 +12,8 @@ infixl 7 <<, >> -- unused
1212infixl 8 +, -
1313infixl 9 *, /
1414
15+infixl 9 `div`, `mod`
16+
1517-- ------------------------------------------------------------- [ Boolean Ops ]
1618intToBool : Int -> Bool
1719intToBool 0 = False
libs/prelude/Prelude/List.idr+12−12
@@ -447,7 +447,7 @@ transpose ((x::xs) :: xss) = assert_total $ (x :: (mapMaybe head' xss)) :: (tran
447447--------------------------------------------------------------------------------
448448
449449||| Check if something is a member of a list using a custom comparison.
450−elemBy : (a -> a -> Bool) -> a -> List a -> Bool
450+elemBy : %static (a -> a -> Bool) -> a -> List a -> Bool
451451elemBy p e [] = False
452452elemBy p e (x::xs) =
453453 if p e x then
@@ -460,7 +460,7 @@ elem : Eq a => a -> List a -> Bool
460460elem = elemBy (==)
461461
462462||| Find associated information in a list using a custom comparison.
463−lookupBy : (a -> a -> Bool) -> a -> List (a, b) -> Maybe b
463+lookupBy : %static (a -> a -> Bool) -> a -> List (a, b) -> Maybe b
464464lookupBy p e [] = Nothing
465465lookupBy p e (x::xs) =
466466 let (l, r) = x in
@@ -475,7 +475,7 @@ lookup = lookupBy (==)
475475
476476||| Check if any elements of the first list are found in the second, using
477477||| a custom comparison.
478−hasAnyBy : (a -> a -> Bool) -> List a -> List a -> Bool
478+hasAnyBy : %static (a -> a -> Bool) -> List a -> List a -> Bool
479479hasAnyBy p elems [] = False
480480hasAnyBy p elems (x::xs) =
481481 if elemBy p x elems then
@@ -527,7 +527,7 @@ findIndices = findIndices' Z
527527 findIndices' (S cnt) p xs
528528
529529||| Find the index of the first occurrence of an element in a list, using a custom equality test.
530−elemIndexBy : (a -> a -> Bool) -> a -> List a -> Maybe Nat
530+elemIndexBy : %static (a -> a -> Bool) -> a -> List a -> Maybe Nat
531531elemIndexBy p e = findIndex $ p e
532532
533533||| Find the index of the first occurrence of an element in a list,
@@ -536,7 +536,7 @@ elemIndex : Eq a => a -> List a -> Maybe Nat
536536elemIndex = elemIndexBy (==)
537537
538538||| Find all indices for an element in a list, using a custom equality test.
539−elemIndicesBy : (a -> a -> Bool) -> a -> List a -> List Nat
539+elemIndicesBy : %static (a -> a -> Bool) -> a -> List a -> List Nat
540540elemIndicesBy p e = findIndices $ p e
541541
542542||| Find all indices for an element in a list, using the default equality test for the type of list elements.
@@ -572,7 +572,7 @@ filterSmaller {p} (x :: xs) with (p x)
572572
573573||| The nubBy function behaves just like nub, except it uses a user-supplied
574574||| equality predicate instead of the overloaded == function.
575−nubBy : (a -> a -> Bool) -> List a -> List a
575+nubBy : %static (a -> a -> Bool) -> List a -> List a
576576nubBy = nubBy' []
577577 where
578578 nubBy' : List a -> (a -> a -> Bool) -> List a -> List a
@@ -595,7 +595,7 @@ nub : Eq a => List a -> List a
595595nub = nubBy (==)
596596
597597||| The deleteBy function behaves like delete, but takes a user-supplied equality predicate.
598−deleteBy : (a -> a -> Bool) -> a -> List a -> List a
598+deleteBy : %static (a -> a -> Bool) -> a -> List a -> List a
599599deleteBy _ _ [] = []
600600deleteBy eq x (y::ys) = if x `eq` y then ys else y :: deleteBy eq x ys
601601
@@ -622,7 +622,7 @@ delete = deleteBy (==)
622622(\\) = foldl (flip delete)
623623
624624||| The unionBy function returns the union of two lists by user-supplied equality predicate.
625−unionBy : (a -> a -> Bool) -> List a -> List a -> List a
625+unionBy : %static (a -> a -> Bool) -> List a -> List a -> List a
626626unionBy eq xs ys = xs ++ foldl (flip (deleteBy eq)) (nubBy eq ys) xs
627627
628628||| Compute the union of two lists according to their `Eq` implementation.
@@ -747,7 +747,7 @@ replaceOn a b l = map (\c => if c == a then b else c) l
747747||| @ eq the equality comparison
748748||| @ left the potential prefix
749749||| @ right the list that may have `left` as its prefix
750−isPrefixOfBy : (eq : a -> a -> Bool) -> (left, right : List a) -> Bool
750+isPrefixOfBy : %static (eq : a -> a -> Bool) -> (left, right : List a) -> Bool
751751isPrefixOfBy p [] right = True
752752isPrefixOfBy p left [] = False
753753isPrefixOfBy p (x::xs) (y::ys) =
@@ -760,7 +760,7 @@ isPrefixOfBy p (x::xs) (y::ys) =
760760isPrefixOf : Eq a => List a -> List a -> Bool
761761isPrefixOf = isPrefixOfBy (==)
762762
763−isSuffixOfBy : (a -> a -> Bool) -> List a -> List a -> Bool
763+isSuffixOfBy : %static (a -> a -> Bool) -> List a -> List a -> Bool
764764isSuffixOfBy p left right = isPrefixOfBy p (reverse left) (reverse right)
765765
766766||| The isSuffixOf function takes two lists and returns True iff the first list is a suffix of the second.
@@ -795,7 +795,7 @@ sorted (x::xs) =
795795||| Merge two sorted lists using an arbitrary comparison
796796||| predicate. Note that the lists must have been sorted using this
797797||| predicate already.
798−mergeBy : (a -> a -> Ordering) -> List a -> List a -> List a
798+mergeBy : %static (a -> a -> Ordering) -> List a -> List a -> List a
799799mergeBy order [] right = right
800800mergeBy order left [] = left
801801mergeBy order (x::xs) (y::ys) =
@@ -811,7 +811,7 @@ merge = mergeBy compare
811811|||
812812||| @ cmp how to compare elements
813813||| @ xs the list to sort
814−sortBy : (cmp : a -> a -> Ordering) -> (xs : List a) -> List a
814+sortBy : %static (cmp : a -> a -> Ordering) -> (xs : List a) -> List a
815815sortBy cmp [] = []
816816sortBy cmp [x] = [x]
817817sortBy cmp xs = let (x, y) = split xs in
samples/tutorial/BTreeMod.idr+5−5
@@ -1,20 +1,20 @@
11module btree
22
3−abstract data BTree a = Leaf
4− | Node (BTree a) a (BTree a)
3+export data BTree a = Leaf
4+ | Node (BTree a) a (BTree a)
55
6−abstract
6+export
77insert : Ord a => a -> BTree a -> BTree a
88insert x Leaf = Node Leaf x Leaf
99insert x (Node l v r) = if (x < v) then (Node (insert x l) v r)
1010 else (Node l v (insert x r))
1111
12−abstract
12+export
1313toList : BTree a -> List a
1414toList Leaf = []
1515toList (Node l v r) = btree.toList l ++ (v :: btree.toList r)
1616
17−abstract
17+export
1818toTree : Ord a => List a -> BTree a
1919toTree [] = Leaf
2020toTree (x :: xs) = insert x (toTree xs)
src/IRTS/CodegenC.hs+7−1
@@ -220,8 +220,14 @@ bcc i (PROJECT l loc a) = indent i ++ "PROJECT(vm, " ++ creg l ++ ", " ++ show l
220220 ", " ++ show a ++ ");\n"
221221bcc i (PROJECTINTO r t idx)
222222 = indent i ++ creg r ++ " = GETARG(" ++ creg t ++ ", " ++ show idx ++ ");\n"
223+bcc i (CASE True r [(_, alt)] Nothing)
224+ = indent i ++ showCode i alt
225+ where
226+ showCode :: Int -> [BC] -> String
227+ showCode i bc = "{\n" ++ concatMap (bcc (i + 1)) bc ++
228+ indent i ++ "}\n"
223229bcc i (CASE True r code def)
224− | length code < 4 && length code > 0 = showCase i def code
230+ | length code < 6 && length code > 1 = showCase i def code
225231 where
226232 showCode :: Int -> [BC] -> String
227233 showCode i bc = "{\n" ++ concatMap (bcc (i + 1)) bc ++
src/IRTS/JavaScript/Codegen.hs+1−4
@@ -112,15 +112,12 @@ makeExportDecls defs (Export _ _ e) =
112112 ]
113113 uncurryF name argTy Nothing = name
114114
115− addApplyForIO (FIO _) f = T.concat ["function(){ return (",f, ").apply(this,arguments)()}"]
116− addApplyForIO _ f = f
117−
118115 makeExport (ExportData _) =
119116 []
120117 makeExport (ExportFun name (FStr exportname) retTy argTy) =
121118 [T.concat [ T.pack $ exportname
122119 , ": "
123− , addApplyForIO retTy $ uncurryF (jsName name) argTy (getArgList' name defs)
120+ , uncurryF (jsName name) argTy (getArgList' name defs)
124121 ]
125122 ]
126123
src/IRTS/JavaScript/PrimOp.hs−2
@@ -26,8 +26,6 @@ data JsPrimTy = PTBool | PTAny deriving (Eq, Ord)
2626type PrimF = [JsExpr] -> JsExpr
2727type PrimDec = (Bool, JsPrimTy, PrimF) -- the bool indicates if bigint library is used or not
2828
29−deriving instance Ord PrimFn
30−
3129primDB :: Map.Map PrimFn PrimDec
3230primDB =
3331 Map.fromList [
src/IRTS/Lang.hs+95−32
@@ -16,6 +16,7 @@ import Idris.Core.TT
1616import Control.Monad.State hiding (lift)
1717import Data.Data (Data)
1818import Data.List
19+import qualified Data.Map.Strict as Map
1920import Data.Typeable (Typeable)
2021import GHC.Generics (Generic)
2122
@@ -44,26 +45,26 @@ data LExp = LV Name
4445 | LOp PrimFn [LExp]
4546 | LNothing
4647 | LError String
47− deriving Eq
48+ deriving (Eq, Ord)
4849
4950data FDesc = FCon Name
5051 | FStr String
5152 | FUnknown
5253 | FIO FDesc
5354 | FApp Name [FDesc]
54− deriving (Show, Eq)
55+ deriving (Show, Eq, Ord)
5556
5657data Export = ExportData FDesc -- Exported data descriptor (usually string)
5758 | ExportFun Name -- Idris name
5859 FDesc -- Exported function descriptor
5960 FDesc -- Return type descriptor
6061 [FDesc] -- Argument types
61− deriving (Show, Eq)
62+ deriving (Show, Eq, Ord)
6263
6364data ExportIFace = Export Name -- FFI descriptor
6465 String -- interface file
6566 [Export]
66− deriving (Show, Eq)
67+ deriving (Show, Eq, Ord)
6768
6869-- Primitive operators. Backends are not *required* to implement all
6970-- of these, but should report an error if they are unable
@@ -96,12 +97,12 @@ data PrimFn = LPlus ArithTy | LMinus ArithTy | LTimes ArithTy
9697 | LCrash
9798
9899 | LNoOp
99− deriving (Show, Eq, Generic)
100+ deriving (Show, Eq, Ord, Generic)
100101
101102-- Supported target languages for foreign calls
102103
103104data FCallType = FStatic | FObject | FConstructor
104− deriving (Show, Eq)
105+ deriving (Show, Eq, Ord)
105106
106107data FType = FArith ArithTy
107108 | FFunction
@@ -112,24 +113,24 @@ data FType = FArith ArithTy
112113 | FManagedPtr
113114 | FCData
114115 | FAny
115− deriving (Show, Eq)
116+ deriving (Show, Eq, Ord)
116117
117118-- FIXME: Why not use this for all the IRs now?
118119data LAlt' e = LConCase Int Name [Name] e
119120 | LConstCase Const e
120121 | LDefaultCase e
121− deriving (Show, Eq, Functor, Data, Typeable)
122+ deriving (Show, Eq, Ord, Functor, Data, Typeable)
122123
123124type LAlt = LAlt' LExp
124125
125126data LDecl = LFun [LOpt] Name [Name] LExp -- options, name, arg names, def
126127 | LConstructor Name Int Int -- constructor name, tag, arity
127− deriving (Show, Eq)
128+ deriving (Show, Eq, Ord)
128129
129130type LDefs = Ctxt LDecl
130131
131132data LOpt = Inline | NoInline
132− deriving (Show, Eq)
133+ deriving (Show, Eq, Ord)
133134
134135addTags :: Int -> [(Name, LDecl)] -> (Int, [(Name, LDecl)])
135136addTags i ds = tag i ds []
@@ -140,37 +141,71 @@ addTags i ds = tag i ds []
140141 tag i (x : as) acc = tag i as (x : acc)
141142 tag i [] acc = (i, reverse acc)
142143
143−data LiftState = LS Name Int [(Name, LDecl)]
144+data LiftState = LS (Maybe Name) Int [(Name, LDecl)]
145+ (Map.Map ([Name], LExp) Name) -- map from args/expressions
146+ -- to names, so we don't create the same function
147+ -- multiple times
148+
149+setBaseName :: Name -> State LiftState ()
150+setBaseName n
151+ = do LS _ i ds done <- get
152+ put (LS (Just n) i ds done)
144153
145154lname (NS n x) i = NS (lname n i) x
146155lname (UN n) i = MN i n
147156lname x i = sMN i (showCG x ++ "_lam")
148157
149−liftAll :: [(Name, LDecl)] -> [(Name, LDecl)]
150−liftAll xs = concatMap (\ (x, d) -> lambdaLift x d) xs
151−
152−lambdaLift :: Name -> LDecl -> [(Name, LDecl)]
153−lambdaLift n (LFun opts _ args e)
154− = let (e', (LS _ _ decls)) = runState (lift args e) (LS n 0 []) in
155− (n, LFun opts n args e') : decls
156−lambdaLift n x = [(n, x)]
157−
158158getNextName :: State LiftState Name
159−getNextName = do LS n i ds <- get
160− put (LS n (i + 1) ds)
161− return (lname n i)
159+getNextName
160+ = do LS mn i ds done <- get
161+ let newn = case mn of
162+ Nothing -> lname (sUN "_") i
163+ Just n -> lname n i
164+ put (LS mn (i + 1) ds done)
165+ return newn
166+
167+renameArgs :: [Name] -> LExp -> ([Name], LExp)
168+renameArgs args e
169+ = let newargNames = map (\i -> sMN i "lift") [0..]
170+ newargs = zip args newargNames in
171+ (map snd newargs, rename newargs e)
162172
163173addFn :: Name -> LDecl -> State LiftState ()
164−addFn fn d = do LS n i ds <- get
165− put (LS n i ((fn, d) : ds))
174+addFn fn d
175+ = do LS n i ds done <- get
176+ put (LS n i ((fn, d) : ds) done)
177+
178+makeFn :: [Name] -> LExp -> State LiftState Name
179+makeFn args exp
180+ = do fn <- getNextName
181+ let (args', exp') = renameArgs args exp
182+ LS n i ds done <- get
183+ case Map.lookup (args', exp') done of
184+ Just fn -> return fn
185+ Nothing ->
186+ do addFn fn (LFun [Inline] fn args' exp')
187+ LS n i ds done <- get
188+ put (LS n i ds (Map.insert (args', exp') fn done))
189+ return fn
190+
191+liftAll :: [(Name, LDecl)] -> [(Name, LDecl)]
192+liftAll xs =
193+ let (LS _ _ decls _) = execState (mapM_ liftDef xs) (LS Nothing 0 [] Map.empty) in
194+ decls
195+
196+liftDef :: (Name, LDecl) -> State LiftState ()
197+liftDef (n, LFun opts _ args e) =
198+ do setBaseName n
199+ e' <- lift args e
200+ addFn n (LFun opts n args e')
201+liftDef (n, x) = addFn n x
166202
167203lift :: [Name] -> LExp -> State LiftState LExp
168204lift env (LV v) = return (LV v) -- Lifting happens before these can exist...
169205lift env (LApp tc (LV n) args) = do args' <- mapM (lift env) args
170206 return (LApp tc (LV n) args')
171207lift env (LApp tc f args) = do f' <- lift env f
172− fn <- getNextName
173− addFn fn (LFun [Inline] fn env f')
208+ fn <- makeFn env f'
174209 args' <- mapM (lift env) args
175210 return (LApp tc (LV fn) (map LV env ++ args'))
176211lift env (LLazyApp n args) = do args' <- mapM (lift env) args
@@ -180,18 +215,17 @@ lift env (LLazyExp (LConst c)) = return (LConst c)
180215-- = lift env (LLazyApp f args)
181216lift env (LLazyExp e) = do e' <- lift env e
182217 let usedArgs = nub $ usedIn env e'
183− fn <- getNextName
184− addFn fn (LFun [NoInline] fn usedArgs e')
218+ fn <- makeFn usedArgs e'
185219 return (LLazyApp fn (map LV usedArgs))
186220lift env (LForce e) = do e' <- lift env e
187221 return (LForce e')
188222lift env (LLet n v e) = do v' <- lift env v
189223 e' <- lift (env ++ [n]) e
190224 return (LLet n v' e')
225+lift env (LLam args (LLam args' e)) = lift env (LLam (args ++ args') e)
191226lift env (LLam args e) = do e' <- lift (env ++ args) e
192227 let usedArgs = nub $ usedIn env e'
193− fn <- getNextName
194− addFn fn (LFun [Inline] fn (usedArgs ++ args) e')
228+ fn <- makeFn (usedArgs ++ args) e'
195229 return (LApp False (LV fn) (map LV usedArgs))
196230lift env (LProj t i) = do t' <- lift env t
197231 return (LProj t' i)
@@ -329,6 +363,35 @@ lsubst n new (LCase t e alts) = let e' = lsubst n new e
329363 LCase t e' alts'
330364lsubst n new tm = tm
331365
366+rename :: [(Name, Name)] -> LExp -> LExp
367+rename ns tm@(LV x)
368+ = case lookup x ns of
369+ Just n -> LV n
370+ _ -> tm
371+rename ns (LApp t e args)
372+ = let e' = rename ns e
373+ args' = map (rename ns) args in
374+ LApp t e' args'
375+rename ns (LLazyApp fn args)
376+ = let args' = map (rename ns) args in
377+ LLazyApp fn args'
378+rename ns (LLazyExp e) = LLazyExp (rename ns e)
379+rename ns (LForce e) = LForce (rename ns e)
380+rename ns (LLet v val sc) = LLet v (rename ns val) (rename ns sc)
381+rename ns (LLam args sc) = LLam args (rename ns sc)
382+rename ns (LProj e i) = LProj (rename ns e) i
383+rename ns (LCon lv t cn args) = let args' = map (rename ns) args in
384+ LCon lv t cn args'
385+rename ns (LOp op args) = let args' = map (rename ns) args in
386+ LOp op args'
387+rename ns (LForeign fd rd args)
388+ = let args' = map (\(d, a) -> (d, rename ns a)) args in
389+ LForeign fd rd args'
390+rename ns (LCase t e alts) = let e' = rename ns e
391+ alts' = map (fmap (rename ns)) alts in
392+ LCase t e' alts'
393+rename ns tm = tm
394+
332395instance Show LExp where
333396 show e = show' [] "" e where
334397 show' env ind (LV n) = show n
@@ -357,7 +420,7 @@ instance Show LExp where
357420 atloc (Just l) = "@" ++ show (LV l) ++ ":"
358421
359422 show' env ind (LCase up e alts)
360− = "case" ++ update ++ show' env ind e ++ " of \n" ++ fmt alts
423+ = "case" ++ update ++ "(" ++ show' env ind e ++ ") of \n" ++ fmt alts
361424 where
362425 update = case up of
363426 Shared -> " "
src/IRTS/LangOpts.hs+163−7
@@ -35,13 +35,22 @@ nextN = do i <- get
3535doInline :: LDefs -> LDecl -> LDecl
3636doInline defs d@(LConstructor _ _ _) = d
3737doInline defs (LFun opts topn args exp)
38− = let res = evalState (eval [] initEnv [topn] defs exp)
39− (length args) in
40−-- = let res = evalState (inlineWith [topn] (map (\n -> (n, LV n)) args) exp) 0 in
38+ = let inl = evalState (eval [] initEnv [topn] defs exp)
39+ (length args)
40+ -- do some case floating, which might arise as a result
41+ -- then, eta contract
42+ res = eta $ caseFloats 10 inl in
4143 case res of
4244 LLam args' body -> LFun opts topn (map snd initNames ++ args') body
4345 _ -> LFun opts topn (map snd initNames) res
4446 where
47+ caseFloats 0 tm = tm
48+ caseFloats n tm
49+ = let res = caseFloat tm in
50+ if res == tm
51+ then res
52+ else caseFloats (n-1) res
53+
4554 initNames = zipWith (\n i -> (n, newn n i)) args [0..]
4655 initEnv = map (\(n, n') -> (n, LV n')) initNames
4756 newn (UN n) i = MN i n
@@ -61,7 +70,11 @@ eval :: [LExp] -> [(Name, LExp)] -> [Name] -> LDefs -> LExp -> State Int LExp
6170eval stk env rec defs (LLazyApp n es)
6271 = unload stk <$> LLazyApp n <$> (mapM (eval [] env rec defs) es)
6372eval stk env rec defs (LForce e)
64− = unload stk <$> LForce <$> eval [] env rec defs e
73+ = do e' <- eval [] env rec defs e
74+ case e' of
75+ LLazyExp forced -> return $ unload stk forced
76+ LLazyApp n es -> return $ unload stk (LApp False (LV n) es)
77+ _ -> return (unload stk (LForce e'))
6578eval stk env rec defs (LLazyExp e)
6679 = unload stk <$> LLazyExp <$> eval [] env rec defs e
6780-- Special case for io_bind, because it needs to keep executing the first
@@ -93,8 +106,15 @@ eval stk env rec defs (LProj exp i)
93106eval stk env rec defs (LCon loc i n es)
94107 = unload stk <$> (LCon loc i n <$> mapM (eval [] env rec defs) es)
95108eval stk env rec defs (LCase ty e alts)
96− = LCase ty <$> eval [] env rec defs e
97− <*> mapM (evalAlt stk env rec defs) alts
109+ = do alts' <- mapM (evalAlt stk env rec defs) alts
110+ e' <- eval [] env rec defs e
111+ -- If they're all lambdas, bind the lambda at the top
112+ let prefix = getLams (map getRHS alts')
113+ case prefix of
114+ [] -> return $ conOpt $ LCase ty e' (replaceInAlts e' alts')
115+ args -> do alts_red <- mapM (dropArgs args) alts'
116+ return $ LLam args
117+ (conOpt (LCase ty e' (replaceInAlts e' alts_red)))
98118eval stk env rec defs (LOp f es)
99119 = unload stk <$> LOp f <$> mapM (eval [] env rec defs) es
100120eval stk env rec defs (LForeign t s args)
@@ -109,7 +129,7 @@ eval stk env rec defs (LLam args sc)
109129 [] -> eval stk' env' rec defs sc
110130 as -> do ns' <- mapM (\n -> do n' <- nextN
111131 return (n, n')) args'
112− LLam (map snd ns') <$>
132+ unload stk' <$> LLam (map snd ns') <$>
113133 eval [] (map (\ (n, n') -> (n, LV n')) ns' ++ env')
114134 rec defs sc
115135eval stk env rec defs var@(LV n)
@@ -123,6 +143,8 @@ eval stk env rec defs var@(LV n)
123143 Just (LFun opts _ args body) <- lookupCtxtExact n defs,
124144 Inline `elem` opts ->
125145 apply stk env (n : rec) defs var args body
146+ | Just (LConstructor n t a) <- lookupCtxtExact n defs ->
147+ return (LCon Nothing t n stk)
126148 | otherwise -> return (unload stk var)
127149eval stk env rec defs t = return (unload stk t)
128150
@@ -140,3 +162,137 @@ apply :: [LExp] -> [(Name, LExp)] -> [Name] -> LDefs -> LExp ->
140162 [Name] -> LExp -> State Int LExp
141163apply stk env rec defs var args body
142164 = eval stk env rec defs (LLam args body)
165+
166+dropArgs :: [Name] -> LAlt -> State Int LAlt
167+dropArgs as (LConCase i n es (LLam args rhs))
168+ = do let old = take (length as) args
169+ rhs' <- eval [] (zipWith (\ o n -> (o, LV n)) old as) [] emptyContext rhs
170+ return (LConCase i n es rhs')
171+dropArgs as (LConstCase c (LLam args rhs))
172+ = do let old = take (length as) args
173+ rhs' <- eval [] (zipWith (\ o n -> (o, LV n)) old as) [] emptyContext rhs
174+ return (LConstCase c rhs')
175+dropArgs as (LDefaultCase (LLam args rhs))
176+ = do let old = take (length as) args
177+ rhs' <- eval [] (zipWith (\ o n -> (o, LV n)) old as) [] emptyContext rhs
178+ return (LDefaultCase rhs')
179+
180+caseFloat :: LExp -> LExp
181+caseFloat (LApp tc e es) = LApp tc (caseFloat e) (map caseFloat es)
182+caseFloat (LLazyExp e) = LLazyExp (caseFloat e)
183+caseFloat (LForce e) = LForce (caseFloat e)
184+caseFloat (LCon up i n es) = LCon up i n (map caseFloat es)
185+caseFloat (LOp f es) = LOp f (map caseFloat es)
186+caseFloat (LLam ns sc) = LLam ns (caseFloat sc)
187+caseFloat (LLet v val sc) = LLet v (caseFloat val) (caseFloat sc)
188+caseFloat (LCase _ (LCase ct exp alts) alts')
189+ | all conRHS alts || length alts == 1
190+ = conOpt $ replaceInCase (LCase ct (caseFloat exp) (map (updateWith alts') alts))
191+ where
192+ conRHS (LConCase _ _ _ (LCon _ _ _ _)) = True
193+ conRHS (LConstCase _ (LCon _ _ _ _)) = True
194+ conRHS (LDefaultCase (LCon _ _ _ _)) = True
195+ conRHS _ = False
196+
197+ updateWith alts (LConCase i n es rhs) =
198+ LConCase i n es (caseFloat (conOpt (LCase Shared (caseFloat rhs) alts)))
199+ updateWith alts (LConstCase c rhs) =
200+ LConstCase c (caseFloat (conOpt (LCase Shared (caseFloat rhs) alts)))
201+ updateWith alts (LDefaultCase rhs) =
202+ LDefaultCase (caseFloat (conOpt (LCase Shared (caseFloat rhs) alts)))
203+
204+caseFloat (LCase ct exp alts')
205+ = conOpt $ replaceInCase (LCase ct (caseFloat exp) (map cfAlt alts'))
206+ where
207+ cfAlt (LConCase i n es rhs) = LConCase i n es (caseFloat rhs)
208+ cfAlt (LConstCase c rhs) = LConstCase c (caseFloat rhs)
209+ cfAlt (LDefaultCase rhs) = LDefaultCase (caseFloat rhs)
210+caseFloat exp = exp
211+
212+-- Case of constructor
213+conOpt :: LExp -> LExp
214+conOpt (LCase ct (LCon _ t n args) alts)
215+ = pickAlt n args alts
216+ where
217+ pickAlt n args (LConCase i n' es rhs : as) | n == n'
218+ = substAll (zip es args) rhs
219+ pickAlt _ _ (LDefaultCase rhs : as) = rhs
220+ pickAlt n args (_ : as) = pickAlt n args as
221+ pickAlt n args [] = error "Can't happen pickAlt - impossible case found"
222+
223+ substAll [] rhs = rhs
224+ substAll ((n, tm) : ss) rhs = lsubst n tm (substAll ss rhs)
225+conOpt tm = tm
226+
227+replaceInCase :: LExp -> LExp
228+replaceInCase (LCase ty e alts)
229+ = LCase ty e (replaceInAlts e alts)
230+replaceInCase exp = exp
231+
232+replaceInAlts :: LExp -> [LAlt] -> [LAlt]
233+replaceInAlts exp alts = dropDups $ concatMap (replaceInAlt exp) alts
234+
235+-- Drop overlapping case (arising from case merging of overlapping
236+-- patterns)
237+dropDups (alt@(LConCase _ i n ns) : alts)
238+ = alt : dropDups (filter (notTag i) alts)
239+ where
240+ notTag i (LConCase _ j n ns) = i /= j
241+ notTag _ _ = True
242+dropDups (c : alts) = c : dropDups alts
243+dropDups [] = []
244+
245+
246+replaceInAlt :: LExp -> LAlt -> [LAlt]
247+-- In an alternative, if the case appears on the right hand side, replace
248+-- it with the given expression, to preserve sharing
249+replaceInAlt exp@(LV _) (LConCase i con args rhs)
250+ = [LConCase i con args $
251+ replaceExp (LCon Nothing i con (map LV args)) exp rhs]
252+-- if a default case inspects the same variable as the case it's in,
253+-- remove the inspection and replace with the alternatives
254+-- (i.e. merge the inner case block)
255+replaceInAlt exp@(LV var) (LDefaultCase (LCase ty (LV var') alts))
256+ | var == var' = alts
257+replaceInAlt exp a = [a]
258+
259+replaceExp :: LExp -> LExp -> LExp -> LExp
260+replaceExp (LCon _ t n args) new (LCon _ t' n' args')
261+ | n == n' && args == args' = new
262+replaceExp (LCon _ t n args) new (LApp _ (LV n') args')
263+ | n == n' && args == args' = new
264+replaceExp old new tm = tm
265+
266+-- dropArgs as (LConstCase c rhs) = LConstCase c (dropRHS as rhs)
267+-- dropArgs as (LDefaultCase rhs) = LDefaultCase (dropRHS as rhs)
268+
269+getRHS (LConCase i n es rhs) = rhs
270+getRHS (LConstCase _ rhs) = rhs
271+getRHS (LDefaultCase rhs) = rhs
272+
273+getLams [] = []
274+getLams (LLam args tm : cs) = getLamPrefix args cs
275+getLams _ = []
276+
277+getLamPrefix as [] = as
278+getLamPrefix as (LLam args tm : cs)
279+ | length args < length as = getLamPrefix args cs
280+ | otherwise = getLamPrefix as cs
281+getLamPrefix as (_ : cs) = []
282+
283+-- eta contract ('\x -> f x' can just be compiled as 'f' when f is local)
284+eta :: LExp -> LExp
285+eta (LApp tc a es) = LApp tc (eta a) (map eta es)
286+eta (LLazyApp n es) = LLazyApp n (map eta es)
287+eta (LLazyExp e) = LLazyExp (eta e)
288+eta (LForce e) = LForce (eta e)
289+eta (LLet n val sc) = LLet n (eta val) (eta sc)
290+eta (LLam args (LApp tc f args'))
291+ | args' == map LV args = eta f
292+eta (LLam args e) = LLam args (eta e)
293+eta (LProj e i) = LProj (eta e) i
294+eta (LCon a t n es) = LCon a t n (map eta es)
295+eta (LCase ct e alts) = LCase ct (eta e) (map (fmap eta) alts)
296+eta (LOp f es) = LOp f (map eta es)
297+eta tm = tm
298+
src/Idris/Parser.hs+13−5
@@ -649,9 +649,6 @@ fnOpt = do keyword "total"; return TotalFn
649649 <|> NoImplicit <$ P.try (lchar '%' *> reserved "no_implicit")
650650 <|> Inlinable <$ P.try (lchar '%' *> reserved "inline")
651651 <|> StaticFn <$ P.try (lchar '%' *> reserved "static")
652− <|> do fc <- P.try $ extent $ lchar '%' *> reserved "assert_total"
653− parserWarning fc Nothing (Msg "%assert_total is deprecated. Use the 'assert_total' function instead.")
654− return AssertTotal
655652 <|> ErrorHandler <$ P.try (lchar '%' *> reserved "error_handler")
656653 <|> ErrorReverse <$ P.try (lchar '%' *> reserved "error_reverse")
657654 <|> ErrorReduce <$ P.try (lchar '%' *> reserved "error_reduce")
@@ -880,10 +877,15 @@ interface_ syn = do (doc, argDocs, acc)
880877 fundeps :: IdrisParser [(Name, FC)]
881878 fundeps = do lchar '|'; P.sepBy (withExtent name) (lchar ',')
882879
880+ classWarning :: String
881+ classWarning = "Use of a fragile keyword `class`. " ++
882+ "`class` is provided for those coming from Haskell. " ++
883+ "Please use `interface` instead, which is equivalent."
884+
883885 interfaceKeyword :: IdrisParser ()
884886 interfaceKeyword = keyword "interface"
885887 <|> do fc <- extent $ keyword "class"
886− parserWarning fc Nothing (Msg "The 'class' keyword is deprecated. Use 'interface' instead.")
888+ parserWarning fc Nothing (Msg classWarning)
887889
888890 carg :: IdrisParser (Name, FC, PTerm)
889891 carg = do lchar '('; (i, ifc) <- withExtent name; lchar ':'; ty <- expr syn; lchar ')'
@@ -928,10 +930,16 @@ implementation syn = do (doc, argDocs) <- docstring syn
928930 let n = expandNS syn n_in
929931 return n
930932 <?> "implementation name"
933+
934+ instanceWarning :: String
935+ instanceWarning = "Use of fragile keyword `instance`. " ++
936+ "`instance` is provided for those coming from Haskell. " ++
937+ "Please use `implementation` (which is equivalent) instead, or omit it."
938+
931939 implementationKeyword :: IdrisParser ()
932940 implementationKeyword = keyword "implementation"
933941 <|> do fc <- extent $ keyword "instance"
934− parserWarning fc Nothing (Msg "The 'instance' keyword is deprecated. Use 'implementation' (or omit it) instead.")
942+ parserWarning fc Nothing (Msg instanceWarning)
935943
936944 implementationUsing :: IdrisParser [Name]
937945 implementationUsing = do keyword "using"
src/Idris/Parser/Expr.hs−3
@@ -1408,9 +1408,6 @@ Static ::=
14081408-}
14091409static :: IdrisParser Static
14101410static = Static <$ reserved "%static"
1411− <|> do fc <- extent $ reserved "[static]"
1412− parserWarning fc Nothing (Msg "The use of [static] is deprecated, use %static instead.")
1413− return Static
14141411 <|> return Dynamic
14151412 <?> "static modifier"
14161413
src/Idris/Parser/Helpers.hs+5−21
@@ -260,7 +260,7 @@ float = token . P.try $ P.float
260260reservedIdentifiers :: HS.HashSet String
261261reservedIdentifiers = HS.fromList
262262 [ "Type"
263− , "abstract", "case", "class", "codata", "constructor", "corecord", "data"
263+ , "case", "class", "codata", "constructor", "corecord", "data"
264264 , "do", "dsl", "else", "export", "if", "implementation", "implicit"
265265 , "import", "impossible", "in", "infix", "infixl", "infixr", "instance"
266266 , "interface", "let", "mutual", "namespace", "of", "parameters", "partial"
@@ -520,26 +520,10 @@ notOpenBraces = do ist <- get
520520
521521{- | Parses an accessibilty modifier (e.g. public, private) -}
522522accessibility' :: IdrisParser Accessibility
523−accessibility'
524− = do fc <- extent $ reserved "public"
525− gotexp <- optional (reserved "export")
526− case gotexp of
527− Just _ -> return ()
528− Nothing -> do
529− ist <- get
530− put ist { parserWarnings =
531− (fc, Msg "'public' is deprecated. Use 'public export' instead.")
532− : parserWarnings ist }
533− return Public
534− <|> do fc <- extent $ reserved "abstract"
535− ist <- get
536− put ist { parserWarnings =
537− (fc, Msg "The 'abstract' keyword is deprecated. Use 'export' instead.")
538− : parserWarnings ist }
539− return Frozen
540− <|> do reserved "export"; return Frozen
541− <|> do reserved "private"; return Private
542− <?> "accessibility modifier"
523+accessibility' = Public <$ reserved "public" <* reserved "export"
524+ <|> Frozen <$ reserved "export"
525+ <|> Private <$ reserved "private"
526+ <?> "accessibility modifier"
543527
544528accessibility :: IdrisParser Accessibility
545529accessibility = do acc <- optional accessibility'
stack-nightly.yamldeleted−17
@@ -1,17 +0,0 @@
1−#recheck extra-deps next on resolver or cabal file change
2−resolver: nightly-2017-11-25
3−
4−packages:
5− - location: .
6−
7−flags:
8− idris:
9− FFI: true
10− GMP: true
11−
12−ghc-options:
13− idris: -fwarn-unused-imports -fwarn-unused-binds
14−
15−nix:
16− enable: false
17− shell-file: stack-shell.nix
stack.yaml+2−5
@@ -1,13 +1,10 @@
11#recheck extra-deps next on resolver or cabal file change
2−resolver: lts-9.17
2+resolver: lts-10.0
33
44packages:
55 - location: .
66
7−extra-deps:
8− - binary-0.8.5.1
9− - cheapskate-0.1.1
10− - megaparsec-6.2.0
7+extra-deps: []
118
129flags:
1310 idris:
test/README.md+1
@@ -91,6 +91,7 @@ Tests are categorised with the following test families (and their identifiers):
9191+ *reg*: Regression tests, covering previous bug fixes
9292+ *regression*: Regression tests, covering previous bug fixes
9393+ *sourceLocation*: Interaction with files from Idris
94++ *st*: ST, state transition systems
9495+ *sugar*: Syntactic sugar, syntax extensions
9596+ *syntax*: Syntax extensions
9697+ *tactics*: Testing for tactics
test/TestData.hs+8
@@ -276,6 +276,14 @@ testFamiliesData = [
276276 ( 3 , ANY )]),
277277 ("sourceLocation", "Source location",
278278 [ ( 1 , ANY )]),
279+ ("st", "ST",
280+ [ ( 1, C_CG),
281+ ( 2, C_CG),
282+ ( 3, C_CG),
283+ ( 4, C_CG),
284+ ( 5, C_CG),
285+ ( 6, C_CG),
286+ ( 7, C_CG)]),
279287 ("sugar", "Syntactic sugar",
280288 [ ( 1, ANY ),
281289 ( 2, ANY ),
test/st001/expectednew file+8
@@ -0,0 +1,8 @@
1+# test001:
2+--test IO:
3+["HELLO!!\n", "WORLD!!"]
4+2
5+--test IOExcept:
6+["HELLO!!\n", "WORLD!!"]
7+2
8+()
test/st001/runnew file+6
@@ -0,0 +1,6 @@
1+#!/usr/bin/env bash
2+${IDRIS:-idris} $@ -p contrib test001.idr -o test001
3+echo "# test001:"
4+./test001
5+rm -f test001 *.ibc
6+
test/st001/test001.idrnew file+66
@@ -0,0 +1,66 @@
1+module Main
2+
3+import Control.IOExcept
4+import Control.ST
5+import Control.ST.File
6+import Control.ST.ImplicitCall
7+
8+increment : (x : Var) -> STrans m () [ x ::: State Int ]
9+ (const [x ::: State Int])
10+increment x = do num <- read x
11+ write x (num + 1)
12+
13+readFileCount : (ConsoleIO m, File m) =>
14+ (fileHandle : Var)
15+ -> (count : Var)
16+ -> {auto prf : ValidModeRead mode}
17+ -> ST m (Either FileError (List String))
18+ [ count ::: (State Int),
19+ fileHandle ::: FileHandleI {m} mode ]
20+readFileCount fh cnt =
21+ readAcc fh cnt []
22+ where
23+ readAcc : (ConsoleIO m, File m) =>
24+ (fileHandle : Var)
25+ -> (count : Var)
26+ -> List String
27+ -> {auto prf : ValidModeRead mode}
28+ -> ST m (Either FileError (List String))
29+ [ count ::: (State Int),
30+ fileHandle ::: FileHandleI {m} mode ]
31+ readAcc fileHandle cnt acc = with ST do
32+ e <- (eof fileHandle)
33+ if (not e)
34+ then do Right str <- (readLine fileHandle)
35+ | Left ferr => pure (Left ferr)
36+ (increment cnt)
37+ readAcc fileHandle cnt (str :: acc)
38+ else do let rev = reverse acc
39+ pure (Right rev)
40+
41+testFile : (ConsoleIO m, File m) => ST m () []
42+testFile = with ST do
43+ Right fileHandle <- open "testFile" Read
44+ | Left ferr => do putStrLn (show ferr)
45+ pure ()
46+ count <- new 0
47+ Right fContents <- readFileCount fileHandle count
48+ | Left ferr => do putStrLn (show ferr)
49+ delete count
50+ close fileHandle
51+ pure ()
52+ putStrLn (show fContents)
53+ putStrLn (show !(read count))
54+ delete count
55+ close fileHandle
56+ pure ()
57+
58+main : IO ()
59+main = do putStrLn "--test IO:"
60+ run testFile
61+ putStrLn "--test IOExcept:"
62+ ioe_run (run testFile)
63+ (\err => putStrLn err)
64+ (\ok => printLn ok)
65+
66+-- EOF -------------------------------------------------------------------------
test/st001/testFilenew file+2
@@ -0,0 +1,2 @@
1+HELLO!!
2+WORLD!!
test/st002/expectednew file+8
@@ -0,0 +1,8 @@
1+# test002:
2+--test IO:
3+['H', 'E', 'L', 'L', 'O', '!', '!', '\n', 'W', 'O', 'R', 'L', 'D', '!', '!', '\NUL']
4+16
5+--test IOExcept:
6+['H', 'E', 'L', 'L', 'O', '!', '!', '\n', 'W', 'O', 'R', 'L', 'D', '!', '!', '\NUL']
7+16
8+()
test/st002/runnew file+6
@@ -0,0 +1,6 @@
1+#!/usr/bin/env bash
2+${IDRIS:-idris} $@ -p contrib test002.idr -o test002
3+echo "# test002:"
4+./test002
5+rm -f test002 *.ibc
6+
test/st002/test002.idrnew file+66
@@ -0,0 +1,66 @@
1+module Main
2+
3+import Control.IOExcept
4+import Control.ST
5+import Control.ST.File
6+import Control.ST.ImplicitCall
7+
8+increment : (x : Var) -> STrans m () [ x ::: State Int ]
9+ (const [x ::: State Int])
10+increment x = do num <- read x
11+ write x (num + 1)
12+
13+readFileCount : (ConsoleIO m, File m) =>
14+ (fileHandle : Var)
15+ -> (count : Var)
16+ -> {auto prf : ValidModeRead mode}
17+ -> ST m (Either FileError (List Char))
18+ [ count ::: (State Int),
19+ fileHandle ::: FileHandleI {m} mode ]
20+readFileCount fh cnt =
21+ readAcc fh cnt []
22+ where
23+ readAcc : (ConsoleIO m, File m) =>
24+ (fileHandle : Var)
25+ -> (count : Var)
26+ -> List Char
27+ -> {auto prf : ValidModeRead mode}
28+ -> ST m (Either FileError (List Char))
29+ [ count ::: (State Int),
30+ fileHandle ::: FileHandleI {m} mode ]
31+ readAcc fileHandle cnt acc = with ST do
32+ e <- (eof fileHandle)
33+ if (not e)
34+ then do Right chr <- (readChar fileHandle)
35+ | Left ferr => pure (Left ferr)
36+ (increment cnt)
37+ readAcc fileHandle cnt (chr :: acc)
38+ else do let rev = reverse acc
39+ pure (Right rev)
40+
41+testFile : (ConsoleIO m, File m) => ST m () []
42+testFile = with ST do
43+ Right fileHandle <- open "testFile" Read
44+ | Left ferr => do putStrLn (show ferr)
45+ pure ()
46+ count <- new 0
47+ Right fContents <- readFileCount fileHandle count
48+ | Left ferr => do putStrLn (show ferr)
49+ delete count
50+ close fileHandle
51+ pure ()
52+ putStrLn (show fContents)
53+ putStrLn (show !(read count))
54+ delete count
55+ close fileHandle
56+ pure ()
57+
58+main : IO ()
59+main = do putStrLn "--test IO:"
60+ run testFile
61+ putStrLn "--test IOExcept:"
62+ ioe_run (run testFile)
63+ (\err => putStrLn err)
64+ (\ok => printLn ok)
65+
66+-- EOF -------------------------------------------------------------------------
test/st002/testFilenew file+2
@@ -0,0 +1,2 @@
1+HELLO!!
2+WORLD!!
test/st003/expectednew file+8
@@ -0,0 +1,8 @@
1+# test003:
2+--test IO:
3+HELLO!!
4+WORLD!!
5+--test IOExcept:
6+HELLO!!
7+WORLD!!
8+()
test/st003/runnew file+6
@@ -0,0 +1,6 @@
1+#!/usr/bin/env bash
2+${IDRIS:-idris} $@ -p contrib test003.idr -o test003
3+echo "# test003:"
4+./test003
5+rm -f test003 *.ibc
6+
test/st003/test003.idrnew file+25
@@ -0,0 +1,25 @@
1+module Main
2+
3+import Control.IOExcept
4+import Control.ST
5+import Control.ST.File
6+import Control.ST.ImplicitCall
7+
8+testFile : (ConsoleIO m, File m) => ST m () []
9+testFile = with ST do
10+ Right str <- readFile "testFile"
11+ | Left ferr => do putStrLn (show ferr)
12+ pure ()
13+ putStrLn str
14+ pure ()
15+
16+
17+main : IO ()
18+main = do putStrLn "--test IO:"
19+ run testFile
20+ putStrLn "--test IOExcept:"
21+ ioe_run (run testFile)
22+ (\err => putStrLn err)
23+ (\ok => printLn ok)
24+
25+-- EOF -------------------------------------------------------------------------
test/st003/testFilenew file+2
@@ -0,0 +1,2 @@
1+HELLO!!
2+WORLD!!
test/st004/expectednew file+6
@@ -0,0 +1,6 @@
1+# test004:
2+--test IO:
3+File Not Found
4+--test IOExcept:
5+File Not Found
6+()
test/st004/runnew file+6
@@ -0,0 +1,6 @@
1+#!/usr/bin/env bash
2+${IDRIS:-idris} $@ -p contrib test004.idr -o test004
3+echo "# test004:"
4+./test004
5+rm -f test004 *.ibc
6+
test/st004/test004.idrnew file+24
@@ -0,0 +1,24 @@
1+module Main
2+
3+import Control.IOExcept
4+import Control.ST
5+import Control.ST.File
6+import Control.ST.ImplicitCall
7+
8+testFile : (ConsoleIO m, File m) => ST m () []
9+testFile = with ST do
10+ Right str <- readFile "noneexistingtestFile"
11+ | Left ferr => do putStrLn (show ferr)
12+ pure ()
13+ putStr str
14+ pure ()
15+
16+main : IO ()
17+main = do putStrLn "--test IO:"
18+ run testFile
19+ putStrLn "--test IOExcept:"
20+ ioe_run (run testFile)
21+ (\err => putStrLn err)
22+ (\ok => printLn ok)
23+
24+-- EOF -------------------------------------------------------------------------
test/st005/expectednew file+6
@@ -0,0 +1,6 @@
1+# test005:
2+--test IO:
3+--test IOExcept:
4+()
5+HELLO!!
6+WORLD!!
test/st005/runnew file+7
@@ -0,0 +1,7 @@
1+#!/usr/bin/env bash
2+${IDRIS:-idris} $@ -p contrib test005.idr -o test005
3+echo "# test005:"
4+./test005
5+cat writeTestFile
6+rm -f test005 writeTestFile *.ibc
7+
test/st005/test005.idrnew file+33
@@ -0,0 +1,33 @@
1+module Main
2+
3+import Control.IOExcept
4+import Control.ST
5+import Control.ST.File
6+import Control.ST.ImplicitCall
7+
8+testFile : (ConsoleIO m, File m) => ST m () []
9+testFile = with ST do
10+ Right fileHandle <- open "writeTestFile" WriteTruncate
11+ | Left ferr => do putStrLn (show ferr)
12+ pure ()
13+ Right _ <- writeLine fileHandle "HELLO!!"
14+ | Left ferr => do putStrLn (show ferr)
15+ close fileHandle
16+ pure ()
17+ Right _ <- writeLine fileHandle "WORLD!!"
18+ | Left ferr => do putStrLn (show ferr)
19+ close fileHandle
20+ pure ()
21+ close fileHandle
22+ pure ()
23+
24+
25+main : IO ()
26+main = do putStrLn "--test IO:"
27+ run testFile
28+ putStrLn "--test IOExcept:"
29+ ioe_run (run testFile)
30+ (\err => putStrLn err)
31+ (\ok => printLn ok)
32+
33+-- EOF -------------------------------------------------------------------------
test/st006/expectednew file+5
@@ -0,0 +1,5 @@
1+# test006:
2+--test IO:
3+--test IOExcept:
4+()
5+HELLO!!WORLD!!
test/st006/runnew file+6
@@ -0,0 +1,6 @@
1+#!/usr/bin/env bash
2+${IDRIS:-idris} $@ -p contrib test006.idr -o test006
3+echo "# test006:"
4+./test006
5+cat writeStringTestFile
6+rm -f test006 writeStringTestFile *.ibc
test/st006/test006.idrnew file+37
@@ -0,0 +1,37 @@
1+module Main
2+
3+import Control.IOExcept
4+import Control.ST
5+import Control.ST.File
6+import Control.ST.ImplicitCall
7+
8+testFile : (ConsoleIO m, File m) => ST m () []
9+testFile = with ST do
10+ Right fileHandle <- open "writeStringTestFile" WriteTruncate
11+ | Left ferr => do putStrLn (show ferr)
12+ pure ()
13+ Right _ <- writeString fileHandle "HELLO!!"
14+ | Left ferr => do putStrLn (show ferr)
15+ close fileHandle
16+ pure ()
17+ Right _ <- writeString fileHandle "WORLD!!"
18+ | Left ferr => do putStrLn (show ferr)
19+ close fileHandle
20+ pure ()
21+ Right _ <- writeString fileHandle "\n"
22+ | Left ferr => do putStrLn (show ferr)
23+ close fileHandle
24+ pure ()
25+ close fileHandle
26+ pure ()
27+
28+
29+main : IO ()
30+main = do putStrLn "--test IO:"
31+ run testFile
32+ putStrLn "--test IOExcept:"
33+ ioe_run (run testFile)
34+ (\err => putStrLn err)
35+ (\ok => printLn ok)
36+
37+-- EOF -------------------------------------------------------------------------
test/st007/expectednew file+6
@@ -0,0 +1,6 @@
1+# test007:
2+--test IO:
3+--test IOExcept:
4+()
5+HELLO!!
6+WORLD!!
test/st007/runnew file+6
@@ -0,0 +1,6 @@
1+#!/usr/bin/env bash
2+${IDRIS:-idris} $@ -p contrib test007.idr -o test007
3+echo "# test007:"
4+./test007
5+cat writeFileTestFile
6+rm -f test007 writeFileTestFile *.ibc
test/st007/test007.idrnew file+24
@@ -0,0 +1,24 @@
1+module Main
2+
3+import Control.IOExcept
4+import Control.ST
5+import Control.ST.File
6+import Control.ST.ImplicitCall
7+
8+testFile : (ConsoleIO m, File m) => ST m () []
9+testFile = with ST do
10+ Right _ <- writeFile "writeFileTestFile" "HELLO!!\nWORLD!!\n"
11+ | Left ferr => do putStrLn (show ferr)
12+ pure ()
13+ pure ()
14+
15+
16+main : IO ()
17+main = do putStrLn "--test IO:"
18+ run testFile
19+ putStrLn "--test IOExcept:"
20+ ioe_run (run testFile)
21+ (\err => putStrLn err)
22+ (\ok => printLn ok)
23+
24+-- EOF -------------------------------------------------------------------------
test/views001/views001.idr+1−1
@@ -26,7 +26,7 @@ mergeSort xs with (splitRec xs)
2626testList : Int -> Int -> List Int -> List Int
2727testList 0 seed acc = acc
2828-- Need to explicitly mod since different back ends overflow differently
29−testList x seed acc = let seed' = seed * 12345 + 768 `mod` 65536 in
29+testList x seed acc = let seed' = (seed * 12345 + 768) `mod` 65536 in
3030 testList (x - 1) seed'
3131 ((seed' `mod` 100) :: acc)
3232
test/views001/views001a.idr+1−1
@@ -13,7 +13,7 @@ mergeSort xs with (splitRec xs)
1313testList : Int -> Int -> List Int -> List Int
1414testList 0 seed acc = acc
1515-- Need to explicitly mod since different back ends overflow differently
16−testList x seed acc = let seed' = seed * 12345 + 768 `mod` 65536 in
16+testList x seed acc = let seed' = (seed * 12345 + 768) `mod` 65536 in
1717 testList (x - 1) seed'
1818 ((seed' `mod` 100) :: acc)
1919
test/views002/views002.idr+1−1
@@ -11,7 +11,7 @@ qsort inp with (filtered (<) inp)
1111testList : Int -> Int -> List Int -> List Int
1212testList 0 seed acc = acc
1313-- Need to explicitly mod since different back ends overflow differently
14−testList x seed acc = let seed' = seed * 12345 + 768 `mod` 65536 in
14+testList x seed acc = let seed' = (seed * 12345 + 768) `mod` 65536 in
1515 testList (x - 1) seed'
1616 ((seed' `mod` 100) :: acc)
1717