on master help sign in
Merge remote-tracking branch 'upstream/master' into error-reflection
commit887b6e28fd7db06f2ba36e8c51296c99a713211c authorDavid Raymond Christiansen <david@davidchristiansen.dk> dateThu 23 Jan 2014, 15:46 (13 years ago) parent0ab30e75080735
38 files changed+1183−95
CONTRIBUTING.md+37−13 CONTRIBUTORS+2 idris.cabal+12 libs/Makefile+3 libs/base/Data/Fun.idr+8 libs/base/Data/Rel.idr+13 libs/base/Decidable/Decidable.idr+9−5 libs/base/Decidable/Order.idr+2−6 libs/base/Language/Reflection/Errors.idr+1 libs/base/base.ipkg+2−1 libs/neweffects/Effect/Default.idr+44 libs/neweffects/Effect/Exception.idr+39 libs/neweffects/Effect/File.idr+62 libs/neweffects/Effect/Memory.idr+175 libs/neweffects/Effect/Monad.idr+21 libs/neweffects/Effect/Random.idr+25 libs/neweffects/Effect/Select.idr+23 libs/neweffects/Effect/State.idr+40 libs/neweffects/Effect/StdIO.idr+63 libs/neweffects/Effects.idr+268 libs/neweffects/Makefile+14 libs/neweffects/neweffects.ipkg+9 libs/prelude/Prelude.idr+6−2 rts/idris_stdfgn.c+4 rts/idris_stdfgn.h+1 src/IRTS/CodegenJavaScript.hs+119−20 src/Idris/Core/Elaborate.hs+19−11 src/Idris/Core/Evaluate.hs+9−8 src/Idris/Core/TT.hs+82−13 src/Idris/Core/Unify.hs+25−5 src/Idris/Delaborate.hs+5 src/Idris/ElabDecls.hs+2−2 src/Idris/ElabTerm.hs+8−1 src/Idris/IBC.hs+9−5 src/Idris/REPL.hs+1−1 src/Util/Zlib.hs+15 test/reg031/expected+1−1 test/reg031/reg031.idr+5−1
CONTRIBUTING.md+37−13
@@ -30,34 +30,54 @@ Please clean up any messes that you find, and don't leave behind new messes for
3030Idris developers and hackers try to adhere to something similar to the [successful git branching model](http://nvie.com/posts/a-successful-git-branching-model/).
3131The steps are straightforward.
3232
33+### New contributors
34+
3335For those new to the project:
3436
35−1. Fork the `idris-dev` repo e.g.
37+1. Fork our [main development repository](https://github.com/idris-lang/Idris-dev) `idris-dev` on github e.g.
38+2. Clone your fork to your local machine:
39+
40+```
41+$ git clone git@github.com/<your github user name>/Idris-dev.git
42+```
43+
44+3. Add `idris-lang/Idris-dev` as a remote upstream
3645
37− $ git clone git@github.com/<your github user name>/Idris-dev.git
38− $ git remote add upstream git@github.com:idris-lang/Idris-dev.git
46+```
47+$ git remote add upstream git@github.com:idris-lang/Idris-dev.git
48+```
49+
50+### Existing Contributors
3951
4052For those already contributing to the project:
4153
42−1. Ensure your existing clone is up-to-date with current HEAD e.g.
54+1. Ensure your existing clone is up-to-date with current `HEAD` e.g.
55+
56+```
57+$ git fetch upstream
58+$ git merge upstream/master
59+```
4360
44− $ git fetch upstream
45− $ git merge upstream/master
61+### Remaining Steps
4662
47−The remaining steps are the same:
63+The remaining steps are the same for both new and existing contributors:
4864
49651. Create, and checkout onto, a topic branch on which to base you work.
5066 * This is typically the master branch.
5167 * For your own sanity, please avoid working on the `master` branch.
5268
53− $ git branch fix/master/my_contrib master
54− $ git checkout fix/master/my_contrib
69+```
70+$ git branch fix/master/my_contrib master
71+$ git checkout fix/master/my_contrib
72+```
5573
56741. Make commits of logical units.
57751. Check for unnecessary whitespace with
5876
59− $ git diff --check
60−
77+```
78+$ git diff --check
79+```
80+
61811. Make sure your commit messages are along the lines of:
6282
6383 Short (50 chars or less) summary of changes
@@ -79,11 +99,15 @@ The remaining steps are the same:
79991. Make sure you have added any necessary tests for your changes.
801001. Run all the tests to assure nothing else was accidentally broken.
81101
82− $ make test
102+```
103+$ make test
104+```
83105
841061. Push your changes to a topic branch in your fork of the repository.
85107
86− $ git push origin fix/master/my_contrib
108+```
109+$ git push origin fix/master/my_contrib
110+```
87111
881121. Go to GitHub and submit a pull request to `idris-dev`
89113
CONTRIBUTORS+2
@@ -15,6 +15,7 @@ Hannes Mehnert
1515Mekeor Melire
1616Melissa Mozifian
1717Dominic Mulligan
18+Jan de Muijnck-Hughes
1819raichoo
1920Tom Prince
2021Seo Sanghyeon
@@ -26,3 +27,4 @@ Leif Warner
2627Daniel Waterworth
2728Jonas Westerlund
2829Reynir Reynisson
30+
idris.cabal+12
@@ -95,6 +95,11 @@ Extra-source-files:
9595 libs/effects/Effect/*.idr
9696 libs/effects/*.idr
9797
98+ libs/neweffects/Makefile
99+ libs/neweffects/neweffects.ipkg
100+ libs/neweffects/Effect/*.idr
101+ libs/neweffects/*.idr
102+
98103 libs/javascript/*.idr
99104 libs/javascript/JavaScript/*.idr
100105 libs/javascript/Makefile
@@ -192,6 +197,12 @@ Extra-source-files:
192197 test/reg029/run
193198 test/reg029/*.idr
194199 test/reg029/expected
200+ test/reg030/run
201+ test/reg030/*.idr
202+ test/reg030/expected
203+ test/reg031/run
204+ test/reg031/*.idr
205+ test/reg031/expected
195206 test/test001/run
196207 test/test001/*.idr
197208 test/test001/expected
@@ -415,6 +426,7 @@ Library
415426 Util.Pretty
416427 , Util.System
417428 , Util.Net
429+ , Util.Zlib
418430
419431 , Pkg.PParser
420432
libs/Makefile+3
@@ -2,6 +2,7 @@ build:
22 $(MAKE) -C prelude build
33 $(MAKE) -C base build
44 $(MAKE) -C effects build
5+ $(MAKE) -C neweffects build
56 $(MAKE) -C javascript build
67
78
@@ -9,12 +10,14 @@ install:
910 $(MAKE) -C prelude install
1011 $(MAKE) -C base install
1112 $(MAKE) -C effects install
13+ $(MAKE) -C neweffects install
1214 $(MAKE) -C javascript install
1315
1416clean:
1517 $(MAKE) -C prelude clean
1618 $(MAKE) -C base clean
1719 $(MAKE) -C effects clean
20+ $(MAKE) -C neweffects clean
1821 $(MAKE) -C javascript clean
1922
2023.PHONY: build install clean
libs/base/Data/Fun.idrnew file+8
@@ -0,0 +1,8 @@
1+module Data.Fun
2+
3+--------------------------------------------------------------------------------
4+-- Build an n-ary function type from a Vect of Types and a result type
5+--------------------------------------------------------------------------------
6+Fun : Vect n Type -> Type -> Type
7+Fun [] r = r
8+Fun (t::ts) r = t -> Fun ts r
libs/base/Data/Rel.idrnew file+13
@@ -0,0 +1,13 @@
1+module Data.Rel
2+
3+import Data.Fun
4+
5+--------------------------------------------------------------------------------
6+-- Build an n-ary relation type from a Vect of Types
7+--------------------------------------------------------------------------------
8+Rel : Vect n Type -> Type
9+Rel ts = Fun ts Type
10+
11+liftRel : (ts : Vect n Type) -> (p : Rel ts) -> (Type -> Type) -> Type
12+liftRel [] p f = f p
13+liftRel (t :: ts) p f = (x : t) -> liftRel ts (p x) f
libs/base/Decidable/Decidable.idr+9−5
@@ -1,17 +1,21 @@
11module Decidable.Decidable
22
3+import Data.Rel
4+
35%access public
46
57--------------------------------------------------------------------------------
68-- Typeclass for decidable n-ary Relations
79--------------------------------------------------------------------------------
810
9−using (t : Type)
10− class Rel (p : t) where
11− total liftRel : (Type -> Type) -> Type
11+-- Note: Instance resolution for Decidable is likely to not work in the REPL
12+-- at the moment.
13+class Decidable (ts : Vect k Type) (p : Rel ts) where
14+ total decide : liftRel ts p Dec
1215
13− class (Rel p) => Decidable (p : t) where
14− total decide : liftRel {p} Dec
16+-- 'No such variable {k506}'
17+--decision : Decidable ts p => (ts : Vect k Type) -> (p : Rel ts) -> liftRel ts p Dec
18+--decision ts p = decide {ts} {p}
1519
1620using (P : Type, p : P)
1721 data Given : Dec P -> Type where
libs/base/Decidable/Order.idr+2−6
@@ -71,12 +71,8 @@ decideNatLTE x (S y) with (decEq x (S y))
7171 | Yes nLTEm = Yes (nLTESm nLTEm)
7272 | No nGTm = No (nGTSm nGTm)
7373
74−instance Rel NatLTE where
75− liftRel P = (n : Nat) -> (m : Nat) -> P (NatLTE n m)
76−
77−instance Decidable NatLTE where
74+instance Decidable [Nat,Nat] NatLTE where
7875 decide = decideNatLTE
7976
8077lte : (m : Nat) -> (n : Nat) -> Dec (NatLTE m n)
81−lte m n = decide {p = NatLTE} m n
82−
78+lte m n = decide {ts = [Nat,Nat]} {p = NatLTE} m n
libs/base/Language/Reflection/Errors.idr+1
@@ -15,6 +15,7 @@ data Err = Msg String
1515 -- unification succeed
1616 | InfiniteUnify TTName TT (List (TTName, TT))
1717 | CantConvert TT TT (List (TTName, TT))
18+ | CantSolveGoal TT (List (TTName, TT))
1819 | UnifyScope TTName TTName TT (List (TTName, TT))
1920 | CantInferType String
2021 | NonFunctionType TT TT
libs/base/base.ipkg+2−1
@@ -23,7 +23,8 @@ modules = System,
2323 Data.ZZ, Data.Sign,
2424 Data.SortedMap, Data.SortedSet, Data.BoundedList,
2525 Data.Vect, Data.HVect, Data.Vect.Quantifiers,
26− Data.Floats, Data.Complex, Data.Heap,
26+ Data.Floats, Data.Complex, Data.Heap, Data.Fun,
27+ Data.Rel,
2728
2829 Control.Isomorphism,
2930 Control.Monad.Identity,
libs/neweffects/Effect/Default.idrnew file+44
@@ -0,0 +1,44 @@
1+module Default
2+
3+class Default a where
4+ default : a
5+
6+instance Default Int where
7+ default = 0
8+
9+instance Default Integer where
10+ default = 0
11+
12+instance Default Float where
13+ default = 0
14+
15+instance Default Nat where
16+ default = 0
17+
18+instance Default Char where
19+ default = '\0'
20+
21+instance Default String where
22+ default = ""
23+
24+instance Default Bool where
25+ default = False
26+
27+instance Default () where
28+ default = ()
29+
30+instance (Default a, Default b) => Default (a, b) where
31+ default = (default, default)
32+
33+instance Default (Maybe a) where
34+ default = Nothing
35+
36+instance Default (List a) where
37+ default = []
38+
39+instance Default a => Default (Vect n a) where
40+ default = mkDef _ where
41+ mkDef : (n : Nat) -> Vect n a
42+ mkDef Z = []
43+ mkDef (S k) = default :: mkDef k
44+
libs/neweffects/Effect/Exception.idrnew file+39
@@ -0,0 +1,39 @@
1+module Effect.Exception
2+
3+import Effects
4+import System
5+import Control.IOExcept
6+
7+data Exception : Type -> Effect where
8+ Raise : a -> { () } Exception a b
9+
10+instance Handler (Exception a) Maybe where
11+ handle _ (Raise e) k = Nothing
12+
13+instance Show a => Handler (Exception a) IO where
14+ handle _ (Raise e) k = do print e
15+ believe_me (exit 1)
16+
17+instance Handler (Exception a) (IOExcept a) where
18+ handle _ (Raise e) k = ioM (return (Left e))
19+
20+instance Handler (Exception a) (Either a) where
21+ handle _ (Raise e) k = Left e
22+
23+EXCEPTION : Type -> EFFECT
24+EXCEPTION t = MkEff () (Exception t)
25+
26+raise : a -> { [EXCEPTION a ] } Eff m b
27+raise err = Raise err
28+
29+
30+
31+
32+
33+
34+-- TODO: Catching exceptions mid program?
35+-- probably need to invoke a new interpreter
36+
37+-- possibly add a 'handle' to the Eff language so that an alternative
38+-- handler can be introduced mid interpretation?
39+
libs/neweffects/Effect/File.idrnew file+62
@@ -0,0 +1,62 @@
1+module Effect.File
2+
3+import Effects
4+import Control.IOExcept
5+
6+data OpenFile : Mode -> Type where
7+ FH : File -> OpenFile m
8+
9+openOK : Mode -> Bool -> Type
10+openOK m True = OpenFile m
11+openOK m False = ()
12+
13+data FileIO : Effect where
14+ Open : String -> (m : Mode) ->
15+ {() ==> if result then OpenFile m else ()} FileIO Bool
16+ Close : {OpenFile m ==> ()} FileIO ()
17+
18+ ReadLine : {OpenFile Read} FileIO String
19+ WriteLine : String -> {OpenFile Write} FileIO ()
20+ EOF : {OpenFile Read} FileIO Bool
21+
22+instance Handler FileIO IO where
23+ handle () (Open fname m) k = do h <- openFile fname m
24+ valid <- validFile h
25+ if valid then k True (FH h)
26+ else k False ()
27+ handle (FH h) Close k = do closeFile h
28+ k () ()
29+ handle (FH h) ReadLine k = do str <- fread h
30+ k str (FH h)
31+ handle (FH h) (WriteLine str) k = do fwrite h str
32+ k () (FH h)
33+ handle (FH h) EOF k = do e <- feof h
34+ k e (FH h)
35+
36+FILE_IO : Type -> EFFECT
37+FILE_IO t = MkEff t FileIO
38+
39+open : Handler FileIO e =>
40+ String -> (m : Mode) ->
41+ { [FILE_IO ()] ==> [FILE_IO (if result then OpenFile m else ())] } Eff e Bool
42+open f m = Open f m
43+
44+close : Handler FileIO e =>
45+ { [FILE_IO (OpenFile m)] ==> [FILE_IO ()] } Eff e ()
46+close = Close
47+
48+readLine : Handler FileIO e =>
49+ { [FILE_IO (OpenFile Read)] } Eff e String
50+readLine = ReadLine
51+
52+writeLine : Handler FileIO e =>
53+ String -> { [FILE_IO (OpenFile Write)] } Eff e ()
54+writeLine str = WriteLine str
55+
56+eof : Handler FileIO e =>
57+ { [FILE_IO (OpenFile Read)] } Eff e Bool
58+eof = EOF
59+
60+
61+
62+
libs/neweffects/Effect/Memory.idrnew file+175
@@ -0,0 +1,175 @@
1+module Effect.Memory
2+
3+import Effects
4+import Control.IOExcept
5+
6+%access public
7+
8+abstract
9+data MemoryChunk : Nat -> Nat -> Type where
10+ CH : Ptr -> MemoryChunk size initialized
11+
12+abstract
13+data RawMemory : Effect where
14+ Allocate : (n : Nat) ->
15+ RawMemory () () (\v => MemoryChunk n 0)
16+ Free : RawMemory () (MemoryChunk n i) (\v => ())
17+ Initialize : Bits8 ->
18+ (size : Nat) ->
19+ so (i + size <= n) ->
20+ RawMemory () (MemoryChunk n i) (\v => MemoryChunk n (i + size))
21+ Peek : (offset : Nat) ->
22+ (size : Nat) ->
23+ so (offset + size <= i) ->
24+ RawMemory (Vect size Bits8)
25+ (MemoryChunk n i) (\v => MemoryChunk n i)
26+ Poke : (offset : Nat) ->
27+ (Vect size Bits8) ->
28+ so (offset <= i && offset + size <= n) ->
29+ RawMemory () (MemoryChunk n i) (\v => MemoryChunk n (max i (offset + size)))
30+ Move : (src : MemoryChunk src_size src_init) ->
31+ (dst_offset : Nat) ->
32+ (src_offset : Nat) ->
33+ (size : Nat) ->
34+ so (dst_offset <= dst_init && dst_offset + size <= dst_size) ->
35+ so (src_offset + size <= src_init) ->
36+ RawMemory () (MemoryChunk dst_size dst_init)
37+ (\v => MemoryChunk dst_size (max dst_init (dst_offset + size)))
38+ GetRawPtr : RawMemory (MemoryChunk n i) (MemoryChunk n i) (\v => MemoryChunk n i)
39+
40+private
41+do_malloc : Nat -> IOExcept String Ptr
42+do_malloc size with (fromInteger (cast size) == size)
43+ | True = do ptr <- ioe_lift $ mkForeign (FFun "malloc" [FInt] FPtr) (fromInteger $ cast size)
44+ fail <- ioe_lift $ nullPtr ptr
45+ if fail then ioe_fail "Cannot allocate memory"
46+ else return ptr
47+ | False = ioe_fail "The target architecture does not support adressing enough memory"
48+
49+private
50+do_memset : Ptr -> Nat -> Bits8 -> Nat -> IO ()
51+do_memset ptr offset c size
52+ = mkForeign (FFun "idris_memset" [FPtr, FInt, FByte, FInt] FUnit)
53+ ptr (fromInteger $ cast offset) c (fromInteger $ cast size)
54+
55+private
56+do_free : Ptr -> IO ()
57+do_free ptr = mkForeign (FFun "free" [FPtr] FUnit) ptr
58+
59+private
60+do_memmove : Ptr -> Ptr -> Nat -> Nat -> Nat -> IO ()
61+do_memmove dest src dest_offset src_offset size
62+ = mkForeign (FFun "idris_memmove" [FPtr, FPtr, FInt, FInt, FInt] FUnit)
63+ dest src (fromInteger $ cast dest_offset) (fromInteger $ cast src_offset) (fromInteger $ cast size)
64+
65+private
66+do_peek : Ptr -> Nat -> (size : Nat) -> IO (Vect size Bits8)
67+do_peek _ _ Z = return (Prelude.Vect.Nil)
68+do_peek ptr offset (S n)
69+ = do b <- mkForeign (FFun "idris_peek" [FPtr, FInt] FByte) ptr (fromInteger $ cast offset)
70+ bs <- do_peek ptr (S offset) n
71+ Prelude.Monad.return (Prelude.Vect.(::) b bs)
72+
73+private
74+do_poke : Ptr -> Nat -> Vect size Bits8 -> IO ()
75+do_poke _ _ [] = return ()
76+do_poke ptr offset (b::bs)
77+ = do mkForeign (FFun "idris_poke" [FPtr, FInt, FByte] FUnit) ptr (fromInteger $ cast offset) b
78+ do_poke ptr (S offset) bs
79+
80+instance Handler RawMemory (IOExcept String) where
81+ handle () (Allocate n) k
82+ = do ptr <- do_malloc n
83+ k () (CH ptr)
84+ handle {-{res = MemoryChunk _ offset}-} (CH ptr) (Initialize {i} c size _) k
85+ = ioe_lift (do_memset ptr i c size) $> k () (CH ptr)
86+ handle (CH ptr) (Free) k
87+ = ioe_lift (do_free ptr) $> k () ()
88+ handle (CH ptr) (Peek offset size _) k
89+ = do res <- ioe_lift (do_peek ptr offset size)
90+ k res (CH ptr)
91+ handle (CH ptr) (Poke offset content _) k
92+ = do ioe_lift (do_poke ptr offset content)
93+ k () (CH ptr)
94+ handle (CH dest_ptr) (Move (CH src_ptr) dest_offset src_offset size _ _) k
95+ = do ioe_lift (do_memmove dest_ptr src_ptr dest_offset src_offset size)
96+ k () (CH dest_ptr)
97+ handle chunk (GetRawPtr) k
98+ = k chunk chunk
99+
100+RAW_MEMORY : Type -> EFFECT
101+RAW_MEMORY t = MkEff t RawMemory
102+
103+allocate : (n : Nat) ->
104+ Eff m () [RAW_MEMORY ()] (\v => [RAW_MEMORY (MemoryChunk n 0)])
105+allocate size = Allocate size
106+
107+initialize : {i : Nat} ->
108+ {n : Nat} ->
109+ Bits8 ->
110+ (size : Nat) ->
111+ so (i + size <= n) ->
112+ Eff m () [RAW_MEMORY (MemoryChunk n i)]
113+ (\v => [RAW_MEMORY (MemoryChunk n (i + size))])
114+initialize c size prf = Initialize c size prf
115+
116+free : Eff m () [RAW_MEMORY (MemoryChunk n i)] (\v => [RAW_MEMORY ()])
117+free = Free
118+
119+peek : {i : Nat} ->
120+ (offset : Nat) ->
121+ (size : Nat) ->
122+ so (offset + size <= i) ->
123+ { [RAW_MEMORY (MemoryChunk n i)] } Eff m (Vect size Bits8)
124+peek offset size prf = Peek offset size prf
125+
126+poke : {n : Nat} ->
127+ {i : Nat} ->
128+ (offset : Nat) ->
129+ Vect size Bits8 ->
130+ so (offset <= i && offset + size <= n) ->
131+ Eff m () [RAW_MEMORY (MemoryChunk n i)]
132+ (\v => [RAW_MEMORY (MemoryChunk n (max i (offset + size)))])
133+poke offset content prf = Poke offset content prf
134+
135+private
136+getRawPtr : { [RAW_MEMORY (MemoryChunk n i)] } Eff m (MemoryChunk n i)
137+getRawPtr = GetRawPtr
138+
139+private
140+move' : {dst_size : Nat} ->
141+ {dst_init : Nat} ->
142+ {src_init : Nat} ->
143+ (src_ptr : MemoryChunk src_size src_init) ->
144+ (dst_offset : Nat) ->
145+ (src_offset : Nat) ->
146+ (size : Nat) ->
147+ so (dst_offset <= dst_init && dst_offset + size <= dst_size) ->
148+ so (src_offset + size <= src_init) ->
149+ Eff m () [RAW_MEMORY (MemoryChunk dst_size dst_init)]
150+ (\v => [RAW_MEMORY (MemoryChunk dst_size (max dst_init (dst_offset + size)))])
151+move' src_ptr dst_offset src_offset size dst_bounds src_bounds
152+ = Move src_ptr dst_offset src_offset size dst_bounds src_bounds
153+
154+data MoveDescriptor = Dst | Src
155+
156+move : {dst_size : Nat} ->
157+ {dst_init : Nat} ->
158+ {src_size : Nat} ->
159+ {src_init : Nat} ->
160+ (dst_offset : Nat) ->
161+ (src_offset : Nat) ->
162+ (size : Nat) ->
163+ so (dst_offset <= dst_init && dst_offset + size <= dst_size) ->
164+ so (src_offset + size <= src_init) ->
165+ Eff m ()
166+ [ Dst ::: RAW_MEMORY (MemoryChunk dst_size dst_init)
167+ , Src ::: RAW_MEMORY (MemoryChunk src_size src_init)]
168+ (\v =>
169+ [ Dst ::: RAW_MEMORY (MemoryChunk dst_size (max dst_init (dst_offset + size)))
170+ , Src ::: RAW_MEMORY (MemoryChunk src_size src_init)])
171+move dst_offset src_offset size dst_bounds src_bounds
172+ = do src_ptr <- Src :- getRawPtr
173+ Dst :- move' src_ptr dst_offset src_offset size dst_bounds src_bounds
174+ return ()
175+
libs/neweffects/Effect/Monad.idrnew file+21
@@ -0,0 +1,21 @@
1+module Effect.Monad
2+
3+import Effects
4+
5+-- Eff is a monad too, so we can happily use it in a monad transformer.
6+
7+using (xs : List EFFECT, m : Type -> Type)
8+ instance Functor (\a => EffM m a xs (\v => xs)) where
9+ map f prog = do t <- prog
10+ value (f t)
11+
12+ instance Applicative (\a => EffM m a xs (\v => xs)) where
13+ pure = value
14+ (<$>) f a = do f' <- f
15+ a' <- a
16+ value (f' a')
17+
18+ instance Monad (\a => Eff m a xs (\v => xs)) where
19+ (>>=) = Effects.(>>=)
20+
21+
libs/neweffects/Effect/Random.idrnew file+25
@@ -0,0 +1,25 @@
1+module Effect.Random
2+
3+import Effects
4+
5+data Random : Effect where
6+ getRandom : { Integer } Random Integer
7+ setSeed : Integer -> { Integer } Random ()
8+
9+using (m : Type -> Type)
10+ instance Handler Random m where
11+ handle seed getRandom k
12+ = let seed' = (1664525 * seed + 1013904223) `prim__sremBigInt` (pow 2 32) in
13+ k seed' seed'
14+ handle seed (setSeed n) k = k () n
15+
16+RND : EFFECT
17+RND = MkEff Integer Random
18+
19+rndInt : Integer -> Integer -> { [RND] } Eff m Integer
20+rndInt lower upper = do v <- getRandom
21+ return (v `prim__sremBigInt` (upper - lower) + lower)
22+
23+srand : Integer -> { [RND] } Eff m ()
24+srand n = setSeed n
25+
libs/neweffects/Effect/Select.idrnew file+23
@@ -0,0 +1,23 @@
1+module Effect.Select
2+
3+import Effects
4+
5+data Selection : Effect where
6+ Select : List a -> { () } Selection a
7+
8+instance Handler Selection Maybe where
9+ handle _ (Select xs) k = tryAll xs where
10+ tryAll [] = Nothing
11+ tryAll (x :: xs) = case k x () of
12+ Nothing => tryAll xs
13+ Just v => Just v
14+
15+instance Handler Selection List where
16+ handle r (Select xs) k = concatMap (\x => k x r) xs
17+
18+SELECT : EFFECT
19+SELECT = MkEff () Selection
20+
21+select : List a -> { [SELECT] } Eff m a
22+select xs = Select xs
23+
libs/neweffects/Effect/State.idrnew file+40
@@ -0,0 +1,40 @@
1+module Effect.State
2+
3+import Effects
4+
5+%access public
6+
7+data State : Effect where
8+ Get : { a } State a
9+ Put : b -> { a ==> b } State ()
10+
11+using (m : Type -> Type)
12+ instance Handler State m where
13+ handle st Get k = k st st
14+ handle st (Put n) k = k () n
15+
16+STATE : Type -> EFFECT
17+STATE t = MkEff t State
18+
19+get : { [STATE x] } Eff m x
20+get = Get
21+
22+put : x -> { [STATE x] } Eff m ()
23+put val = Put val
24+
25+putM : y -> { [STATE x] ==> [STATE y] } Eff m ()
26+putM val = Put val
27+
28+update : (x -> x) -> { [STATE x] } Eff m ()
29+update f = put (f !get)
30+
31+updateM : (x -> y) -> { [STATE x] ==> [STATE y] } Eff m ()
32+updateM f = putM (f !get)
33+
34+locally : x -> ({ [STATE x] } Eff m t) -> { [STATE y] } Eff m t
35+locally newst prog = do st <- get
36+ putM newst
37+ val <- prog
38+ putM st
39+ return val
40+
libs/neweffects/Effect/StdIO.idrnew file+63
@@ -0,0 +1,63 @@
1+module Effect.StdIO
2+
3+import Effects
4+import Control.IOExcept
5+
6+data StdIO : Effect where
7+ PutStr : String -> { () } StdIO ()
8+ GetStr : { () } StdIO String
9+
10+instance Handler StdIO IO where
11+ handle () (PutStr s) k = do putStr s; k () ()
12+ handle () GetStr k = do x <- getLine; k x ()
13+
14+{-
15+instance Handler StdIO (IOExcept a) where
16+ handle () (PutStr s) k = do ioe_lift (putStr s); k () ()
17+ handle () GetStr k = do x <- ioe_lift getLine; k () x
18+
19+-- Handle effects in a pure way, for simulating IO for unit testing/proof
20+
21+data IOStream a = MkStream (List String -> (a, List String))
22+
23+instance Handler StdIO IOStream where
24+ handle () (PutStr s) k
25+ = MkStream (\x => case k () () of
26+ MkStream f => let (res, str) = f x in
27+ (res, s :: str))
28+ handle {a} () GetStr k
29+ = MkStream (\x => case x of
30+ [] => cont "" []
31+ (t :: ts) => cont t ts)
32+ where
33+ cont : String -> List String -> (a, List String)
34+ cont t ts = case k () t of
35+ MkStream f => f ts
36+
37+-}
38+
39+--- The Effect and associated functions
40+
41+STDIO : EFFECT
42+STDIO = MkEff () StdIO
43+
44+putStr : Handler StdIO e => String -> { [STDIO] } Eff e ()
45+putStr s = PutStr s
46+
47+putStrLn : Handler StdIO e => String -> { [STDIO] } Eff e ()
48+putStrLn s = putStr (s ++ "\n")
49+
50+getStr : Handler StdIO e => { [STDIO] } Eff e String
51+getStr = GetStr
52+
53+-- mkStrFn : Env IOStream xs ->
54+-- Eff IOStream xs a ->
55+-- List String -> (a, List String)
56+-- mkStrFn {a} env p input = case mkStrFn' of
57+-- MkStream f => f input
58+-- where injStream : a -> IOStream a
59+-- injStream v = MkStream (\x => (v, []))
60+-- mkStrFn' : IOStream a
61+-- mkStrFn' = runWith injStream env p
62+--
63+--
libs/neweffects/Effects.idrnew file+268
@@ -0,0 +1,268 @@
1+module Effects
2+
3+import Language.Reflection
4+import Control.Catchable
5+import Effect.Default
6+
7+%access public
8+
9+---- Effects
10+
11+Effect : Type
12+Effect = (x : Type) -> Type -> (x -> Type) -> Type
13+
14+data EFFECT : Type where
15+ MkEff : Type -> Effect -> EFFECT
16+
17+class Handler (e : Effect) (m : Type -> Type) where
18+ handle : res -> (eff : e t res resk) ->
19+ ((x : t) -> resk x -> m a) -> m a
20+
21+-- A bit of syntactic sugar ('syntax' is not very flexible so we only go
22+-- up to a small number of parameters...)
23+
24+syntax "{" [inst] "==>" [outst] "}" [eff] = eff inst (\result => outst)
25+syntax "{" [inst] "}" [eff] = eff inst (\result => inst)
26+
27+---- Properties and proof construction
28+
29+using (xs : List a, ys : List a)
30+ data SubList : List a -> List a -> Type where
31+ SubNil : SubList {a} [] []
32+ Keep : SubList xs ys -> SubList (x :: xs) (x :: ys)
33+ Drop : SubList xs ys -> SubList xs (x :: ys)
34+
35+ subListId : SubList xs xs
36+ subListId {xs = Nil} = SubNil
37+ subListId {xs = x :: xs} = Keep subListId
38+
39+namespace Env
40+ data Env : (m : Type -> Type) -> List EFFECT -> Type where
41+ Nil : Env m Nil
42+ (::) : Handler eff m => a -> Env m xs -> Env m (MkEff a eff :: xs)
43+
44+data EffElem : Effect -> Type ->
45+ List EFFECT -> Type where
46+ Here : EffElem x a (MkEff a x :: xs)
47+ There : EffElem x a xs -> EffElem x a (y :: xs)
48+
49+-- make an environment corresponding to a sub-list
50+dropEnv : Env m ys -> SubList xs ys -> Env m xs
51+dropEnv [] SubNil = []
52+dropEnv (v :: vs) (Keep rest) = v :: dropEnv vs rest
53+dropEnv (v :: vs) (Drop rest) = dropEnv vs rest
54+
55+updateWith : (ys' : List a) -> (xs : List a) ->
56+ SubList ys xs -> List a
57+updateWith (y :: ys) (x :: xs) (Keep rest) = y :: updateWith ys xs rest
58+updateWith ys (x :: xs) (Drop rest) = x :: updateWith ys xs rest
59+updateWith [] [] SubNil = []
60+updateWith (y :: ys) [] SubNil = y :: ys
61+updateWith [] (x :: xs) (Keep rest) = []
62+
63+-- put things back, replacing old with new in the sub-environment
64+rebuildEnv : Env m ys' -> (prf : SubList ys xs) ->
65+ Env m xs -> Env m (updateWith ys' xs prf)
66+rebuildEnv [] SubNil env = env
67+rebuildEnv (x :: xs) (Keep rest) (y :: env) = x :: rebuildEnv xs rest env
68+rebuildEnv xs (Drop rest) (y :: env) = y :: rebuildEnv xs rest env
69+rebuildEnv (x :: xs) SubNil [] = x :: xs
70+
71+---- The Effect EDSL itself ----
72+
73+-- some proof automation
74+
75+%reflection
76+reflectListEffElem : List a -> Tactic
77+reflectListEffElem [] = Refine "Here" `Seq` Solve
78+reflectListEffElem (x :: xs)
79+ = Try (Refine "Here" `Seq` Solve)
80+ (Refine "There" `Seq` (Solve `Seq` reflectListEffElem xs))
81+-- TMP HACK! FIXME!
82+-- The evaluator needs a 'function case' to know its a reflection function
83+-- until we propagate that information! Without this, the _ case won't get
84+-- matched.
85+reflectListEffElem (x ++ y) = Refine "Here" `Seq` Solve
86+reflectListEffElem _ = Refine "Here" `Seq` Solve
87+
88+%reflection
89+reflectSubList : List a -> Tactic
90+reflectSubList [] = Refine "subListId" `Seq` Solve
91+reflectSubList (x :: xs)
92+ = Try (Refine "subListId" `Seq` Solve)
93+ (Try (Refine "Keep" `Seq` (Solve `Seq` reflectSubList xs))
94+ (Refine "Drop" `Seq` (Solve `Seq` reflectSubList xs)))
95+reflectSubList (x ++ y) = Refine "subListId" `Seq` Solve
96+reflectSubList _ = Refine "subListId" `Seq` Solve
97+
98+%reflection
99+reflectEff : (P : Type) -> Tactic
100+reflectEff (EffElem m a xs)
101+ = reflectListEffElem xs `Seq` Solve
102+reflectEff (SubList xs ys)
103+ = reflectSubList ys `Seq` Solve
104+
105+updateResTy : (val : t) ->
106+ (xs : List EFFECT) -> EffElem e a xs -> e t a b ->
107+ List EFFECT
108+updateResTy {b} val (MkEff a e :: xs) Here n = (MkEff (b val) e) :: xs
109+updateResTy val (x :: xs) (There p) n = x :: updateResTy val xs p n
110+
111+-- updateResTyImm : (xs : List EFFECT) -> EffElem e a xs -> Type ->
112+-- List EFFECT
113+-- updateResTyImm (MkEff a e :: xs) Here b = (MkEff b e) :: xs
114+-- updateResTyImm (x :: xs) (There p) b = x :: updateResTyImm xs p b
115+
116+infix 5 :::, :-, :=
117+
118+data LRes : lbl -> Type -> Type where
119+ (:=) : (x : lbl) -> res -> LRes x res
120+
121+(:::) : lbl -> EFFECT -> EFFECT
122+(:::) {lbl} x (MkEff r e) = MkEff (LRes x r) e
123+
124+using (lbl : Type)
125+ instance Default a => Default (LRes lbl a) where
126+ default = lbl := default
127+
128+private
129+unlabel : {l : ty} -> Env m [l ::: x] -> Env m [x]
130+unlabel {m} {x = MkEff a eff} [l := v] = [v]
131+
132+private
133+relabel : (l : ty) -> Env m xs -> Env m (map (\x => l ::: x) xs)
134+relabel {xs = []} l [] = []
135+relabel {xs = (MkEff a e :: xs)} l (v :: vs) = (l := v) :: relabel l vs
136+
137+-- the language of Effects
138+
139+data Eff : (m : Type -> Type) ->
140+ (x : Type) ->
141+ List EFFECT -> (x -> List EFFECT) -> Type where
142+ value : a -> Eff m a xs (\v => xs)
143+ ebind : Eff m a xs xs' ->
144+ ((val : a) -> Eff m b (xs' val) xs'') -> Eff m b xs xs''
145+ effect : (prf : EffElem e a xs) ->
146+ (eff : e t a b) ->
147+ Eff m t xs (\v => updateResTy v xs prf eff)
148+
149+ lift : (prf : SubList ys xs) ->
150+ Eff m t ys ys' -> Eff m t xs (\v => updateWith (ys' v) xs prf)
151+ new : Handler e m =>
152+ res ->
153+ Eff m a (MkEff res e :: xs) (\v => (MkEff res' e :: xs')) ->
154+ Eff m a xs (\v => xs')
155+ catch : Catchable m err =>
156+ Eff m a xs xs' -> (err -> Eff m a xs xs') ->
157+ Eff m a xs xs'
158+
159+ (:-) : (l : ty) ->
160+ Eff m t [x] xs' -> -- [x] (\v => xs) ->
161+ Eff m t [l ::: x] (\v => map (l :::) (xs' v))
162+
163+(>>=) : Eff m a xs xs' ->
164+ ((val : a) -> Eff m b (xs' val) xs'') -> Eff m b xs xs''
165+(>>=) = ebind
166+
167+implicit
168+lift' : Eff m t ys ys' ->
169+ {default tactics { byReflection reflectEff; }
170+ prf : SubList ys xs} ->
171+ Eff m t xs (\v => updateWith (ys' v) xs prf)
172+lift' e {prf} = lift prf e
173+
174+implicit
175+effect' : {a, b: _} -> {e : Effect} ->
176+ (eff : e t a b) ->
177+ {default tactics { byReflection reflectEff; }
178+ prf : EffElem e a xs} ->
179+ Eff m t xs (\v => updateResTy v xs prf eff)
180+effect' e {prf} = effect prf e
181+
182+return : a -> Eff m a xs (\v => xs)
183+return x = value x
184+
185+-- for idiom brackets
186+
187+infixl 2 <$>
188+
189+pure : a -> Eff m a xs (\v => xs)
190+pure = value
191+
192+(<$>) : Eff m (a -> b) xs (\v => xs) ->
193+ Eff m a xs (\v => xs) -> Eff m b xs (\v => xs)
194+(<$>) prog v = do fn <- prog
195+ arg <- v
196+ return (fn arg)
197+
198+-- an interpreter
199+
200+private
201+execEff : Env m xs -> (p : EffElem e res xs) ->
202+ (eff : e a res resk) ->
203+ ((v : a) -> Env m (updateResTy v xs p eff) -> m t) -> m t
204+execEff (val :: env) Here eff' k
205+ = handle val eff' (\v, res => k v (res :: env))
206+execEff (val :: env) (There p) eff k
207+ = execEff env p eff (\v, env' => k v (val :: env'))
208+
209+-- Q: Instead of m b, implement as StateT (Env m xs') m b, so that state
210+-- updates can be propagated even through failing computations?
211+
212+eff : Env m xs -> Eff m a xs xs' -> ((x : a) -> Env m (xs' x) -> m b) -> m b
213+eff env (value x) k = k x env
214+eff env (prog `ebind` c) k
215+ = eff env prog (\p', env' => eff env' (c p') k)
216+eff env (effect prf effP) k = execEff env prf effP k
217+eff env (lift prf effP) k
218+ = let env' = dropEnv env prf in
219+ eff env' effP (\p', envk => k p' (rebuildEnv envk prf env))
220+eff env (new r prog) k
221+ = let env' = r :: env in
222+ eff env' prog (\p' => \ (v :: envk) => k p' envk)
223+eff env (catch prog handler) k
224+ = catch (eff env prog k)
225+ (\e => eff env (handler e) k)
226+-- FIXME:
227+-- xs is needed explicitly because otherwise the pattern binding for
228+-- 'l' appears too late. Solution seems to be to reorder patterns at the
229+-- end so that everything is in scope when it needs to be.
230+eff {xs = [l ::: x]} env (l :- prog) k
231+ = let env' = unlabel env in
232+ eff env' prog (\p', envk => k p' (relabel l envk))
233+
234+run : Applicative m => Env m xs -> Eff m a xs xs' -> m a
235+run env prog = eff env prog (\r, env => pure r)
236+
237+-- yuck :)
238+syntax MkDefaultEnv = (| [], [default], [default, default],
239+ [default, default, default],
240+ [default, default, default, default],
241+ [default, default, default, default, default],
242+ [default, default, default, default, default, default],
243+ [default, default, default, default, default, default, default],
244+ [default, default, default, default, default, default, default, default] |)
245+
246+run' : Applicative m => {default MkDefaultEnv env : Env m xs} -> Eff m a xs xs' -> m a
247+run' {env} prog = eff env prog (\r, env => pure r)
248+
249+runEnv : Applicative m => Env m xs -> Eff m a xs xs' ->
250+ m (x : a ** Env m (xs' x))
251+runEnv env prog = eff env prog (\r, env => pure (r ** env))
252+
253+runPure : Env id xs -> Eff id a xs xs' -> a
254+runPure env prog = eff env prog (\r, env => r)
255+
256+runWith : (a -> m a) -> Env m xs -> Eff m a xs xs' -> m a
257+runWith inj env prog = eff env prog (\r, env => inj r)
258+
259+-- some higher order things
260+
261+mapE : Applicative m => (a -> {xs} Eff m b) -> List a -> {xs} Eff m (List b)
262+mapE f [] = pure []
263+mapE f (x :: xs) = [| f x :: mapE f xs |]
264+
265+when : Applicative m => Bool -> ({xs} Eff m ()) -> {xs} Eff m ()
266+when True e = e
267+when False e = pure ()
268+
libs/neweffects/Makefilenew file+14
@@ -0,0 +1,14 @@
1+IDRIS := idris
2+
3+build:
4+ $(IDRIS) --build neweffects.ipkg
5+
6+clean:
7+ $(IDRIS) --clean neweffects.ipkg
8+
9+install:
10+ $(IDRIS) --install neweffects.ipkg
11+
12+rebuild: clean build
13+
14+.PHONY: build clean install rebuild
libs/neweffects/neweffects.ipkgnew file+9
@@ -0,0 +1,9 @@
1+package neweffects
2+
3+opts = "--nobasepkgs -i ../prelude -i ../base"
4+modules = Effects, Effect.Default,
5+
6+ Effect.Exception, Effect.File, Effect.State,
7+ Effect.Random, Effect.StdIO, Effect.Select,
8+ Effect.Memory
9+
libs/prelude/Prelude.idr+6−2
@@ -532,12 +532,16 @@ ferror (FHandle h) = do err <- do_ferror h
532532partial
533533nullPtr : Ptr -> IO Bool
534534nullPtr p = do ok <- mkForeign (FFun "isNull" [FPtr] FInt) p
535− return (ok /= 0);
535+ return (ok /= 0)
536536
537537partial
538538nullStr : String -> IO Bool
539539nullStr p = do ok <- mkForeign (FFun "isNull" [FString] FInt) p
540− return (ok /= 0);
540+ return (ok /= 0)
541+
542+eqPtr : Ptr -> Ptr -> IO Bool
543+eqPtr x y = do eq <- mkForeign (FFun "idris_eqPtr" [FPtr, FPtr] FInt) x y
544+ return (eq /= 0)
541545
542546partial
543547validFile : File -> IO Bool
rts/idris_stdfgn.c+4
@@ -36,6 +36,10 @@ int isNull(void* ptr) {
3636 return ptr==NULL;
3737}
3838
39+int idris_eqPtr(void* x, void* y) {
40+ return x==y;
41+}
42+
3943void* idris_stdin() {
4044 return (void*)stdin;
4145}
rts/idris_stdfgn.h+1
@@ -12,6 +12,7 @@ int fileEOF(void* h);
1212int fileError(void* h);
1313void fputStr(void*h, char* str);
1414
15+int idris_eqPtr(void* x, void* y);
1516int isNull(void* ptr);
1617void* idris_stdin();
1718
src/IRTS/CodegenJavaScript.hs+119−20
@@ -314,6 +314,9 @@ jsSubst var new (JSIndex obj field) =
314314jsSubst var new (JSCond conds) =
315315 JSCond (map ((jsSubst var new) *** (jsSubst var new)) conds)
316316
317+jsSubst var new (JSAssign lhs rhs) =
318+ JSAssign (jsSubst var new lhs) (jsSubst var new rhs)
319+
317320jsSubst _ _ js = js
318321
319322
@@ -328,16 +331,24 @@ isJSConstant js
328331 | otherwise = False
329332
330333inlineJS :: JS -> JS
334+inlineJS (JSReturn (JSApp (JSFunction ["cse"] body) [val@(JSVar _)])) =
335+ inlineJS $ jsSubst "cse" val body
336+
337+inlineJS (JSReturn (JSApp (JSFunction [arg] cond@(JSCond _)) [val])) =
338+ JSSeq [ JSAlloc arg (Just (inlineJS val))
339+ , inlineJS cond
340+ ]
341+
331342inlineJS (JSApp (JSProj (JSFunction args (JSReturn body)) "apply") [
332− JSThis,JSProj (JSIdent var) "vars"
343+ JSThis,JSProj var "vars"
333344 ])
334− | var /= "cse" =
335− inlineApply args body 0
345+ | var /= JSIdent "cse" =
346+ inlineApply args body 0
336347 where
337− inlineApply [] body _ = body
348+ inlineApply [] body _ = inlineJS body
338349 inlineApply (a:as) body n =
339350 inlineApply as (
340− jsSubst a (JSIndex (JSProj (JSIdent var) "vars") (JSNum (JSInt n))) body
351+ jsSubst a (JSIndex (JSProj var "vars") (JSNum (JSInt n))) body
341352 ) (n + 1)
342353
343354inlineJS (JSApp (JSIdent "__IDR__mEVAL0") [val])
@@ -348,9 +359,6 @@ inlineJS (JSApp (JSIdent "__IDRRT__tailcall") [
348359 ])
349360 | isJSConstant val = val
350361
351−inlineJS (JSApp (JSFunction [] (JSSeq ret)) []) =
352− JSApp (JSFunction [] (JSSeq (map inlineJS ret))) []
353−
354362inlineJS (JSApp (JSFunction [arg] (JSReturn ret)) [val])
355363 | JSNew con [tag, vals] <- ret
356364 , opt <- inlineJS val =
@@ -430,6 +438,96 @@ reduceJS js = reduceLoop [] ([], js)
430438funName :: JS -> String
431439funName (JSAlloc fun _) = fun
432440
441+initConstructors :: [JS] -> [JS]
442+initConstructors js =
443+ let tags = nub $ sort $ concat (map getTags js) in
444+ map createConstant tags ++ replaceConstructors tags js
445+ where
446+ getTags :: JS -> [Int]
447+ getTags (JSNew "__IDRRT__Con" [JSNum (JSInt tag), JSArray []]) = [tag]
448+
449+ getTags (JSNew _ args) = concatMap getTags args
450+
451+ getTags (JSFunction _ body) = getTags body
452+
453+ getTags (JSReturn ret) = getTags ret
454+
455+ getTags (JSApp lhs rhs) = getTags lhs ++ concatMap getTags rhs
456+
457+ getTags (JSSeq seq) = concatMap getTags seq
458+
459+ getTags (JSOp _ lhs rhs) = getTags lhs ++ getTags rhs
460+
461+ getTags (JSProj obj _) = getTags obj
462+
463+ getTags (JSArray vals) = concatMap getTags vals
464+
465+ getTags (JSAssign lhs rhs) = getTags lhs ++ getTags rhs
466+
467+ getTags (JSAlloc _ (Just val)) = getTags val
468+
469+ getTags (JSCond conds) =
470+ concatMap (uncurry (++)) $ map (getTags *** getTags) conds
471+
472+ getTags (JSTernary c t f) = getTags c ++ getTags t ++ getTags f
473+
474+ getTags js = []
475+
476+ replaceConstructors :: [Int] -> [JS] -> [JS]
477+ replaceConstructors tags js = map (replaceHelper tags) js
478+ where
479+ replaceHelper :: [Int] -> JS -> JS
480+ replaceHelper tags (JSNew "__IDRRT__Con" [JSNum (JSInt tag), JSArray []])
481+ | tag `elem` tags = JSIdent ("__IDRCTR__" ++ show tag)
482+
483+ replaceHelper tags (JSNew con args) =
484+ JSNew con $ map (replaceHelper tags) args
485+
486+ replaceHelper tags (JSFunction fun body) =
487+ JSFunction fun (replaceHelper tags body)
488+
489+ replaceHelper tags (JSReturn ret) =
490+ JSReturn (replaceHelper tags ret)
491+
492+ replaceHelper tags (JSApp lhs rhs) =
493+ JSApp (replaceHelper tags lhs) (map (replaceHelper tags) rhs)
494+
495+ replaceHelper tags (JSSeq seq) =
496+ JSSeq $ map (replaceHelper tags) seq
497+
498+ replaceHelper tags (JSOp op lhs rhs) =
499+ JSOp op (replaceHelper tags lhs) (replaceHelper tags rhs)
500+
501+ replaceHelper tags (JSProj obj field) =
502+ JSProj (replaceHelper tags obj) field
503+
504+ replaceHelper tags (JSArray vals) =
505+ JSArray $ map (replaceHelper tags) vals
506+
507+ replaceHelper tags (JSAssign lhs rhs) =
508+ JSAssign (replaceHelper tags lhs) (replaceHelper tags rhs)
509+
510+ replaceHelper tags (JSAlloc var (Just val)) =
511+ JSAlloc var $ Just (replaceHelper tags val)
512+
513+ replaceHelper tags (JSCond conds) =
514+ JSCond (map ((replaceHelper tags) *** (replaceHelper tags)) conds)
515+
516+ replaceHelper tags (JSTernary c t f) =
517+ JSTernary (replaceHelper tags c) (
518+ replaceHelper tags t
519+ ) (
520+ replaceHelper tags f
521+ )
522+
523+ replaceHelper tags js = js
524+
525+ createConstant :: Int -> JS
526+ createConstant tag =
527+ JSAlloc ("__IDRCTR__" ++ show tag) (Just (
528+ JSNew (idrRTNamespace ++ "Con") [JSNum (JSInt tag), JSArray []]
529+ ))
530+
433531removeIDs :: [JS] -> [JS]
434532removeIDs js =
435533 case partition isID js of
@@ -651,7 +749,7 @@ codegenJavaScript target definitions filename outputType = do
651749
652750 functions :: [String]
653751 functions =
654− map (compileJS . reduceConstants) ((reduceJS . removeIDs) $ map (optimizeJS . translateDeclaration) def)
752+ map compileJS $ initConstructors (map reduceConstants ((reduceJS . removeIDs) $ map (optimizeJS . translateDeclaration) def))
655753
656754 mainLoop :: String
657755 mainLoop = compileJS $
@@ -780,7 +878,7 @@ translateConstant c =
780878
781879translateDeclaration :: (String, SDecl) -> JS
782880translateDeclaration (path, SFun name params stackSize body)
783− | (MN _ ap) <- name
881+ | (MN _ ap) <- name
784882 , (SLet var val next) <- body
785883 , (SChkCase cvar cases) <- next
786884 , ap == txt "APPLY" =
@@ -789,20 +887,21 @@ translateDeclaration (path, SFun name params stackSize body)
789887 JSSeq [ lookupTable [(var, "chk")] var cases
790888 , jsDecl $ JSFunction ["fn0", "arg0"] (
791889 JSSeq [ JSAlloc "__var_0" (Just $ JSIdent "fn0")
792− , JSReturn $ jsLet (translateVariableName var) (
793− translateExpression val
794− ) (JSTernary (
795− (JSVar var `jsInstanceOf` jsCon) `jsAnd`
796− (hasProp lookupTableName (translateVariableName var))
797− ) (JSIdent $
798− lookupTableName ++ lookup
799− ) JSNull
800− )
890+ , JSAlloc (translateVariableName var) (
891+ Just $ translateExpression val
892+ )
893+ , JSReturn $ (JSTernary (
894+ (JSVar var `jsInstanceOf` jsCon) `jsAnd`
895+ (hasProp lookupTableName (translateVariableName var))
896+ ) (JSIdent $
897+ lookupTableName ++ lookup
898+ ) JSNull
899+ )
801900 ]
802901 )
803902 ]
804903
805− | (MN _ ev) <- name
904+ | (MN _ ev) <- name
806905 , (SChkCase var cases) <- body
807906 , ev == txt "EVAL" =
808907 JSSeq [ lookupTable [] var cases
src/Idris/Core/Elaborate.hs+19−11
@@ -609,17 +609,24 @@ arg n tyhole = do ty <- unique_hole tyhole
609609 forall n (Var ty)
610610
611611-- try a tactic, if it adds any unification problem, return an error
612−no_errors :: Elab' aux () -> Elab' aux ()
613−no_errors tac
614− = do ps <- get_probs
615− tac
616− ps' <- get_probs
617− if (length ps' > length ps) then
618− case reverse ps' of
619− ((x,y,env,err) : _) ->
620− let env' = map (\(x, b) -> (x, binderTy b)) env in
621− lift $ tfail $ CantUnify False x y err env' 0
622− else return $! ()
612+no_errors :: Elab' aux () -> Maybe Err -> Elab' aux ()
613+no_errors tac err
614+ = do ps <- get_probs
615+ s <- get
616+ case err of
617+ Nothing -> tac
618+ Just e -> -- update the error, if there is one.
619+ case runStateT tac s of
620+ Error _ -> lift $ Error e
621+ OK (a, s') -> do put s'
622+ return a
623+ ps' <- get_probs
624+ if (length ps' > length ps) then
625+ case reverse ps' of
626+ ((x,y,env,err) : _) ->
627+ let env' = map (\(x, b) -> (x, binderTy b)) env in
628+ lift $ tfail $ CantUnify False x y err env' 0
629+ else return $! ()
623630
624631-- Try a tactic, if it fails, try another
625632try :: Elab' aux a -> Elab' aux a -> Elab' aux a
@@ -642,6 +649,7 @@ try' t1 t2 proofSearch
642649 where recoverableErr err@(CantUnify r x y _ _ _)
643650 = -- traceWhen r (show err) $
644651 r || proofSearch
652+ recoverableErr (CantSolveGoal _ _) = False
645653 recoverableErr (ProofSearchFail _) = False
646654 recoverableErr _ = True
647655
src/Idris/Core/Evaluate.hs+9−8
@@ -228,11 +228,11 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
228228 ev ntimes stk top env (P nt n ty)
229229 = liftM (VP nt n) (ev ntimes stk top env ty)
230230 ev ntimes stk top env (V i)
231− | i < length env && i >= 0 = return $ env !! i
231+ | i < length env && i >= 0 = return $ snd (env !! i)
232232 | otherwise = return $ VV i
233233 ev ntimes stk top env (Bind n (Let t v) sc)
234234 = do v' <- ev ntimes stk top env v --(finalise v)
235− sc' <- ev ntimes stk top (v' : env) sc
235+ sc' <- ev ntimes stk top ((n, v') : env) sc
236236 wknV (-1) sc'
237237-- | otherwise
238238-- = do t' <- ev ntimes stk top env t
@@ -247,12 +247,13 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
247247 ev ntimes stk top env (Bind n (NLet t v) sc)
248248 = do t' <- ev ntimes stk top env (finalise t)
249249 v' <- ev ntimes stk top env (finalise v)
250− sc' <- ev ntimes stk top (v' : env) sc
250+ sc' <- ev ntimes stk top ((n, v') : env) sc
251251 return $ VBind True n (Let t' v') (\x -> return sc')
252252 ev ntimes stk top env (Bind n b sc)
253253 = do b' <- vbind env b
254+ let n' = uniqueName n (map fst env)
254255 return $ VBind True -- (vinstances 0 sc < 2)
255− n b' (\x -> ev ntimes stk False (x:env) sc)
256+ n' b' (\x -> ev ntimes stk False ((n, x):env) sc)
256257 where vbind env t
257258-- | simpl
258259-- = fmapMB (\tm -> ev ((MN 0 "STOP", 0) : ntimes)
@@ -345,7 +346,7 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
345346-- _ -> return $ unload env f args
346347-- specApply stk env f args = return $ unload env f args
347348
348− unload :: [Value] -> Value -> [Value] -> Value
349+ unload :: [(Name, Value)] -> Value -> [Value] -> Value
349350 unload env f [] = f
350351 unload env f (a:as) = unload env (VApp f a) as
351352
@@ -360,12 +361,12 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
360361 | otherwise = return (Nothing, args)
361362
362363 evTree :: [(Name, Int)] -> [Name] -> Bool ->
363− [Value] -> [(Name, Value)] -> SC -> Eval (Maybe Value)
364+ [(Name, Value)] -> [(Name, Value)] -> SC -> Eval (Maybe Value)
364365 evTree ntimes stk top env amap (UnmatchedCase str) = return Nothing
365366 evTree ntimes stk top env amap (STerm tm)
366367 = do let etm = pToVs (map fst amap) tm
367368 etm' <- ev ntimes stk (not (conHeaded tm))
368− (map snd amap ++ env) etm
369+ (amap ++ env) etm
369370 return $ Just etm'
370371 evTree ntimes stk top env amap (ProjCase t alts)
371372 = do t' <- ev ntimes stk top env t
@@ -394,7 +395,7 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
394395 chooseAlt env f' (getValArgs f')
395396 alts amap
396397
397− chooseAlt :: [Value] -> Value -> (Value, [Value]) -> [CaseAlt] ->
398+ chooseAlt :: [(Name, Value)] -> Value -> (Value, [Value]) -> [CaseAlt] ->
398399 [(Name, Value)] ->
399400 Eval (Maybe ([(Name, Value)], SC))
400401 chooseAlt env _ (VP (DCon i a) _ _, args) alts amap
src/Idris/Core/TT.hs+82−13
@@ -99,6 +99,7 @@ data Err = Msg String
9999 -- unification succeed
100100 | InfiniteUnify Name Term [(Name, Type)]
101101 | CantConvert Term Term [(Name, Type)]
102+ | CantSolveGoal Term [(Name, Type)]
102103 | UnifyScope Name Name Term [(Name, Type)]
103104 | CantInferType String
104105 | NonFunctionType Term Term
@@ -156,6 +157,7 @@ score (CantUnify _ _ _ m _ s) = s + score m
156157score (CantResolve _) = 20
157158score (NoSuchVariable _) = 1000
158159score (ProofSearchFail _) = 10000
160+score (CantSolveGoal _ _) = 10000
159161score (InternalMsg _) = -1
160162score _ = 0
161163
@@ -164,6 +166,7 @@ instance Show Err where
164166 show (InternalMsg s) = "Internal error: " ++ show s
165167 show (CantUnify _ l r e sc i) = "CantUnify " ++ show l ++ " " ++ show r ++ " "
166168 ++ show e ++ " in " ++ show sc ++ " " ++ show i
169+ show (CantSolveGoal g _) = "CantSolve " ++ show g
167170 show (Inaccessible n) = show n ++ " is not an accessible pattern variable"
168171 show (ProviderError msg) = "Type provider error: " ++ msg
169172 show (LoadingFailed fn e) = "Loading " ++ fn ++ " failed: (TT) " ++ show e
@@ -334,6 +337,8 @@ emptyContext = Map.empty
334337mapCtxt :: (a -> b) -> Ctxt a -> Ctxt b
335338mapCtxt = fmap . fmap
336339
340+-- |Return True if the argument 'Name' should be interpreted as the name of a
341+-- typeclass.
337342tcname (UN xs) | T.null xs = False
338343 | otherwise = T.head xs == '@'
339344tcname (NS n _) = tcname n
@@ -503,11 +508,18 @@ deriving instance Binary Raw
503508deriving instance NFData Raw
504509!-}
505510
506−-- | All binding forms are represented in a unform fashion.
511+-- The type parameter `b` will normally be something like `TT Name` or just
512+-- `Raw`. We do not make a type-level distinction between TT terms that happen
513+-- to be TT types and TT terms that are not TT types.
514+-- | All binding forms are represented in a uniform fashion. This type only represents
515+-- the types of bindings (and their values, if any); the attached identifiers are part
516+-- of the 'Bind' constructor for the 'TT' type.
507517data Binder b = Lam { binderTy :: !b {-^ type annotation for bound variable-}}
508518 | Pi { binderTy :: !b }
519+ {-^ A binding that occurs in a function type expression, e.g. @(x:Int) -> ...@ -}
509520 | Let { binderTy :: !b,
510521 binderVal :: b {-^ value for bound variable-}}
522+ -- ^ A binding that occurs in a @let@ expression
511523 | NLet { binderTy :: !b,
512524 binderVal :: b }
513525 | Hole { binderTy :: !b}
@@ -516,6 +528,7 @@ data Binder b = Lam { binderTy :: !b {-^ type annotation for bound variable-}
516528 | Guess { binderTy :: !b,
517529 binderVal :: b }
518530 | PVar { binderTy :: !b }
531+ -- ^ A pattern variable
519532 | PVTy { binderTy :: !b }
520533 deriving (Show, Eq, Ord, Functor)
521534{-!
@@ -594,8 +607,8 @@ type UCs = (Int, [UConstraint])
594607
595608data NameType = Bound
596609 | Ref
597− | DCon Int Int -- ^ Data constructor; Ints are tag and arity
598− | TCon Int Int -- ^ Type constructor; Ints are tag and arity
610+ | DCon {nt_tag :: Int, nt_arity :: Int} -- ^ Data constructor
611+ | TCon {nt_tag :: Int, nt_arity :: Int} -- ^ Type constructor
599612 deriving (Show, Ord)
600613{-!
601614deriving instance Binary NameType
@@ -615,8 +628,12 @@ instance Eq NameType where
615628 TCon _ a == TCon _ b = (a == b) -- ignore tag
616629 _ == _ = False
617630
618−-- | Terms in the core language
619−data TT n = P NameType n (TT n) -- ^ named references
631+-- | Terms in the core language. The type parameter is the type of
632+-- identifiers used for bindings and explicit named references;
633+-- usually we use @TT 'Name'@.
634+data TT n = P NameType n (TT n) -- ^ named references with type
635+ -- (P for "Parameter", motivated by McKinna and Pollack's
636+ -- Pure Type Systems Formalized)
620637 | V !Int -- ^ a resolved de Bruijn-indexed variable
621638 | Bind n !(Binder (TT n)) (TT n) -- ^ a binding
622639 | App !(TT n) (TT n) -- ^ function, function type, arg
@@ -640,10 +657,14 @@ instance TermSize a => TermSize [a] where
640657 termsize n (x : xs) = termsize n x + termsize n xs
641658
642659instance TermSize (TT Name) where
643− termsize n (P _ x _)
644− | x == n = 1000000 -- recursive => really big
660+ termsize n (P _ n' _)
661+ | n' == n = 1000000 -- recursive => really big
645662 | otherwise = 1
646663 termsize n (V _) = 1
664+ -- for `Bind` terms, we can erroneously declare a term
665+ -- "recursive => really big" if the name of the bound
666+ -- variable is the same as the name we're using
667+ -- So generate a different name in that case.
647668 termsize n (Bind n' (Let t v) sc)
648669 = let rn = if n == n' then sMN 0 "noname" else n in
649670 termsize rn v + termsize rn sc
@@ -709,6 +730,7 @@ vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
709730 instancesB _ = 0
710731vinstances i t = 0
711732
733+-- | Replace the outermost (index 0) de Bruijn variable with the given term
712734instantiate :: TT n -> TT n -> TT n
713735instantiate e = subst 0 where
714736 subst i (V x) | i == x = e
@@ -717,6 +739,9 @@ instantiate e = subst 0 where
717739 subst i (Proj x idx) = Proj (subst i x) idx
718740 subst i t = t
719741
742+-- | As 'instantiate', but also decrement the indices of all de Bruijn variables
743+-- remaining in the term, so that there are no more references to the variable
744+-- that has been substituted.
720745substV :: TT n -> TT n -> TT n
721746substV x tm = dropV 0 (instantiate x tm) where
722747 dropV i (V x) | x > i = V (x - 1)
@@ -726,6 +751,8 @@ substV x tm = dropV 0 (instantiate x tm) where
726751 dropV i (Proj x idx) = Proj (dropV i x) idx
727752 dropV i t = t
728753
754+-- | Replace all non-free de Bruijn references in the given term with references
755+-- to the name of their binding.
729756explicitNames :: TT n -> TT n
730757explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
731758 Bind x b'
@@ -735,6 +762,8 @@ explicitNames (App f a) = App (explicitNames f) (explicitNames a)
735762explicitNames (Proj x idx) = Proj (explicitNames x) idx
736763explicitNames t = t
737764
765+-- | Replace references to the given 'Name'-like id with references to
766+-- de Bruijn index 0.
738767pToV :: Eq n => n -> TT n -> TT n
739768pToV n = pToV' n 0
740769pToV' n i (P _ x _) | n == x = V i
@@ -764,6 +793,9 @@ pToVs ns tm = pToVs' ns tm 0 where
764793 pToVs' [] tm i = tm
765794 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
766795
796+-- | Replace de Bruijn indices in the given term with explicit references to
797+-- the names of the bindings they refer to. It is an error if the given term
798+-- contains free de Bruijn indices.
767799vToP :: TT n -> TT n
768800vToP = vToP' [] where
769801 vToP' env (V i) = let (n, b) = (env !! i) in
@@ -773,6 +805,8 @@ vToP = vToP' [] where
773805 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
774806 vToP' env t = t
775807
808+-- | Replace every non-free reference to the name of a binding in
809+-- the given term with a de Bruijn index.
776810finalise :: Eq n => TT n -> TT n
777811finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
778812finalise (App f a) = App (finalise f) (finalise a)
@@ -787,7 +821,12 @@ pEraseType (App f a) = App (pEraseType f) (pEraseType a)
787821pEraseType (Bind n b sc) = Bind n (fmap pEraseType b) (pEraseType sc)
788822pEraseType t = t
789823
790−subst :: Eq n => n -> TT n -> TT n -> TT n
824+-- | As 'instantiate', but in addition to replacing @'V' 0@,
825+-- replace references to the given 'Name'-like id.
826+subst :: Eq n => n {-^ The id to replace -} ->
827+ TT n {-^ The replacement term -} ->
828+ TT n {-^ The term to replace in -} ->
829+ TT n
791830subst n v tm = instantiate v (pToV n tm)
792831
793832-- If there are no Vs in the term (i.e. in proof state)
@@ -800,19 +839,25 @@ psubst n v tm = s' tm where
800839 s' (Proj t idx) = Proj (s' t) idx
801840 s' t = t
802841
842+-- | As 'subst', but takes a list of (name, substitution) pairs instead
843+-- of a single name and substitution
803844substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
804845substNames [] t = t
805846substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
806847
807−substTerm :: Eq n => TT n -> TT n -> TT n -> TT n
848+-- | Replaces all terms equal (in the sense of @(==)@) to
849+-- the old term with the new term.
850+substTerm :: Eq n => TT n {-^ Old term -} ->
851+ TT n {-^ New term -} ->
852+ TT n {-^ template term -}
853+ -> TT n
808854substTerm old new = st where
809855 st t | t == old = new
810856 st (App f a) = App (st f) (st a)
811857 st (Bind x b sc) = Bind x (fmap st b) (st sc)
812858 st t = t
813859
814−-- Returns true if V 0 and bound name n do not occur in the term
815−
860+-- | Returns true if V 0 and bound name n do not occur in the term
816861noOccurrence :: Eq n => n -> TT n -> Bool
817862noOccurrence n t = no' 0 t
818863 where
@@ -847,6 +892,8 @@ unApply t = ua [] t where
847892 ua args (App f a) = ua (a:args) f
848893 ua args t = (t, args)
849894
895+-- | Returns a term representing the application of the first argument
896+-- (a function) to every element of the second argument.
850897mkApp :: TT n -> [TT n] -> TT n
851898mkApp f [] = f
852899mkApp f (a:as) = mkApp (App f a) as
@@ -859,6 +906,10 @@ unList tm = case unApply tm of
859906 return $ x:rest
860907 (f, args) -> Nothing
861908
909+-- | Cast a 'TT' term to a 'Raw' value, discarding universe information and
910+-- the types of named references and replacing all de Bruijn indices
911+-- with the corresponding name. It is an error if there are free de
912+-- Bruijn indices.
862913forget :: TT Name -> Raw
863914forget tm = fe [] tm
864915 where
@@ -873,13 +924,21 @@ forget tm = fe [] tm
873924 fe env (TType i) = RType
874925 fe env Erased = RConstant Forgot
875926
927+-- | Introduce a 'Bind' into the given term for each element of the
928+-- given list of (name, binder) pairs.
876929bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
877−bindAll [] t =t
930+bindAll [] t = t
878931bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
879932
933+-- | Like 'bindAll', but the 'Binder's are 'TT' terms instead.
934+-- The first argument is a function to map @TT@ terms to @Binder@s.
935+-- This function might often be something like 'Lam', which directly
936+-- constructs a @Binder@ from a @TT@ term.
880937bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
881938bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
882939
940+-- | Return a list of pairs of the names of the outermost 'Pi'-bound
941+-- variables in the given term, together with their types.
883942getArgTys :: TT n -> [(n, TT n)]
884943getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
885944getArgTys _ = []
@@ -927,7 +986,7 @@ type Type = Term
927986
928987type Env = EnvTT Name
929988
930−-- an environment with de Bruijn indices 'normalised' so that they all refer to
989+-- | an environment with de Bruijn indices 'normalised' so that they all refer to
931990-- this environment
932991
933992newtype WkEnvTT n = Wk (EnvTT n)
@@ -965,6 +1024,7 @@ instance Show Const where
9651024 show PtrType = "Ptr"
9661025 show VoidType = "Void"
9671026
1027+showEnv :: (Eq n, Show n) => EnvTT n -> TT n -> String
9681028showEnv env t = showEnv' env t False
9691029showEnvDbg env t = showEnv' env t True
9701030
@@ -1002,6 +1062,7 @@ prettyEnv env t = prettyEnv' env t False
10021062 prettySe p env Erased debug = text "[_]"
10031063 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
10041064
1065+ -- Render a `Binder` and its name
10051066 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
10061067 prettySb env n (Hole t) = prettyB env "?defer" "." n t
10071068 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
@@ -1010,9 +1071,14 @@ prettyEnv env t = prettyEnv' env t False
10101071 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
10111072 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
10121073
1074+ -- Use `op` and `sc` to delimit `n` (a binding name) and its type
1075+ -- declaration
1076+ -- e.g. "λx : Int =>" for the Lam case
10131077 prettyB env op sc n t debug =
10141078 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
10151079
1080+ -- Like `prettyB`, but handle the bindings that have values in addition
1081+ -- to names and types
10161082 prettyBv env op sc n t v debug =
10171083 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
10181084 prettySe 10 env v debug <> text sc
@@ -1085,9 +1151,12 @@ weakenEnv env = wk (length env - 1) env
10851151 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
10861152 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
10871153
1154+-- | Weaken every term in the environment by the given amount
10881155weakenTmEnv :: Int -> EnvTT n -> EnvTT n
10891156weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
10901157
1158+-- | Gather up all the outer 'PVar's and 'Hole's in an expression and reintroduce
1159+-- them in a canonical order
10911160orderPats :: Term -> Term
10921161orderPats tm = op [] tm
10931162 where
src/Idris/Core/Unify.hs+25−5
@@ -35,22 +35,24 @@ match_unify :: Context -> Env -> TT Name -> TT Name -> [Name] -> [Name] ->
3535 TC [(Name, TT Name)]
3636match_unify ctxt env topx topy dont holes =
3737 case runStateT (un [] topx topy) (UI 0 []) of
38− OK (v, UI _ []) -> return (trimSolutions v)
38+ OK (v, UI _ []) -> return (map (renameBinders env) (trimSolutions v))
3939 res ->
4040 let topxn = normalise ctxt env topx
4141 topyn = normalise ctxt env topy in
4242 case runStateT (un [] topxn topyn)
4343 (UI 0 []) of
4444 OK (v, UI _ fails) ->
45− return (trimSolutions v)
45+ return (map (renameBinders env) (trimSolutions v))
4646 Error e ->
4747 -- just normalise the term we're matching against
4848 case runStateT (un [] topxn topy)
4949 (UI 0 []) of
5050 OK (v, UI _ fails) ->
51− return (trimSolutions v)
51+ return (map (renameBinders env) (trimSolutions v))
5252 _ -> tfail e
5353 where
54+
55+
5456 un names (P _ x _) tm
5557 | holeIn env x || x `elem` holes
5658 = do sc 1; checkCycle names (x, tm)
@@ -127,6 +129,23 @@ match_unify ctxt env topx topy dont holes =
127129 (inst ns tm) (errEnv env))
128130 where inst [] tm = tm
129131 inst ((n, _) : ns) tm = inst ns (substV (P Bound n Erased) tm)
132+
133+renameBinders :: Env -> (Name, TT Name) -> (Name, TT Name)
134+renameBinders env (x, tm) = (x, uniqueBinders tm)
135+ where
136+ uniqueBinders (Bind n b sc)
137+ | n `elem` map fst env
138+ = let n' = uniqueName n (map fst env) in
139+ Bind n' (fmap uniqueBinders b)
140+ (uniqueBinders (rename n n' sc))
141+ | otherwise = Bind n (fmap uniqueBinders b) (uniqueBinders sc)
142+ uniqueBinders (App f a) = App (uniqueBinders f) (uniqueBinders a)
143+ uniqueBinders t = t
144+
145+ rename n n' (P nt x ty) | n == x = P nt n' ty
146+ rename n n' (Bind x b sc) = Bind x (fmap (rename n n') b) (rename n n' sc)
147+ rename n n' (App f a) = App (rename n n' f) (rename n n' a)
148+ rename n n' t = t
130149
131150trimSolutions ns = dropPairs ns
132151 where dropPairs [] = []
@@ -154,7 +173,7 @@ unify ctxt env topx topy dont holes =
154173-- trace ("Unifying " ++ show (topx, topy)) $
155174 -- don't bother if topx and topy are different at the head
156175 case runStateT (un False [] topx topy) (UI 0 []) of
157− OK (v, UI _ []) -> return (trimSolutions v,
176+ OK (v, UI _ []) -> return (map (renameBinders env) (trimSolutions v),
158177 [])
159178 res ->
160179 let topxn = normalise ctxt env topx
@@ -163,7 +182,8 @@ unify ctxt env topx topy dont holes =
163182 case runStateT (un False [] topxn topyn)
164183 (UI 0 []) of
165184 OK (v, UI _ fails) ->
166− return (trimSolutions v, reverse fails)
185+ return (map (renameBinders env) (trimSolutions v),
186+ reverse fails)
167187-- Error e@(CantUnify False _ _ _ _ _) -> tfail e
168188 Error e -> tfail e
169189 where
src/Idris/Delaborate.hs+5
@@ -142,6 +142,11 @@ pshow i (CantConvert x y env)
142142 "Can't convert" ++ indented (showImp (Just i) imps colour (delab i x)) ++ "with"
143143 ++ indented (showImp (Just i) imps colour (delab i y)) ++
144144 if (opt_errContext (idris_options i)) then showSc i env else ""
145+pshow i (CantSolveGoal x env)
146+ = let imps = opt_showimp (idris_options i) in
147+ let colour = idris_colourRepl i in
148+ "Can't solve goal " ++ indented (showImp (Just i) imps colour (delab i x)) ++
149+ if (opt_errContext (idris_options i)) then showSc i env else ""
145150pshow i (UnifyScope n out tm env)
146151 = let imps = opt_showimp (idris_options i) in
147152 let colour = idris_colourRepl i in
src/Idris/ElabDecls.hs+2−2
@@ -1332,7 +1332,7 @@ elabClause info opts (cnum, PClause fc fname lhs_in withs rhs_in whereblock)
13321332 return (tm, ds, is))
13331333 logLvl 5 "DONE CHECK"
13341334 logLvl 2 $ "---> " ++ show rhs'
1335− when (not (null defer)) $ iLOG $ "DEFERRED " ++ show defer
1335+ when (not (null defer)) $ iLOG $ "DEFERRED " ++ show (map fst defer)
13361336 def' <- checkDef fc defer
13371337 let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, False))) def'
13381338 addDeferred def''
@@ -2126,7 +2126,7 @@ elabDecl' _ _ _ = return () -- skipped this time
21262126
21272127elabCaseBlock info opts d@(PClauses f o n ps)
21282128 = do addIBC (IBCDef n)
2129− logLvl 6 $ "CASE BLOCK: " ++ show (n, d)
2129+ logLvl 5 $ "CASE BLOCK: " ++ show (n, d)
21302130 let opts' = nub (o ++ opts)
21312131 -- propagate totality assertion to the new definitions
21322132 when (AssertTotal `elem` opts) $ setFlags n [AssertTotal]
src/Idris/ElabTerm.hs+8−1
@@ -864,7 +864,9 @@ collectDeferred top t = return t
864864runTac :: Bool -> IState -> PTactic -> ElabD ()
865865runTac autoSolve ist tac
866866 = do env <- get_env
867− no_errors $ runT (fmap (addImplBound ist (map fst env)) tac)
867+ g <- goal
868+ no_errors (runT (fmap (addImplBound ist (map fst env)) tac))
869+ (Just (CantSolveGoal g (map (\(n, b) -> (n, binderTy b)) env)))
868870 where
869871 runT (Intro []) = do g <- goal
870872 attack; intro (bname g)
@@ -1468,6 +1470,11 @@ reflectErr (CantConvert t t' ctxt) =
14681470 , reflect t'
14691471 , reflectCtxt ctxt
14701472 ]
1473+reflectErr (CantSolveGoal t ctxt) =
1474+ raw_apply (Var $ reflErrName "CantSolveGoal")
1475+ [ reflect t
1476+ , reflectCtxt ctxt
1477+ ]
14711478reflectErr (UnifyScope n n' t ctxt) =
14721479 raw_apply (Var $ reflErrName "UnifyScope")
14731480 [ reflectName n
src/Idris/IBC.hs+9−5
@@ -21,11 +21,9 @@ import Control.Monad.State.Strict hiding (get, put)
2121import qualified Control.Monad.State.Strict as ST
2222import System.FilePath
2323import System.Directory
24−import Codec.Compression.Zlib
24+import Codec.Compression.Zlib (compress)
25+import Util.Zlib (decompressEither)
2526
26−import Debug.Trace
27−
28−import Paths_idris
2927
3028ibcVersion :: Word8
3129ibcVersion = 54
@@ -74,9 +72,15 @@ loadIBC fp = do iLOG $ "Loading ibc " ++ fp
7472 ibcf <- runIO $ (bdecode fp :: IO IBCFile)
7573 process ibcf fp
7674
75+bencode :: Binary a => FilePath -> a -> IO ()
7776bencode f d = B.writeFile f (compress (encode d))
77+
78+bdecode :: Binary b => FilePath -> IO b
7879bdecode f = do d' <- B.readFile f
79− return (decode (decompress d'))
80+ either
81+ (\(_, e) -> error $ "Invalid / corrupted zip format on " ++ show f ++ ": " ++ e)
82+ (return . decode)
83+ (decompressEither d')
8084
8185writeIBC :: FilePath -> FilePath -> Idris ()
8286writeIBC src f
src/Idris/REPL.hs+1−1
@@ -744,7 +744,7 @@ process h fn (DoProofSearch updatefile l n hints)
744744 | length cs >= length n
745745 = case splitAt (length n) cs of
746746 (mv, c:cs) ->
747− if (isSpace c && mv == n)
747+ if ((isSpace c || c == ')' || c == '}') && mv == n)
748748 then addBracket brack new ++ (c : cs)
749749 else '?' : mv ++ c : updateMeta True cs n new
750750 (mv, []) -> if (mv == n) then addBracket brack new else '?' : mv
src/Util/Zlib.hsnew file+15
@@ -0,0 +1,15 @@
1+module Util.Zlib (decompressEither) where
2+
3+-- From http://stackoverflow.com/questions/10043102/how-to-catch-the-decompress-ioerror/10045963#10045963
4+import Codec.Compression.Zlib.Internal
5+import Data.ByteString.Lazy (ByteString, fromChunks)
6+import Control.Arrow (right)
7+
8+decompressEither :: ByteString -> Either (DecompressError, String) ByteString
9+decompressEither = finalise
10+ . foldDecompressStream cons nil err
11+ . decompressWithErrors zlibFormat defaultDecompressParams
12+ where err errorCode errorString = Left (errorCode, errorString)
13+ nil = Right []
14+ cons chunk = right (chunk :)
15+ finalise = right fromChunks
test/reg031/expected+1−1
@@ -1 +1 @@
1−[10, -128, -55, -1, 10, 51, 10, 52]
1+[10, 128, 201, 255, 10, 51, 10, 52]
test/reg031/reg031.idr+5−1
@@ -1,4 +1,8 @@
11module Main
22
33main : IO ()
4−main = print . map ord . unpack $ "\x0a\x80\xC9\xFF\n3\n4"
4+main = print . map val . unpack $ "\x0a\x80\xC9\xFF\n3\n4"
5+ where
6+ -- make the values positive if the backend has signed chars
7+ val : Char -> Int
8+ val = flip mod 256 . (+256) . ord