on master help sign in
Merge remote-tracking branch 'upstream/master' into error-reflection
887b6e2David Raymond Christiansen
CONTRIBUTING.md+37−13
@@ -30,34 +30,54 @@ Please clean up any messes that you find, and don't leave behind new messes for
30Idris developers and hackers try to adhere to something similar to the [successful git branching model](http://nvie.com/posts/a-successful-git-branching-model/).
30Idris developers and hackers try to adhere to something similar to the [successful git branching model](http://nvie.com/posts/a-successful-git-branching-model/).
31The steps are straightforward.
31The steps are straightforward.
32
32
33+### New contributors
34+
33For those new to the project:
35For those new to the project:
34
36
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
36
45
37− $ git clone git@github.com/<your github user name>/Idris-dev.git
46+```
38− $ git remote add upstream git@github.com:idris-lang/Idris-dev.git
47+$ git remote add upstream git@github.com:idris-lang/Idris-dev.git
48+```
49+
50+### Existing Contributors
39
51
40For those already contributing to the project:
52For those already contributing to the project:
41
53
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+```
43
60
44− $ git fetch upstream
61+### Remaining Steps
45− $ git merge upstream/master
46
62
47−The remaining steps are the same:
63+The remaining steps are the same for both new and existing contributors:
48
64
491. Create, and checkout onto, a topic branch on which to base you work.
651. Create, and checkout onto, a topic branch on which to base you work.
50 * This is typically the master branch.
66 * This is typically the master branch.
51 * For your own sanity, please avoid working on the `master` branch.
67 * For your own sanity, please avoid working on the `master` branch.
52
68
69+```
53− $ git branch fix/master/my_contrib master
70+$ git branch fix/master/my_contrib master
54− $ git checkout fix/master/my_contrib
71+$ git checkout fix/master/my_contrib
72+```
55
73
561. Make commits of logical units.
741. Make commits of logical units.
571. Check for unnecessary whitespace with
751. Check for unnecessary whitespace with
58
76
77+```
59− $ git diff --check
78+$ git diff --check
60−
79+```
80+
611. Make sure your commit messages are along the lines of:
811. Make sure your commit messages are along the lines of:
62
82
63 Short (50 chars or less) summary of changes
83 Short (50 chars or less) summary of changes
@@ -79,11 +99,15 @@ The remaining steps are the same:
791. Make sure you have added any necessary tests for your changes.
991. Make sure you have added any necessary tests for your changes.
801. Run all the tests to assure nothing else was accidentally broken.
1001. Run all the tests to assure nothing else was accidentally broken.
81
101
102+```
82− $ make test
103+$ make test
104+```
83
105
841. Push your changes to a topic branch in your fork of the repository.
1061. Push your changes to a topic branch in your fork of the repository.
85
107
108+```
86− $ git push origin fix/master/my_contrib
109+$ git push origin fix/master/my_contrib
110+```
87
111
881. Go to GitHub and submit a pull request to `idris-dev`
1121. Go to GitHub and submit a pull request to `idris-dev`
89
113
CONTRIBUTORS+2
@@ -15,6 +15,7 @@ Hannes Mehnert
15Mekeor Melire
15Mekeor Melire
16Melissa Mozifian
16Melissa Mozifian
17Dominic Mulligan
17Dominic Mulligan
18+Jan de Muijnck-Hughes
18raichoo
19raichoo
19Tom Prince
20Tom Prince
20Seo Sanghyeon
21Seo Sanghyeon
@@ -26,3 +27,4 @@ Leif Warner
26Daniel Waterworth
27Daniel Waterworth
27Jonas Westerlund
28Jonas Westerlund
28Reynir Reynisson
29Reynir Reynisson
30+
idris.cabal+12
@@ -95,6 +95,11 @@ Extra-source-files:
95 libs/effects/Effect/*.idr
95 libs/effects/Effect/*.idr
96 libs/effects/*.idr
96 libs/effects/*.idr
97
97
98+ libs/neweffects/Makefile
99+ libs/neweffects/neweffects.ipkg
100+ libs/neweffects/Effect/*.idr
101+ libs/neweffects/*.idr
102+
98 libs/javascript/*.idr
103 libs/javascript/*.idr
99 libs/javascript/JavaScript/*.idr
104 libs/javascript/JavaScript/*.idr
100 libs/javascript/Makefile
105 libs/javascript/Makefile
@@ -192,6 +197,12 @@ Extra-source-files:
192 test/reg029/run
197 test/reg029/run
193 test/reg029/*.idr
198 test/reg029/*.idr
194 test/reg029/expected
199 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
195 test/test001/run
206 test/test001/run
196 test/test001/*.idr
207 test/test001/*.idr
197 test/test001/expected
208 test/test001/expected
@@ -415,6 +426,7 @@ Library
415 Util.Pretty
426 Util.Pretty
416 , Util.System
427 , Util.System
417 , Util.Net
428 , Util.Net
429+ , Util.Zlib
418
430
419 , Pkg.PParser
431 , Pkg.PParser
420
432
libs/Makefile+3
@@ -2,6 +2,7 @@ build:
2 $(MAKE) -C prelude build
2 $(MAKE) -C prelude build
3 $(MAKE) -C base build
3 $(MAKE) -C base build
4 $(MAKE) -C effects build
4 $(MAKE) -C effects build
5+ $(MAKE) -C neweffects build
5 $(MAKE) -C javascript build
6 $(MAKE) -C javascript build
6
7
7
8
@@ -9,12 +10,14 @@ install:
9 $(MAKE) -C prelude install
10 $(MAKE) -C prelude install
10 $(MAKE) -C base install
11 $(MAKE) -C base install
11 $(MAKE) -C effects install
12 $(MAKE) -C effects install
13+ $(MAKE) -C neweffects install
12 $(MAKE) -C javascript install
14 $(MAKE) -C javascript install
13
15
14clean:
16clean:
15 $(MAKE) -C prelude clean
17 $(MAKE) -C prelude clean
16 $(MAKE) -C base clean
18 $(MAKE) -C base clean
17 $(MAKE) -C effects clean
19 $(MAKE) -C effects clean
20+ $(MAKE) -C neweffects clean
18 $(MAKE) -C javascript clean
21 $(MAKE) -C javascript clean
19
22
20.PHONY: build install clean
23.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 @@
1module Decidable.Decidable
1module Decidable.Decidable
2
2
3+import Data.Rel
4+
3%access public
5%access public
4
6
5--------------------------------------------------------------------------------
7--------------------------------------------------------------------------------
6-- Typeclass for decidable n-ary Relations
8-- Typeclass for decidable n-ary Relations
7--------------------------------------------------------------------------------
9--------------------------------------------------------------------------------
8
10
9−using (t : Type)
11+-- Note: Instance resolution for Decidable is likely to not work in the REPL
12+-- at the moment.
10− class Rel (p : t) where
13+class Decidable (ts : Vect k Type) (p : Rel ts) where
11− total liftRel : (Type -> Type) -> Type
14+ total decide : liftRel ts p Dec
12
15
13− class (Rel p) => Decidable (p : t) where
16+-- 'No such variable {k506}'
14− total decide : liftRel {p} Dec
17+--decision : Decidable ts p => (ts : Vect k Type) -> (p : Rel ts) -> liftRel ts p Dec
18+--decision ts p = decide {ts} {p}
15
19
16using (P : Type, p : P)
20using (P : Type, p : P)
17 data Given : Dec P -> Type where
21 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))
71 | Yes nLTEm = Yes (nLTESm nLTEm)
71 | Yes nLTEm = Yes (nLTESm nLTEm)
72 | No nGTm = No (nGTSm nGTm)
72 | No nGTm = No (nGTSm nGTm)
73
73
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
78 decide = decideNatLTE
75 decide = decideNatLTE
79
76
80lte : (m : Nat) -> (n : Nat) -> Dec (NatLTE m n)
77lte : (m : Nat) -> (n : Nat) -> Dec (NatLTE m n)
81−lte m n = decide {p = NatLTE} m n
78+lte m n = decide {ts = [Nat,Nat]} {p = NatLTE} m n
82−
libs/base/Language/Reflection/Errors.idr+1
@@ -15,6 +15,7 @@ data Err = Msg String
15 -- unification succeed
15 -- unification succeed
16 | InfiniteUnify TTName TT (List (TTName, TT))
16 | InfiniteUnify TTName TT (List (TTName, TT))
17 | CantConvert TT TT (List (TTName, TT))
17 | CantConvert TT TT (List (TTName, TT))
18+ | CantSolveGoal TT (List (TTName, TT))
18 | UnifyScope TTName TTName TT (List (TTName, TT))
19 | UnifyScope TTName TTName TT (List (TTName, TT))
19 | CantInferType String
20 | CantInferType String
20 | NonFunctionType TT TT
21 | NonFunctionType TT TT
libs/base/base.ipkg+2−1
@@ -23,7 +23,8 @@ modules = System,
23 Data.ZZ, Data.Sign,
23 Data.ZZ, Data.Sign,
24 Data.SortedMap, Data.SortedSet, Data.BoundedList,
24 Data.SortedMap, Data.SortedSet, Data.BoundedList,
25 Data.Vect, Data.HVect, Data.Vect.Quantifiers,
25 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,
27
28
28 Control.Isomorphism,
29 Control.Isomorphism,
29 Control.Monad.Identity,
30 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
532partial
532partial
533nullPtr : Ptr -> IO Bool
533nullPtr : Ptr -> IO Bool
534nullPtr p = do ok <- mkForeign (FFun "isNull" [FPtr] FInt) p
534nullPtr p = do ok <- mkForeign (FFun "isNull" [FPtr] FInt) p
535− return (ok /= 0);
535+ return (ok /= 0)
536
536
537partial
537partial
538nullStr : String -> IO Bool
538nullStr : String -> IO Bool
539nullStr p = do ok <- mkForeign (FFun "isNull" [FString] FInt) p
539nullStr 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)
541
545
542partial
546partial
543validFile : File -> IO Bool
547validFile : File -> IO Bool
rts/idris_stdfgn.c+4
@@ -36,6 +36,10 @@ int isNull(void* ptr) {
36 return ptr==NULL;
36 return ptr==NULL;
37}
37}
38
38
39+int idris_eqPtr(void* x, void* y) {
40+ return x==y;
41+}
42+
39void* idris_stdin() {
43void* idris_stdin() {
40 return (void*)stdin;
44 return (void*)stdin;
41}
45}
rts/idris_stdfgn.h+1
@@ -12,6 +12,7 @@ int fileEOF(void* h);
12int fileError(void* h);
12int fileError(void* h);
13void fputStr(void*h, char* str);
13void fputStr(void*h, char* str);
14
14
15+int idris_eqPtr(void* x, void* y);
15int isNull(void* ptr);
16int isNull(void* ptr);
16void* idris_stdin();
17void* idris_stdin();
17
18
src/IRTS/CodegenJavaScript.hs+119−20
@@ -314,6 +314,9 @@ jsSubst var new (JSIndex obj field) =
314jsSubst var new (JSCond conds) =
314jsSubst var new (JSCond conds) =
315 JSCond (map ((jsSubst var new) *** (jsSubst var new)) conds)
315 JSCond (map ((jsSubst var new) *** (jsSubst var new)) conds)
316
316
317+jsSubst var new (JSAssign lhs rhs) =
318+ JSAssign (jsSubst var new lhs) (jsSubst var new rhs)
319+
317jsSubst _ _ js = js
320jsSubst _ _ js = js
318
321
319
322
@@ -328,16 +331,24 @@ isJSConstant js
328 | otherwise = False
331 | otherwise = False
329
332
330inlineJS :: JS -> JS
333inlineJS :: 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+
331inlineJS (JSApp (JSProj (JSFunction args (JSReturn body)) "apply") [
342inlineJS (JSApp (JSProj (JSFunction args (JSReturn body)) "apply") [
332− JSThis,JSProj (JSIdent var) "vars"
343+ JSThis,JSProj var "vars"
333 ])
344 ])
334− | var /= "cse" =
345+ | var /= JSIdent "cse" =
335− inlineApply args body 0
346+ inlineApply args body 0
336 where
347 where
337− inlineApply [] body _ = body
348+ inlineApply [] body _ = inlineJS body
338 inlineApply (a:as) body n =
349 inlineApply (a:as) body n =
339 inlineApply as (
350 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
341 ) (n + 1)
352 ) (n + 1)
342
353
343inlineJS (JSApp (JSIdent "__IDR__mEVAL0") [val])
354inlineJS (JSApp (JSIdent "__IDR__mEVAL0") [val])
@@ -348,9 +359,6 @@ inlineJS (JSApp (JSIdent "__IDRRT__tailcall") [
348 ])
359 ])
349 | isJSConstant val = val
360 | isJSConstant val = val
350
361
351−inlineJS (JSApp (JSFunction [] (JSSeq ret)) []) =
352− JSApp (JSFunction [] (JSSeq (map inlineJS ret))) []
353−
354inlineJS (JSApp (JSFunction [arg] (JSReturn ret)) [val])
362inlineJS (JSApp (JSFunction [arg] (JSReturn ret)) [val])
355 | JSNew con [tag, vals] <- ret
363 | JSNew con [tag, vals] <- ret
356 , opt <- inlineJS val =
364 , opt <- inlineJS val =
@@ -430,6 +438,96 @@ reduceJS js = reduceLoop [] ([], js)
430funName :: JS -> String
438funName :: JS -> String
431funName (JSAlloc fun _) = fun
439funName (JSAlloc fun _) = fun
432
440
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+
433removeIDs :: [JS] -> [JS]
531removeIDs :: [JS] -> [JS]
434removeIDs js =
532removeIDs js =
435 case partition isID js of
533 case partition isID js of
@@ -651,7 +749,7 @@ codegenJavaScript target definitions filename outputType = do
651
749
652 functions :: [String]
750 functions :: [String]
653 functions =
751 functions =
654− map (compileJS . reduceConstants) ((reduceJS . removeIDs) $ map (optimizeJS . translateDeclaration) def)
752+ map compileJS $ initConstructors (map reduceConstants ((reduceJS . removeIDs) $ map (optimizeJS . translateDeclaration) def))
655
753
656 mainLoop :: String
754 mainLoop :: String
657 mainLoop = compileJS $
755 mainLoop = compileJS $
@@ -780,7 +878,7 @@ translateConstant c =
780
878
781translateDeclaration :: (String, SDecl) -> JS
879translateDeclaration :: (String, SDecl) -> JS
782translateDeclaration (path, SFun name params stackSize body)
880translateDeclaration (path, SFun name params stackSize body)
783− | (MN _ ap) <- name
881+ | (MN _ ap) <- name
784 , (SLet var val next) <- body
882 , (SLet var val next) <- body
785 , (SChkCase cvar cases) <- next
883 , (SChkCase cvar cases) <- next
786 , ap == txt "APPLY" =
884 , ap == txt "APPLY" =
@@ -789,20 +887,21 @@ translateDeclaration (path, SFun name params stackSize body)
789 JSSeq [ lookupTable [(var, "chk")] var cases
887 JSSeq [ lookupTable [(var, "chk")] var cases
790 , jsDecl $ JSFunction ["fn0", "arg0"] (
888 , jsDecl $ JSFunction ["fn0", "arg0"] (
791 JSSeq [ JSAlloc "__var_0" (Just $ JSIdent "fn0")
889 JSSeq [ JSAlloc "__var_0" (Just $ JSIdent "fn0")
792− , JSReturn $ jsLet (translateVariableName var) (
890+ , JSAlloc (translateVariableName var) (
793− translateExpression val
891+ Just $ translateExpression val
892+ )
794− ) (JSTernary (
893+ , JSReturn $ (JSTernary (
795− (JSVar var `jsInstanceOf` jsCon) `jsAnd`
894+ (JSVar var `jsInstanceOf` jsCon) `jsAnd`
796− (hasProp lookupTableName (translateVariableName var))
895+ (hasProp lookupTableName (translateVariableName var))
797− ) (JSIdent $
896+ ) (JSIdent $
798− lookupTableName ++ lookup
897+ lookupTableName ++ lookup
799− ) JSNull
898+ ) JSNull
800− )
899+ )
801 ]
900 ]
802 )
901 )
803 ]
902 ]
804
903
805− | (MN _ ev) <- name
904+ | (MN _ ev) <- name
806 , (SChkCase var cases) <- body
905 , (SChkCase var cases) <- body
807 , ev == txt "EVAL" =
906 , ev == txt "EVAL" =
808 JSSeq [ lookupTable [] var cases
907 JSSeq [ lookupTable [] var cases
src/Idris/Core/Elaborate.hs+19−11
@@ -609,17 +609,24 @@ arg n tyhole = do ty <- unique_hole tyhole
609 forall n (Var ty)
609 forall n (Var ty)
610
610
611-- try a tactic, if it adds any unification problem, return an error
611-- try a tactic, if it adds any unification problem, return an error
612−no_errors :: Elab' aux () -> Elab' aux ()
612+no_errors :: Elab' aux () -> Maybe Err -> Elab' aux ()
613−no_errors tac
613+no_errors tac err
614− = do ps <- get_probs
614+ = do ps <- get_probs
615− tac
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
616− ps' <- get_probs
623+ ps' <- get_probs
617− if (length ps' > length ps) then
624+ if (length ps' > length ps) then
618− case reverse ps' of
625+ case reverse ps' of
619− ((x,y,env,err) : _) ->
626+ ((x,y,env,err) : _) ->
620− let env' = map (\(x, b) -> (x, binderTy b)) env in
627+ let env' = map (\(x, b) -> (x, binderTy b)) env in
621− lift $ tfail $ CantUnify False x y err env' 0
628+ lift $ tfail $ CantUnify False x y err env' 0
622− else return $! ()
629+ else return $! ()
623
630
624-- Try a tactic, if it fails, try another
631-- Try a tactic, if it fails, try another
625try :: Elab' aux a -> Elab' aux a -> Elab' aux a
632try :: Elab' aux a -> Elab' aux a -> Elab' aux a
@@ -642,6 +649,7 @@ try' t1 t2 proofSearch
642 where recoverableErr err@(CantUnify r x y _ _ _)
649 where recoverableErr err@(CantUnify r x y _ _ _)
643 = -- traceWhen r (show err) $
650 = -- traceWhen r (show err) $
644 r || proofSearch
651 r || proofSearch
652+ recoverableErr (CantSolveGoal _ _) = False
645 recoverableErr (ProofSearchFail _) = False
653 recoverableErr (ProofSearchFail _) = False
646 recoverableErr _ = True
654 recoverableErr _ = True
647
655
src/Idris/Core/Evaluate.hs+9−8
@@ -228,11 +228,11 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
228 ev ntimes stk top env (P nt n ty)
228 ev ntimes stk top env (P nt n ty)
229 = liftM (VP nt n) (ev ntimes stk top env ty)
229 = liftM (VP nt n) (ev ntimes stk top env ty)
230 ev ntimes stk top env (V i)
230 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)
232 | otherwise = return $ VV i
232 | otherwise = return $ VV i
233 ev ntimes stk top env (Bind n (Let t v) sc)
233 ev ntimes stk top env (Bind n (Let t v) sc)
234 = do v' <- ev ntimes stk top env v --(finalise v)
234 = 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
236 wknV (-1) sc'
236 wknV (-1) sc'
237-- | otherwise
237-- | otherwise
238-- = do t' <- ev ntimes stk top env t
238-- = do t' <- ev ntimes stk top env t
@@ -247,12 +247,13 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
247 ev ntimes stk top env (Bind n (NLet t v) sc)
247 ev ntimes stk top env (Bind n (NLet t v) sc)
248 = do t' <- ev ntimes stk top env (finalise t)
248 = do t' <- ev ntimes stk top env (finalise t)
249 v' <- ev ntimes stk top env (finalise v)
249 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
251 return $ VBind True n (Let t' v') (\x -> return sc')
251 return $ VBind True n (Let t' v') (\x -> return sc')
252 ev ntimes stk top env (Bind n b sc)
252 ev ntimes stk top env (Bind n b sc)
253 = do b' <- vbind env b
253 = do b' <- vbind env b
254+ let n' = uniqueName n (map fst env)
254 return $ VBind True -- (vinstances 0 sc < 2)
255 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)
256 where vbind env t
257 where vbind env t
257-- | simpl
258-- | simpl
258-- = fmapMB (\tm -> ev ((MN 0 "STOP", 0) : ntimes)
259-- = fmapMB (\tm -> ev ((MN 0 "STOP", 0) : ntimes)
@@ -345,7 +346,7 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
345-- _ -> return $ unload env f args
346-- _ -> return $ unload env f args
346-- specApply stk env f args = return $ unload env f args
347-- specApply stk env f args = return $ unload env f args
347
348
348− unload :: [Value] -> Value -> [Value] -> Value
349+ unload :: [(Name, Value)] -> Value -> [Value] -> Value
349 unload env f [] = f
350 unload env f [] = f
350 unload env f (a:as) = unload env (VApp f a) as
351 unload env f (a:as) = unload env (VApp f a) as
351
352
@@ -360,12 +361,12 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
360 | otherwise = return (Nothing, args)
361 | otherwise = return (Nothing, args)
361
362
362 evTree :: [(Name, Int)] -> [Name] -> Bool ->
363 evTree :: [(Name, Int)] -> [Name] -> Bool ->
363− [Value] -> [(Name, Value)] -> SC -> Eval (Maybe Value)
364+ [(Name, Value)] -> [(Name, Value)] -> SC -> Eval (Maybe Value)
364 evTree ntimes stk top env amap (UnmatchedCase str) = return Nothing
365 evTree ntimes stk top env amap (UnmatchedCase str) = return Nothing
365 evTree ntimes stk top env amap (STerm tm)
366 evTree ntimes stk top env amap (STerm tm)
366 = do let etm = pToVs (map fst amap) tm
367 = do let etm = pToVs (map fst amap) tm
367 etm' <- ev ntimes stk (not (conHeaded tm))
368 etm' <- ev ntimes stk (not (conHeaded tm))
368− (map snd amap ++ env) etm
369+ (amap ++ env) etm
369 return $ Just etm'
370 return $ Just etm'
370 evTree ntimes stk top env amap (ProjCase t alts)
371 evTree ntimes stk top env amap (ProjCase t alts)
371 = do t' <- ev ntimes stk top env t
372 = do t' <- ev ntimes stk top env t
@@ -394,7 +395,7 @@ eval traceon ctxt ntimes genv tm opts = ev ntimes [] True [] tm where
394 chooseAlt env f' (getValArgs f')
395 chooseAlt env f' (getValArgs f')
395 alts amap
396 alts amap
396
397
397− chooseAlt :: [Value] -> Value -> (Value, [Value]) -> [CaseAlt] ->
398+ chooseAlt :: [(Name, Value)] -> Value -> (Value, [Value]) -> [CaseAlt] ->
398 [(Name, Value)] ->
399 [(Name, Value)] ->
399 Eval (Maybe ([(Name, Value)], SC))
400 Eval (Maybe ([(Name, Value)], SC))
400 chooseAlt env _ (VP (DCon i a) _ _, args) alts amap
401 chooseAlt env _ (VP (DCon i a) _ _, args) alts amap
src/Idris/Core/TT.hs+82−13
@@ -99,6 +99,7 @@ data Err = Msg String
99 -- unification succeed
99 -- unification succeed
100 | InfiniteUnify Name Term [(Name, Type)]
100 | InfiniteUnify Name Term [(Name, Type)]
101 | CantConvert Term Term [(Name, Type)]
101 | CantConvert Term Term [(Name, Type)]
102+ | CantSolveGoal Term [(Name, Type)]
102 | UnifyScope Name Name Term [(Name, Type)]
103 | UnifyScope Name Name Term [(Name, Type)]
103 | CantInferType String
104 | CantInferType String
104 | NonFunctionType Term Term
105 | NonFunctionType Term Term
@@ -156,6 +157,7 @@ score (CantUnify _ _ _ m _ s) = s + score m
156score (CantResolve _) = 20
157score (CantResolve _) = 20
157score (NoSuchVariable _) = 1000
158score (NoSuchVariable _) = 1000
158score (ProofSearchFail _) = 10000
159score (ProofSearchFail _) = 10000
160+score (CantSolveGoal _ _) = 10000
159score (InternalMsg _) = -1
161score (InternalMsg _) = -1
160score _ = 0
162score _ = 0
161
163
@@ -164,6 +166,7 @@ instance Show Err where
164 show (InternalMsg s) = "Internal error: " ++ show s
166 show (InternalMsg s) = "Internal error: " ++ show s
165 show (CantUnify _ l r e sc i) = "CantUnify " ++ show l ++ " " ++ show r ++ " "
167 show (CantUnify _ l r e sc i) = "CantUnify " ++ show l ++ " " ++ show r ++ " "
166 ++ show e ++ " in " ++ show sc ++ " " ++ show i
168 ++ show e ++ " in " ++ show sc ++ " " ++ show i
169+ show (CantSolveGoal g _) = "CantSolve " ++ show g
167 show (Inaccessible n) = show n ++ " is not an accessible pattern variable"
170 show (Inaccessible n) = show n ++ " is not an accessible pattern variable"
168 show (ProviderError msg) = "Type provider error: " ++ msg
171 show (ProviderError msg) = "Type provider error: " ++ msg
169 show (LoadingFailed fn e) = "Loading " ++ fn ++ " failed: (TT) " ++ show e
172 show (LoadingFailed fn e) = "Loading " ++ fn ++ " failed: (TT) " ++ show e
@@ -334,6 +337,8 @@ emptyContext = Map.empty
334mapCtxt :: (a -> b) -> Ctxt a -> Ctxt b
337mapCtxt :: (a -> b) -> Ctxt a -> Ctxt b
335mapCtxt = fmap . fmap
338mapCtxt = fmap . fmap
336
339
340+-- |Return True if the argument 'Name' should be interpreted as the name of a
341+-- typeclass.
337tcname (UN xs) | T.null xs = False
342tcname (UN xs) | T.null xs = False
338 | otherwise = T.head xs == '@'
343 | otherwise = T.head xs == '@'
339tcname (NS n _) = tcname n
344tcname (NS n _) = tcname n
@@ -503,11 +508,18 @@ deriving instance Binary Raw
503deriving instance NFData Raw
508deriving instance NFData Raw
504!-}
509!-}
505
510
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.
506−-- | All binding forms are represented in a unform fashion.
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.
507data Binder b = Lam { binderTy :: !b {-^ type annotation for bound variable-}}
517data Binder b = Lam { binderTy :: !b {-^ type annotation for bound variable-}}
508 | Pi { binderTy :: !b }
518 | Pi { binderTy :: !b }
519+ {-^ A binding that occurs in a function type expression, e.g. @(x:Int) -> ...@ -}
509 | Let { binderTy :: !b,
520 | Let { binderTy :: !b,
510 binderVal :: b {-^ value for bound variable-}}
521 binderVal :: b {-^ value for bound variable-}}
522+ -- ^ A binding that occurs in a @let@ expression
511 | NLet { binderTy :: !b,
523 | NLet { binderTy :: !b,
512 binderVal :: b }
524 binderVal :: b }
513 | Hole { binderTy :: !b}
525 | Hole { binderTy :: !b}
@@ -516,6 +528,7 @@ data Binder b = Lam { binderTy :: !b {-^ type annotation for bound variable-}
516 | Guess { binderTy :: !b,
528 | Guess { binderTy :: !b,
517 binderVal :: b }
529 binderVal :: b }
518 | PVar { binderTy :: !b }
530 | PVar { binderTy :: !b }
531+ -- ^ A pattern variable
519 | PVTy { binderTy :: !b }
532 | PVTy { binderTy :: !b }
520 deriving (Show, Eq, Ord, Functor)
533 deriving (Show, Eq, Ord, Functor)
521{-!
534{-!
@@ -594,8 +607,8 @@ type UCs = (Int, [UConstraint])
594
607
595data NameType = Bound
608data NameType = Bound
596 | Ref
609 | Ref
597− | DCon Int Int -- ^ Data constructor; Ints are tag and arity
610+ | DCon {nt_tag :: Int, nt_arity :: Int} -- ^ Data constructor
598− | TCon Int Int -- ^ Type constructor; Ints are tag and arity
611+ | TCon {nt_tag :: Int, nt_arity :: Int} -- ^ Type constructor
599 deriving (Show, Ord)
612 deriving (Show, Ord)
600{-!
613{-!
601deriving instance Binary NameType
614deriving instance Binary NameType
@@ -615,8 +628,12 @@ instance Eq NameType where
615 TCon _ a == TCon _ b = (a == b) -- ignore tag
628 TCon _ a == TCon _ b = (a == b) -- ignore tag
616 _ == _ = False
629 _ == _ = False
617
630
618−-- | Terms in the core language
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'@.
619−data TT n = P NameType n (TT n) -- ^ named references
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)
620 | V !Int -- ^ a resolved de Bruijn-indexed variable
637 | V !Int -- ^ a resolved de Bruijn-indexed variable
621 | Bind n !(Binder (TT n)) (TT n) -- ^ a binding
638 | Bind n !(Binder (TT n)) (TT n) -- ^ a binding
622 | App !(TT n) (TT n) -- ^ function, function type, arg
639 | App !(TT n) (TT n) -- ^ function, function type, arg
@@ -640,10 +657,14 @@ instance TermSize a => TermSize [a] where
640 termsize n (x : xs) = termsize n x + termsize n xs
657 termsize n (x : xs) = termsize n x + termsize n xs
641
658
642instance TermSize (TT Name) where
659instance TermSize (TT Name) where
643− termsize n (P _ x _)
660+ termsize n (P _ n' _)
644− | x == n = 1000000 -- recursive => really big
661+ | n' == n = 1000000 -- recursive => really big
645 | otherwise = 1
662 | otherwise = 1
646 termsize n (V _) = 1
663 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.
647 termsize n (Bind n' (Let t v) sc)
668 termsize n (Bind n' (Let t v) sc)
648 = let rn = if n == n' then sMN 0 "noname" else n in
669 = let rn = if n == n' then sMN 0 "noname" else n in
649 termsize rn v + termsize rn sc
670 termsize rn v + termsize rn sc
@@ -709,6 +730,7 @@ vinstances i (Bind x b sc) = instancesB b + vinstances (i + 1) sc
709 instancesB _ = 0
730 instancesB _ = 0
710vinstances i t = 0
731vinstances i t = 0
711
732
733+-- | Replace the outermost (index 0) de Bruijn variable with the given term
712instantiate :: TT n -> TT n -> TT n
734instantiate :: TT n -> TT n -> TT n
713instantiate e = subst 0 where
735instantiate e = subst 0 where
714 subst i (V x) | i == x = e
736 subst i (V x) | i == x = e
@@ -717,6 +739,9 @@ instantiate e = subst 0 where
717 subst i (Proj x idx) = Proj (subst i x) idx
739 subst i (Proj x idx) = Proj (subst i x) idx
718 subst i t = t
740 subst i t = t
719
741
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.
720substV :: TT n -> TT n -> TT n
745substV :: TT n -> TT n -> TT n
721substV x tm = dropV 0 (instantiate x tm) where
746substV x tm = dropV 0 (instantiate x tm) where
722 dropV i (V x) | x > i = V (x - 1)
747 dropV i (V x) | x > i = V (x - 1)
@@ -726,6 +751,8 @@ substV x tm = dropV 0 (instantiate x tm) where
726 dropV i (Proj x idx) = Proj (dropV i x) idx
751 dropV i (Proj x idx) = Proj (dropV i x) idx
727 dropV i t = t
752 dropV i t = t
728
753
754+-- | Replace all non-free de Bruijn references in the given term with references
755+-- to the name of their binding.
729explicitNames :: TT n -> TT n
756explicitNames :: TT n -> TT n
730explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
757explicitNames (Bind x b sc) = let b' = fmap explicitNames b in
731 Bind x b'
758 Bind x b'
@@ -735,6 +762,8 @@ explicitNames (App f a) = App (explicitNames f) (explicitNames a)
735explicitNames (Proj x idx) = Proj (explicitNames x) idx
762explicitNames (Proj x idx) = Proj (explicitNames x) idx
736explicitNames t = t
763explicitNames t = t
737
764
765+-- | Replace references to the given 'Name'-like id with references to
766+-- de Bruijn index 0.
738pToV :: Eq n => n -> TT n -> TT n
767pToV :: Eq n => n -> TT n -> TT n
739pToV n = pToV' n 0
768pToV n = pToV' n 0
740pToV' n i (P _ x _) | n == x = V i
769pToV' n i (P _ x _) | n == x = V i
@@ -764,6 +793,9 @@ pToVs ns tm = pToVs' ns tm 0 where
764 pToVs' [] tm i = tm
793 pToVs' [] tm i = tm
765 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
794 pToVs' (n:ns) tm i = pToV' n i (pToVs' ns tm (i+1))
766
795
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.
767vToP :: TT n -> TT n
799vToP :: TT n -> TT n
768vToP = vToP' [] where
800vToP = vToP' [] where
769 vToP' env (V i) = let (n, b) = (env !! i) in
801 vToP' env (V i) = let (n, b) = (env !! i) in
@@ -773,6 +805,8 @@ vToP = vToP' [] where
773 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
805 vToP' env (App f a) = App (vToP' env f) (vToP' env a)
774 vToP' env t = t
806 vToP' env t = t
775
807
808+-- | Replace every non-free reference to the name of a binding in
809+-- the given term with a de Bruijn index.
776finalise :: Eq n => TT n -> TT n
810finalise :: Eq n => TT n -> TT n
777finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
811finalise (Bind x b sc) = Bind x (fmap finalise b) (pToV x (finalise sc))
778finalise (App f a) = App (finalise f) (finalise a)
812finalise (App f a) = App (finalise f) (finalise a)
@@ -787,7 +821,12 @@ pEraseType (App f a) = App (pEraseType f) (pEraseType a)
787pEraseType (Bind n b sc) = Bind n (fmap pEraseType b) (pEraseType sc)
821pEraseType (Bind n b sc) = Bind n (fmap pEraseType b) (pEraseType sc)
788pEraseType t = t
822pEraseType t = t
789
823
824+-- | As 'instantiate', but in addition to replacing @'V' 0@,
825+-- replace references to the given 'Name'-like id.
790−subst :: Eq n => n -> TT n -> TT n -> TT n
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
791subst n v tm = instantiate v (pToV n tm)
830subst n v tm = instantiate v (pToV n tm)
792
831
793-- If there are no Vs in the term (i.e. in proof state)
832-- If there are no Vs in the term (i.e. in proof state)
@@ -800,19 +839,25 @@ psubst n v tm = s' tm where
800 s' (Proj t idx) = Proj (s' t) idx
839 s' (Proj t idx) = Proj (s' t) idx
801 s' t = t
840 s' t = t
802
841
842+-- | As 'subst', but takes a list of (name, substitution) pairs instead
843+-- of a single name and substitution
803substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
844substNames :: Eq n => [(n, TT n)] -> TT n -> TT n
804substNames [] t = t
845substNames [] t = t
805substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
846substNames ((n, tm) : xs) t = subst n tm (substNames xs t)
806
847
848+-- | Replaces all terms equal (in the sense of @(==)@) to
849+-- the old term with the new term.
807−substTerm :: Eq n => TT n -> TT n -> TT n -> TT n
850+substTerm :: Eq n => TT n {-^ Old term -} ->
851+ TT n {-^ New term -} ->
852+ TT n {-^ template term -}
853+ -> TT n
808substTerm old new = st where
854substTerm old new = st where
809 st t | t == old = new
855 st t | t == old = new
810 st (App f a) = App (st f) (st a)
856 st (App f a) = App (st f) (st a)
811 st (Bind x b sc) = Bind x (fmap st b) (st sc)
857 st (Bind x b sc) = Bind x (fmap st b) (st sc)
812 st t = t
858 st t = t
813
859
814−-- Returns true if V 0 and bound name n do not occur in the term
860+-- | Returns true if V 0 and bound name n do not occur in the term
815−
816noOccurrence :: Eq n => n -> TT n -> Bool
861noOccurrence :: Eq n => n -> TT n -> Bool
817noOccurrence n t = no' 0 t
862noOccurrence n t = no' 0 t
818 where
863 where
@@ -847,6 +892,8 @@ unApply t = ua [] t where
847 ua args (App f a) = ua (a:args) f
892 ua args (App f a) = ua (a:args) f
848 ua args t = (t, args)
893 ua args t = (t, args)
849
894
895+-- | Returns a term representing the application of the first argument
896+-- (a function) to every element of the second argument.
850mkApp :: TT n -> [TT n] -> TT n
897mkApp :: TT n -> [TT n] -> TT n
851mkApp f [] = f
898mkApp f [] = f
852mkApp f (a:as) = mkApp (App f a) as
899mkApp f (a:as) = mkApp (App f a) as
@@ -859,6 +906,10 @@ unList tm = case unApply tm of
859 return $ x:rest
906 return $ x:rest
860 (f, args) -> Nothing
907 (f, args) -> Nothing
861
908
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.
862forget :: TT Name -> Raw
913forget :: TT Name -> Raw
863forget tm = fe [] tm
914forget tm = fe [] tm
864 where
915 where
@@ -873,13 +924,21 @@ forget tm = fe [] tm
873 fe env (TType i) = RType
924 fe env (TType i) = RType
874 fe env Erased = RConstant Forgot
925 fe env Erased = RConstant Forgot
875
926
927+-- | Introduce a 'Bind' into the given term for each element of the
928+-- given list of (name, binder) pairs.
876bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
929bindAll :: [(n, Binder (TT n))] -> TT n -> TT n
877−bindAll [] t =t
930+bindAll [] t = t
878bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
931bindAll ((n, b) : bs) t = Bind n b (bindAll bs t)
879
932
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.
880bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
937bindTyArgs :: (TT n -> Binder (TT n)) -> [(n, TT n)] -> TT n -> TT n
881bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
938bindTyArgs b xs = bindAll (map (\ (n, ty) -> (n, b ty)) xs)
882
939
940+-- | Return a list of pairs of the names of the outermost 'Pi'-bound
941+-- variables in the given term, together with their types.
883getArgTys :: TT n -> [(n, TT n)]
942getArgTys :: TT n -> [(n, TT n)]
884getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
943getArgTys (Bind n (Pi t) sc) = (n, t) : getArgTys sc
885getArgTys _ = []
944getArgTys _ = []
@@ -927,7 +986,7 @@ type Type = Term
927
986
928type Env = EnvTT Name
987type Env = EnvTT Name
929
988
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
931-- this environment
990-- this environment
932
991
933newtype WkEnvTT n = Wk (EnvTT n)
992newtype WkEnvTT n = Wk (EnvTT n)
@@ -965,6 +1024,7 @@ instance Show Const where
965 show PtrType = "Ptr"
1024 show PtrType = "Ptr"
966 show VoidType = "Void"
1025 show VoidType = "Void"
967
1026
1027+showEnv :: (Eq n, Show n) => EnvTT n -> TT n -> String
968showEnv env t = showEnv' env t False
1028showEnv env t = showEnv' env t False
969showEnvDbg env t = showEnv' env t True
1029showEnvDbg env t = showEnv' env t True
970
1030
@@ -1002,6 +1062,7 @@ prettyEnv env t = prettyEnv' env t False
1002 prettySe p env Erased debug = text "[_]"
1062 prettySe p env Erased debug = text "[_]"
1003 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
1063 prettySe p env (TType i) debug = text "Type" <+> (text . show $ i)
1004
1064
1065+ -- Render a `Binder` and its name
1005 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
1066 prettySb env n (Lam t) = prettyB env "λ" "=>" n t
1006 prettySb env n (Hole t) = prettyB env "?defer" "." n t
1067 prettySb env n (Hole t) = prettyB env "?defer" "." n t
1007 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
1068 prettySb env n (Pi t) = prettyB env "(" ") ->" n t
@@ -1010,9 +1071,14 @@ prettyEnv env t = prettyEnv' env t False
1010 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
1071 prettySb env n (Let t v) = prettyBv env "let" "in" n t v
1011 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
1072 prettySb env n (Guess t v) = prettyBv env "??" "in" n t v
1012
1073
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
1013 prettyB env op sc n t debug =
1077 prettyB env op sc n t debug =
1014 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
1078 text op <> pretty n <+> colon <+> prettySe 10 env t debug <> text sc
1015
1079
1080+ -- Like `prettyB`, but handle the bindings that have values in addition
1081+ -- to names and types
1016 prettyBv env op sc n t v debug =
1082 prettyBv env op sc n t v debug =
1017 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
1083 text op <> pretty n <+> colon <+> prettySe 10 env t debug <+> text "=" <+>
1018 prettySe 10 env v debug <> text sc
1084 prettySe 10 env v debug <> text sc
@@ -1085,9 +1151,12 @@ weakenEnv env = wk (length env - 1) env
1085 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
1151 weakenTmB i (Guess t v) = Guess (weakenTm i t) (weakenTm i v)
1086 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
1152 weakenTmB i t = t { binderTy = weakenTm i (binderTy t) }
1087
1153
1154+-- | Weaken every term in the environment by the given amount
1088weakenTmEnv :: Int -> EnvTT n -> EnvTT n
1155weakenTmEnv :: Int -> EnvTT n -> EnvTT n
1089weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
1156weakenTmEnv i = map (\ (n, b) -> (n, fmap (weakenTm i) b))
1090
1157
1158+-- | Gather up all the outer 'PVar's and 'Hole's in an expression and reintroduce
1159+-- them in a canonical order
1091orderPats :: Term -> Term
1160orderPats :: Term -> Term
1092orderPats tm = op [] tm
1161orderPats tm = op [] tm
1093 where
1162 where
src/Idris/Core/Unify.hs+25−5
@@ -35,22 +35,24 @@ match_unify :: Context -> Env -> TT Name -> TT Name -> [Name] -> [Name] ->
35 TC [(Name, TT Name)]
35 TC [(Name, TT Name)]
36match_unify ctxt env topx topy dont holes =
36match_unify ctxt env topx topy dont holes =
37 case runStateT (un [] topx topy) (UI 0 []) of
37 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))
39 res ->
39 res ->
40 let topxn = normalise ctxt env topx
40 let topxn = normalise ctxt env topx
41 topyn = normalise ctxt env topy in
41 topyn = normalise ctxt env topy in
42 case runStateT (un [] topxn topyn)
42 case runStateT (un [] topxn topyn)
43 (UI 0 []) of
43 (UI 0 []) of
44 OK (v, UI _ fails) ->
44 OK (v, UI _ fails) ->
45− return (trimSolutions v)
45+ return (map (renameBinders env) (trimSolutions v))
46 Error e ->
46 Error e ->
47 -- just normalise the term we're matching against
47 -- just normalise the term we're matching against
48 case runStateT (un [] topxn topy)
48 case runStateT (un [] topxn topy)
49 (UI 0 []) of
49 (UI 0 []) of
50 OK (v, UI _ fails) ->
50 OK (v, UI _ fails) ->
51− return (trimSolutions v)
51+ return (map (renameBinders env) (trimSolutions v))
52 _ -> tfail e
52 _ -> tfail e
53 where
53 where
54+
55+
54 un names (P _ x _) tm
56 un names (P _ x _) tm
55 | holeIn env x || x `elem` holes
57 | holeIn env x || x `elem` holes
56 = do sc 1; checkCycle names (x, tm)
58 = do sc 1; checkCycle names (x, tm)
@@ -127,6 +129,23 @@ match_unify ctxt env topx topy dont holes =
127 (inst ns tm) (errEnv env))
129 (inst ns tm) (errEnv env))
128 where inst [] tm = tm
130 where inst [] tm = tm
129 inst ((n, _) : ns) tm = inst ns (substV (P Bound n Erased) tm)
131 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
130
149
131trimSolutions ns = dropPairs ns
150trimSolutions ns = dropPairs ns
132 where dropPairs [] = []
151 where dropPairs [] = []
@@ -154,7 +173,7 @@ unify ctxt env topx topy dont holes =
154-- trace ("Unifying " ++ show (topx, topy)) $
173-- trace ("Unifying " ++ show (topx, topy)) $
155 -- don't bother if topx and topy are different at the head
174 -- don't bother if topx and topy are different at the head
156 case runStateT (un False [] topx topy) (UI 0 []) of
175 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),
158 [])
177 [])
159 res ->
178 res ->
160 let topxn = normalise ctxt env topx
179 let topxn = normalise ctxt env topx
@@ -163,7 +182,8 @@ unify ctxt env topx topy dont holes =
163 case runStateT (un False [] topxn topyn)
182 case runStateT (un False [] topxn topyn)
164 (UI 0 []) of
183 (UI 0 []) of
165 OK (v, UI _ fails) ->
184 OK (v, UI _ fails) ->
166− return (trimSolutions v, reverse fails)
185+ return (map (renameBinders env) (trimSolutions v),
186+ reverse fails)
167-- Error e@(CantUnify False _ _ _ _ _) -> tfail e
187-- Error e@(CantUnify False _ _ _ _ _) -> tfail e
168 Error e -> tfail e
188 Error e -> tfail e
169 where
189 where
src/Idris/Delaborate.hs+5
@@ -142,6 +142,11 @@ pshow i (CantConvert x y env)
142 "Can't convert" ++ indented (showImp (Just i) imps colour (delab i x)) ++ "with"
142 "Can't convert" ++ indented (showImp (Just i) imps colour (delab i x)) ++ "with"
143 ++ indented (showImp (Just i) imps colour (delab i y)) ++
143 ++ indented (showImp (Just i) imps colour (delab i y)) ++
144 if (opt_errContext (idris_options i)) then showSc i env else ""
144 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 ""
145pshow i (UnifyScope n out tm env)
150pshow i (UnifyScope n out tm env)
146 = let imps = opt_showimp (idris_options i) in
151 = let imps = opt_showimp (idris_options i) in
147 let colour = idris_colourRepl i in
152 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)
1332 return (tm, ds, is))
1332 return (tm, ds, is))
1333 logLvl 5 "DONE CHECK"
1333 logLvl 5 "DONE CHECK"
1334 logLvl 2 $ "---> " ++ show rhs'
1334 logLvl 2 $ "---> " ++ show rhs'
1335− when (not (null defer)) $ iLOG $ "DEFERRED " ++ show defer
1335+ when (not (null defer)) $ iLOG $ "DEFERRED " ++ show (map fst defer)
1336 def' <- checkDef fc defer
1336 def' <- checkDef fc defer
1337 let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, False))) def'
1337 let def'' = map (\(n, (i, top, t)) -> (n, (i, top, t, False))) def'
1338 addDeferred def''
1338 addDeferred def''
@@ -2126,7 +2126,7 @@ elabDecl' _ _ _ = return () -- skipped this time
2126
2126
2127elabCaseBlock info opts d@(PClauses f o n ps)
2127elabCaseBlock info opts d@(PClauses f o n ps)
2128 = do addIBC (IBCDef n)
2128 = do addIBC (IBCDef n)
2129− logLvl 6 $ "CASE BLOCK: " ++ show (n, d)
2129+ logLvl 5 $ "CASE BLOCK: " ++ show (n, d)
2130 let opts' = nub (o ++ opts)
2130 let opts' = nub (o ++ opts)
2131 -- propagate totality assertion to the new definitions
2131 -- propagate totality assertion to the new definitions
2132 when (AssertTotal `elem` opts) $ setFlags n [AssertTotal]
2132 when (AssertTotal `elem` opts) $ setFlags n [AssertTotal]
src/Idris/ElabTerm.hs+8−1
@@ -864,7 +864,9 @@ collectDeferred top t = return t
864runTac :: Bool -> IState -> PTactic -> ElabD ()
864runTac :: Bool -> IState -> PTactic -> ElabD ()
865runTac autoSolve ist tac
865runTac autoSolve ist tac
866 = do env <- get_env
866 = do env <- get_env
867+ g <- goal
867− no_errors $ runT (fmap (addImplBound ist (map fst env)) tac)
868+ no_errors (runT (fmap (addImplBound ist (map fst env)) tac))
869+ (Just (CantSolveGoal g (map (\(n, b) -> (n, binderTy b)) env)))
868 where
870 where
869 runT (Intro []) = do g <- goal
871 runT (Intro []) = do g <- goal
870 attack; intro (bname g)
872 attack; intro (bname g)
@@ -1468,6 +1470,11 @@ reflectErr (CantConvert t t' ctxt) =
1468 , reflect t'
1470 , reflect t'
1469 , reflectCtxt ctxt
1471 , reflectCtxt ctxt
1470 ]
1472 ]
1473+reflectErr (CantSolveGoal t ctxt) =
1474+ raw_apply (Var $ reflErrName "CantSolveGoal")
1475+ [ reflect t
1476+ , reflectCtxt ctxt
1477+ ]
1471reflectErr (UnifyScope n n' t ctxt) =
1478reflectErr (UnifyScope n n' t ctxt) =
1472 raw_apply (Var $ reflErrName "UnifyScope")
1479 raw_apply (Var $ reflErrName "UnifyScope")
1473 [ reflectName n
1480 [ reflectName n
src/Idris/IBC.hs+9−5
@@ -21,11 +21,9 @@ import Control.Monad.State.Strict hiding (get, put)
21import qualified Control.Monad.State.Strict as ST
21import qualified Control.Monad.State.Strict as ST
22import System.FilePath
22import System.FilePath
23import System.Directory
23import System.Directory
24−import Codec.Compression.Zlib
24+import Codec.Compression.Zlib (compress)
25+import Util.Zlib (decompressEither)
25
26
26−import Debug.Trace
27−
28−import Paths_idris
29
27
30ibcVersion :: Word8
28ibcVersion :: Word8
31ibcVersion = 54
29ibcVersion = 54
@@ -74,9 +72,15 @@ loadIBC fp = do iLOG $ "Loading ibc " ++ fp
74 ibcf <- runIO $ (bdecode fp :: IO IBCFile)
72 ibcf <- runIO $ (bdecode fp :: IO IBCFile)
75 process ibcf fp
73 process ibcf fp
76
74
75+bencode :: Binary a => FilePath -> a -> IO ()
77bencode f d = B.writeFile f (compress (encode d))
76bencode f d = B.writeFile f (compress (encode d))
77+
78+bdecode :: Binary b => FilePath -> IO b
78bdecode f = do d' <- B.readFile f
79bdecode f = do d' <- B.readFile f
80+ either
81+ (\(_, e) -> error $ "Invalid / corrupted zip format on " ++ show f ++ ": " ++ e)
79− return (decode (decompress d'))
82+ (return . decode)
83+ (decompressEither d')
80
84
81writeIBC :: FilePath -> FilePath -> Idris ()
85writeIBC :: FilePath -> FilePath -> Idris ()
82writeIBC src f
86writeIBC src f
src/Idris/REPL.hs+1−1
@@ -744,7 +744,7 @@ process h fn (DoProofSearch updatefile l n hints)
744 | length cs >= length n
744 | length cs >= length n
745 = case splitAt (length n) cs of
745 = case splitAt (length n) cs of
746 (mv, c:cs) ->
746 (mv, c:cs) ->
747− if (isSpace c && mv == n)
747+ if ((isSpace c || c == ')' || c == '}') && mv == n)
748 then addBracket brack new ++ (c : cs)
748 then addBracket brack new ++ (c : cs)
749 else '?' : mv ++ c : updateMeta True cs n new
749 else '?' : mv ++ c : updateMeta True cs n new
750 (mv, []) -> if (mv == n) then addBracket brack new else '?' : mv
750 (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 @@
1module Main
1module Main
2
2
3main : IO ()
3main : 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