on master help sign in
Merge branch 'master' into fix/master/1211
532ef6cEdwin Brady
.github/ISSUE_TEMPLATE.mdnew file+9
@@ -0,0 +1,9 @@
1+Please attach complete source files that exhibit the issue in addition
2+to quoting from them here.
3+
4+# Steps to Reproduce
5+
6+# Expected Behavior
7+
8+# Observed Behavior
9+
.gitignore+1
@@ -1,5 +1,6 @@
1# Build artefacts
1# Build artefacts
2dist
2dist
3+dist-newstyle
3*.ibc
4*.ibc
4*.o
5*.o
5*.a
6*.a
.travis.yml−13
@@ -11,15 +11,6 @@ matrix:
11 include:
11 include:
12 - env: CABALVER="1.24" GHCVER="8.0.1" STACKVER="7.14" STYLISH=YES
12 - env: CABALVER="1.24" GHCVER="8.0.1" STACKVER="7.14" STYLISH=YES
13 addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1,hscolour], sources: [hvr-ghc]}}
13 addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1,hscolour], sources: [hvr-ghc]}}
14− - os: osx
15− env: CABALVER="1.24" GHCVER="8.0.1" TESTS="test_c"
16− compiler: ": #GHC 8.0.1"
17− - env: CABALVER="1.20" GHCVER="7.6.3" TESTS="test_c"
18− compiler: ": #GHC 7.6.3"
19− addons: {apt: {packages: [cabal-install-1.20,ghc-7.6.3,cppcheck,hscolour], sources: [hvr-ghc]}}
20− - env: CABALVER="1.20" GHCVER="7.8.4" TESTS="test_c"
21− compiler: ": #GHC 7.8.4"
22− addons: {apt: {packages: [cabal-install-1.20,ghc-7.8.4,cppcheck,hscolour], sources: [hvr-ghc]}}
23 - env: CABALVER="1.22" GHCVER="7.10.3" TESTS="lib_doc doc"
14 - env: CABALVER="1.22" GHCVER="7.10.3" TESTS="lib_doc doc"
24 compiler: ": #GHC 7.10.3"
15 compiler: ": #GHC 7.10.3"
25 addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3,cppcheck,hscolour], sources: [hvr-ghc]}}
16 addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3,cppcheck,hscolour], sources: [hvr-ghc]}}
@@ -38,10 +29,6 @@ matrix:
38 - env: CABALVER="1.24" GHCVER="8.0.1" TESTS="test_c"
29 - env: CABALVER="1.24" GHCVER="8.0.1" TESTS="test_c"
39 compiler: ": #GHC 8.0.1"
30 compiler: ": #GHC 8.0.1"
40 addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1,cppcheck,hscolour], sources: [hvr-ghc]}}
31 addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1,cppcheck,hscolour], sources: [hvr-ghc]}}
41− allow_failures:
42− - os: osx
43− env: CABALVER="1.24" GHCVER="8.0.1" TESTS="test_c"
44− compiler: ": #GHC 8.0.1"
45 fast-finish: true
32 fast-finish: true
46
33
47cache:
34cache:
CHANGELOG.md+15−1
@@ -1,7 +1,21 @@
1−# New in 1.0.1
1+# New in 1.1.*
2+
3++ Addition of `Text.Literate`, a module for working with literate
4+ source files.
5+
6+# New in 1.1.1
7+
8++ Erasure analysis is now faster thanks to a bit smarter constraint solving.
9++ Fixed installation issue
10++ Fixed a potential segfault when concatenating strings
11+
12+# New in 1.1.0
2
13
3## Library Updates
14## Library Updates
4
15
16++ Added `Text.PrettyPrint.WL` an implementation of the Wadler-Leijen
17+ Pretty-Print algorithm. Useful for those wishing to pretty print
18+ things.
5+ Added `Text.Lexer` and `Text.Parser` to `contrib`. These are small libraries
19+ Added `Text.Lexer` and `Text.Parser` to `contrib`. These are small libraries
6 for implementing total lexical analysers and parsers.
20 for implementing total lexical analysers and parsers.
7+ New instances:
21+ New instances:
CONTRIBUTING.md+15
@@ -20,6 +20,21 @@ Here are a few guidelines that we would like contributors to follow so that we c
20Before you report an issue, or wish to add cool functionality please try and check to see if there are existing [issues](https://github.com/idris-lang/Idris-dev/issues) and [pull requests](https://github.com/idris-lang/Idris-dev/pulls).
20Before you report an issue, or wish to add cool functionality please try and check to see if there are existing [issues](https://github.com/idris-lang/Idris-dev/issues) and [pull requests](https://github.com/idris-lang/Idris-dev/pulls).
21We do not want you wasting your time, duplicating somebody's work!
21We do not want you wasting your time, duplicating somebody's work!
22
22
23+### Template
24+Try as closely as possible to describe the issue, ensuring that it has sections that match the following headings:
25+> \# Steps to Reproduce
26+>
27+> \# Expected Behavior
28+>
29+> \# Observed Behavior
30+>
31+>
32+
33+In addition, please attach complete source files that exhibit the issue to quoting from them in the issue.
34+
35+### Feature Requests
36+We would be delighted to receive feature requests only if they are feasible to implement and the author is willing to implement the suggested features themself. The current Idris developer team consists mostly of volunteers, and so it is unfortunately hard to accommodate implementing nice-to-have ideas that are not essential for core language development.
37+
23## The Campsite Rule
38## The Campsite Rule
24
39
25We try to follow the **campsite rule**: leave the code base in better condition than you found it.
40We try to follow the **campsite rule**: leave the code base in better condition than you found it.
CONTRIBUTORS+2
@@ -151,6 +151,7 @@ Michael Gilliland
151Michael Hensler
151Michael Hensler
152Michael Maloney
152Michael Maloney
153Michael McGirr
153Michael McGirr
154+Michael Morgan
154Michael Thompson
155Michael Thompson
155Michael Weiss
156Michael Weiss
156Miikka Koskinen
157Miikka Koskinen
@@ -200,6 +201,7 @@ Sven Koschnicke
200tdidriksen
201tdidriksen
201Tenor Biel
202Tenor Biel
202Thomas Cooper
203Thomas Cooper
204+Thomas Scholtes
203Tim Dysinger
205Tim Dysinger
204Tim McGilchrist
206Tim McGilchrist
205Timo Petteri Sinnemäki
207Timo Petteri Sinnemäki
Setup.hs+54−42
@@ -1,11 +1,15 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2
2
3+#if !defined(MIN_VERSION_Cabal)
4+# define MIN_VERSION_Cabal(x,y,z) 0
5+#endif
6+
3import Control.Monad
7import Control.Monad
4import Data.IORef
8import Data.IORef
5import Control.Exception (SomeException, catch)
9import Control.Exception (SomeException, catch)
6
10
7import Distribution.Simple
11import Distribution.Simple
8−import Distribution.Simple.BuildPaths (autogenModulesDir)
12+import Distribution.Simple.BuildPaths
9import Distribution.Simple.InstallDirs as I
13import Distribution.Simple.InstallDirs as I
10import Distribution.Simple.LocalBuildInfo as L
14import Distribution.Simple.LocalBuildInfo as L
11import qualified Distribution.Simple.Setup as S
15import qualified Distribution.Simple.Setup as S
@@ -22,6 +26,11 @@ import System.Directory
22import qualified System.FilePath.Posix as Px
26import qualified System.FilePath.Posix as Px
23import System.Process
27import System.Process
24
28
29+#if (MIN_VERSION_Cabal(2,0,0))
30+import Distribution.Types.UnqualComponentName
31+#endif
32+
33+
25-- After Idris is built, we need to check and install the prelude and other libs
34-- After Idris is built, we need to check and install the prelude and other libs
26
35
27-- -----------------------------------------------------------------------------
36-- -----------------------------------------------------------------------------
@@ -56,32 +65,37 @@ windres verbosity = P.runProgramInvocation verbosity . P.simpleProgramInvocation
56
65
57usesGMP :: S.ConfigFlags -> Bool
66usesGMP :: S.ConfigFlags -> Bool
58usesGMP flags =
67usesGMP flags =
59− case lookup (FlagName "gmp") (S.configConfigurationsFlags flags) of
68+ case lookup (mkFlagName "gmp") (S.configConfigurationsFlags flags) of
60 Just True -> True
69 Just True -> True
61 Just False -> False
70 Just False -> False
62 Nothing -> False
71 Nothing -> False
63
72
64execOnly :: S.ConfigFlags -> Bool
73execOnly :: S.ConfigFlags -> Bool
65execOnly flags =
74execOnly flags =
66− case lookup (FlagName "execonly") (S.configConfigurationsFlags flags) of
75+ case lookup (mkFlagName "execonly") (S.configConfigurationsFlags flags) of
67 Just True -> True
76 Just True -> True
68 Just False -> False
77 Just False -> False
69 Nothing -> False
78 Nothing -> False
70
79
71isRelease :: S.ConfigFlags -> Bool
80isRelease :: S.ConfigFlags -> Bool
72isRelease flags =
81isRelease flags =
73− case lookup (FlagName "release") (S.configConfigurationsFlags flags) of
82+ case lookup (mkFlagName "release") (S.configConfigurationsFlags flags) of
74 Just True -> True
83 Just True -> True
75 Just False -> False
84 Just False -> False
76 Nothing -> False
85 Nothing -> False
77
86
78isFreestanding :: S.ConfigFlags -> Bool
87isFreestanding :: S.ConfigFlags -> Bool
79isFreestanding flags =
88isFreestanding flags =
80− case lookup (FlagName "freestanding") (S.configConfigurationsFlags flags) of
89+ case lookup (mkFlagName "freestanding") (S.configConfigurationsFlags flags) of
81 Just True -> True
90 Just True -> True
82 Just False -> False
91 Just False -> False
83 Nothing -> False
92 Nothing -> False
84
93
94+#if !(MIN_VERSION_Cabal(2,0,0))
95+mkFlagName :: String -> FlagName
96+mkFlagName = FlagName
97+#endif
98+
85-- -----------------------------------------------------------------------------
99-- -----------------------------------------------------------------------------
86-- Clean
100-- Clean
87
101
@@ -151,20 +165,22 @@ generateToolchainModule verbosity srcDir toolDir = do
151 createDirectoryIfMissingVerbose verbosity True srcDir
165 createDirectoryIfMissingVerbose verbosity True srcDir
152 rewriteFile toolPath (commonContent ++ toolContent)
166 rewriteFile toolPath (commonContent ++ toolContent)
153
167
154−idrisConfigure _ flags _ local = do
168+idrisConfigure _ flags pkgdesc local = do
155 configureRTS
169 configureRTS
170+ withLibLBI pkgdesc local $ \_ libcfg -> do
171+ let libAutogenDir = autogenComponentModulesDir local libcfg
156− generateVersionModule verbosity (autogenModulesDir local) (isRelease (configFlags local))
172+ generateVersionModule verbosity libAutogenDir (isRelease (configFlags local))
157− if isFreestanding $ configFlags local
173+ if isFreestanding $ configFlags local
158− then do
174+ then do
159− toolDir <- lookupEnv "IDRIS_TOOLCHAIN_DIR"
175+ toolDir <- lookupEnv "IDRIS_TOOLCHAIN_DIR"
160− generateToolchainModule verbosity (autogenModulesDir local) toolDir
176+ generateToolchainModule verbosity libAutogenDir toolDir
161− targetDir <- lookupEnv "IDRIS_LIB_DIR"
177+ targetDir <- lookupEnv "IDRIS_LIB_DIR"
162− case targetDir of
178+ case targetDir of
163− Just d -> generateTargetModule verbosity (autogenModulesDir local) d
179+ Just d -> generateTargetModule verbosity libAutogenDir d
164− Nothing -> error $ "Trying to build freestanding without a target directory."
180+ Nothing -> error $ "Trying to build freestanding without a target directory."
165− ++ " Set it by defining IDRIS_LIB_DIR."
181+ ++ " Set it by defining IDRIS_LIB_DIR."
166− else
182+ else
167− generateToolchainModule verbosity (autogenModulesDir local) Nothing
183+ generateToolchainModule verbosity libAutogenDir Nothing
168 where
184 where
169 verbosity = S.fromFlag $ S.configVerbosity flags
185 verbosity = S.fromFlag $ S.configVerbosity flags
170 version = pkgVersion . package $ localPkgDescr local
186 version = pkgVersion . package $ localPkgDescr local
@@ -175,6 +191,10 @@ idrisConfigure _ flags _ local = do
175 -- the file after configure.
191 -- the file after configure.
176 configureRTS = make verbosity ["-C", "rts", "clean"]
192 configureRTS = make verbosity ["-C", "rts", "clean"]
177
193
194+#if !(MIN_VERSION_Cabal(2,0,0))
195+ autogenComponentModulesDir lbi _ = autogenModulesDir lbi
196+#endif
197+
178idrisPreSDist args flags = do
198idrisPreSDist args flags = do
179 let dir = S.fromFlag (S.sDistDirectory flags)
199 let dir = S.fromFlag (S.sDistDirectory flags)
180 let verb = S.fromFlag (S.sDistVerbosity flags)
200 let verb = S.fromFlag (S.sDistVerbosity flags)
@@ -213,11 +233,16 @@ getVersion args flags = do
213 let buildinfo = (emptyBuildInfo { cppOptions = ["-DVERSION="++hash] }) :: BuildInfo
233 let buildinfo = (emptyBuildInfo { cppOptions = ["-DVERSION="++hash] }) :: BuildInfo
214 return (Just buildinfo, [])
234 return (Just buildinfo, [])
215
235
236+
237+#if !(MIN_VERSION_Cabal(2,0,0))
238+mkUnqualComponentName = id
239+#endif
240+
216idrisPreBuild args flags = do
241idrisPreBuild args flags = do
217#ifdef mingw32_HOST_OS
242#ifdef mingw32_HOST_OS
218 createDirectoryIfMissingVerbose verbosity True dir
243 createDirectoryIfMissingVerbose verbosity True dir
219 windres verbosity ["icons/idris_icon.rc","-o", dir++"/idris_icon.o"]
244 windres verbosity ["icons/idris_icon.rc","-o", dir++"/idris_icon.o"]
220− return (Nothing, [("idris", emptyBuildInfo { ldOptions = [dir ++ "/idris_icon.o"] })])
245+ return (Nothing, [(mkUnqualComponentName "idris", emptyBuildInfo { ldOptions = [dir ++ "/idris_icon.o"] })])
221 where
246 where
222 verbosity = S.fromFlag $ S.buildVerbosity flags
247 verbosity = S.fromFlag $ S.buildVerbosity flags
223 dir = S.fromFlagOrDefault "dist" $ S.buildDistPref flags
248 dir = S.fromFlagOrDefault "dist" $ S.buildDistPref flags
@@ -225,9 +250,10 @@ idrisPreBuild args flags = do
225 return (Nothing, [])
250 return (Nothing, [])
226#endif
251#endif
227
252
228−idrisBuild _ flags _ local = unless (execOnly (configFlags local)) $ do
253+idrisBuild _ flags _ local
254+ = if (execOnly (configFlags local)) then buildRTS
229− buildStdLib
255+ else do buildStdLib
230− buildRTS
256+ buildRTS
231 where
257 where
232 verbosity = S.fromFlag $ S.buildVerbosity flags
258 verbosity = S.fromFlag $ S.buildVerbosity flags
233
259
@@ -246,10 +272,11 @@ idrisBuild _ flags _ local = unless (execOnly (configFlags local)) $ do
246-- -----------------------------------------------------------------------------
272-- -----------------------------------------------------------------------------
247-- Copy/Install
273-- Copy/Install
248
274
249−idrisInstall verbosity copy pkg local = unless (execOnly (configFlags local)) $ do
275+idrisInstall verbosity copy pkg local
276+ = if (execOnly (configFlags local)) then installRTS
250− installStdLib
277+ else do installStdLib
251− installRTS
278+ installRTS
252− installManPage
279+ installManPage
253 where
280 where
254 target = datadir $ L.absoluteInstallDirs pkg local copy
281 target = datadir $ L.absoluteInstallDirs pkg local copy
255
282
@@ -274,26 +301,15 @@ idrisInstall verbosity copy pkg local = unless (execOnly (configFlags local)) $
274-- -----------------------------------------------------------------------------
301-- -----------------------------------------------------------------------------
275-- Test
302-- Test
276
303
277−-- FIXME: We use the __GLASGOW_HASKELL__ macro because MIN_VERSION_cabal seems
278−-- to be broken !
279−
280-- There are two "dataDir" in cabal, and they don't relate to each other.
304-- There are two "dataDir" in cabal, and they don't relate to each other.
281-- When fetching modules, idris uses the second path (in the pkg record),
305-- When fetching modules, idris uses the second path (in the pkg record),
282-- which by default is the root folder of the project.
306-- which by default is the root folder of the project.
283-- We want it to be the install directory where we put the idris libraries.
307-- We want it to be the install directory where we put the idris libraries.
284fixPkg pkg target = pkg { dataDir = target }
308fixPkg pkg target = pkg { dataDir = target }
285
309
286−-- The "Args" argument of the testHooks has been added in cabal 1.22.0,
287−-- and should therefore be ignored for prior versions.
288−#if __GLASGOW_HASKELL__ < 710
289−originalTestHook _ = testHook simpleUserHooks
290−#else
291−originalTestHook = testHook simpleUserHooks
292−#endif
293−
294idrisTestHook args pkg local hooks flags = do
310idrisTestHook args pkg local hooks flags = do
295 let target = datadir $ L.absoluteInstallDirs pkg local NoCopyDest
311 let target = datadir $ L.absoluteInstallDirs pkg local NoCopyDest
296− originalTestHook args (fixPkg pkg target) local hooks flags
312+ testHook simpleUserHooks args (fixPkg pkg target) local hooks flags
297
313
298-- -----------------------------------------------------------------------------
314-- -----------------------------------------------------------------------------
299-- Main
315-- Main
@@ -314,9 +330,5 @@ main = defaultMainWithHooks $ simpleUserHooks
314 , preSDist = idrisPreSDist
330 , preSDist = idrisPreSDist
315 , sDistHook = idrisSDist (sDistHook simpleUserHooks)
331 , sDistHook = idrisSDist (sDistHook simpleUserHooks)
316 , postSDist = idrisPostSDist
332 , postSDist = idrisPostSDist
317−#if __GLASGOW_HASKELL__ < 710
318− , testHook = idrisTestHook ()
319−#else
320 , testHook = idrisTestHook
333 , testHook = idrisTestHook
321−#endif
322 }
334 }
appveyor.yml+5−4
@@ -6,9 +6,9 @@ init:
6 mkdir C:\ghc
6 mkdir C:\ghc
7
7
8 Invoke-WebRequest "http://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-unknown-mingw32.tar.xz" -OutFile C:\ghc\ghc.tar.xz -UserAgent "Curl"
8 Invoke-WebRequest "http://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-unknown-mingw32.tar.xz" -OutFile C:\ghc\ghc.tar.xz -UserAgent "Curl"
9−
9+
10 7z x C:\ghc\ghc.tar.xz -oC:\ghc
10 7z x C:\ghc\ghc.tar.xz -oC:\ghc
11−
11+
12 7z x C:\ghc\ghc.tar -oC:\ghc
12 7z x C:\ghc\ghc.tar -oC:\ghc
13
13
14 $env:PATH="$env:PATH;c:\ghc\ghc-7.10.3\bin;$HOME\AppData\Roaming\cabal\bin"
14 $env:PATH="$env:PATH;c:\ghc\ghc-7.10.3\bin;$HOME\AppData\Roaming\cabal\bin"
@@ -21,6 +21,7 @@ environment:
21 MSYSTEM: MINGW64
21 MSYSTEM: MINGW64
22 MSYS2_PATH_TYPE: inherit
22 MSYS2_PATH_TYPE: inherit
23build_script:
23build_script:
24+- ps: >-
24−- ps: c:\msys64\usr\bin\bash -l -c "cd $env:current_posix && cabal install -fffi -j4 --enable-tests"
25+ c:\msys64\usr\bin\bash -l -c "cd $env:current_posix && cabal install -fffi --enable-tests 2>&1"
25test_script:
26test_script:
26−- ps: c:\msys64\usr\bin\bash -l -c "cd $env:current_posix && make test_c"
27+- ps: c:\msys64\usr\bin\bash -l -c "cd $env:current_posix && make test_c 2>&1"
benchmarks/fasta/fasta.idr−4
@@ -38,10 +38,6 @@ replicate : Int -> Char -> String
38replicate 0 c = ""
38replicate 0 c = ""
39replicate n c = singleton c <+> replicate (n-1) c
39replicate n c = singleton c <+> replicate (n-1) c
40
40
41−scanl : (f : acc -> a -> acc) -> acc -> List a -> List acc
42−scanl f q ls = q :: (case ls of
43− [] => []
44− x::xs => scanl f (f q x) xs)
45
41
46accum : (Char,Double) -> (Char,Double) -> (Char,Double)
42accum : (Char,Double) -> (Char,Double) -> (Char,Double)
47accum (_,p) (c,q) = (c,p+q)
43accum (_,p) (c,q) = (c,p+q)
docs/reference/partial-evaluation.rst+10−10
@@ -4,15 +4,15 @@ Static Arguments and Partial Evaluation
4
4
5As of version 0.9.15, Idris has support for *partial evaluation* of
5As of version 0.9.15, Idris has support for *partial evaluation* of
6statically known arguments. This involves creating specialised versions
6statically known arguments. This involves creating specialised versions
7−of functions with arguments annotated as ``[static]``.
7+of functions with arguments annotated as ``%static``.
8
8
9(This is an implementation of the partial evaluator described in `this
9(This is an implementation of the partial evaluator described in `this
10ICFP 2010
10ICFP 2010
11paper <http://eb.host.cs.st-andrews.ac.uk/writings/icfp10.pdf>`__.
11paper <http://eb.host.cs.st-andrews.ac.uk/writings/icfp10.pdf>`__.
12Please refer to this for more precise definitions of what follows.)
12Please refer to this for more precise definitions of what follows.)
13
13
14−Partial evaluation is switched on by default. It can be disabled with
14+Partial evaluation is switched off by default since Idris 1.0. It can
15−the ``--no-partial-eval`` flag.
15+be enabled with the ``--partial-eval`` flag.
16
16
17Introductory Example
17Introductory Example
18--------------------
18--------------------
@@ -66,18 +66,18 @@ Automatic specialisation of ``pow``
66~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
66~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67
67
68The trick is to mark the statically known arguments with the
68The trick is to mark the statically known arguments with the
69−``[static]`` flag:
69+``%static`` flag:
70
70
71::
71::
72
72
73− my_pow : Nat -> [static] Nat -> Nat
73+ my_pow : Nat -> %static Nat -> Nat
74 my_pow k Z = 1
74 my_pow k Z = 1
75 my_pow k (S j) = mult k (my_pow k j)
75 my_pow k (S j) = mult k (my_pow k j)
76
76
77When an argument is annotated in this way, Idris will try to create a
77When an argument is annotated in this way, Idris will try to create a
78specialised version whenever it accounts a call with a concrete value
78specialised version whenever it accounts a call with a concrete value
79(i.e. a constant, constructor form, or globally defined function) in a
79(i.e. a constant, constructor form, or globally defined function) in a
80−``[static]`` position. If ``my_pow`` is defined this way, and ``powFn``
80+``%static`` position. If ``my_pow`` is defined this way, and ``powFn``
81defined as above, we can see the effect by typing ``:printdef powFn`` at
81defined as above, we can see the effect by typing ``:printdef powFn`` at
82the REPL:
82the REPL:
83
83
@@ -108,7 +108,7 @@ Specialising Type Classes
108-------------------------
108-------------------------
109
109
110Type class dictionaries are very often statically known, so Idris
110Type class dictionaries are very often statically known, so Idris
111−automatically marks any type class constraint as ``[static]`` and builds
111+automatically marks any type class constraint as ``%static`` and builds
112specialised versions of top level functions where the class is
112specialised versions of top level functions where the class is
113instantiated. For example, given:
113instantiated. For example, given:
114
114
@@ -177,7 +177,7 @@ writing ``map`` as follows:
177
177
178::
178::
179
179
180− my_map : [static] (a -> b) -> List a -> List b
180+ my_map : %static (a -> b) -> List a -> List b
181 my_map f [] = []
181 my_map f [] = []
182 my_map f (x :: xs) = f x :: my_map f xs
182 my_map f (x :: xs) = f x :: my_map f xs
183
183
@@ -246,11 +246,11 @@ Then, a function which calculates the factorial of its input:
246 (App (App eMult (App eFac (Op (-) x (Val 1)))) x))
246 (App (App eMult (App eFac (Op (-) x (Val 1)))) x))
247
247
248The interpreter's type is written as follows, marking the expression to
248The interpreter's type is written as follows, marking the expression to
249−be evaluated as ``[static]``:
249+be evaluated as ``%static``:
250
250
251::
251::
252
252
253− interp : (env : Env gamma) -> [static] (e : Expr gamma t) -> interpTy t
253+ interp : (env : Env gamma) -> %static (e : Expr gamma t) -> interpTy t
254
254
255This means that if we write an Idris program to calculate a factorial by
255This means that if we write an Idris program to calculate a factorial by
256calling ``interp`` on ``eFac``, the resulting definition will be
256calling ``interp`` on ``eFac``, the resulting definition will be
docs/reference/syntax-guide.rst+1−1
@@ -223,7 +223,7 @@ Every occurence of the the defined type in a constructor argument will be
223wrapped in the ``Inf`` type constructor. This has the effect of delaying the
223wrapped in the ``Inf`` type constructor. This has the effect of delaying the
224evaluation of the second argument when the data constructor is applied.
224evaluation of the second argument when the data constructor is applied.
225An ``Inf`` argument is constructed using ``Delay`` (which Idris will insert
225An ``Inf`` argument is constructed using ``Delay`` (which Idris will insert
226−implicitly) adn evaluated using ``Force`` (again inserted implicitly).
226+implicitly) and evaluated using ``Force`` (again inserted implicitly).
227
227
228Furthermore, recursive calls under a ``Delay`` must be guarded by a constructor
228Furthermore, recursive calls under a ``Delay`` must be guarded by a constructor
229to pass the totality checker.
229to pass the totality checker.
docs/st/composing.rst+1−1
@@ -437,7 +437,7 @@ using the SDL bindings as follows:
437
437
438.. code-block:: idris
438.. code-block:: idris
439
439
440− interface Draw IO where
440+ implementation Draw IO where
441 Surface = State SDLSurface
441 Surface = State SDLSurface
442
442
443 initWindow x y = do Just srf <- lift (startSDL x y)
443 initWindow x y = do Just srf <- lift (startSDL x y)
idris.cabal+29−49
@@ -1,5 +1,5 @@
1Name: idris
1Name: idris
2−Version: 1.0
2+Version: 1.1.1
3License: BSD3
3License: BSD3
4License-file: LICENSE
4License-file: LICENSE
5Author: Edwin Brady
5Author: Edwin Brady
@@ -40,11 +40,11 @@ Description: Idris is a general purpose language with full dependent types.
40 .
40 .
41 * Hugs style interactive environment
41 * Hugs style interactive environment
42
42
43−Cabal-Version: >= 1.8.1
43+Cabal-Version: >= 1.18
44
44
45Build-type: Custom
45Build-type: Custom
46
46
47−Tested-With: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1
47+Tested-With: GHC == 7.10.3, GHC == 8.0.1
48
48
49Data-files: idrisdoc/styles.css
49Data-files: idrisdoc/styles.css
50 jsrts/jsbn/jsbn-browser.js
50 jsrts/jsbn/jsbn-browser.js
@@ -97,6 +97,14 @@ source-repository head
97 type: git
97 type: git
98 location: git://github.com/idris-lang/Idris-dev.git
98 location: git://github.com/idris-lang/Idris-dev.git
99
99
100+custom-setup
101+ setup-depends:
102+ Cabal >= 1.10 && <2.1,
103+ base >= 4 && <5,
104+ directory,
105+ filepath,
106+ process
107+
100Flag FFI
108Flag FFI
101 Description: Build support for libffi
109 Description: Build support for libffi
102 Default: False
110 Default: False
@@ -259,17 +267,17 @@ Library
259 , Tools_idris
267 , Tools_idris
260
268
261 Build-depends: base >=4 && <5
269 Build-depends: base >=4 && <5
262− , aeson >= 0.6 && < 1.2
270+ , aeson >= 0.6 && < 1.3
263 , annotated-wl-pprint >= 0.7 && < 0.8
271 , annotated-wl-pprint >= 0.7 && < 0.8
264 , ansi-terminal < 0.7
272 , ansi-terminal < 0.7
265 , ansi-wl-pprint < 0.7
273 , ansi-wl-pprint < 0.7
266 , array >= 0.4.0.1 && < 0.6
274 , array >= 0.4.0.1 && < 0.6
267 , base64-bytestring < 1.1
275 , base64-bytestring < 1.1
268− , binary >= 0.7 && < 0.9
276+ , binary >= 0.8.4.1 && < 0.9
269 , blaze-html >= 0.6.1.3 && < 0.10
277 , blaze-html >= 0.6.1.3 && < 0.10
270 , blaze-markup >= 0.5.2.1 && < 0.9
278 , blaze-markup >= 0.5.2.1 && < 0.9
271 , bytestring < 0.11
279 , bytestring < 0.11
272− , cheapskate < 0.2
280+ , cheapskate >= 0.1.1 && < 0.2
273 , code-page >= 0.1 && < 0.2
281 , code-page >= 0.1 && < 0.2
274 , containers >= 0.5 && < 0.6
282 , containers >= 0.5 && < 0.6
275 , deepseq < 1.5
283 , deepseq < 1.5
@@ -277,20 +285,22 @@ Library
277 , filepath < 1.5
285 , filepath < 1.5
278 , fingertree >= 0.1 && < 0.2
286 , fingertree >= 0.1 && < 0.2
279 , haskeline >= 0.7 && < 0.8
287 , haskeline >= 0.7 && < 0.8
280− , ieee754 >= 0.7 && <= 0.8.0
288+ , ieee754 >= 0.7 && < 0.9
281 , mtl >= 2.1 && < 2.3
289 , mtl >= 2.1 && < 2.3
282 , network < 2.7
290 , network < 2.7
283− , optparse-applicative >= 0.11 && < 0.14
291+ , optparse-applicative >= 0.13 && < 0.15
284 , parsers >= 0.9 && < 0.13
292 , parsers >= 0.9 && < 0.13
285 , pretty < 1.2
293 , pretty < 1.2
294+ , process < 1.7
286 , regex-tdfa >= 1.2
295 , regex-tdfa >= 1.2
296+ , safe >= 0.3.9
287 , split < 0.3
297 , split < 0.3
288 , terminal-size < 0.4
298 , terminal-size < 0.4
289 , text >=1.2.1.0 && < 1.3
299 , text >=1.2.1.0 && < 1.3
290− , time >= 1.4 && < 1.7
300+ , time >= 1.4 && < 1.9
291 , transformers < 0.6
301 , transformers < 0.6
292 , transformers-compat >= 0.3
302 , transformers-compat >= 0.3
293− , trifecta >= 1.6 && < 1.7
303+ , trifecta >= 1.6 && < 1.8
294 , uniplate >=1.6 && < 1.7
304 , uniplate >=1.6 && < 1.7
295 , unordered-containers < 0.3
305 , unordered-containers < 0.3
296 , utf8-string < 1.1
306 , utf8-string < 1.1
@@ -300,47 +310,14 @@ Library
300 , fsnotify >= 0.2 && < 2.2
310 , fsnotify >= 0.2 && < 2.2
301 , async < 2.2
311 , async < 2.2
302
312
303−
313+ Default-Language: Haskell2010
304− -- zlib >= 0.6.1 is broken with GHC < 7.10.3
305− -- Travis is broken for 7.6 and 7.8 with a newer process
306− if impl(ghc < 7.10.3)
307− build-depends: zlib < 0.6.1
308− , process < 1.3
309− else
310− build-depends: process < 1.5
311−
312− -- safe 0.3.10 is having issues with cabal 1.20 and ghc 7.6.3, the
313− -- hvr ghc ppa doesn't provide a new enough cabal library. Temporary
314− -- fix until hvr ghc ppa is fixed or we deprecate support for 7.6.3.
315− if impl(ghc < 7.8.4)
316− build-depends: safe == 0.3.9
317− else
318− build-depends: safe >= 0.3.9
319−
320− if impl(ghc < 7.8.4)
321− build-depends: tagsoup < 0.14.1
322−
323− Extensions: MultiParamTypeClasses
324− , DeriveFoldable
325− , DeriveTraversable
326− , FunctionalDependencies
327− , FlexibleContexts
328− , FlexibleInstances
329− , TemplateHaskell
330−
331 ghc-prof-options: -auto-all -caf-all
314 ghc-prof-options: -auto-all -caf-all
332
315
333− if os(linux)
334− build-depends: unix < 2.8
335− if os(freebsd)
336− build-depends: unix < 2.8
337− if os(dragonfly)
338− build-depends: unix < 2.8
339− if os(darwin)
340− build-depends: unix < 2.8
341 if os(windows)
316 if os(windows)
342 build-depends: mintty >= 0.1 && < 0.2
317 build-depends: mintty >= 0.1 && < 0.2
343 , Win32 < 2.4
318 , Win32 < 2.4
319+ else
320+ build-depends: unix < 2.8
344 if flag(FFI)
321 if flag(FFI)
345 build-depends: libffi < 0.2
322 build-depends: libffi < 0.2
346 cpp-options: -DIDRIS_FFI
323 cpp-options: -DIDRIS_FFI
@@ -365,6 +342,7 @@ Executable idris
365 , haskeline >= 0.7
342 , haskeline >= 0.7
366 , transformers
343 , transformers
367
344
345+ Default-Language: Haskell2010
368 ghc-prof-options: -auto-all -caf-all
346 ghc-prof-options: -auto-all -caf-all
369 ghc-options: -threaded -rtsopts -funbox-strict-fields -with-rtsopts=-I0
347 ghc-options: -threaded -rtsopts -funbox-strict-fields -with-rtsopts=-I0
370
348
@@ -382,17 +360,16 @@ Test-suite regression-and-feature-tests
382 , filepath
360 , filepath
383 , directory
361 , directory
384 , haskeline >= 0.7
362 , haskeline >= 0.7
385− , optparse-applicative >= 0.11 && < 0.14
363+ , optparse-applicative >= 0.13 && < 0.15
386 , tagged
364 , tagged
387 , tasty >= 0.8
365 , tasty >= 0.8
388 , tasty-golden >= 2.0
366 , tasty-golden >= 2.0
389 , tasty-rerun >= 1.0.0
367 , tasty-rerun >= 1.0.0
390 , bytestring
368 , bytestring
391 , transformers
369 , transformers
392− if impl(ghc < 7.10)
393− Extensions: DeriveDataTypeable
394
370
395
371
372+ Default-Language: Haskell2010
396 ghc-prof-options: -auto-all -caf-all
373 ghc-prof-options: -auto-all -caf-all
397 ghc-options: -threaded -rtsopts -with-rtsopts=-N -funbox-strict-fields
374 ghc-options: -threaded -rtsopts -with-rtsopts=-N -funbox-strict-fields
398
375
@@ -406,6 +383,7 @@ Executable idris-codegen-c
406 , haskeline >= 0.7
383 , haskeline >= 0.7
407 , transformers
384 , transformers
408
385
386+ Default-Language: Haskell2010
409 ghc-prof-options: -auto-all -caf-all
387 ghc-prof-options: -auto-all -caf-all
410 ghc-options: -threaded -rtsopts -funbox-strict-fields
388 ghc-options: -threaded -rtsopts -funbox-strict-fields
411
389
@@ -419,6 +397,7 @@ Executable idris-codegen-javascript
419 , haskeline >= 0.7
397 , haskeline >= 0.7
420 , transformers
398 , transformers
421
399
400+ Default-Language: Haskell2010
422 ghc-prof-options: -auto-all -caf-all
401 ghc-prof-options: -auto-all -caf-all
423 ghc-options: -threaded -rtsopts -funbox-strict-fields
402 ghc-options: -threaded -rtsopts -funbox-strict-fields
424
403
@@ -432,5 +411,6 @@ Executable idris-codegen-node
432 , haskeline >= 0.7
411 , haskeline >= 0.7
433 , transformers
412 , transformers
434
413
414+ Default-Language: Haskell2010
435 ghc-prof-options: -auto-all -caf-all
415 ghc-prof-options: -auto-all -caf-all
436 ghc-options: -threaded -rtsopts -funbox-strict-fields
416 ghc-options: -threaded -rtsopts -funbox-strict-fields
jsrts/Runtime-node.js+1−1
@@ -22,7 +22,7 @@ $JSRTS.prim_readStr = function () {
22 }
22 }
23 i++;
23 i++;
24 if (i == b.length) {
24 if (i == b.length) {
25− nb = new Buffer(b.length * 2);
25+ var nb = new Buffer(b.length * 2);
26 b.copy(nb)
26 b.copy(nb)
27 b = nb;
27 b = nb;
28 }
28 }
libs/base/System.idr+1
@@ -97,5 +97,6 @@ time = do MkRaw t <- foreign FFI_C "idris_time" (IO (Raw Integer))
97usleep : (i : Int) -> { auto prf : So (i >= 0 && i <= 1000000) } -> IO ()
97usleep : (i : Int) -> { auto prf : So (i >= 0 && i <= 1000000) } -> IO ()
98usleep i = foreign FFI_C "usleep" (Int -> IO ()) i
98usleep i = foreign FFI_C "usleep" (Int -> IO ()) i
99
99
100+||| Execute a program and returns its exit status code.
100system : String -> IO Int
101system : String -> IO Int
101system cmd = foreign FFI_C "system" (String -> IO Int) cmd
102system cmd = foreign FFI_C "system" (String -> IO Int) cmd
libs/contrib/CFFI/Types.idr+5−5
@@ -29,11 +29,11 @@ Show CType where
29 show PTR = "PTR"
29 show PTR = "PTR"
30
30
31Show Composite where
31Show Composite where
32− show (T ct) = show ct
32+ showPrec d (T ct) = showPrec d ct
33− show (ARRAY n t) = "ARRAY " ++ show n ++ " " ++ show t
33+ showPrec d (ARRAY n t) = showCon d "ARRAY" $ showArg n ++ showArg t
34− show (STRUCT xs) = "STRUCT " ++ show xs
34+ showPrec d (STRUCT xs) = showCon d "STRUCT" $ showArg xs
35− show (UNION xs) = "UNION " ++ show xs
35+ showPrec d (UNION xs) = showCon d "UNION" $ showArg xs
36− show (PACKEDSTRUCT xs) = "PACKEDSTRUCT " ++ show xs
36+ showPrec d (PACKEDSTRUCT xs) = showCon d "PACKEDSTRUCT" $ showArg xs
37
37
38||| What Idris type the C type is marshalled to
38||| What Idris type the C type is marshalled to
39translate : CType -> Type
39translate : CType -> Type
libs/contrib/Data/Pairs/Implicit.idrnew file+13
@@ -0,0 +1,13 @@
1+||| Implicit conversions for erased dependent pairs.
2+module Data.Pairs.Implicit
3+
4+%access public export
5+%default total
6+
7+||| Convert an Evidence to its proof.
8+implicit evidence : (x : Exists p) -> p (getWitness x)
9+evidence = getProof
10+
11+||| Convert an Element to its value (a.k.a. witness).
12+implicit element : Subset a p -> a
13+element = getWitness
libs/contrib/Data/Stream/Extra.idrnew file+10
@@ -0,0 +1,10 @@
1+module Data.Stream.Extra
2+
3+%access public export
4+%default total
5+
6+||| Insert elements from a Foldable at the start of an existing Stream
7+||| @ pfx the Foldable containing elements to prepend
8+||| @ stream the Stream to prepend the elements to
9+startWith : Foldable t => (pfx : t a) -> (stream : Stream a) -> Stream a
10+startWith pfx stream = foldr (\x, xs => x :: xs) stream pfx
libs/contrib/Data/ZZ.idr+2−2
@@ -24,8 +24,8 @@ absZ (Pos n) = n
24absZ (NegS n) = S n
24absZ (NegS n) = S n
25
25
26implementation Show ZZ where
26implementation Show ZZ where
27− show (Pos n) = show n
27+ showPrec d (Pos n) = showPrec d n
28− show (NegS n) = "-" ++ show (S n)
28+ showPrec d (NegS n) = showParens (d >= PrefixMinus) $ "-" ++ showPrec PrefixMinus (S n)
29
29
30negNat : Nat -> ZZ
30negNat : Nat -> ZZ
31negNat Z = Pos Z
31negNat Z = Pos Z
libs/contrib/Interfaces/Correlative.idrnew file+55
@@ -0,0 +1,55 @@
1+module Interfaces.Correlative
2+
3+import Data.Vect
4+
5+%access public export
6+%default total
7+
8+infixl 2 </>
9+
10+||| A Correlative functor is a functor where, given `(xs, ys : Correlative f)`,
11+||| certain elements from xs and ys can be paired with one another due to some
12+||| intrinsic property of `f`. Elements that cannot be paired are discarded.
13+interface Functor f => Correlative (f : Type -> Type) where
14+ (</>) : f (a -> b) -> f a -> f b
15+
16+||| Combine two containers elementwise using some function.
17+zipWith : Correlative f => (a -> b -> c) -> f a -> f b -> f c
18+zipWith f xs ys = (map f xs) </> ys
19+
20+||| Combine three containers elementwise using some function.
21+zipWith3 : Correlative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
22+zipWith3 f xs ys zs = (map f xs) </> ys </> zs
23+
24+||| Combine two containers elementwise into a container of pairs.
25+zip : Correlative f => f a -> f b -> f (a, b)
26+zip = zipWith (\x, y => (x, y))
27+
28+||| Combine three containers elementwise into a container of tuples.
29+zip3 : Correlative f => f a -> f b -> f c -> f (a, b, c)
30+zip3 = zipWith3 (\x, y, z => (x, y, z))
31+
32+||| Convert a container of pairs into a pair of containers.
33+unzip : Functor t => t (a, b) -> (t a, t b)
34+unzip xs = (map fst xs, map snd xs)
35+
36+||| Convert a container of tuples into a tuple of containers.
37+unzip3 : Functor t => t (a, b, c) -> (t a, t b, t c)
38+unzip3 xs = (map fst xs, unzip (map snd xs))
39+
40+Correlative Maybe where
41+ (</>) = (<*>)
42+
43+Correlative (Either a) where
44+ (</>) = (<*>)
45+
46+Correlative List where
47+ (</>) [] _ = []
48+ (</>) _ [] = []
49+ (</>) (f :: fs) (x :: xs) = f x :: (fs </> xs)
50+
51+Correlative Stream where
52+ (</>) = (<*>)
53+
54+Correlative (Vect n) where
55+ (</>) = (<*>)
libs/contrib/Network/Socket.idr+1−5
@@ -8,10 +8,6 @@ import public Network.Socket.Data
8import Network.Socket.Raw
8import Network.Socket.Raw
9
9
10%include C "idris_net.h"
10%include C "idris_net.h"
11−%include C "sys/types.h"
12−%include C "sys/socket.h"
13−%include C "unistd.h"
14−%include C "netdb.h"
15
11
16%access export
12%access export
17
13
@@ -24,7 +20,7 @@ socket : (fam : SocketFamily)
24 -> (pnum : ProtocolNumber)
20 -> (pnum : ProtocolNumber)
25 -> IO (Either SocketError Socket)
21 -> IO (Either SocketError Socket)
26socket sf st pn = do
22socket sf st pn = do
27− socket_res <- foreign FFI_C "socket"
23+ socket_res <- foreign FFI_C "idrnet_socket"
28 (Int -> Int -> Int -> IO Int)
24 (Int -> Int -> Int -> IO Int)
29 (toCode sf) (toCode st) pn
25 (toCode sf) (toCode st) pn
30
26
libs/contrib/Network/Socket/Raw.idr−3
@@ -8,9 +8,6 @@ module Network.Socket.Raw
8import public Network.Socket.Data
8import public Network.Socket.Data
9
9
10%include C "idris_net.h"
10%include C "idris_net.h"
11−%include C "sys/types.h"
12−%include C "sys/socket.h"
13−%include C "netdb.h"
14
11
15%access public export
12%access public export
16
13
libs/contrib/Text/Lexer.idr+161−32
@@ -3,12 +3,13 @@ module Text.Lexer
3%default total
3%default total
4
4
5||| A language of token recognisers.
5||| A language of token recognisers.
6−||| The `consumes` flag is True is the recogniser is guaranteed to consume
6+||| @ consumes If `True`, this recogniser is guaranteed to consume at
7−||| at least one character
7+||| least one character of input when it succeeds.
8export
8export
9data Recognise : (consumes : Bool) -> Type where
9data Recognise : (consumes : Bool) -> Type where
10 Empty : Recognise False
10 Empty : Recognise False
11 Fail : Recognise c
11 Fail : Recognise c
12+ Expect : Recognise c -> Recognise False
12 Pred : (Char -> Bool) -> Recognise True
13 Pred : (Char -> Bool) -> Recognise True
13 SeqEat : Recognise True -> Inf (Recognise e) -> Recognise True
14 SeqEat : Recognise True -> Inf (Recognise e) -> Recognise True
14 SeqEmpty : Recognise e1 -> Recognise e2 -> Recognise (e1 || e2)
15 SeqEmpty : Recognise e1 -> Recognise e2 -> Recognise (e1 || e2)
@@ -23,11 +24,11 @@ public export
23inf : Bool -> Type -> Type
24inf : Bool -> Type -> Type
24inf True t = Inf t
25inf True t = Inf t
25inf False t = t
26inf False t = t
26−
27+
27||| Sequence two recognisers. If either consumes a character, the sequence
28||| Sequence two recognisers. If either consumes a character, the sequence
28||| is guaranteed to consume a character.
29||| is guaranteed to consume a character.
29export %inline
30export %inline
30−(<+>) : {c1 : Bool} ->
31+(<+>) : {c1 : Bool} ->
31 Recognise c1 -> inf c1 (Recognise c2) -> Recognise (c1 || c2)
32 Recognise c1 -> inf c1 (Recognise c2) -> Recognise (c1 || c2)
32(<+>) {c1 = False} = SeqEmpty
33(<+>) {c1 = False} = SeqEmpty
33(<+>) {c1 = True} = SeqEat
34(<+>) {c1 = True} = SeqEat
@@ -38,6 +39,22 @@ export
38(<|>) : Recognise c1 -> Recognise c2 -> Recognise (c1 && c2)
39(<|>) : Recognise c1 -> Recognise c2 -> Recognise (c1 && c2)
39(<|>) = Alt
40(<|>) = Alt
40
41
42+||| Positive lookahead. Never consumes input.
43+export
44+expect : Recognise c -> Recognise False
45+expect = Expect
46+
47+||| Negative lookahead. Never consumes input.
48+export
49+reject : Recognise c -> Recognise False
50+reject Empty = Fail
51+reject Fail = Empty
52+reject (Expect x) = reject x
53+reject (Pred f) = Expect (Pred (not . f))
54+reject (SeqEat r1 r2) = reject r1 <|> Expect (SeqEat r1 (reject r2))
55+reject (SeqEmpty r1 r2) = reject r1 <|> Expect (SeqEmpty r1 (reject r2))
56+reject (Alt r1 r2) = reject r1 <+> reject r2
57+
41||| Recognise a specific character
58||| Recognise a specific character
42export
59export
43is : Char -> Lexer
60is : Char -> Lexer
@@ -48,22 +65,46 @@ export
48isNot : Char -> Lexer
65isNot : Char -> Lexer
49isNot x = Pred (/=x)
66isNot x = Pred (/=x)
50
67
68+||| Recognise a lexer or recognise no input. This is not guaranteed
69+||| to consume input
70+export
71+opt : Lexer -> Recognise False
72+opt l = l <|> Empty
73+
51||| Recognise a sequence of at least one sub-lexers
74||| Recognise a sequence of at least one sub-lexers
52export
75export
53some : Lexer -> Lexer
76some : Lexer -> Lexer
54−some l = l <+> (some l <|> Empty)
77+some l = l <+> opt (some l)
55
78
56||| Recognise a sequence of at zero or more sub-lexers. This is not
79||| Recognise a sequence of at zero or more sub-lexers. This is not
57||| guaranteed to consume input
80||| guaranteed to consume input
58export
81export
59many : Lexer -> Recognise False
82many : Lexer -> Recognise False
60−many l = some l <|> Empty
83+many l = opt (some l)
84+
85+||| Recognise the first matching lexer from a non-empty list.
86+export
87+choice : (xs : List Lexer) -> {auto ok : NonEmpty xs} -> Lexer
88+choice (x :: []) = x
89+choice (x :: xs@(_ :: _)) = x <|> choice xs
90+
91+||| Recognise many instances of `l` until an instance of `end` is
92+||| encountered.
93+|||
94+||| Useful for defining comments.
95+export
96+manyTill : (l : Lexer) -> (end : Lexer) -> Recognise False
97+manyTill l end = end <|> opt (l <+> manyTill l end)
61
98
62||| Recognise any character
99||| Recognise any character
63export
100export
64any : Lexer
101any : Lexer
65any = Pred (const True)
102any = Pred (const True)
66
103
104+||| Recognise any character if the sub-lexer `l` fails.
105+non : (l : Lexer) -> Lexer
106+non l = reject l <+> any
107+
67||| Recognise no input (doesn't consume any input)
108||| Recognise no input (doesn't consume any input)
68export
109export
69empty : Recognise False
110empty : Recognise False
@@ -86,7 +127,7 @@ getString : StrLen -> String
86getString (MkStrLen str n) = str
127getString (MkStrLen str n) = str
87
128
88strIndex : StrLen -> Nat -> Maybe Char
129strIndex : StrLen -> Nat -> Maybe Char
89−strIndex (MkStrLen str len) i
130+strIndex (MkStrLen str len) i
90 = if i >= len then Nothing
131 = if i >= len then Nothing
91 else Just (assert_total (prim__strIndex str (cast i)))
132 else Just (assert_total (prim__strIndex str (cast i)))
92
133
@@ -102,70 +143,159 @@ strTail start (MkStrLen str len)
102scan : Recognise c -> Nat -> StrLen -> Maybe Nat
143scan : Recognise c -> Nat -> StrLen -> Maybe Nat
103scan Empty idx str = pure idx
144scan Empty idx str = pure idx
104scan Fail idx str = Nothing
145scan Fail idx str = Nothing
146+scan (Expect r) idx str
147+ = case scan r idx str of
148+ Just _ => pure idx
149+ Nothing => Nothing
105−scan (Pred f) idx str
150+scan (Pred f) idx str
106 = do c <- strIndex str idx
151 = do c <- strIndex str idx
107 if f c
152 if f c
108 then Just (idx + 1)
153 then Just (idx + 1)
109 else Nothing
154 else Nothing
110−scan (SeqEat r1 r2) idx str
155+scan (SeqEat r1 r2) idx str
111 = do idx' <- scan r1 idx str
156 = do idx' <- scan r1 idx str
112 -- TODO: Can we prove totality instead by showing idx has increased?
157 -- TODO: Can we prove totality instead by showing idx has increased?
113 assert_total (scan r2 idx' str)
158 assert_total (scan r2 idx' str)
114−scan (SeqEmpty r1 r2) idx str
159+scan (SeqEmpty r1 r2) idx str
115 = do idx' <- scan r1 idx str
160 = do idx' <- scan r1 idx str
116 scan r2 idx' str
161 scan r2 idx' str
117−scan (Alt r1 r2) idx str
162+scan (Alt r1 r2) idx str
118 = case scan r1 idx str of
163 = case scan r1 idx str of
119 Nothing => scan r2 idx str
164 Nothing => scan r2 idx str
120 Just idx => Just idx
165 Just idx => Just idx
121
166
122takeToken : Lexer -> StrLen -> Maybe (String, StrLen)
167takeToken : Lexer -> StrLen -> Maybe (String, StrLen)
123−takeToken lex str
168+takeToken lex str
124 = do i <- scan lex 0 str -- i must be > 0 if successful
169 = do i <- scan lex 0 str -- i must be > 0 if successful
125 pure (substr 0 i (getString str), strTail i str)
170 pure (substr 0 i (getString str), strTail i str)
126
171
127−||| Recognise a digit 0-9
172+||| Recognise a single digit 0-9
173+export
174+digit : Lexer
175+digit = pred isDigit
176+
177+||| Recognise one or more digits
128export
178export
129digits : Lexer
179digits : Lexer
130−digits = some (Pred isDigit)
180+digits = some digit
131
181
132||| Recognise a specific string
182||| Recognise a specific string
133export
183export
134exact : String -> Lexer
184exact : String -> Lexer
135exact str with (unpack str)
185exact str with (unpack str)
136 exact str | [] = Fail -- Not allowed, Lexer has to consume
186 exact str | [] = Fail -- Not allowed, Lexer has to consume
137− exact str | (x :: xs)
187+ exact str | (x :: xs)
138 = foldl SeqEmpty (is x) (map is xs)
188 = foldl SeqEmpty (is x) (map is xs)
139
189
190+||| Recognise a single hexidecimal digit
191+export
192+hexDigit : Lexer
193+hexDigit = digit <|> oneOf "abcdefABCDEF"
194+
195+||| Recognise one or more hexidecimal digits
196+export
197+hexDigits : Lexer
198+hexDigits = some hexDigit
199+
200+||| Recognise a single alpha character
201+export
202+alpha : Lexer
203+alpha = pred isAlpha
204+
205+||| Recognise one or more alpha characters
206+export
207+alphas : Lexer
208+alphas = some alpha
209+
210+||| Recognise a lowercase alpha character
211+export
212+lower : Lexer
213+lower = pred isLower
214+
215+||| Recognise one or more lowercase alpha characters
216+export
217+lowers : Lexer
218+lowers = some lower
219+
220+||| Recognise an uppercase alpha character
221+export
222+upper : Lexer
223+upper = pred isUpper
224+
225+||| Recognise one or more uppercase alpha characters
226+export
227+uppers : Lexer
228+uppers = some upper
229+
230+||| Recognise an alphanumeric character
231+export
232+alphaNum : Lexer
233+alphaNum = pred isAlphaNum
234+
235+||| Recognise one or more alphanumeric characters
236+export
237+alphaNums : Lexer
238+alphaNums = some alphaNum
239+
140−||| Recognise a whitespace character
240+||| Recognise a single whitespace character
141export
241export
142space : Lexer
242space : Lexer
143−space = some (pred isSpace)
243+space = pred isSpace
244+
245+||| Recognise one or more whitespace characters
246+export
247+spaces : Lexer
248+spaces = some space
144
249
145−||| Recognise a non-alphanumeric, non-whitespace character
250+||| Recognise a single non-whitespace, non-alphanumeric character
146export
251export
147symbol : Lexer
252symbol : Lexer
148−symbol = some (pred (\x => not (isAlphaNum x) && not (isSpace x)))
253+symbol = pred (\x => not (isSpace x || isAlphaNum x))
254+
255+||| Recognise one or more non-whitespace, non-alphanumeric characters
256+export
257+symbols : Lexer
258+symbols = some symbol
149
259
150−strChar : Lexer
260+||| Recognise zero or more occurrences of a sub-lexer between
151−strChar = (is '\\' <+> any) <|> isNot '"'
261+||| delimiting lexers
262+export
263+surround : (start : Lexer) -> (end : Lexer) -> (l : Lexer) -> Lexer
264+surround start end l = start <+> manyTill l end
265+
266+||| Recognise zero or more occurrences of a sub-lexer surrounded
267+||| by the same quote lexer on both sides (useful for strings)
268+export
269+quote : (q : Lexer) -> (l : Lexer) -> Lexer
270+quote q l = surround q q l
271+
272+||| Recognise an escape character (often '\\') followed by a sub-lexer
273+export
274+escape : (esc : Char) -> Lexer -> Lexer
275+escape esc l = is esc <+> l
152
276
153||| Recognise a string literal, including escaped characters.
277||| Recognise a string literal, including escaped characters.
154||| (Note: doesn't yet handle escape sequences such as \123)
278||| (Note: doesn't yet handle escape sequences such as \123)
155export
279export
156stringLit : Lexer
280stringLit : Lexer
157−stringLit = is '"' <+> many strChar <+> is '"'
281+stringLit = quote (is '"') (escape '\\' any <|> any)
158
282
159||| Recognise a character literal, including escaped characters.
283||| Recognise a character literal, including escaped characters.
160||| (Note: doesn't yet handle escape sequences such as \123)
284||| (Note: doesn't yet handle escape sequences such as \123)
161export
285export
162charLit : Lexer
286charLit : Lexer
163−charLit = is '\'' <+> strChar <+> is '\''
287+charLit = let q = '\'' in
288+ is q <+> (escape '\\' any <|> isNot q) <+> is q
164
289
165||| Recognise an integer literal (possibly with a '-' prefix)
290||| Recognise an integer literal (possibly with a '-' prefix)
166export
291export
167intLit : Lexer
292intLit : Lexer
168−intLit = (is '-' <|> Empty) <+> digits
293+intLit = opt (is '-') <+> digits
294+
295+||| Recognise a hexidecimal literal, prefixed by "0x" or "0X"
296+export
297+hexLit : Lexer
298+hexLit = is '0' <+> oneOf "xX" <+> hexDigits
169
299
170||| A mapping from lexers to the tokens they produce.
300||| A mapping from lexers to the tokens they produce.
171||| This is a list of pairs `(Lexer, String -> tokenType)`
301||| This is a list of pairs `(Lexer, String -> tokenType)`
@@ -185,8 +315,8 @@ record TokenData a where
185
315
186fspanEnd : Nat -> (Char -> Bool) -> String -> (Nat, String)
316fspanEnd : Nat -> (Char -> Bool) -> String -> (Nat, String)
187fspanEnd k p "" = (k, "")
317fspanEnd k p "" = (k, "")
188−fspanEnd k p xxs
318+fspanEnd k p xxs
189− = assert_total $
319+ = assert_total $
190 let x = prim__strHead xxs
320 let x = prim__strHead xxs
191 xs = prim__strTail xxs in
321 xs = prim__strTail xxs in
192 if p x then fspanEnd (S k) p xs
322 if p x then fspanEnd (S k) p xs
@@ -195,14 +325,14 @@ fspanEnd k p xxs
195-- Faster version of 'span' from the prelude (avoids unpacking)
325-- Faster version of 'span' from the prelude (avoids unpacking)
196export
326export
197fspan : (Char -> Bool) -> String -> (String, String)
327fspan : (Char -> Bool) -> String -> (String, String)
198−fspan p xs
328+fspan p xs
199 = let (end, rest) = fspanEnd 0 p xs in
329 = let (end, rest) = fspanEnd 0 p xs in
200 (substr 0 end xs, rest)
330 (substr 0 end xs, rest)
201
331
202tokenise : (line : Int) -> (col : Int) ->
332tokenise : (line : Int) -> (col : Int) ->
203− List (TokenData a) -> TokenMap a ->
333+ List (TokenData a) -> TokenMap a ->
204 StrLen -> (List (TokenData a), (Int, Int, StrLen))
334 StrLen -> (List (TokenData a), (Int, Int, StrLen))
205−tokenise line col acc tmap str
335+tokenise line col acc tmap str
206 = case getFirstToken tmap str of
336 = case getFirstToken tmap str of
207 Just (tok, line', col', rest) =>
337 Just (tok, line', col', rest) =>
208 -- assert total because getFirstToken must consume something
338 -- assert total because getFirstToken must consume something
@@ -213,7 +343,7 @@ tokenise line col acc tmap str
213 countNLs str = List.length (filter (== '\n') str)
343 countNLs str = List.length (filter (== '\n') str)
214
344
215 getCols : String -> Int -> Int
345 getCols : String -> Int -> Int
216− getCols x c
346+ getCols x c
217 = case fspan (/= '\n') (reverse x) of
347 = case fspan (/= '\n') (reverse x) of
218 (incol, "") => c + cast (length incol)
348 (incol, "") => c + cast (length incol)
219 (incol, _) => cast (length incol)
349 (incol, _) => cast (length incol)
@@ -223,7 +353,7 @@ tokenise line col acc tmap str
223 getFirstToken ((lex, fn) :: ts) str
353 getFirstToken ((lex, fn) :: ts) str
224 = case takeToken lex str of
354 = case takeToken lex str of
225 Just (tok, rest) => Just (MkToken line col (fn tok),
355 Just (tok, rest) => Just (MkToken line col (fn tok),
226− line + cast (countNLs (unpack tok)),
356+ line + cast (countNLs (unpack tok)),
227 getCols tok col, rest)
357 getCols tok col, rest)
228 Nothing => getFirstToken ts str
358 Nothing => getFirstToken ts str
229
359
@@ -235,4 +365,3 @@ export
235lex : TokenMap a -> String -> (List (TokenData a), (Int, Int, String))
365lex : TokenMap a -> String -> (List (TokenData a), (Int, Int, String))
236lex tmap str = let (ts, (l, c, str')) = tokenise 0 0 [] tmap (mkStr str) in
366lex tmap str = let (ts, (l, c, str')) = tokenise 0 0 [] tmap (mkStr str) in
237 (ts, (l, c, getString str'))
367 (ts, (l, c, getString str'))
238−
libs/contrib/Text/Literate.idrnew file+155
@@ -0,0 +1,155 @@
1+||| A simple module to process 'literate' documents.
2+|||
3+||| The module uses a lexer to split the document into code blocks,
4+||| delineated by user-defined markers, and code lines that are
5+||| indicated be a line marker. The lexer returns a document stripped
6+||| of non-code elements but preserving the original document's line
7+||| count. Column numbering of code lines are not preserved.
8+|||
9+||| The underlying tokeniser is greedy.
10+|||
11+||| Once it identifies a line marker it reads a prettifying space then
12+||| consumes until the end of line. Once identifies a starting code
13+||| block marker, the lexer will consume input until the next
14+||| identifiable end block is encountered. Any other content is
15+||| treated as part of the original document.
16+|||
17+||| Thus, the input literate files *must* be well-formed w.r.t
18+||| to code line markers and code blocks.
19+|||
20+||| A further restriction is that literate documents cannot contain
21+||| the markers within the document's main text: This will confuse the
22+||| lexer.
23+|||
24+module Text.Literate
25+
26+import Text.Lexer
27+
28+import Data.List.Views
29+
30+%default total
31+
32+untilEOL : Recognise False
33+untilEOL = manyTill any (is '\n')
34+
35+line : String -> Lexer
36+line s = exact s <+> space <+> untilEOL
37+
38+block : String -> String -> Lexer
39+block s e = exact s <+> manyTill any (exact e)
40+
41+data Token = CodeBlock String String String
42+ | Any String
43+ | CodeLine String String
44+
45+Show Token where
46+ showPrec d (CodeBlock l r x) = showCon d "CodeBlock" $ showArg l ++ showArg r ++ showArg x
47+ showPrec d (Any x) = showCon d "Any" $ showArg x
48+ showPrec d (CodeLine m x) = showCon d "CodeLine" $ showArg m ++ showArg x
49+
50+rawTokens : (delims : List (String, String))
51+ -> (markers : List String)
52+ -> TokenMap (Token)
53+rawTokens delims ls =
54+ map (\(l,r) => (block l r, CodeBlock l r)) delims
55+ ++ map (\m => (line m, CodeLine m)) ls
56+ ++ [(any, Any)]
57+
58+||| Merge the tokens into a single source file.
59+reduce : List (TokenData Token) -> String -> String
60+reduce [] acc = acc
61+reduce (MkToken _ _ (Any x) :: rest) acc = reduce rest (acc ++ blank_content)
62+ where
63+ -- Preserve the original document's line count.
64+ blank_content : String
65+ blank_content = if elem '\n' (unpack x)
66+ then concat $ replicate (length (lines x)) "\n"
67+ else ""
68+reduce (MkToken _ _ (CodeLine m src) :: rest) acc =
69+ reduce rest (acc ++ (substr
70+ (length m + 1) -- remove space to right of marker.
71+ (length src)
72+ src))
73+
74+reduce (MkToken _ _ (CodeBlock l r src) :: rest) acc with (lines src) -- Strip the deliminators surrounding the block.
75+ reduce (MkToken _ _ (CodeBlock l r src) :: rest) acc | [] = reduce rest acc -- 1
76+ reduce (MkToken _ _ (CodeBlock l r src) :: rest) acc | (s :: ys) with (snocList ys)
77+ reduce (MkToken _ _ (CodeBlock l r src) :: rest) acc | (s :: []) | Empty = reduce rest acc -- 2
78+ reduce (MkToken _ _ (CodeBlock l r src) :: rest) acc | (s :: (srcs ++ [f])) | (Snoc rec) =
79+ reduce rest (acc ++ "\n" ++ unlines srcs ++ "\n")
80+
81+-- [ NOTE ] 1 & 2 shouldn't happen as code blocks are well formed i.e. have two deliminators.
82+
83+
84+public export
85+record LiterateError where
86+ constructor MkLitErr
87+ line : Int
88+ column : Int
89+ input : String
90+
91+||| Description of literate styles.
92+|||
93+||| A 'literate' style comprises of
94+|||
95+||| + a list of code block deliminators (`deliminators`);
96+||| + a list of code line markers (`line_markers`); and
97+||| + a list of known file extensions `file_extensions`.
98+|||
99+||| Some example specifications:
100+|||
101+||| + Bird Style
102+|||
103+|||```
104+|||MkLitStyle Nil [">", "<"] Nil
105+|||```
106+|||
107+||| + Literate Haskell (for LaTeX)
108+|||
109+|||```
110+|||MkLitStyle [("\\begin{code}", "\\end{code}"),("\\begin{spec}","\\end{spec}")]
111+||| Nil
112+||| ["lhs", "tex"]
113+|||```
114+|||
115+||| + OrgMode
116+|||
117+|||```
118+|||MkLitStyle [("#+BEGIN_SRC idris","#+END_SRC"), ("#+COMMENT idris","#+END_COMMENT")]
119+||| ["#+IDRIS:"]
120+||| ["org"]
121+|||```
122+|||
123+public export
124+record LiterateStyle where
125+ constructor MkLitStyle
126+ ||| The pairs of start and end tags for code blocks.
127+ deliminators : List (String, String)
128+
129+ ||| Line markers that indicate a line contains code.
130+ line_markers : List String
131+
132+ ||| Recognised file extensions. Not used by the module, but will be
133+ ||| of use when connecting to code that reads in the original source
134+ ||| files.
135+ file_extensions : List String
136+
137+||| Given a 'literate specification' extract the code from the
138+||| literate source file (`litStr`) that follows the presented style.
139+|||
140+||| @specification The literate specification to use.
141+||| @litStr The literate source file.
142+|||
143+||| Returns a `LiterateError` if the literate file contains malformed
144+||| code blocks or code lines.
145+|||
146+export
147+extractCode : (specification : LiterateStyle)
148+ -> (litStr : String)
149+ -> Either LiterateError String
150+extractCode (MkLitStyle delims markers exts) str =
151+ case lex (rawTokens delims markers) str of
152+ (toks, (_,_,"")) => Right $ reduce toks ""
153+ (_, (l,c,i)) => Left (MkLitErr l c i)
154+
155+-- --------------------------------------------------------------------- [ EOF ]
libs/contrib/Text/Parser.idr+67−26
@@ -3,7 +3,7 @@ module Text.Parser
3%default total
3%default total
4
4
5-- TODO: Add some primitives for helping with error messages.
5-- TODO: Add some primitives for helping with error messages.
6−-- e.g. perhaps set a string to state what we're currently trying to
6+-- e.g. perhaps set a string to state what we're currently trying to
7-- parse, or to say what the next expected token is in words
7-- parse, or to say what the next expected token is in words
8
8
9||| Description of a language's grammar. The `tok` parameter is the type
9||| Description of a language's grammar. The `tok` parameter is the type
@@ -26,14 +26,14 @@ data Grammar : (tok : Type) -> (consumes : Bool) -> Type -> Type where
26 Grammar tok c1 a -> (a -> Grammar tok c2 b) ->
26 Grammar tok c1 a -> (a -> Grammar tok c2 b) ->
27 Grammar tok (c1 || c2) b
27 Grammar tok (c1 || c2) b
28 Alt : {c1, c2 : Bool} ->
28 Alt : {c1, c2 : Bool} ->
29− Grammar tok c1 ty -> Grammar tok c2 ty ->
29+ Grammar tok c1 ty -> Grammar tok c2 ty ->
30 Grammar tok (c1 && c2) ty
30 Grammar tok (c1 && c2) ty
31
31
32public export
32public export
33inf : Bool -> Type -> Type
33inf : Bool -> Type -> Type
34inf True t = Inf t
34inf True t = Inf t
35inf False t = t
35inf False t = t
36−
36+
37||| Sequence two grammars. If either consumes some input, the sequence is
37||| Sequence two grammars. If either consumes some input, the sequence is
38||| guaranteed to consume some input. If the first one consumes input, the
38||| guaranteed to consume some input. If the first one consumes input, the
39||| second is allowed to be recursive (because it means some input has been
39||| second is allowed to be recursive (because it means some input has been
@@ -44,11 +44,11 @@ export %inline
44 Grammar tok (c1 || c2) b
44 Grammar tok (c1 || c2) b
45(>>=) {c1 = False} = SeqEmpty
45(>>=) {c1 = False} = SeqEmpty
46(>>=) {c1 = True} = SeqEat
46(>>=) {c1 = True} = SeqEat
47−
47+
48||| Give two alternative grammars. If both consume, the combination is
48||| Give two alternative grammars. If both consume, the combination is
49||| guaranteed to consume.
49||| guaranteed to consume.
50export
50export
51−(<|>) : Grammar tok c1 ty -> Grammar tok c2 ty ->
51+(<|>) : Grammar tok c1 ty -> Grammar tok c2 ty ->
52 Grammar tok (c1 && c2) ty
52 Grammar tok (c1 && c2) ty
53(<|>) = Alt
53(<|>) = Alt
54
54
@@ -82,21 +82,21 @@ export
82eof : Grammar tok False ()
82eof : Grammar tok False ()
83eof = EOF
83eof = EOF
84
84
85−||| Commit to an alternative; if the current branch of an alternative
85+||| Commit to an alternative; if the current branch of an alternative
86||| fails to parse, no more branches will be tried
86||| fails to parse, no more branches will be tried
87export
87export
88commit : Grammar tok False ()
88commit : Grammar tok False ()
89commit = Commit
89commit = Commit
90
90
91data ParseResult : List tok -> (consumes : Bool) -> Type -> Type where
91data ParseResult : List tok -> (consumes : Bool) -> Type -> Type where
92− Failure : {xs : List tok} ->
92+ Failure : {xs : List tok} ->
93 (committed : Bool) ->
93 (committed : Bool) ->
94 (err : String) -> (rest : List tok) -> ParseResult xs c ty
94 (err : String) -> (rest : List tok) -> ParseResult xs c ty
95 EmptyRes : (committed : Bool) ->
95 EmptyRes : (committed : Bool) ->
96 (val : ty) -> (more : List tok) -> ParseResult more False ty
96 (val : ty) -> (more : List tok) -> ParseResult more False ty
97 NonEmptyRes : (committed : Bool) ->
97 NonEmptyRes : (committed : Bool) ->
98 (val : ty) -> (more : List tok) ->
98 (val : ty) -> (more : List tok) ->
99− ParseResult (x :: xs ++ more) c ty
99+ ParseResult (x :: xs ++ more) c ty
100
100
101weakenRes : {whatever, c : Bool} -> {xs : List tok} ->
101weakenRes : {whatever, c : Bool} -> {xs : List tok} ->
102 ParseResult xs c ty -> ParseResult xs (whatever && c) ty
102 ParseResult xs c ty -> ParseResult xs (whatever && c) ty
@@ -105,13 +105,13 @@ weakenRes {whatever=True} (EmptyRes com val xs) = EmptyRes com val xs
105weakenRes {whatever=False} (EmptyRes com val xs) = EmptyRes com val xs
105weakenRes {whatever=False} (EmptyRes com val xs) = EmptyRes com val xs
106weakenRes (NonEmptyRes com val more) = NonEmptyRes com val more
106weakenRes (NonEmptyRes com val more) = NonEmptyRes com val more
107
107
108−shorter : (more : List tok) -> .(ys : List tok) ->
108+shorter : (more : List tok) -> .(ys : List tok) ->
109 LTE (S (length more)) (S (length (ys ++ more)))
109 LTE (S (length more)) (S (length (ys ++ more)))
110shorter more [] = lteRefl
110shorter more [] = lteRefl
111shorter more (x :: xs) = LTESucc (lteSuccLeft (shorter more xs))
111shorter more (x :: xs) = LTESucc (lteSuccLeft (shorter more xs))
112
112
113doParse : {c : Bool} ->
113doParse : {c : Bool} ->
114− (commit : Bool) -> (xs : List tok) -> (act : Grammar tok c ty) ->
114+ (commit : Bool) -> (xs : List tok) -> (act : Grammar tok c ty) ->
115 ParseResult xs c ty
115 ParseResult xs c ty
116doParse com xs act with (sizeAccessible xs)
116doParse com xs act with (sizeAccessible xs)
117 doParse com xs (Empty val) | sml = EmptyRes com val xs
117 doParse com xs (Empty val) | sml = EmptyRes com val xs
@@ -120,17 +120,17 @@ doParse com xs act with (sizeAccessible xs)
120 doParse com xs Commit | sml = EmptyRes True () xs
120 doParse com xs Commit | sml = EmptyRes True () xs
121
121
122 doParse com [] (Terminal f) | sml = Failure com "End of input" []
122 doParse com [] (Terminal f) | sml = Failure com "End of input" []
123− doParse com (x :: xs) (Terminal f) | sml
123+ doParse com (x :: xs) (Terminal f) | sml
124 = maybe
124 = maybe
125 (Failure com "Unrecognised token" (x :: xs))
125 (Failure com "Unrecognised token" (x :: xs))
126 (\a => NonEmptyRes com {xs=[]} a xs)
126 (\a => NonEmptyRes com {xs=[]} a xs)
127 (f x)
127 (f x)
128 doParse com [] EOF | sml = EmptyRes com () []
128 doParse com [] EOF | sml = EmptyRes com () []
129− doParse com (x :: xs) EOF | sml
129+ doParse com (x :: xs) EOF | sml
130 = Failure com "Expected end of input" (x :: xs)
130 = Failure com "Expected end of input" (x :: xs)
131 doParse com [] (NextIs f) | sml = Failure com "End of input" []
131 doParse com [] (NextIs f) | sml = Failure com "End of input" []
132− doParse com (x :: xs) (NextIs f) | sml
132+ doParse com (x :: xs) (NextIs f) | sml
133− = if f x
133+ = if f x
134 then EmptyRes com x (x :: xs)
134 then EmptyRes com x (x :: xs)
135 else Failure com "Unrecognised token" (x :: xs)
135 else Failure com "Unrecognised token" (x :: xs)
136 doParse com xs (Alt x y) | sml with (doParse False xs x | sml)
136 doParse com xs (Alt x y) | sml with (doParse False xs x | sml)
@@ -140,19 +140,19 @@ doParse com xs act with (sizeAccessible xs)
140 then Failure com msg ts
140 then Failure com msg ts
141 else weakenRes (doParse False xs y | sml)
141 else weakenRes (doParse False xs y | sml)
142 -- Successfully parsed the first option, so use the outer commit flag
142 -- Successfully parsed the first option, so use the outer commit flag
143− doParse com xs (Alt x y) | sml | (EmptyRes _ val xs)
143+ doParse com xs (Alt x y) | sml | (EmptyRes _ val xs)
144 = EmptyRes com val xs
144 = EmptyRes com val xs
145− doParse com (z :: (ys ++ more)) (Alt x y) | sml | (NonEmptyRes _ val more)
145+ doParse com (z :: (ys ++ more)) (Alt x y) | sml | (NonEmptyRes _ val more)
146 = NonEmptyRes com val more
146 = NonEmptyRes com val more
147 doParse com xs (SeqEmpty act next) | (Access morerec)
147 doParse com xs (SeqEmpty act next) | (Access morerec)
148 = case doParse com xs act | Access morerec of
148 = case doParse com xs act | Access morerec of
149 Failure com msg ts => Failure com msg ts
149 Failure com msg ts => Failure com msg ts
150− EmptyRes com val xs =>
150+ EmptyRes com val xs =>
151 case doParse com xs (next val) | (Access morerec) of
151 case doParse com xs (next val) | (Access morerec) of
152 Failure com' msg ts => Failure com' msg ts
152 Failure com' msg ts => Failure com' msg ts
153 EmptyRes com' val xs => EmptyRes com' val xs
153 EmptyRes com' val xs => EmptyRes com' val xs
154 NonEmptyRes com' val more => NonEmptyRes com' val more
154 NonEmptyRes com' val more => NonEmptyRes com' val more
155− NonEmptyRes {x} {xs=ys} com val more =>
155+ NonEmptyRes {x} {xs=ys} com val more =>
156 case (doParse com more (next val) | morerec _ (shorter more ys)) of
156 case (doParse com more (next val) | morerec _ (shorter more ys)) of
157 Failure com' msg ts => Failure com' msg ts
157 Failure com' msg ts => Failure com' msg ts
158 EmptyRes com' val _ => NonEmptyRes com' val more
158 EmptyRes com' val _ => NonEmptyRes com' val more
@@ -160,13 +160,13 @@ doParse com xs act with (sizeAccessible xs)
160 rewrite appendAssociative (x :: ys) (x1 :: xs1) more' in
160 rewrite appendAssociative (x :: ys) (x1 :: xs1) more' in
161 NonEmptyRes com' val more'
161 NonEmptyRes com' val more'
162 doParse com xs (SeqEat act next) | sml with (doParse com xs act | sml)
162 doParse com xs (SeqEat act next) | sml with (doParse com xs act | sml)
163− doParse com xs (SeqEat act next) | sml | Failure com' msg ts
163+ doParse com xs (SeqEat act next) | sml | Failure com' msg ts
164 = Failure com' msg ts
164 = Failure com' msg ts
165− doParse com (x :: (ys ++ more)) (SeqEat act next) | (Access morerec) | (NonEmptyRes com' val more)
165+ doParse com (x :: (ys ++ more)) (SeqEat act next) | (Access morerec) | (NonEmptyRes com' val more)
166 = case doParse com' more (next val) | morerec _ (shorter more ys) of
166 = case doParse com' more (next val) | morerec _ (shorter more ys) of
167 Failure com' msg ts => Failure com' msg ts
167 Failure com' msg ts => Failure com' msg ts
168 EmptyRes com' val _ => NonEmptyRes com' val more
168 EmptyRes com' val _ => NonEmptyRes com' val more
169− NonEmptyRes {x=x1} {xs=xs1} com' val more' =>
169+ NonEmptyRes {x=x1} {xs=xs1} com' val more' =>
170 rewrite appendAssociative (x :: ys) (x1 :: xs1) more' in
170 rewrite appendAssociative (x :: ys) (x1 :: xs1) more' in
171 NonEmptyRes com' val more'
171 NonEmptyRes com' val more'
172 -- This next line is not strictly necessary, but it stops the coverage
172 -- This next line is not strictly necessary, but it stops the coverage
@@ -180,7 +180,7 @@ data ParseError tok = Error String (List tok)
180||| returns a pair of the parse result and the unparsed tokens (the remaining
180||| returns a pair of the parse result and the unparsed tokens (the remaining
181||| input).
181||| input).
182export
182export
183−parse : (xs : List tok) -> (act : Grammar tok c ty) ->
183+parse : (xs : List tok) -> (act : Grammar tok c ty) ->
184 Either (ParseError tok) (ty, List tok)
184 Either (ParseError tok) (ty, List tok)
185parse xs act
185parse xs act
186 = case doParse False xs act of
186 = case doParse False xs act of
@@ -190,7 +190,7 @@ parse xs act
190
190
191||| Parse one or more things
191||| Parse one or more things
192export
192export
193−some : Grammar tok True a ->
193+some : Grammar tok True a ->
194 Grammar tok True (List a)
194 Grammar tok True (List a)
195some p = do x <- p
195some p = do x <- p
196 (do xs <- some p
196 (do xs <- some p
@@ -198,14 +198,14 @@ some p = do x <- p
198
198
199||| Parse zero or more things (may match the empty input)
199||| Parse zero or more things (may match the empty input)
200export
200export
201−many : Grammar tok True a ->
201+many : Grammar tok True a ->
202 Grammar tok False (List a)
202 Grammar tok False (List a)
203many p = some p
203many p = some p
204 <|> pure []
204 <|> pure []
205
205
206||| Parse one or more things, separated by another thing
206||| Parse one or more things, separated by another thing
207export
207export
208−sepBy1 : Grammar tok True () -> Grammar tok True a ->
208+sepBy1 : Grammar tok True () -> Grammar tok True a ->
209 Grammar tok True (List a)
209 Grammar tok True (List a)
210sepBy1 sep p = do x <- p
210sepBy1 sep p = do x <- p
211 (do sep
211 (do sep
@@ -215,7 +215,7 @@ sepBy1 sep p = do x <- p
215||| Parse zero or more things, separated by another thing. May
215||| Parse zero or more things, separated by another thing. May
216||| match the empty input.
216||| match the empty input.
217export
217export
218−sepBy : Grammar tok True () -> Grammar tok True a ->
218+sepBy : Grammar tok True () -> Grammar tok True a ->
219 Grammar tok False (List a)
219 Grammar tok False (List a)
220sepBy sep p = sepBy1 sep p <|> pure []
220sepBy sep p = sepBy1 sep p <|> pure []
221
221
@@ -227,3 +227,44 @@ optional : Grammar tok True a -> (ifNothing : a) ->
227optional p def = p <|> pure def
227optional p def = p <|> pure def
228
228
229
229
230+||| Parse an instance of `p` that is between `left` and `right`.
231+export
232+between : (left : Grammar tok True ())
233+ -> (right : Grammar tok True ())
234+ -> (p : Grammar tok True a)
235+ -> Grammar tok True a
236+between left right contents = do
237+ left
238+ res <- contents
239+ right
240+ pure res
241+
242+||| Parse one or more instances of `p` separated by `s`, returning the
243+||| parsed items and proof the resulting list is non-empty.
244+export
245+sepBy1' : (sep : Grammar tok True ())
246+ -> (p : Grammar tok True a)
247+ -> Grammar tok True (xs : List a ** NonEmpty xs)
248+sepBy1' sep p
249+ = do x <- p
250+ (do sep
251+ xs <- sepBy1 sep p
252+ pure (x :: xs ** IsNonEmpty)) <|> pure ([x] ** IsNonEmpty)
253+
254+||| Parse one or more instances of `p`, returning the parsed items and proof the resulting list is non-empty.
255+export
256+some' : (p : Grammar tok True a)
257+ -> Grammar tok True (xs : List a ** NonEmpty xs)
258+some' p = do
259+ x <- p
260+ (do xs <- some p
261+ pure (x::xs ** IsNonEmpty)) <|> pure ([x] ** IsNonEmpty)
262+
263+
264+||| Optionally parse a thing. If the grammar provides a default use `optional` instead.
265+export
266+maybe : Grammar tok True a
267+ -> Grammar tok False (Maybe a)
268+maybe p =
269+ (do res <- p; pure $ Just res)
270+ <|> pure Nothing
libs/contrib/Text/PrettyPrint/WL.idrnew file+18
@@ -0,0 +1,18 @@
1+||| A revised Idris port of the Wadler-Leijen pretty-printer.
2+|||
3+||| This port of the Wadler-Leijen Pretty-Printer is based upon the
4+||| port originally created by Shayan Najd [1]. We have changed the
5+||| render function to be total using a technique based on
6+||| continuations proposed by gallais [2], and fix minor errors in the
7+||| original Idris port.
8+|||
9+||| [1] https://github.com/shayan-najd/wl-pprint
10+||| [2] https://gallais.github.io/blog/termination-tricks.html
11+module Text.PrettyPrint.WL
12+
13+import public Text.PrettyPrint.WL.Core
14+import public Text.PrettyPrint.WL.Characters
15+import public Text.PrettyPrint.WL.Combinators
16+
17+%default total
18+%access export
libs/contrib/Text/PrettyPrint/WL/Characters.idrnew file+103
@@ -0,0 +1,103 @@
1+||| Commonly used characters
2+module Text.PrettyPrint.WL.Characters
3+
4+import Text.PrettyPrint.WL.Core
5+
6+%default total
7+%access export
8+
9+lparen : Doc
10+lparen = char '('
11+
12+rparen : Doc
13+rparen = char ')'
14+
15+langle : Doc
16+langle = char '<'
17+
18+rangle : Doc
19+rangle = char '>'
20+
21+lbrace : Doc
22+lbrace = char '{'
23+
24+rbrace : Doc
25+rbrace = char '}'
26+
27+lbracket : Doc
28+lbracket = char '['
29+
30+rbracket : Doc
31+rbracket = char ']'
32+
33+squote : Doc
34+squote = char '\''
35+
36+dquote : Doc
37+dquote = char '"'
38+
39+semi : Doc
40+semi = char ';'
41+
42+colon : Doc
43+colon = char ':'
44+
45+comma : Doc
46+comma = char ','
47+
48+space : Doc
49+space = char ' '
50+
51+dot : Doc
52+dot = char '.'
53+
54+backslash : Doc
55+backslash = char '\\'
56+
57+forwardslash : Doc
58+forwardslash = char '/'
59+
60+equals : Doc
61+equals = char '='
62+
63+pipe : Doc
64+pipe = char '|'
65+
66+bang : Doc
67+bang = char '!'
68+
69+tick : Doc
70+tick = char '`'
71+
72+tilde : Doc
73+tilde = char '~'
74+
75+hash : Doc
76+hash = char '#'
77+
78+asterix : Doc
79+asterix = char '*'
80+
81+ampersand : Doc
82+ampersand = char '&'
83+
84+dash : Doc
85+dash = char '-'
86+
87+question : Doc
88+question = char '?'
89+
90+dollar : Doc
91+dollar = char '$'
92+
93+pound : Doc
94+pound = char '£'
95+
96+euro : Doc
97+euro = char '€'
98+
99+caret : Doc
100+caret = char '^'
101+
102+percent : Doc
103+percent = char '%'
libs/contrib/Text/PrettyPrint/WL/Combinators.idrnew file+259
@@ -0,0 +1,259 @@
1+||| Common combinators.
2+module Text.PrettyPrint.WL.Combinators
3+
4+import Text.PrettyPrint.WL.Core
5+import Text.PrettyPrint.WL.Characters
6+
7+%default total
8+%access export
9+
10+-- --------------------------------------------------- [ Alignment Combinators ]
11+
12+||| The document `(align x)` renders document `x` with the nesting
13+||| level set to the current column. It is used for example to
14+||| implement 'hang'.
15+align : Doc -> Doc
16+align d = column (\k => nesting (\i => nest (k - i) d))
17+
18+||| The hang combinator implements hanging indentation. The document
19+||| `(hang i x)` renders document `x` with a nesting level set to the
20+||| current column plus `i`.
21+hang : Int -> Doc -> Doc
22+hang i d = align (nest i d)
23+
24+||| The document `(indent i x)` indents document `x` with `i` spaces.
25+indent : Int -> Doc -> Doc
26+indent i d = hang i (text (spaces i) <+> d)
27+
28+-- -------------------------------------------------- [ High-Level Combinators ]
29+
30+||| The document `softLine` behaves like `space` if the resulting
31+||| output fits the page, otherwise it behaves like `line`.
32+softLine : Doc
33+softLine = group line
34+
35+||| The document `softbreak` behaves like `empty` if the resulting
36+||| output fits the page, otherwise it behaves like 'line'.
37+softBreak : Doc
38+softBreak = group breakLine
39+
40+infixr 5 |/|, |//|, |$|, |$$|
41+infixr 6 |+|, |++|
42+
43+private
44+concatDoc : Doc -> Doc -> Doc -> Doc
45+concatDoc sep x y = x `beside` (sep `beside` y)
46+
47+||| The document `(x |+| y)` concatenates document `x` and document
48+||| `y`. It is an associative operation having 'empty' as a left and
49+||| right unit.
50+(|+|) : Doc -> Doc -> Doc
51+(|+|) = (<+>)
52+
53+||| The document `(x |++| y)` concatenates document `x` and `y` with a
54+||| `space` in between.
55+(|++|) : Doc -> Doc -> Doc
56+(|++|) = concatDoc space
57+
58+||| The document `(x |/| y)` concatenates document `x` and `y` with a
59+||| 'softline' in between. This effectively puts `x` and `y` either
60+||| next to each other (with a `space` in between) or underneath each
61+||| other.
62+(|/|) : Doc -> Doc -> Doc
63+(|/|) = concatDoc softLine
64+
65+||| The document `(x |//| y)` concatenates document `x` and `y` with
66+||| a 'softbreak' in between. This effectively puts `x` and `y` either
67+||| right next to each other or underneath each other.
68+(|//|) : Doc -> Doc -> Doc
69+(|//|) = concatDoc softBreak
70+
71+||| The document `(x |$| y)` concatenates document `x` and `y` with a
72+||| `line` in between.
73+(|$|) : Doc -> Doc -> Doc
74+(|$|) = concatDoc line
75+
76+||| The document `(x |$$| y)` concatenates document `x` and `y` with
77+||| a `linebreak` in between.
78+(|$$|) : Doc -> Doc -> Doc
79+(|$$|) = concatDoc breakLine
80+
81+||| The document `(vsep xs)` concatenates all documents `xs`
82+||| vertically with `(|$|)`. If a 'group' undoes the line breaks
83+||| inserted by `vsep`, all documents are separated with a space.
84+vsep : List Doc -> Doc
85+vsep = fold (|$|)
86+
87+||| The document `(sep xs)` concatenates all documents `xs` either
88+||| horizontally with `(|++|)`, if it fits the page, or vertically with
89+||| `(|$|)`.
90+sep : List Doc -> Doc
91+sep = group . vsep
92+
93+
94+||| The document `(fillSep xs)` concatenates documents `xs`
95+||| horizontally with `(|++|)` as long as its fits the page, than
96+||| inserts a `line` and continues doing that for all documents in
97+||| `xs`.
98+fillSep : List Doc -> Doc
99+fillSep = fold (|/|)
100+
101+||| The document `(hsep xs)` concatenates all documents `xs`
102+||| horizontally with `(|++|)`.
103+hsep : List Doc -> Doc
104+hsep = fold (|++|)
105+
106+||| The document `(hcat xs)` concatenates all documents `xs`
107+||| horizontally with `(|+|)`.
108+hcat : List Doc -> Doc
109+hcat = fold (<+>)
110+
111+||| The document `(vcat xs)` concatenates all documents `xs`
112+||| vertically with `(|$$|)`. If a `group` undoes the line breaks
113+||| inserted by `vcat`, all documents are directly concatenated.
114+vcat : List Doc -> Doc
115+vcat = fold (|$$|)
116+
117+||| The document `(cat xs)` concatenates all documents `xs` either
118+||| horizontally with `(|+|)`, if it fits the page, or vertically with
119+||| `(|$$|)`.
120+cat : List Doc -> Doc
121+cat = group . vcat
122+
123+||| The document `(fillCat xs)` concatenates documents `xs`
124+||| horizontally with `(|+|)` as long as its fits the page, than inserts
125+||| a `linebreak` and continues doing that for all documents in `xs`.
126+fillCat : List Doc -> Doc
127+fillCat = fold (|//|)
128+
129+||| The document `(enclose l r x)` encloses document `x` between
130+||| documents `l` and `r` using `(|+|)`.
131+enclose : Doc -> Doc -> Doc -> Doc
132+enclose l r x = concatDoc x l r
133+
134+squotes : Doc -> Doc
135+squotes = enclose squote squote
136+
137+dquotes : Doc -> Doc
138+dquotes = enclose dquote dquote
139+
140+braces : Doc -> Doc
141+braces = enclose lbrace rbrace
142+
143+parens : Doc -> Doc
144+parens = enclose lparen rparen
145+
146+angles : Doc -> Doc
147+angles = enclose langle rangle
148+
149+brackets : Doc -> Doc
150+brackets = enclose lbracket rbracket
151+
152+-- ----------------------------------------------------- [ Lists, Sets, Tuples ]
153+
154+||| The document `(encloseSep l r sep xs)` concatenates the documents
155+||| `xs` separated by `sep` and encloses the resulting document by `l`
156+||| and `r`. The documents are rendered horizontally if that fits the
157+||| page. Otherwise they are aligned vertically. All separators are put
158+||| in front of the elements.
159+encloseSep : (l : Doc)
160+ -> (r : Doc)
161+ -> (sep : Doc)
162+ -> (xs : List Doc)
163+ -> Doc
164+encloseSep l r s [] = l <+> r
165+encloseSep l r s [x] = l <+> x <+> r
166+encloseSep l r s xs = align (cat (zipWith (<+>) (l :: replicate (length xs) s) xs) <+> r)
167+
168+||| The document `(list xs)` comma separates the documents `xs` and
169+||| encloses them in square brackets. The documents are rendered
170+||| horizontally if that fits the page. Otherwise they are aligned
171+||| vertically. All comma separators are put in front of the
172+||| elements.
173+list : List Doc -> Doc
174+list = encloseSep lbracket rbracket comma
175+
176+||| The document `(tupled xs)` comma separates the documents `xs`
177+||| and encloses them in parenthesis. The documents are rendered
178+||| horizontally if that fits the page. Otherwise they are aligned
179+||| vertically. All comma separators are put in front of the
180+||| elements.
181+tupled : List Doc -> Doc
182+tupled = encloseSep lparen rparen comma
183+
184+||| The document `(set xs)` separates the documents `xs` with
185+||| commas and encloses them in braces. The documents are
186+||| rendered horizontally if that fits the page. Otherwise they are
187+||| aligned vertically. All comma's are put in front of the
188+||| elements.
189+set : List Doc -> Doc
190+set = encloseSep lbrace rbrace comma
191+
192+||| The document `(semiBraces xs)` separates the documents `xs` with
193+||| semi-colon and encloses them in braces. The documents are
194+||| rendered horizontally if that fits the page. Otherwise they are
195+||| aligned vertically. All semi-colons's are put in front of the
196+||| elements.
197+semiBrace : List Doc -> Doc
198+semiBrace = encloseSep lbrace rbrace semi
199+
200+||| `(punctuate p xs)` concatenates all documents in `xs` with
201+||| document `p` except for the last document.
202+punctuate : Doc -> List Doc -> List Doc
203+punctuate p [] = []
204+punctuate p [x] = [x]
205+punctuate p (x :: xs) = (x <+> p) :: punctuate p xs
206+
207+-- ------------------------------------------------------------------- [ Fills ]
208+
209+width : Doc -> (Int -> Doc) -> Doc
210+width doc f = column (\k => doc <+> column (\k' => f (k' - k)))
211+
212+||| The document `(fillBreak i x)` first renders document `x`. It
213+||| than appends `space`s until the width is equal to `i`. If the
214+||| width of `x` is already larger than `i`, the nesting level is
215+||| increased by `i` and a `line` is appended.
216+fillBreak : (i : Int) -> (x : Doc) -> Doc
217+fillBreak f x =
218+ width x (\w => if (w > f)
219+ then nest f breakLine
220+ else text (spaces (f - w)))
221+
222+||| The document `(fill i x)` renders document `x`. It than appends
223+||| `space`s until the width is equal to `i`. If the width of `x` is
224+||| already larger, nothing is appended. This combinator is quite
225+||| useful in practice to output a list of bindings.
226+fill : (i : Int) -> (x : Doc) -> Doc
227+fill f d =
228+ width d (\w => if (w >= f)
229+ then empty
230+ else text (spaces (f - w)))
231+
232+-- -------------------------------------------------------------- [ Primatives ]
233+
234+||| The document `(literal s)` concatenates all characters in `s`
235+||| using `line` for newline characters and `char` for all other
236+||| characters. It is used instead of 'text' whenever the text contains
237+||| newline characters.
238+literal : (str : String) -> Doc
239+literal str = mkLiteral (unpack str)
240+ where
241+ mkLiteral : List Char -> Doc
242+ mkLiteral Nil = empty
243+ mkLiteral ('\n':: ss) = line <+> mkLiteral ss
244+ mkLiteral (c :: ss) = char c <+> mkLiteral ss
245+
246+bool : Bool -> Doc
247+bool b = text (show b)
248+
249+nat : Nat -> Doc
250+nat n = text (show n)
251+
252+int : Int -> Doc
253+int i = text (show i)
254+
255+integer : Integer -> Doc
256+integer i = text (show i)
257+
258+double : Double -> Doc
259+double d = text (show d)
libs/contrib/Text/PrettyPrint/WL/Core.idrnew file+225
@@ -0,0 +1,225 @@
1+||| Core definitions and primitives.
2+module Text.PrettyPrint.WL.Core
3+
4+%default total
5+%access export
6+
7+-- -------------------------------------------------------------------- [ Core ]
8+
9+||| The abstract data type `Doc` represents pretty documents.
10+|||
11+data Doc : Type where
12+ Empty : Doc
13+ Chara : (c : Char) -> Doc
14+ Text : (len : Int) -> (str : String) -> Doc
15+ Line : (undone : Bool) -> Doc
16+
17+ Cat : (x : Doc) -> (y : Doc) -> Doc
18+ Nest : (lvl : Int) -> (x : Doc) -> Doc
19+ Union : (x : Doc) -> (y : Doc) -> Doc
20+
21+ Column : (f : Int -> Doc) -> Doc
22+ Nesting : (f : Int -> Doc) -> Doc
23+
24+-- -------------------------------------------------------------- [ Primitives ]
25+
26+||| The empty document is, indeed, empty.
27+empty : Doc
28+empty = Empty
29+
30+||| The `line` document advances to the next line and indents to the
31+||| current nesting level. Document `line` behaves like `(text " ")`
32+||| if the line break is undone by 'group'.
33+line : Doc
34+line = Line False
35+
36+||| The document `(char c)` contains the literal character `c`. If the
37+||| character is a newline (`'\n'`) the function returns a line
38+||| document. Ideally, the function 'line' should be used for line
39+||| breaks.
40+char : (c : Char) -> Doc
41+char '\n' = line
42+char c = Chara c
43+
44+||| The document `(text s)` contains the literal string `s`. The
45+||| string shouldn't contain any newline (`'\n'`) characters. If the
46+||| string contains newline characters, the function 'literal' should be
47+||| used.
48+text : (str : String) -> Doc
49+text "" = empty
50+text str = Text (cast $ length str) str
51+
52+||| The `breakLine` document advances to the next line and indents to
53+||| the current nesting level. Document `breakLine` behaves like
54+||| 'empty' if the line break is undone by 'group'.
55+breakLine : Doc
56+breakLine = Line True
57+
58+||| Horizontal concatenation of documents
59+beside : Doc -> Doc -> Doc
60+beside = Cat
61+
62+||| The document `(nest lvl x)` renders document `x` with the current
63+||| indentation level increased by lvl.
64+nest : (lvl : Int)
65+ -> (x : Doc)
66+ -> Doc
67+nest = Nest
68+
69+column : (f : Int -> Doc) -> Doc
70+column = Column
71+
72+nesting : (f : Int -> Doc) -> Doc
73+nesting = Nesting
74+
75+private %inline
76+flatten : Doc -> Doc
77+flatten (Line break) = if break then Empty else Text 1 " "
78+
79+flatten (Cat x y) = Cat (flatten x) (flatten y)
80+flatten (Nest lvl x) = Nest lvl (flatten x)
81+flatten (Union x _) = flatten x
82+flatten (Column f) = Column (\i => flatten $ f i)
83+flatten (Nesting f) = Nesting (\i => flatten $ f i)
84+
85+flatten other = other
86+
87+||| The `group` combinator is used to specify alternative
88+||| layouts. The document `(group x)` undoes all line breaks in
89+||| document `x`. The resulting line is added to the current line if
90+||| that fits the page. Otherwise, the document `x` is rendered without
91+||| any changes.
92+group : Doc -> Doc
93+group x = Union (flatten x) x
94+
95+Semigroup Doc where
96+ (<+>) x y = beside x y
97+
98+Monoid Doc where
99+ neutral = empty
100+
101+fold : (f : Doc -> Doc -> Doc) -> (ds : List Doc) -> Doc
102+fold _ Nil = empty
103+fold f (x::xs) = foldl f x xs
104+
105+-- --------------------------------------------------------------- [ Renderers ]
106+
107+namespace PrettyDoc
108+
109+ ||| The data type `PrettyDoc` represents rendered documents and is
110+ ||| used by the display functions.
111+ data PrettyDoc : Type where
112+ Empty : PrettyDoc
113+ Chara : (c : Char) -> (rest : PrettyDoc) -> PrettyDoc
114+ Text : (len : Int) -> (str : String) -> (rest : PrettyDoc) -> PrettyDoc
115+ Line : (lvl : Int) -> (rest : PrettyDoc) -> PrettyDoc
116+
117+||| Helper function to construct spaces.
118+spaces : (n : Int) -> String
119+spaces n = if n <= 0 then "" else pack $ replicate (cast n) ' '
120+
121+private
122+indentation : Int -> String
123+indentation n = spaces n
124+
125+||| `(showPrettyDoc doc)` takes the output `PrettyDoc` from a
126+||| rendering function and transforms it to a String for printing.
127+showPrettyDoc : (doc : PrettyDoc) -> String
128+showPrettyDoc doc = showPrettyDocS doc ""
129+ where
130+ showPrettyDocS : (doc : PrettyDoc) -> (acc : String) -> String
131+ showPrettyDocS Empty acc = acc
132+ showPrettyDocS (Chara c rest) acc = strCons c (showPrettyDocS rest acc)
133+ showPrettyDocS (Text len str rest) acc = str ++ (showPrettyDocS rest acc)
134+ showPrettyDocS (Line lvl rest) acc = (strCons '\n' (indentation lvl)) ++ showPrettyDocS rest acc
135+
136+private
137+fits : (w : Int) -> (x : PrettyDoc) -> Bool
138+fits w Empty = if w < 0 then False else True
139+fits w (Chara c rest) = if w < 0 then False else fits (w - 1) rest
140+
141+fits w (Text len str rest) = if w < 0 then False else fits (w - len) rest
142+
143+fits w (Line _ _) = if w < 0 then False else True
144+
145+
146+||| Use the Wadler-Leijen algorithm to pretty print the `doc`.
147+||| The algorithm uses a page width of `width` and a ribbon
148+||| width of `(ribbonfrac * width)` characters. The ribbon width is
149+||| the maximal amount of non-indentation characters on a line. The
150+||| parameter `ribbonfrac` should be between `0.0` and `1.0`. If it is
151+||| lower or higher, the ribbon width will be 0 or `width`
152+||| respectively.
153+render : (rfrac : Double)
154+ -> (width : Int)
155+ -> (doc : Doc)
156+ -> PrettyDoc
157+render rfrac w doc = best w 0 0 doc (const Empty)
158+ where
159+ rwidth : Int
160+ rwidth = max 0 $ min w (cast (cast w * rfrac))
161+
162+ nicest : (lvl : Int)
163+ -> (col : Int)
164+ -> (x : PrettyDoc)
165+ -> (y : PrettyDoc)
166+ -> PrettyDoc
167+ nicest n k x y =
168+ let width = min (w - k) (rwidth - k + n)
169+ in if fits width x then x else y
170+
171+ best : (lvl : Int)
172+ -> (col : Int)
173+ -> (curr : Int)
174+ -> (doc : Doc)
175+ -> (k : Int -> PrettyDoc)
176+ -> PrettyDoc
177+ best lvl col curr Empty k = k col
178+ best lvl col curr (Chara c) k = Chara c $ k (col + 1)
179+ best lvl col curr (Text len str) k = Text len str $ k (col + len)
180+ best lvl col curr (Line undone) k = Line curr $ k curr
181+
182+ best lvl col curr (Cat x y) k =
183+ best lvl col curr x (\curr' => best lvl curr' curr y k)
184+
185+ best lvl col curr (Nest x y) k = best lvl col (curr+x) y k
186+
187+ best lvl col curr (Union x y) k =
188+ nicest lvl col (best lvl col curr x k)
189+ (best lvl col curr y k)
190+
191+ best lvl col curr (Column f) k = best lvl col curr (f col) k
192+ best lvl col curr (Nesting f) k = best lvl col curr (f curr) k
193+
194+||| Print the document to a string using the given ribbon fraction
195+||| and page width.
196+toString : (rfrac : Double)
197+ -> (width : Int)
198+ -> (doc : Doc)
199+ -> String
200+toString rfrac width doc = showPrettyDoc (render rfrac width doc)
201+
202+writeDoc : (fname : String)
203+ -> (rfrac : Double)
204+ -> (width : Int)
205+ -> (doc : Doc)
206+ -> IO (Either FileError ())
207+writeDoc fname rfrac width doc = writeFile fname $ toString rfrac width doc
208+
209+namespace Default
210+
211+ ||| Render the document with a default ribbon fraction of 0.4 and page width of 120 characters.
212+ render : (doc : Doc) -> PrettyDoc
213+ render = render 0.4 120
214+
215+ ||| Print the document to a string using a default ribbon fraction
216+ ||| of 0.4 and page width of 120 characters.
217+ toString : (doc : Doc) -> String
218+ toString = toString 0.4 120
219+
220+ ||| Write the doc to `fname` using a default ribbon fraction of 0.4
221+ ||| and page width of 120 characters.
222+ writeDoc : (fname : String)
223+ -> (doc : Doc)
224+ -> IO (Either FileError ())
225+ writeDoc fname doc = writeFile fname $ Default.toString doc
libs/contrib/contrib.ipkg+12−2
@@ -11,6 +11,7 @@ modules = CFFI, CFFI.Types, CFFI.Memory,
11 Control.Pipeline,
11 Control.Pipeline,
12 Control.ST, Control.ST.ImplicitCall, Control.ST.Exception,
12 Control.ST, Control.ST.ImplicitCall, Control.ST.Exception,
13
13
14+ Interfaces.Correlative,
14 Interfaces.Verified,
15 Interfaces.Verified,
15
16
16 Data.Fun, Data.Rel,
17 Data.Fun, Data.Rel,
@@ -22,7 +23,8 @@ modules = CFFI, CFFI.Types, CFFI.Memory,
22 Data.Heap,
23 Data.Heap,
23 Data.SortedMap, Data.SortedSet,
24 Data.SortedMap, Data.SortedSet,
24 Data.CoList, Data.Storable,
25 Data.CoList, Data.Storable,
25− Data.List.Zipper,
26+ Data.List.Zipper,
27+ Data.Pairs.Implicit,
26
28
27 Decidable.Decidable, Decidable.Order,
29 Decidable.Decidable, Decidable.Order,
28
30
@@ -32,4 +34,12 @@ modules = CFFI, CFFI.Types, CFFI.Memory,
32
34
33 Text.Lexer, Text.Parser,
35 Text.Lexer, Text.Parser,
34
36
37+ Text.PrettyPrint.WL,
38+ Text.PrettyPrint.WL.Core,
39+ Text.PrettyPrint.WL.Characters,
40+ Text.PrettyPrint.WL.Combinators,
41+
42+ Text.Literate,
43+
35− Data.Fin.Extra
44+ Data.Fin.Extra,
45+ Data.Stream.Extra
libs/effects/Effect/Logging/Level.idr+9−9
@@ -58,15 +58,15 @@ implementation Cast (LogLevel n) Nat where
58 cast {n} _ = n
58 cast {n} _ = n
59
59
60implementation Show (LogLevel n) where
60implementation Show (LogLevel n) where
61− show OFF = "OFF"
61+ showPrec d OFF = "OFF"
62− show TRACE = "TRACE"
62+ showPrec d TRACE = "TRACE"
63− show DEBUG = "DEBUG"
63+ showPrec d DEBUG = "DEBUG"
64− show INFO = "INFO"
64+ showPrec d INFO = "INFO"
65− show WARN = "WARN"
65+ showPrec d WARN = "WARN"
66− show FATAL = "FATAL"
66+ showPrec d FATAL = "FATAL"
67− show ERROR = "ERROR"
67+ showPrec d ERROR = "ERROR"
68− show ALL = "ALL"
68+ showPrec d ALL = "ALL"
69− show (CUSTOM n) = unwords ["CUSTOM", show n]
69+ showPrec d (CUSTOM n) = showCon d "CUSTOM" $ showArg n
70
70
71implementation Eq (LogLevel n) where
71implementation Eq (LogLevel n) where
72 (==) x y = lvlEq x y
72 (==) x y = lvlEq x y
libs/prelude/Prelude.idr+1−2
@@ -280,8 +280,7 @@ namespace JSNull
280
280
281||| Pointer equality
281||| Pointer equality
282eqPtr : Ptr -> Ptr -> IO Bool
282eqPtr : Ptr -> Ptr -> IO Bool
283−eqPtr x y = do eq <- foreign FFI_C "idris_eqPtr" (Ptr -> Ptr -> IO Int) x y
283+eqPtr x y = pure $ prim__eqPtr x y /= 0
284− pure (eq /= 0)
285
284
286||| Loop while some test is true
285||| Loop while some test is true
287|||
286|||
libs/prelude/Prelude/Bits.idr+4−4
@@ -21,12 +21,12 @@ import Prelude.Strings
21-- Convert to `List Bits8`
21-- Convert to `List Bits8`
22--------------------------------------------------------------------------------
22--------------------------------------------------------------------------------
23
23
24−||| Convert to list of `Bits8` with the most signficant byte at the
24+||| Convert to list of `Bits8` with the most significant byte at the
25||| head.
25||| head.
26b8ToBytes : Bits8 -> List Bits8
26b8ToBytes : Bits8 -> List Bits8
27b8ToBytes b = [b]
27b8ToBytes b = [b]
28
28
29−||| Convert to list of `Bits8` with the most signficant byte at the
29+||| Convert to list of `Bits8` with the most significant byte at the
30||| head.
30||| head.
31b16ToBytes : Bits16 -> List Bits8
31b16ToBytes : Bits16 -> List Bits8
32b16ToBytes b =
32b16ToBytes b =
@@ -34,7 +34,7 @@ b16ToBytes b =
34 , prim__truncB16_B8 b
34 , prim__truncB16_B8 b
35 ]
35 ]
36
36
37−||| Convert to list of `Bits8` with the most signficant byte at the
37+||| Convert to list of `Bits8` with the most significant byte at the
38||| head.
38||| head.
39b32ToBytes : Bits32 -> List Bits8
39b32ToBytes : Bits32 -> List Bits8
40b32ToBytes b =
40b32ToBytes b =
@@ -44,7 +44,7 @@ b32ToBytes b =
44 , prim__truncB32_B8 b
44 , prim__truncB32_B8 b
45 ]
45 ]
46
46
47−||| Convert to list of `Bits8` with the most signficant byte at the
47+||| Convert to list of `Bits8` with the most significant byte at the
48||| head.
48||| head.
49b64ToBytes : Bits64 -> List Bits8
49b64ToBytes : Bits64 -> List Bits8
50b64ToBytes b =
50b64ToBytes b =
libs/prelude/Prelude/List.idr+5−1
@@ -378,7 +378,7 @@ scanl : (b -> a -> b) -> b -> List a -> List b
378scanl f q [] = [q]
378scanl f q [] = [q]
379scanl f q (x::xs) = q :: scanl f (f q x) xs
379scanl f q (x::xs) = q :: scanl f (f q x) xs
380
380
381−||| The scanl1 function is a variant of scanl that doesn't require an explicit
381+||| The scanl1 function is a variant of scanl that doesn't require an explicit
382||| starting value.
382||| starting value.
383||| It assumes the first element of the list to be the starting value and then
383||| It assumes the first element of the list to be the starting value and then
384||| starts the fold with the element following it.
384||| starts the fold with the element following it.
@@ -855,6 +855,10 @@ catMaybes (x::xs) =
855-- Properties
855-- Properties
856--------------------------------------------------------------------------------
856--------------------------------------------------------------------------------
857
857
858+||| (::) is injective
859+consInjective : (x :: xs) = (y :: ys) -> (x = y, xs = ys)
860+consInjective Refl = (Refl, Refl)
861+
858||| The empty list is a right identity for append.
862||| The empty list is a right identity for append.
859appendNilRightNeutral : (l : List a) ->
863appendNilRightNeutral : (l : List a) ->
860 l ++ [] = l
864 l ++ [] = l
libs/prelude/Prelude/Nat.idr+10−2
@@ -147,7 +147,7 @@ lteSuccRight : LTE n m -> LTE n (S m)
147lteSuccRight LTEZero = LTEZero
147lteSuccRight LTEZero = LTEZero
148lteSuccRight (LTESucc x) = LTESucc (lteSuccRight x)
148lteSuccRight (LTESucc x) = LTESucc (lteSuccRight x)
149
149
150−||| n + 1 < m implies n < m
150+||| n + 1 < m implies n < m
151lteSuccLeft : LTE (S n) m -> LTE n m
151lteSuccLeft : LTE (S n) m -> LTE n m
152lteSuccLeft (LTESucc x) = lteSuccRight x
152lteSuccLeft (LTESucc x) = lteSuccRight x
153
153
@@ -160,6 +160,11 @@ lteAddRight : (n : Nat) -> LTE n (plus n m)
160lteAddRight Z = LTEZero
160lteAddRight Z = LTEZero
161lteAddRight (S k) = LTESucc (lteAddRight k)
161lteAddRight (S k) = LTESucc (lteAddRight k)
162
162
163+||| If a number is not less than another, it is greater than or equal to it
164+notLTImpliesGTE : Not (LT a b) -> GTE a b
165+notLTImpliesGTE {b = Z} _ = LTEZero
166+notLTImpliesGTE {a = Z} {b = S k} notLt = absurd (notLt (LTESucc LTEZero))
167+notLTImpliesGTE {a = S k} {b = S j} notLt = LTESucc (notLTImpliesGTE (notLt . LTESucc))
163
168
164||| Boolean test than one Nat is less than or equal to another
169||| Boolean test than one Nat is less than or equal to another
165total lte : Nat -> Nat -> Bool
170total lte : Nat -> Nat -> Bool
@@ -231,7 +236,10 @@ Cast Integer Nat where
231 cast = fromInteger
236 cast = fromInteger
232
237
233Cast String Nat where
238Cast String Nat where
234− cast str = cast (the Integer (cast str))
239+ cast str = cast (the Integer (cast str))
240+
241+Cast Nat String where
242+ cast n = cast (the Integer (cast n))
235
243
236||| A wrapper for Nat that specifies the semigroup and monoid implementations that use (*)
244||| A wrapper for Nat that specifies the semigroup and monoid implementations that use (*)
237record Multiplicative where
245record Multiplicative where
libs/pruviloj/Pruviloj/Core.idr+48−2
@@ -225,13 +225,16 @@ refine tm =
225 countPi (RBind _ (Pi _ _) body) = S (countPi body)
225 countPi (RBind _ (Pi _ _) body) = S (countPi body)
226 countPi _ = Z
226 countPi _ = Z
227
227
228+||| A helper to extract the type representation for term.
229+getTTType : Raw -> Elab TT
230+getTTType r = snd <$> check !getEnv r
228
231
229||| Split a pair into its projections, binding them in the context
232||| Split a pair into its projections, binding them in the context
230||| with the supplied names. A special case of Coq's `inversion`.
233||| with the supplied names. A special case of Coq's `inversion`.
231both : Raw -> TTName -> TTName -> Elab ()
234both : Raw -> TTName -> TTName -> Elab ()
232both tm n1 n2 =
235both tm n1 n2 =
233 do -- We don't know that the term is canonical, so let-bind projections applied to it
236 do -- We don't know that the term is canonical, so let-bind projections applied to it
234− (A, B) <- isPairTy (snd !(check !getEnv tm))
237+ (A, B) <- isPairTy !(getTTType tm)
235 remember n1 A; apply `(fst {a=~A} {b=~B} ~tm) []; solve
238 remember n1 A; apply `(fst {a=~A} {b=~B} ~tm) []; solve
236 remember n2 B; apply `(snd {a=~A} {b=~B} ~tm) []; solve
239 remember n2 B; apply `(snd {a=~A} {b=~B} ~tm) []; solve
237 where
240 where
@@ -253,7 +256,6 @@ unproduct tm =
253 try (unproduct (Var n1))
256 try (unproduct (Var n1))
254 try (unproduct (Var n2))
257 try (unproduct (Var n2))
255
258
256−
257||| A special-purpose tactic that attempts to solve a goal using
259||| A special-purpose tactic that attempts to solve a goal using
258||| `Refl`. This is useful for ensuring that goals in fact are trivial
260||| `Refl`. This is useful for ensuring that goals in fact are trivial
259||| when developing or testing other tactics; otherwise, consider
261||| when developing or testing other tactics; otherwise, consider
@@ -268,3 +270,47 @@ reflexivity =
268 , NamePart `{reflexivity}
270 , NamePart `{reflexivity}
269 , TextPart "is not applicable."
271 , TextPart "is not applicable."
270 ]
272 ]
273+
274+||| Attempt to swap the sides of equality in a goal. If the goal is `x = y`,
275+||| after the invocation the focus will be on a hole of type `y = x`.
276+symmetry : Elab ()
277+symmetry =
278+ do [_,_,_,_,res] <- apply (Var `{{sym}}) [True, True, True, True, False]
279+ | _ => fail [TextPart "Failed while applying", NamePart `{symmetry}]
280+ solve
281+ focus res
282+
283+||| Swap the sides of an equality, saving the result in a `let`-binding.
284+||| Returns the generated name.
285+|||
286+||| @ t the equality proof to swap
287+||| @ hint a hint to use for generating the variable name for the result
288+symmetryAs : (t : Raw) -> (hint : String) -> Elab TTName
289+symmetryAs t hint =
290+ case !(getTTType t) of
291+ `((=) {A=~A} {B=~B} ~l ~r) =>
292+ do af <- forget A
293+ bf <- forget B
294+ lf <- forget l
295+ rf <- forget r
296+ let ts = the Raw $ `(sym {a=~af} {b=~bf} {left=~lf} {right=~rf} ~t)
297+ n <- gensym hint
298+ letbind n !(forget !(getTTType ts)) ts
299+ pure n
300+ tt => fail [TermPart tt, TextPart "is not an equality"]
301+
302+||| Apply a function term to an argument term, saving the result in a
303+||| `let`-binding. Returns the generated name.
304+|||
305+||| @ f the function to apply
306+||| @ x the term to apply to
307+||| @ hint a hint to use for generating the variable name for the result
308+applyAs : (f : Raw) -> (x : Raw) -> (hint : String) -> Elab TTName
309+applyAs f x hint =
310+ case !(getTTType f) of
311+ `(~xty -> ~yty) =>
312+ do let fx = RApp f x
313+ n <- gensym hint
314+ letbind n !(forget !(getTTType fx)) fx
315+ pure n
316+ ftt => fail [TermPart ftt, TextPart "is not a function"]
libs/pruviloj/Pruviloj/Derive/Eliminators.idr+2−2
@@ -130,8 +130,8 @@ getElimTy info ctors =
130data ElimArg = IHArgument TTName | NormalArgument TTName
130data ElimArg = IHArgument TTName | NormalArgument TTName
131
131
132implementation Show ElimArg where
132implementation Show ElimArg where
133− show (IHArgument x) = "IHArgument " ++ show x
133+ showPrec d (IHArgument x) = showCon d "IHArgument" $ showArg x
134− show (NormalArgument x) = "NormalArgument " ++ show x
134+ showPrec d (NormalArgument x) = showCon d "NormalArgument" $ showArg x
135
135
136getElimClause : TyConInfo -> (elimn : TTName) -> (methCount : Nat) ->
136getElimClause : TyConInfo -> (elimn : TTName) -> (methCount : Nat) ->
137 (TTName, List CtorArg, Raw) -> Nat -> Elab (FunClause Raw)
137 (TTName, List CtorArg, Raw) -> Nat -> Elab (FunClause Raw)
rts/Makefile+3−4
@@ -2,7 +2,7 @@ include ../config.mk
2
2
3OBJS = idris_rts.o idris_heap.o idris_gc.o idris_gmp.o idris_bitstring.o \
3OBJS = idris_rts.o idris_heap.o idris_gc.o idris_gmp.o idris_bitstring.o \
4 idris_opts.o idris_stats.o idris_utf8.o idris_stdfgn.o mini-gmp.o \
4 idris_opts.o idris_stats.o idris_utf8.o idris_stdfgn.o mini-gmp.o \
5− idris_buffer.o getline.o
5+ idris_buffer.o getline.o idris_net.o
6HDRS = idris_rts.h idris_heap.h idris_gc.h idris_gmp.h idris_bitstring.h \
6HDRS = idris_rts.h idris_heap.h idris_gc.h idris_gmp.h idris_bitstring.h \
7 idris_opts.h idris_stats.h mini-gmp.h idris_stdfgn.h idris_net.h \
7 idris_opts.h idris_stats.h mini-gmp.h idris_stdfgn.h idris_net.h \
8 idris_buffer.h idris_utf8.h getline.h
8 idris_buffer.h idris_utf8.h getline.h
@@ -20,10 +20,9 @@ endif
20endif
20endif
21
21
22ifeq ($(OS), windows)
22ifeq ($(OS), windows)
23− OBJS += windows/idris_net.o windows/win_utils.o
23+ OBJS += windows/win_utils.o
24else
24else
25 CFLAGS += -fPIC
25 CFLAGS += -fPIC
26− OBJS += idris_net.o
27endif
26endif
28
27
29LIBTARGET = libidris_rts.a
28LIBTARGET = libidris_rts.a
@@ -31,7 +30,7 @@ LIBTARGET = libidris_rts.a
31build: $(LIBTARGET) $(DYLIBTARGET)
30build: $(LIBTARGET) $(DYLIBTARGET)
32
31
33$(LIBTARGET) : $(OBJS)
32$(LIBTARGET) : $(OBJS)
34− $(AR) r $(LIBTARGET) $(OBJS)
33+ $(AR) rc $(LIBTARGET) $(OBJS)
35 $(RANLIB) $(LIBTARGET)
34 $(RANLIB) $(LIBTARGET)
36
35
37install :
36install :
rts/idris_net.c+36−7
@@ -3,15 +3,34 @@
3// MIT Licensed. Have fun!
3// MIT Licensed. Have fun!
4#include "idris_net.h"
4#include "idris_net.h"
5#include <errno.h>
5#include <errno.h>
6−#include <netdb.h>
7#include <stdbool.h>
6#include <stdbool.h>
8#include <stdlib.h>
7#include <stdlib.h>
9#include <stdio.h>
8#include <stdio.h>
10#include <string.h>
9#include <string.h>
11−#include <sys/types.h>
10+
12−#include <sys/socket.h>
11+#ifndef WIN32
13#include <netinet/in.h>
12#include <netinet/in.h>
14#include <arpa/inet.h>
13#include <arpa/inet.h>
14+#else
15+static int socket_inited = 0;
16+static WSADATA wsa_data;
17+
18+static void clean_sockets(void) {
19+ WSACleanup();
20+}
21+
22+static int check_init(void) {
23+ if (!socket_inited) {
24+ int result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
25+ if (result == NO_ERROR) {
26+ socket_inited = 1;
27+ atexit(clean_sockets);
28+ }
29+ }
30+ return socket_inited;
31+}
32+#endif
33+
15
34
16void buf_htonl(void* buf, int len) {
35void buf_htonl(void* buf, int len) {
17 int* buf_i = (int*) buf;
36 int* buf_i = (int*) buf;
@@ -37,6 +56,16 @@ void idrnet_free(void* ptr) {
37 free(ptr);
56 free(ptr);
38}
57}
39
58
59+
60+int idrnet_socket(int domain, int type, int protocol) {
61+#ifdef WIN32
62+ if (!check_init()) {
63+ return -1;
64+ }
65+#endif
66+ return socket(domain, type, protocol);
67+}
68+
40// We call this from quite a few functions. Given a textual host and an int port,
69// We call this from quite a few functions. Given a textual host and an int port,
41// populates a struct addrinfo.
70// populates a struct addrinfo.
42int idrnet_getaddrinfo(struct addrinfo** address_res, char* host, int port,
71int idrnet_getaddrinfo(struct addrinfo** address_res, char* host, int port,
@@ -65,7 +94,7 @@ int idrnet_getaddrinfo(struct addrinfo** address_res, char* host, int port,
65int idrnet_bind(int sockfd, int family, int socket_type, char* host, int port) {
94int idrnet_bind(int sockfd, int family, int socket_type, char* host, int port) {
66 struct addrinfo* address_res;
95 struct addrinfo* address_res;
67 int addr_res = idrnet_getaddrinfo(&address_res, host, port, family, socket_type);
96 int addr_res = idrnet_getaddrinfo(&address_res, host, port, family, socket_type);
68− if (addr_res == -1) {
97+ if (addr_res != 0) {
69 //printf("Lib err: bind getaddrinfo\n");
98 //printf("Lib err: bind getaddrinfo\n");
70 return -1;
99 return -1;
71 }
100 }
@@ -82,7 +111,7 @@ int idrnet_bind(int sockfd, int family, int socket_type, char* host, int port) {
82int idrnet_connect(int sockfd, int family, int socket_type, char* host, int port) {
111int idrnet_connect(int sockfd, int family, int socket_type, char* host, int port) {
83 struct addrinfo* remote_host;
112 struct addrinfo* remote_host;
84 int addr_res = idrnet_getaddrinfo(&remote_host, host, port, family, socket_type);
113 int addr_res = idrnet_getaddrinfo(&remote_host, host, port, family, socket_type);
85− if (addr_res == -1) {
114+ if (addr_res != 0) {
86 return -1;
115 return -1;
87 }
116 }
88
117
@@ -189,7 +218,7 @@ int idrnet_sendto(int sockfd, char* data, char* host, int port, int family) {
189
218
190 struct addrinfo* remote_host;
219 struct addrinfo* remote_host;
191 int addr_res = idrnet_getaddrinfo(&remote_host, host, port, family, SOCK_DGRAM);
220 int addr_res = idrnet_getaddrinfo(&remote_host, host, port, family, SOCK_DGRAM);
192− if (addr_res == -1) {
221+ if (addr_res != 0) {
193 return -1;
222 return -1;
194 }
223 }
195
224
@@ -203,7 +232,7 @@ int idrnet_sendto_buf(int sockfd, void* buf, int buf_len, char* host, int port,
203
232
204 struct addrinfo* remote_host;
233 struct addrinfo* remote_host;
205 int addr_res = idrnet_getaddrinfo(&remote_host, host, port, family, SOCK_DGRAM);
234 int addr_res = idrnet_getaddrinfo(&remote_host, host, port, family, SOCK_DGRAM);
206− if (addr_res == -1) {
235+ if (addr_res != 0) {
207 //printf("lib err: sendto getaddrinfo \n");
236 //printf("lib err: sendto getaddrinfo \n");
208 return -1;
237 return -1;
209 }
238 }
rts/idris_net.h+13
@@ -1,6 +1,17 @@
1#ifndef IDRISNET_H
1#ifndef IDRISNET_H
2#define IDRISNET_H
2#define IDRISNET_H
3
3
4+// Includes used by the idris-file.
5+#ifdef WIN32
6+#include <winsock2.h>
7+#include <Ws2tcpip.h>
8+#else
9+#include <netdb.h>
10+#include <unistd.h>
11+#include <sys/types.h>
12+#include <sys/socket.h>
13+#endif
14+
4struct sockaddr_storage;
15struct sockaddr_storage;
5struct addrinfo;
16struct addrinfo;
6
17
@@ -24,6 +35,8 @@ void idrnet_free(void* ptr);
24// Gets value of errno
35// Gets value of errno
25int idrnet_errno();
36int idrnet_errno();
26
37
38+int idrnet_socket(int domain, int type, int protocol);
39+
27// Bind
40// Bind
28int idrnet_bind(int sockfd, int family, int socket_type, char* host, int port);
41int idrnet_bind(int sockfd, int family, int socket_type, char* host, int port);
29
42
rts/idris_rts.c+10−4
@@ -460,6 +460,11 @@ void dumpVal(VAL v) {
460 case CT_STRING:
460 case CT_STRING:
461 printf("STR[%s]", v->info.str.str);
461 printf("STR[%s]", v->info.str.str);
462 break;
462 break;
463+ case CT_STROFFSET:
464+ printf("OFFSET[");
465+ dumpVal((VAL)(v->info.str_offset->str));
466+ printf("]");
467+ break;
463 case CT_FWD:
468 case CT_FWD:
464 printf("CT_FWD ");
469 printf("CT_FWD ");
465 dumpVal((VAL)(v->info.ptr));
470 dumpVal((VAL)(v->info.ptr));
@@ -591,15 +596,16 @@ VAL idris_castStrFloat(VM* vm, VAL i) {
591VAL idris_concat(VM* vm, VAL l, VAL r) {
596VAL idris_concat(VM* vm, VAL l, VAL r) {
592 char *rs = GETSTR(r);
597 char *rs = GETSTR(r);
593 char *ls = GETSTR(l);
598 char *ls = GETSTR(l);
594− // dumpVal(l);
599+ int llen = GETSTRLEN(l);
595− // printf("\n");
600+ int rlen = GETSTRLEN(r);
601+
596− Closure* cl = allocate(sizeof(Closure) + GETSTRLEN(l) + GETSTRLEN(r) + 1, 0);
602+ Closure* cl = allocate(sizeof(Closure) + llen + rlen + 1, 0);
597 SETTY(cl, CT_STRING);
603 SETTY(cl, CT_STRING);
598 cl->info.str.str = (char*)cl + sizeof(Closure);
604 cl->info.str.str = (char*)cl + sizeof(Closure);
599 strcpy(cl->info.str.str, ls);
605 strcpy(cl->info.str.str, ls);
600 strcat(cl->info.str.str, rs);
606 strcat(cl->info.str.str, rs);
601
607
602− cl->info.str.len = GETSTRLEN(l) + GETSTRLEN(r);
608+ cl->info.str.len = llen + rlen;
603 return cl;
609 return cl;
604}
610}
605
611
rts/idris_rts.h+2−7
@@ -206,14 +206,9 @@ typedef void(*func)(VM*, VAL*);
206#define CTAG(x) (((x)->info.c.tag_arity) >> 8)
206#define CTAG(x) (((x)->info.c.tag_arity) >> 8)
207#define CARITY(x) ((x)->info.c.tag_arity & 0x000000ff)
207#define CARITY(x) ((x)->info.c.tag_arity & 0x000000ff)
208
208
209−// Use top 16 bits for saying which heap value is in
210−// Bottom 16 bits for closure type
211−
212−#define GETTY(x) ((x)->ty & 0x0000ffff)
213−#define SETTY(x,t) (x)->ty = (((x)->ty & 0xffff0000) | (t))
214
209
215−#define GETHEAP(x) ((x)->ty >> 16)
210+#define GETTY(x) ((x)->ty)
216−#define SETHEAP(x,y) (x)->ty = (((x)->ty & 0x0000ffff) | ((y) << 16))
211+#define SETTY(x,t) ((x)->ty = t)
217
212
218// Integers, floats and operators
213// Integers, floats and operators
219
214
rts/idris_stdfgn.c−4
@@ -103,10 +103,6 @@ int isNull(void* ptr) {
103 return ptr==NULL;
103 return ptr==NULL;
104}
104}
105
105
106−int idris_eqPtr(void* x, void* y) {
107− return x==y;
108−}
109−
110void* idris_stdin() {
106void* idris_stdin() {
111 return (void*)stdin;
107 return (void*)stdin;
112}
108}
rts/idris_stdfgn.h−2
@@ -29,8 +29,6 @@ VAL idris_getString(VM* vm, void* buffer);
29void* do_popen(const char* cmd, const char* mode);
29void* do_popen(const char* cmd, const char* mode);
30int fpoll(void* h);
30int fpoll(void* h);
31
31
32−
33−int idris_eqPtr(void* x, void* y);
34int isNull(void* ptr);
32int isNull(void* ptr);
35void* idris_stdin();
33void* idris_stdin();
36
34
rts/windows/idris_net.cdeleted−200
@@ -1,200 +0,0 @@
1−// C-Side of the Idris network library
2−// (C) Simon Fowler, 2014
3−// MIT Licensed. Have fun!
4−#include "../idris_net.h"
5−
6−#include <errno.h>
7−#include <stdbool.h>
8−#include <stdlib.h>
9−#include <stdio.h>
10−#include <string.h>
11−#include <Winsock2.h>
12−#include <Ws2tcpip.h>
13−
14−
15−// inet_ntop isn't defined in the old mingw delivered with GHC,
16−// so put the prototype here, cribbed from a newer version of it
17−WINSOCK_API_LINKAGE LPCSTR WSAAPI InetNtopA(INT Family, PVOID pAddr,
18− LPSTR pStringBuf, size_t StringBufSize);
19−
20−static int socket_inited = 0;
21−static WSADATA wsa_data;
22−
23−void* idrnet_malloc(int size) {
24− return malloc(size);
25−}
26−
27−void idrnet_free(void* ptr) {
28− free(ptr);
29−}
30−
31−static void clean_sockets(void) {
32− WSACleanup();
33−}
34−
35−static int check_init(void)
36−{
37− if (!socket_inited) {
38− int result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
39− if (result == NO_ERROR) {
40− socket_inited = 1;
41− atexit(clean_sockets);
42− }
43− }
44− return socket_inited;
45−}
46−
47−int idrnet_bind(int sockfd, int family, int socket_type, char* host, int port) {
48− struct addrinfo hints;
49− struct addrinfo* address_res;
50− // Convert port into string
51− char str_port[8];
52− sprintf(str_port, "%d", port);
53−
54− if (!check_init()) {
55− return -1;
56− }
57− // Set up hints structure
58− memset(&hints, 0, sizeof(hints)); // zero out hints
59− hints.ai_family = family;
60− hints.ai_socktype = socket_type;
61−
62− // If the length of the hostname is 0 (i.e, it was set to Nothing in Idris)
63− // then we want to instruct the C library to fill in the IP automatically
64− if (strlen(host) == 0) {
65− hints.ai_flags = AI_PASSIVE; // fill in IP automatically
66− }
67−
68− int addr_res = getaddrinfo(host, str_port, &hints, &address_res);
69− if (addr_res == -1) {
70− return -1;
71− }
72−
73− int bind_res = bind(sockfd, address_res->ai_addr, address_res->ai_addrlen);
74− if (bind_res == -1) {
75− return -1;
76− }
77−
78− return 0;
79−}
80−
81−int idrnet_connect(int sockfd, int family, int socket_type, char* host, int port) {
82− char str_port[8];
83− sprintf(str_port, "%d", port);
84− struct addrinfo hints;
85− struct addrinfo* remote_host;
86−
87− if (!check_init()) {
88− return -1;
89− }
90− // Set up hints structure for getaddrinfo
91− memset(&hints, 0, sizeof(hints));
92− hints.ai_family = family;
93− hints.ai_socktype = socket_type;
94−
95− // Get info about the remote host (DNS lookup etc)
96− int addr_res = getaddrinfo(host, str_port, &hints, &remote_host);
97− if (addr_res == -1) {
98− return -1;
99− }
100−
101− int connect_res = connect(sockfd, remote_host->ai_addr, remote_host->ai_addrlen);
102− if (connect_res == -1) {
103− return -1;
104− }
105−
106− return 0;
107−}
108−
109−
110−int idrnet_sockaddr_family(void* sockaddr) {
111− struct sockaddr* addr = (struct sockaddr*) sockaddr;
112− return (int) addr->sa_family;
113−}
114−
115−char* idrnet_sockaddr_ipv4(void* sockaddr) {
116− struct sockaddr_in* addr = (struct sockaddr_in*) sockaddr;
117− char* ip_addr = (char*) malloc(sizeof(char) * INET_ADDRSTRLEN);
118− InetNtopA(AF_INET, &(addr->sin_addr), ip_addr, INET_ADDRSTRLEN);
119− return ip_addr;
120−}
121−
122−void* idrnet_create_sockaddr() {
123− return malloc(sizeof(struct sockaddr_storage));
124−}
125−
126−
127−int idrnet_accept(int sockfd, void* sockaddr) {
128− struct sockaddr* addr = (struct sockaddr*) sockaddr;
129− socklen_t addr_size = 0;
130− if (!check_init()) {
131− return -1;
132− }
133− return accept(sockfd, addr, &addr_size);
134−}
135−
136−int idrnet_send(int sockfd, char* data) {
137− int len = strlen(data); // For now.
138− if (!check_init()) {
139− return -1;
140− }
141− return send(sockfd, (void*) data, len, 0);
142−}
143−
144−int idrnet_send_buf(int sockfd, void* data, int len) {
145− if (!check_init()) {
146− return -1;
147− }
148− return send(sockfd, data, len, 0);
149−}
150−
151−void* idrnet_recv(int sockfd, int len) {
152− if (!check_init()) {
153− return NULL;
154− }
155− idrnet_recv_result* res_struct =
156− (idrnet_recv_result*) malloc(sizeof(idrnet_recv_result));
157−
158− char* buf = malloc(len + 1);
159− int recv_res = recv(sockfd, buf, len, 0);
160− res_struct->result = recv_res;
161−
162− if (recv_res > 0) { // Data was received
163− buf[recv_res + 1] = 0x00; // Null-term, so Idris can interpret it
164− }
165− res_struct->payload = (void*) buf;
166− return (void*) res_struct;
167−}
168−
169−int idrnet_recv_buf(int sockfd, void* buf, int len) {
170− if (!check_init()) {
171− return -1;
172− }
173− return recv(sockfd, buf, len, 0);
174−}
175−
176−int idrnet_get_recv_res(void* res_struct) {
177− return (((idrnet_recv_result*) res_struct)->result);
178−}
179−
180−char* idrnet_get_recv_payload(void* res_struct) {
181− return (((idrnet_recv_result*) res_struct)->payload);
182−}
183−
184−void idrnet_free_recv_struct(void* res_struct) {
185− idrnet_recv_result* i_res_struct =
186− (idrnet_recv_result*) res_struct;
187− if (i_res_struct->payload != NULL) {
188− free(i_res_struct->payload);
189− }
190− free(res_struct);
191−}
192−
193−int idrnet_errno() {
194− return errno;
195−}
196−
197−int idrnet_geteagain() {
198− return EAGAIN;
199−}
200−
scripts/runidrisnew file+25
@@ -0,0 +1,25 @@
1+#!/bin/sh
2+
3+# This is a script that runs an idris program, suitable for use
4+# in a shebang line. We cache the executables by naming them after
5+# the SHA hash of the idris source and looking for it before
6+# compiling
7+RUNIDRIS_DIR="${TEMP:-/tmp}/runidris"
8+if [ ! -d $RUNIDRIS_DIR ]; then
9+ mkdir $RUNIDRIS_DIR
10+ chmod 700 $RUNIDRIS_DIR
11+fi
12+
13+OS=`uname -s`
14+case $OS in
15+ OpenBSD ) TEMP_NAME="runidris-`sha1 -q $1`" ;;
16+ * ) TEMP_NAME="runidris-`sha1sum $1 | cut -c1-40`" ;;
17+esac
18+
19+FP="$RUNIDRIS_DIR/$TEMP_NAME"
20+cp "$1" "$FP.idr" # idris won't compile the script unless it ends in .idr
21+if [ ! -e $FP ]; then
22+ "${IDRIS:-idris}" "$FP.idr" --ibcsubdir "$RUNIDRIS_DIR" -i "." -o $FP
23+fi
24+shift
25+"$FP" "$@"
scripts/runidris-nodenew file+25
@@ -0,0 +1,25 @@
1+#!/bin/sh
2+
3+# This is a script that runs an idris program, suitable for use
4+# in a shebang line. We cache the executables by naming them after
5+# the SHA hash of the idris source and looking for it before
6+# compiling. This is the node version.
7+RUNIDRIS_DIR="${TEMP:-/tmp}/runidris-node"
8+if [ ! -d $RUNIDRIS_DIR ]; then
9+ mkdir $RUNIDRIS_DIR
10+ chmod 700 $RUNIDRIS_DIR
11+fi
12+
13+OS=`uname -s`
14+case $OS in
15+ OpenBSD ) TEMP_NAME="runidris-`sha1 -q $1`" ;;
16+ * ) TEMP_NAME="runidris-`sha1sum $1 | cut -c1-40`" ;;
17+esac
18+
19+FP="$RUNIDRIS_DIR/$TEMP_NAME"
20+cp "$1" "$FP.idr" # idris won't compile the script unless it ends in .idr
21+if [ ! -e "$FP.js" ]; then
22+ "${IDRIS:-idris}" --codegen node --ibcsubdir "$RUNIDRIS_DIR" -i "." "$FP.idr" -o "$FP.js"
23+fi
24+shift
25+node "$FP.js" "$@"
src/IRTS/CodegenC.hs+3−1
@@ -5,6 +5,8 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8+{-# LANGUAGE FlexibleContexts #-}
9+
8module IRTS.CodegenC (codegenC) where
10module IRTS.CodegenC (codegenC) where
9
11
10import Idris.AbsSyntax
12import Idris.AbsSyntax
@@ -183,7 +185,7 @@ bcc i (ASSIGNCONST l c)
183 mkConst (I i) = "MKINT(" ++ show i ++ ")"
185 mkConst (I i) = "MKINT(" ++ show i ++ ")"
184 mkConst (BI i) | i < (2^30) = "MKINT(" ++ show i ++ ")"
186 mkConst (BI i) | i < (2^30) = "MKINT(" ++ show i ++ ")"
185 | otherwise = "MKBIGC(vm,\"" ++ show i ++ "\")"
187 | otherwise = "MKBIGC(vm,\"" ++ show i ++ "\")"
186− mkConst (Fl f) = "MKFLOAT(vm, " ++ show f ++ ")"
188+ mkConst (Fl f) = "MKFLOAT(vm, " ++ (map toUpper $ show f) ++ ")"
187 mkConst (Ch c) = "MKINT(" ++ show (fromEnum c) ++ ")"
189 mkConst (Ch c) = "MKINT(" ++ show (fromEnum c) ++ ")"
188 mkConst (Str s) = "MKSTR(vm, " ++ showCStr s ++ ")"
190 mkConst (Str s) = "MKSTR(vm, " ++ showCStr s ++ ")"
189 mkConst (B8 x) = "idris_b8const(vm, " ++ show x ++ "U)"
191 mkConst (B8 x) = "idris_b8const(vm, " ++ show x ++ "U)"
src/IRTS/Compiler.hs+17−15
@@ -5,7 +5,7 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8−{-# LANGUAGE CPP, PatternGuards, TypeSynonymInstances #-}
8+{-# LANGUAGE CPP, FlexibleContexts, PatternGuards, TypeSynonymInstances #-}
9
9
10module IRTS.Compiler(compile, generate) where
10module IRTS.Compiler(compile, generate) where
11
11
@@ -63,6 +63,8 @@ compile codegen f mtm = do
63 Nothing -> []
63 Nothing -> []
64 Just t -> freeNames t
64 Just t -> freeNames t
65
65
66+ logCodeGen 1 "Running Erasure Analysis"
67+ iReport 3 "Running Erasure Analysis"
66 reachableNames <- performUsageAnalysis
68 reachableNames <- performUsageAnalysis
67 (rootNames ++ getExpNames exports)
69 (rootNames ++ getExpNames exports)
68 maindef <- case mtm of
70 maindef <- case mtm of
@@ -74,7 +76,7 @@ compile codegen f mtm = do
74 libs <- getLibs codegen
76 libs <- getLibs codegen
75 flags <- getFlags codegen
77 flags <- getFlags codegen
76 hdrs <- getHdrs codegen
78 hdrs <- getHdrs codegen
77− impdirs <- allImportDirs
79+ impdirs <- rankedImportDirs f
78 ttDeclarations <- getDeclarations reachableNames
80 ttDeclarations <- getDeclarations reachableNames
79 defsIn <- mkDecls reachableNames
81 defsIn <- mkDecls reachableNames
80 -- if no 'main term' given, generate interface files
82 -- if no 'main term' given, generate interface files
@@ -212,7 +214,7 @@ build (n, d)
212 Just (ar, op) ->
214 Just (ar, op) ->
213 let args = map (\x -> sMN x "op") [0..] in
215 let args = map (\x -> sMN x "op") [0..] in
214 return (n, (LFun [] n (take ar args)
216 return (n, (LFun [] n (take ar args)
215− (LOp op (map (LV . Glob) (take ar args)))))
217+ (LOp op (map LV (take ar args)))))
216 _ -> do def <- mkLDecl n d
218 _ -> do def <- mkLDecl n d
217 logCodeGen 3 $ "Compiled " ++ show n ++ " =\n\t" ++ show def
219 logCodeGen 3 $ "Compiled " ++ show n ++ " =\n\t" ++ show def
218 return (n, def)
220 return (n, def)
@@ -396,7 +398,7 @@ irTerm top vs env tm@(App _ f a) = do
396 -> irTerm top vs env (head argsPruned)
398 -> irTerm top vs env (head argsPruned)
397
399
398 | otherwise -- not newtype, plain data ctor
400 | otherwise -- not newtype, plain data ctor
399− -> buildApp (LV $ Glob n) argsPruned
401+ -> buildApp (LV n) argsPruned
400
402
401 -- not saturated, underapplied
403 -- not saturated, underapplied
402 LT | isNewtype -- newtype
404 LT | isNewtype -- newtype
@@ -405,11 +407,11 @@ irTerm top vs env tm@(App _ f a) = do
405 <$> irTerm top vs env (head argsPruned)
407 <$> irTerm top vs env (head argsPruned)
406
408
407 | isNewtype -- newtype but the value is not among args yet
409 | isNewtype -- newtype but the value is not among args yet
408− -> return . padLams $ \[vn] -> LApp False (LV $ Glob n) [LV $ Glob vn]
410+ -> return . padLams $ \[vn] -> LApp False (LV n) [LV vn]
409
411
410 -- not a newtype, just apply to a constructor
412 -- not a newtype, just apply to a constructor
411 | otherwise
413 | otherwise
412− -> padLams . applyToNames <$> buildApp (LV $ Glob n) argsPruned
414+ -> padLams . applyToNames <$> buildApp (LV n) argsPruned
413
415
414 -- type constructor
416 -- type constructor
415 (P (TCon t a) n _, args) -> return LNothing
417 (P (TCon t a) n _, args) -> return LNothing
@@ -444,7 +446,7 @@ irTerm top vs env tm@(App _ f a) = do
444
446
445 applyToNames :: LExp -> [Name] -> LExp
447 applyToNames :: LExp -> [Name] -> LExp
446 applyToNames tm [] = tm
448 applyToNames tm [] = tm
447− applyToNames tm ns = LApp False tm $ map (LV . Glob) ns
449+ applyToNames tm ns = LApp False tm $ map LV ns
448
450
449 padLambdas :: [Int] -> Int -> Int -> ([Name] -> LExp) -> LExp
451 padLambdas :: [Int] -> Int -> Int -> ([Name] -> LExp) -> LExp
450 padLambdas used startIdx endSIdx mkTerm
452 padLambdas used startIdx endSIdx mkTerm
@@ -455,7 +457,7 @@ irTerm top vs env tm@(App _ f a) = do
455
457
456 applyName :: Name -> IState -> [Term] -> Idris LExp
458 applyName :: Name -> IState -> [Term] -> Idris LExp
457 applyName n ist args =
459 applyName n ist args =
458− LApp False (LV $ Glob n) <$> mapM (irTerm top vs env . erase) (zip [0..] args)
460+ LApp False (LV n) <$> mapM (irTerm top vs env . erase) (zip [0..] args)
459 where
461 where
460 erase (i, x)
462 erase (i, x)
461 | i >= arity || i `elem` used = x
463 | i >= arity || i `elem` used = x
@@ -477,9 +479,9 @@ irTerm top vs env tm@(App _ f a) = do
477 used = maybe [] (map fst . usedpos) $ lookupCtxtExact uName (idris_callgraph ist)
479 used = maybe [] (map fst . usedpos) $ lookupCtxtExact uName (idris_callgraph ist)
478 fst4 (x,_,_,_,_,_) = x
480 fst4 (x,_,_,_,_,_) = x
479
481
480−irTerm top vs env (P _ n _) = return $ LV (Glob n)
482+irTerm top vs env (P _ n _) = return $ LV n
481irTerm top vs env (V i)
483irTerm top vs env (V i)
482− | i >= 0 && i < length env = return $ LV (Glob (env!!i))
484+ | i >= 0 && i < length env = return $ LV (env!!i)
483 | otherwise = ifail $ "bad de bruijn index: " ++ show i
485 | otherwise = ifail $ "bad de bruijn index: " ++ show i
484
486
485irTerm top vs env (Bind n (Lam _ _) sc) = LLam [n'] <$> irTerm top vs (n':env) sc
487irTerm top vs env (Bind n (Lam _ _) sc) = LLam [n'] <$> irTerm top vs (n':env) sc
@@ -544,7 +546,7 @@ irSC top vs (ProjCase tm alts) = do
544irSC top vs (Case up n [ConCase (UN delay) i [_, _, n'] sc])
546irSC top vs (Case up n [ConCase (UN delay) i [_, _, n'] sc])
545 | delay == txt "Delay"
547 | delay == txt "Delay"
546 = do sc' <- irSC top vs sc -- mkForce n' n sc
548 = do sc' <- irSC top vs sc -- mkForce n' n sc
547− return $ lsubst n' (LForce (LV (Glob n))) sc'
549+ return $ lsubst n' (LForce (LV n)) sc'
548
550
549-- There are two transformations in this case:
551-- There are two transformations in this case:
550--
552--
@@ -581,10 +583,10 @@ irSC top vs (Case up n [alt]) = do
581 case replacement of
583 case replacement of
582 Just sc -> irSC top vs sc
584 Just sc -> irSC top vs sc
583 _ -> do
585 _ -> do
584− alt' <- irAlt top vs (LV (Glob n)) alt
586+ alt' <- irAlt top vs (LV n) alt
585 return $ case namesBoundIn alt' `usedIn` subexpr alt' of
587 return $ case namesBoundIn alt' `usedIn` subexpr alt' of
586 [] -> subexpr alt' -- strip the unused top-most case
588 [] -> subexpr alt' -- strip the unused top-most case
587− _ -> LCase up (LV (Glob n)) [alt']
589+ _ -> LCase up (LV n) [alt']
588 where
590 where
589 namesBoundIn :: LAlt -> [Name]
591 namesBoundIn :: LAlt -> [Name]
590 namesBoundIn (LConCase cn i ns sc) = ns
592 namesBoundIn (LConCase cn i ns sc) = ns
@@ -616,7 +618,7 @@ irSC top vs (Case up n alts@[ConCase cn a ns sc, DefaultCase sc']) = do
616 detag <- fgetState (opt_detaggable . ist_optimisation cn)
618 detag <- fgetState (opt_detaggable . ist_optimisation cn)
617 if detag
619 if detag
618 then irSC top vs (Case up n [ConCase cn a ns sc])
620 then irSC top vs (Case up n [ConCase cn a ns sc])
619− else LCase up (LV (Glob n)) <$> mapM (irAlt top vs (LV (Glob n))) alts
621+ else LCase up (LV n) <$> mapM (irAlt top vs (LV n)) alts
620
622
621irSC top vs sc@(Case up n alts) = do
623irSC top vs sc@(Case up n alts) = do
622 -- check that neither alternative needs the newtype optimisation,
624 -- check that neither alternative needs the newtype optimisation,
@@ -626,7 +628,7 @@ irSC top vs sc@(Case up n alts) = do
626 $ ifail ("irSC: non-trivial case-match on detaggable data: " ++ show sc)
628 $ ifail ("irSC: non-trivial case-match on detaggable data: " ++ show sc)
627
629
628 -- everything okay
630 -- everything okay
629− LCase up (LV (Glob n)) <$> mapM (irAlt top vs (LV (Glob n))) alts
631+ LCase up (LV n) <$> mapM (irAlt top vs (LV n)) alts
630 where
632 where
631 isDetaggable (ConCase cn _ _ _) = fgetState $ opt_detaggable . ist_optimisation cn
633 isDetaggable (ConCase cn _ _ _) = fgetState $ opt_detaggable . ist_optimisation cn
632 isDetaggable _ = return False
634 isDetaggable _ = return False
src/IRTS/Defunctionalise.hs+24−25
@@ -19,7 +19,7 @@ To defunctionalise:
198. Add explicit EVAL to case, primitives, and foreign calls
198. Add explicit EVAL to case, primitives, and foreign calls
20
20
21-}
21-}
22−{-# LANGUAGE PatternGuards #-}
22+{-# LANGUAGE FlexibleContexts, PatternGuards #-}
23module IRTS.Defunctionalise(module IRTS.Defunctionalise
23module IRTS.Defunctionalise(module IRTS.Defunctionalise
24 , module IRTS.Lang
24 , module IRTS.Lang
25 ) where
25 ) where
@@ -34,12 +34,12 @@ import Data.List
34import Data.Maybe
34import Data.Maybe
35import Debug.Trace
35import Debug.Trace
36
36
37−data DExp = DV LVar
37+data DExp = DV Name
38 | DApp Bool Name [DExp] -- True = tail call
38 | DApp Bool Name [DExp] -- True = tail call
39 | DLet Name DExp DExp -- name just for pretty printing
39 | DLet Name DExp DExp -- name just for pretty printing
40 | DUpdate Name DExp -- eval expression, then update var with it
40 | DUpdate Name DExp -- eval expression, then update var with it
41 | DProj DExp Int
41 | DProj DExp Int
42− | DC (Maybe LVar) Int Name [DExp]
42+ | DC (Maybe Name) Int Name [DExp]
43 | DCase CaseType DExp [DAlt]
43 | DCase CaseType DExp [DAlt]
44 | DChkCase DExp [DAlt] -- a case where the type is unknown (for EVAL/APPLY)
44 | DChkCase DExp [DAlt] -- a case where the type is unknown (for EVAL/APPLY)
45 | DConst Const
45 | DConst Const
@@ -90,27 +90,27 @@ addApps defs (n, LFun _ _ args e)
90 return (n, DFun n args e')
90 return (n, DFun n args e')
91 where
91 where
92 aa :: [Name] -> LExp -> State ([Name], [(Name, Int)]) DExp
92 aa :: [Name] -> LExp -> State ([Name], [(Name, Int)]) DExp
93− aa env (LV (Glob n)) | n `elem` env = return $ DV (Glob n)
93+ aa env (LV n) | n `elem` env = return $ DV n
94− | otherwise = aa env (LApp False (LV (Glob n)) [])
94+ | otherwise = aa env (LApp False (LV n) [])
95− aa env (LApp tc (LV (Glob n)) args)
95+ aa env (LApp tc (LV n) args)
96 = do args' <- mapM (aa env) args
96 = do args' <- mapM (aa env) args
97 case lookupCtxtExact n defs of
97 case lookupCtxtExact n defs of
98 Just (LConstructor _ i ar) -> return $ DApp tc n args'
98 Just (LConstructor _ i ar) -> return $ DApp tc n args'
99 Just (LFun _ _ as _) -> let arity = length as in
99 Just (LFun _ _ as _) -> let arity = length as in
100 fixApply tc n args' arity
100 fixApply tc n args' arity
101− Nothing -> return $ chainAPPLY (DV (Glob n)) args'
101+ Nothing -> return $ chainAPPLY (DV n) args'
102 aa env (LLazyApp n args)
102 aa env (LLazyApp n args)
103 = do args' <- mapM (aa env) args
103 = do args' <- mapM (aa env) args
104 case lookupCtxtExact n defs of
104 case lookupCtxtExact n defs of
105 Just (LConstructor _ i ar) -> return $ DApp False n args'
105 Just (LConstructor _ i ar) -> return $ DApp False n args'
106 Just (LFun _ _ as _) -> let arity = length as in
106 Just (LFun _ _ as _) -> let arity = length as in
107 fixLazyApply n args' arity
107 fixLazyApply n args' arity
108− Nothing -> return $ chainAPPLY (DV (Glob n)) args'
108+ Nothing -> return $ chainAPPLY (DV n) args'
109− aa env (LForce (LLazyApp n args)) = aa env (LApp False (LV (Glob n)) args)
109+ aa env (LForce (LLazyApp n args)) = aa env (LApp False (LV n) args)
110 aa env (LForce e) = liftM eEVAL (aa env e)
110 aa env (LForce e) = liftM eEVAL (aa env e)
111 aa env (LLet n v sc) = liftM2 (DLet n) (aa env v) (aa (n : env) sc)
111 aa env (LLet n v sc) = liftM2 (DLet n) (aa env v) (aa (n : env) sc)
112 aa env (LCon loc i n args) = liftM (DC loc i n) (mapM (aa env) args)
112 aa env (LCon loc i n args) = liftM (DC loc i n) (mapM (aa env) args)
113− aa env (LProj t@(LV (Glob n)) i)
113+ aa env (LProj t@(LV n) i)
114 | n `elem` env = do t' <- aa env t
114 | n `elem` env = do t' <- aa env t
115 return $ DProj (DUpdate n t') i
115 return $ DProj (DUpdate n t') i
116 aa env (LProj t i) = do t' <- aa env t
116 aa env (LProj t i) = do t' <- aa env t
@@ -170,7 +170,7 @@ addApps defs (n, LFun _ _ args e)
170
170
171 preEval [] t = t
171 preEval [] t = t
172 preEval (x : xs) t
172 preEval (x : xs) t
173− | needsEval x t = DLet x (DV (Glob x)) (preEval xs t)
173+ | needsEval x t = DLet x (DV x) (preEval xs t)
174 | otherwise = preEval xs t
174 | otherwise = preEval xs t
175
175
176 needsEval x (DApp _ _ args) = any (needsEval x) args
176 needsEval x (DApp _ _ args) = any (needsEval x) args
@@ -188,7 +188,7 @@ addApps defs (n, LFun _ _ args e)
188 | otherwise = needsEval x v || needsEval x e
188 | otherwise = needsEval x v || needsEval x e
189 needsEval x (DForeign _ _ args) = any (needsEval x) (map snd args)
189 needsEval x (DForeign _ _ args) = any (needsEval x) (map snd args)
190 needsEval x (DOp op args) = any (needsEval x) args
190 needsEval x (DOp op args) = any (needsEval x) args
191− needsEval x (DProj (DV (Glob x')) _) = x == x'
191+ needsEval x (DProj (DV x') _) = x == x'
192 needsEval x _ = False
192 needsEval x _ = False
193
193
194eEVAL x = DApp False (sMN 0 "EVAL") [x]
194eEVAL x = DApp False (sMN 0 "EVAL") [x]
@@ -207,7 +207,7 @@ toCons ns (n, i)
207 EvalCase (\tlarg ->
207 EvalCase (\tlarg ->
208 (DConCase (-1) (mkFnCon n) (take i (genArgs 0))
208 (DConCase (-1) (mkFnCon n) (take i (genArgs 0))
209 (dupdate tlarg
209 (dupdate tlarg
210− (DApp False n (map (DV . Glob) (take i (genArgs 0))))))))
210+ (DApp False n (map DV (take i (genArgs 0))))))))
211 : [] -- mkApplyCase n 0 i
211 : [] -- mkApplyCase n 0 i
212 | otherwise = []
212 | otherwise = []
213 where dupdate tlarg x = DUpdate tlarg x
213 where dupdate tlarg x = DUpdate tlarg x
@@ -219,7 +219,7 @@ toConsA ns (n, i)
219-- EvalCase (\tlarg ->
219-- EvalCase (\tlarg ->
220-- (DConCase (-1) (mkFnCon n) (take i (genArgs 0))
220-- (DConCase (-1) (mkFnCon n) (take i (genArgs 0))
221-- (dupdate tlarg
221-- (dupdate tlarg
222−-- (DApp False n (map (DV . Glob) (take i (genArgs 0))))))))
222+-- (DApp False n (map DV (take i (genArgs 0))))))))
223 = mkApplyCase n ar i
223 = mkApplyCase n ar i
224 | otherwise = []
224 | otherwise = []
225 where dupdate tlarg x = x
225 where dupdate tlarg x = x
@@ -229,13 +229,13 @@ mkApplyCase fname n ar
229 = let nm = mkUnderCon fname (ar - n) in
229 = let nm = mkUnderCon fname (ar - n) in
230 (nm, n, ApplyCase (DConCase (-1) nm (take n (genArgs 0))
230 (nm, n, ApplyCase (DConCase (-1) nm (take n (genArgs 0))
231 (DApp False (mkUnderCon fname (ar - (n + 1)))
231 (DApp False (mkUnderCon fname (ar - (n + 1)))
232− (map (DV . Glob) (take n (genArgs 0) ++
232+ (map DV (take n (genArgs 0) ++
233 [sMN 0 "arg"])))))
233 [sMN 0 "arg"])))))
234 :
234 :
235 if (ar - (n + 2) >=0 )
235 if (ar - (n + 2) >=0 )
236 then (nm, n, Apply2Case (DConCase (-1) nm (take n (genArgs 0))
236 then (nm, n, Apply2Case (DConCase (-1) nm (take n (genArgs 0))
237 (DApp False (mkUnderCon fname (ar - (n + 2)))
237 (DApp False (mkUnderCon fname (ar - (n + 2)))
238− (map (DV . Glob) (take n (genArgs 0) ++
238+ (map DV (take n (genArgs 0) ++
239 [sMN 0 "arg0", sMN 0 "arg1"])))))
239 [sMN 0 "arg0", sMN 0 "arg1"])))))
240 :
240 :
241 mkApplyCase fname (n + 1) ar
241 mkApplyCase fname (n + 1) ar
@@ -243,9 +243,9 @@ mkApplyCase fname n ar
243
243
244mkEval :: [(Name, Int, EvalApply DAlt)] -> (Name, DDecl)
244mkEval :: [(Name, Int, EvalApply DAlt)] -> (Name, DDecl)
245mkEval xs = (sMN 0 "EVAL", DFun (sMN 0 "EVAL") [sMN 0 "arg"]
245mkEval xs = (sMN 0 "EVAL", DFun (sMN 0 "EVAL") [sMN 0 "arg"]
246− (mkBigCase (sMN 0 "EVAL") 256 (DV (Glob (sMN 0 "arg")))
246+ (mkBigCase (sMN 0 "EVAL") 256 (DV (sMN 0 "arg"))
247 (mapMaybe evalCase xs ++
247 (mapMaybe evalCase xs ++
248− [DDefaultCase (DV (Glob (sMN 0 "arg")))])))
248+ [DDefaultCase (DV (sMN 0 "arg"))])))
249 where
249 where
250 evalCase (n, t, EvalCase x) = Just (x (sMN 0 "arg"))
250 evalCase (n, t, EvalCase x) = Just (x (sMN 0 "arg"))
251 evalCase _ = Nothing
251 evalCase _ = Nothing
@@ -256,7 +256,7 @@ mkApply xs = (sMN 0 "APPLY", DFun (sMN 0 "APPLY") [sMN 0 "fn", sMN 0 "arg"]
256 [] -> DNothing
256 [] -> DNothing
257 cases ->
257 cases ->
258 mkBigCase (sMN 0 "APPLY") 256
258 mkBigCase (sMN 0 "APPLY") 256
259− (DV (Glob (sMN 0 "fn")))
259+ (DV (sMN 0 "fn"))
260 (cases ++
260 (cases ++
261 [DDefaultCase DNothing])))
261 [DDefaultCase DNothing])))
262 where
262 where
@@ -269,14 +269,14 @@ mkApply2 xs = (sMN 0 "APPLY2", DFun (sMN 0 "APPLY2") [sMN 0 "fn", sMN 0 "arg0",
269 [] -> DNothing
269 [] -> DNothing
270 cases ->
270 cases ->
271 mkBigCase (sMN 0 "APPLY") 256
271 mkBigCase (sMN 0 "APPLY") 256
272− (DV (Glob (sMN 0 "fn")))
272+ (DV (sMN 0 "fn"))
273 (cases ++
273 (cases ++
274 [DDefaultCase
274 [DDefaultCase
275 (DApp False (sMN 0 "APPLY")
275 (DApp False (sMN 0 "APPLY")
276 [DApp False (sMN 0 "APPLY")
276 [DApp False (sMN 0 "APPLY")
277− [DV (Glob (sMN 0 "fn")),
277+ [DV (sMN 0 "fn"),
278− DV (Glob (sMN 0 "arg0"))],
278+ DV (sMN 0 "arg0")],
279− DV (Glob (sMN 0 "arg1"))])
279+ DV (sMN 0 "arg1")])
280 ])))
280 ])))
281 where
281 where
282 applyCase (n, t, Apply2Case x) = Just x
282 applyCase (n, t, Apply2Case x) = Just x
@@ -297,8 +297,7 @@ mkUnderCon n missing = sMN missing ("U_" ++ show n)
297
297
298instance Show DExp where
298instance Show DExp where
299 show e = show' [] e where
299 show e = show' [] e where
300− show' env (DV (Loc i)) = "var " ++ env!!i
300+ show' env (DV n) = show n
301− show' env (DV (Glob n)) = "GLOB " ++ show n
302 show' env (DApp _ e args) = show e ++ "(" ++
301 show' env (DApp _ e args) = show e ++ "(" ++
303 showSep ", " (map (show' env) args) ++")"
302 showSep ", " (map (show' env) args) ++")"
304 show' env (DLet n v e) = "let " ++ show n ++ " = " ++ show' env v ++ " in " ++
303 show' env (DLet n v e) = "let " ++ show n ++ " = " ++ show' env v ++ " in " ++
src/IRTS/JavaScript/Codegen.hs+43−55
@@ -20,15 +20,16 @@ import IRTS.JavaScript.Name
20import IRTS.JavaScript.PrimOp
20import IRTS.JavaScript.PrimOp
21import IRTS.JavaScript.Specialize
21import IRTS.JavaScript.Specialize
22import IRTS.Lang
22import IRTS.Lang
23−import IRTS.LangOpts
24import IRTS.System
23import IRTS.System
25
24
25+import Control.Applicative (pure, (<$>))
26import Control.Monad
26import Control.Monad
27import Control.Monad.Trans.State
27import Control.Monad.Trans.State
28−import Data.List (nub)
28+import Data.Foldable (foldMap)
29+import Data.Generics.Uniplate.Data
30+import Data.List
29import Data.Map.Strict (Map)
31import Data.Map.Strict (Map)
30import qualified Data.Map.Strict as Map
32import qualified Data.Map.Strict as Map
31−import Data.Maybe (fromJust)
32import Data.Set (Set)
33import Data.Set (Set)
33import qualified Data.Set as Set
34import qualified Data.Set as Set
34import Data.Text (Text)
35import Data.Text (Text)
@@ -38,23 +39,27 @@ import System.Directory (doesFileExist)
38import System.Environment
39import System.Environment
39import System.FilePath
40import System.FilePath
40
41
41−import Control.Applicative (pure, (<$>))
42−import Data.Char
43−import Data.Data
44−import Data.Generics.Uniplate.Data
45−import Data.List
46−import GHC.Generics (Generic)
47
42
43+-- | Code generation stats hold information about the generated user
44+-- code. Based on that information we add additional code to make
45+-- things work.
48data CGStats = CGStats { usedBigInt :: Bool
46data CGStats = CGStats { usedBigInt :: Bool
49 , partialApplications :: Set Partial
47 , partialApplications :: Set Partial
50 , hiddenClasses :: Set HiddenClass
48 , hiddenClasses :: Set HiddenClass
51 }
49 }
52
50
53−emptyStats :: CGStats
51+-- If we generate code for two declarations we want to merge their code
52+-- generation stats.
53+instance Monoid CGStats where
54−emptyStats = CGStats { partialApplications = Set.empty
54+ mempty = CGStats { partialApplications = Set.empty
55− , hiddenClasses = Set.empty
55+ , hiddenClasses = Set.empty
56− , usedBigInt = False
56+ , usedBigInt = False
57− }
57+ }
58+ mappend x y = CGStats { partialApplications = partialApplications x `Set.union` partialApplications y
59+ , hiddenClasses = hiddenClasses x `Set.union` hiddenClasses y
60+ , usedBigInt = usedBigInt x || usedBigInt y
61+ }
62+
58
63
59data CGConf = CGConf { header :: Text
64data CGConf = CGConf { header :: Text
60 , footer :: Text
65 , footer :: Text
@@ -101,13 +106,11 @@ codegenJs conf ci =
101 let defs' = Map.fromList $ liftDecls ci
106 let defs' = Map.fromList $ liftDecls ci
102 let defs = globlToCon defs'
107 let defs = globlToCon defs'
103 let used = Map.elems $ removeDeadCode defs [sMN 0 "runMain"]
108 let used = Map.elems $ removeDeadCode defs [sMN 0 "runMain"]
104− if debug then
109+ when debug $ do
105− do
106 writeFile (outputFile ci ++ ".LDeclsDebug") $ (unlines $ intersperse "" $ map show used) ++ "\n\n\n"
110 writeFile (outputFile ci ++ ".LDeclsDebug") $ (unlines $ intersperse "" $ map show used) ++ "\n\n\n"
107 putStrLn $ "Finished calculating used"
111 putStrLn $ "Finished calculating used"
108− else pure ()
109
112
110− let (out, stats) = doCodegen conf defs used
113+ let (out, stats) = doCodegen defs used
111
114
112 path <- getIdrisJSRTSDir
115 path <- getIdrisJSRTSDir
113 jsbn <- if usedBigInt stats
116 jsbn <- if usedBigInt stats
@@ -160,20 +163,21 @@ doHiddenClasses x =
160 JsFun (jsNameHiddenClass p) vars $ JsSeq (JsSet (JsProp JsThis "type") (JsInt id)) $ seqJs
163 JsFun (jsNameHiddenClass p) vars $ JsSeq (JsSet (JsProp JsThis "type") (JsInt id)) $ seqJs
161 $ map (\tv -> JsSet (JsProp JsThis tv) (JsVar tv)) vars
164 $ map (\tv -> JsSet (JsProp JsThis tv) (JsVar tv)) vars
162
165
163−doCodegen :: CGConf -> Map Name LDecl -> [LDecl] -> (Text, CGStats)
166+
164−doCodegen conf defs decls =
167+-- | Generate code for each declaration and collect stats.
165− let xs = map (doCodegenDecl conf defs) decls
168+-- LFunctions are turned into JS function declarations. They are
166− groupCGStats x y = CGStats { partialApplications = partialApplications x `Set.union` partialApplications y
169+-- preceded by a comment that gives their name. Constructor
167− , hiddenClasses = hiddenClasses x `Set.union` hiddenClasses y
170+-- declarations are ignored.
168− , usedBigInt = usedBigInt x || usedBigInt y
171+doCodegen :: Map Name LDecl -> [LDecl] -> (Text, CGStats)
169− }
172+doCodegen defs = foldMap (doCodegenDecl defs)
170− in (T.intercalate "\n" $ map fst xs, foldl' groupCGStats emptyStats (map snd xs) )
173+ where
171−
172−doCodegenDecl :: CGConf -> Map Name LDecl -> LDecl -> (Text, CGStats)
174+ doCodegenDecl :: Map Name LDecl -> LDecl -> (Text, CGStats)
173−doCodegenDecl conf defs (LFun _ n args def) =
175+ doCodegenDecl defs (LFun _ name args def) =
174− let (ast, stats) = cgFun conf defs n args def
176+ let (ast, stats) = cgFun defs name args def
175− in (T.concat [jsStmt2Text (JsComment $ T.pack $ show n), "\n", jsStmt2Text ast], stats)
177+ fnComment = jsStmt2Text (JsComment $ T.pack $ show name)
178+ in (T.concat [fnComment, "\n", jsStmt2Text ast, "\n"], stats)
176−doCodegenDecl conf defs (LConstructor n i sz) = ("", emptyStats)
179+ doCodegenDecl defs (LConstructor n i sz) = ("", mempty)
180+
177
181
178seqJs :: [JsStmt] -> JsStmt
182seqJs :: [JsStmt] -> JsStmt
179seqJs [] = JsEmpty
183seqJs [] = JsEmpty
@@ -186,7 +190,6 @@ data CGBodyState = CGBodyState { defs :: Map Name LDecl
186 , currentFnNameAndArgs :: (Text, [Text])
190 , currentFnNameAndArgs :: (Text, [Text])
187 , usedArgsTailCallOptim :: Set (Text, Text)
191 , usedArgsTailCallOptim :: Set (Text, Text)
188 , isTailRec :: Bool
192 , isTailRec :: Bool
189− , conf :: CGConf
190 , usedITBig :: Bool
193 , usedITBig :: Bool
191 , partialApps :: Set Partial
194 , partialApps :: Set Partial
192 , hiddenCls :: Set HiddenClass
195 , hiddenCls :: Set HiddenClass
@@ -212,10 +215,6 @@ addUsedArgsTailCallOptim :: Set (Text, Text) -> State CGBodyState ()
212addUsedArgsTailCallOptim p =
215addUsedArgsTailCallOptim p =
213 modify (\s -> s {usedArgsTailCallOptim = Set.union p (usedArgsTailCallOptim s) })
216 modify (\s -> s {usedArgsTailCallOptim = Set.union p (usedArgsTailCallOptim s) })
214
217
215−getNewCGNames :: Int -> State CGBodyState [Text]
216−getNewCGNames n =
217− mapM (\_ -> getNewCGName) [1..n]
218−
219getConsId :: Name -> State CGBodyState (Int, Int)
218getConsId :: Name -> State CGBodyState (Int, Int)
220getConsId n =
219getConsId n =
221 do
220 do
@@ -238,8 +237,8 @@ data BodyResTarget = ReturnBT
238 | DecConstBT Text
237 | DecConstBT Text
239 | GetExpBT
238 | GetExpBT
240
239
241−cgFun :: CGConf -> Map Name LDecl -> Name -> [Name] -> LExp -> (JsStmt, CGStats)
240+cgFun :: Map Name LDecl -> Name -> [Name] -> LExp -> (JsStmt, CGStats)
242−cgFun cnf dfs n args def = do
241+cgFun dfs n args def = do
243 let fnName = jsName n
242 let fnName = jsName n
244 let argNames = map jsName args
243 let argNames = map jsName args
245 let ((decs, res),st) = runState
244 let ((decs, res),st) = runState
@@ -250,7 +249,6 @@ cgFun cnf dfs n args def = do
250 , currentFnNameAndArgs = (fnName, argNames)
249 , currentFnNameAndArgs = (fnName, argNames)
251 , usedArgsTailCallOptim = Set.empty
250 , usedArgsTailCallOptim = Set.empty
252 , isTailRec = False
251 , isTailRec = False
253− , conf = cnf
254 , usedITBig = False
252 , usedITBig = False
255 , partialApps = Set.empty
253 , partialApps = Set.empty
256 , hiddenCls = Set.empty
254 , hiddenCls = Set.empty
@@ -264,16 +262,6 @@ cgFun cnf dfs n args def = do
264 }
262 }
265 (fn, state')
263 (fn, state')
266
264
267−getSwitchJs :: JsExpr -> [LAlt] -> JsExpr
268−getSwitchJs x alts =
269− if any conCase alts then JsArrayProj (JsInt 0) x
270− else if any constBigIntCase alts then JsForeign "%0.toString()" [x]
271− else x
272− where conCase (LConCase _ _ _ _) = True
273− conCase _ = False
274− constBigIntCase (LConstCase (BI _) _) = True
275− constBigIntCase _ = False
276−
277addRT :: BodyResTarget -> JsExpr -> JsStmt
265addRT :: BodyResTarget -> JsExpr -> JsStmt
278addRT ReturnBT x = JsReturn x
266addRT ReturnBT x = JsReturn x
279addRT (DecBT n) x = JsDecLet n x
267addRT (DecBT n) x = JsDecLet n x
@@ -345,15 +333,15 @@ cgBody rt expr =
345 expr -> cgBody' rt expr
333 expr -> cgBody' rt expr
346
334
347cgBody' :: BodyResTarget -> LExp -> State CGBodyState ([JsStmt], JsStmt)
335cgBody' :: BodyResTarget -> LExp -> State CGBodyState ([JsStmt], JsStmt)
348−cgBody' rt (LV (Glob n)) =
336+cgBody' rt (LV n) =
349 do
337 do
350 argsFn <- getArgList n
338 argsFn <- getArgList n
351 case argsFn of
339 case argsFn of
352− Just a -> cgBody' rt (LApp False (LV (Glob n)) [])
340+ Just a -> cgBody' rt (LApp False (LV n) [])
353 Nothing -> do
341 Nothing -> do
354 n' <- cgName n
342 n' <- cgName n
355 pure $ ([], addRT rt n')
343 pure $ ([], addRT rt n')
356−cgBody' rt (LApp tailcall (LV (Glob fn)) args) =
344+cgBody' rt (LApp tailcall (LV fn) args) =
357 do
345 do
358 let fname = jsName fn
346 let fname = jsName fn
359 st <- get
347 st <- get
@@ -372,10 +360,10 @@ cgBody' rt (LApp tailcall (LV (Glob fn)) args) =
372 app <- formApp fn argVals
360 app <- formApp fn argVals
373 pure (preDecs, addRT rt app)
361 pure (preDecs, addRT rt app)
374
362
375−cgBody' rt (LForce (LLazyApp n args)) = cgBody rt (LApp False (LV (Glob n)) args)
363+cgBody' rt (LForce (LLazyApp n args)) = cgBody rt (LApp False (LV n) args)
376cgBody' rt (LLazyApp n args) =
364cgBody' rt (LLazyApp n args) =
377 do
365 do
378− (d,v) <- cgBody ReturnBT (LApp False (LV (Glob n)) args)
366+ (d,v) <- cgBody ReturnBT (LApp False (LV n) args)
379 pure ([], addRT rt $ jsLazy $ jsStmt2Expr $ JsSeq (seqJs d) v)
367 pure ([], addRT rt $ jsLazy $ jsStmt2Expr $ JsSeq (seqJs d) v)
380cgBody' rt (LForce e) =
368cgBody' rt (LForce e) =
381 do
369 do
src/IRTS/JavaScript/LangTransforms.hs+2−2
@@ -57,7 +57,7 @@ mapMapListKeys f (t:r) x = mapMapListKeys f r $ Map.adjust f t x
57extractGlobs :: Map Name LDecl -> LDecl -> [Name]
57extractGlobs :: Map Name LDecl -> LDecl -> [Name]
58extractGlobs defs (LConstructor _ _ _) = []
58extractGlobs defs (LConstructor _ _ _) = []
59extractGlobs defs (LFun _ _ _ e) =
59extractGlobs defs (LFun _ _ _ e) =
60− let f (LV (Glob x)) = Just x
60+ let f (LV x) = Just x
61 f (LLazyApp x _) = Just x
61 f (LLazyApp x _) = Just x
62 f _ = Nothing
62 f _ = Nothing
63 in [x | Just x <- map f $ universe e, Map.member x defs]
63 in [x | Just x <- map f $ universe e, Map.member x defs]
@@ -102,7 +102,7 @@ globlToCon x =
102 transformBi (f x) x
102 transformBi (f x) x
103 where
103 where
104 f :: Map Name LDecl -> LExp -> LExp
104 f :: Map Name LDecl -> LExp -> LExp
105− f y x@(LV (Glob n)) =
105+ f y x@(LV n) =
106 case Map.lookup n y of
106 case Map.lookup n y of
107 Just (LConstructor _ conId arity) -> LCon Nothing conId n []
107 Just (LConstructor _ conId arity) -> LCon Nothing conId n []
108 _ -> x
108 _ -> x
src/IRTS/JavaScript/PrimOp.hs+4
@@ -119,6 +119,10 @@ primDB =
119 , item (LASHR (ITFixed IT16)) False PTAny $ JsForeign "%0 >> %1"
119 , item (LASHR (ITFixed IT16)) False PTAny $ JsForeign "%0 >> %1"
120 , item (LASHR (ITFixed IT32)) False PTAny $ JsForeign "%0 >> %1|0"
120 , item (LASHR (ITFixed IT32)) False PTAny $ JsForeign "%0 >> %1|0"
121 , item (LASHR (ITFixed IT64)) True PTAny $ JsForeign "%0.shiftRight(%1)"
121 , item (LASHR (ITFixed IT64)) True PTAny $ JsForeign "%0.shiftRight(%1)"
122+ , item (LCompl (ITFixed IT8)) False PTAny $ JsForeign "~%0"
123+ , item (LCompl (ITFixed IT16)) False PTAny $ JsForeign "~%0"
124+ , item (LCompl (ITFixed IT32)) False PTAny $ JsForeign "~%0|0"
125+ , item (LCompl (ITFixed IT64)) True PTAny $ method "not"
122 , item (LEq ATFloat) False PTBool $ binop "==="
126 , item (LEq ATFloat) False PTBool $ binop "==="
123 , item (LEq (ATInt ITNative)) False PTBool $ binop "==="
127 , item (LEq (ATInt ITNative)) False PTBool $ binop "==="
124 , item (LEq (ATInt ITChar)) False PTBool $ binop "==="
128 , item (LEq (ATInt ITChar)) False PTBool $ binop "==="
src/IRTS/Lang.hs+17−17
@@ -5,7 +5,8 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8−{-# LANGUAGE DeriveDataTypeable, DeriveFunctor, DeriveGeneric, PatternGuards #-}
8+{-# LANGUAGE DeriveDataTypeable, DeriveFunctor, DeriveGeneric, FlexibleContexts,
9+ PatternGuards #-}
9
10
10module IRTS.Lang where
11module IRTS.Lang where
11
12
@@ -27,7 +28,7 @@ data LVar = Loc Int | Glob Name
27
28
28-- ASSUMPTION: All variable bindings have unique names here
29-- ASSUMPTION: All variable bindings have unique names here
29-- Constructors commented as lifted are not present in the LIR provided to the different backends.
30-- Constructors commented as lifted are not present in the LIR provided to the different backends.
30−data LExp = LV LVar
31+data LExp = LV Name
31 | LApp Bool LExp [LExp] -- True = tail call
32 | LApp Bool LExp [LExp] -- True = tail call
32 | LLazyApp Name [LExp] -- True = tail call
33 | LLazyApp Name [LExp] -- True = tail call
33 | LLazyExp LExp -- lifted out before compiling
34 | LLazyExp LExp -- lifted out before compiling
@@ -35,7 +36,7 @@ data LExp = LV LVar
35 | LLet Name LExp LExp -- name just for pretty printing
36 | LLet Name LExp LExp -- name just for pretty printing
36 | LLam [Name] LExp -- lambda, lifted out before compiling
37 | LLam [Name] LExp -- lambda, lifted out before compiling
37 | LProj LExp Int -- projection
38 | LProj LExp Int -- projection
38− | LCon (Maybe LVar) -- Location to reallocate, if available
39+ | LCon (Maybe Name) -- Location to reallocate, if available
39 Int Name [LExp]
40 Int Name [LExp]
40 | LCase CaseType LExp [LAlt]
41 | LCase CaseType LExp [LAlt]
41 | LConst Const
42 | LConst Const
@@ -167,13 +168,13 @@ addFn fn d = do LS n i ds <- get
167
168
168lift :: [Name] -> LExp -> State LiftState LExp
169lift :: [Name] -> LExp -> State LiftState LExp
169lift env (LV v) = return (LV v) -- Lifting happens before these can exist...
170lift env (LV v) = return (LV v) -- Lifting happens before these can exist...
170−lift env (LApp tc (LV (Glob n)) args) = do args' <- mapM (lift env) args
171+lift env (LApp tc (LV n) args) = do args' <- mapM (lift env) args
171− return (LApp tc (LV (Glob n)) args')
172+ return (LApp tc (LV n) args')
172lift env (LApp tc f args) = do f' <- lift env f
173lift env (LApp tc f args) = do f' <- lift env f
173 fn <- getNextName
174 fn <- getNextName
174 addFn fn (LFun [Inline] fn env f')
175 addFn fn (LFun [Inline] fn env f')
175 args' <- mapM (lift env) args
176 args' <- mapM (lift env) args
176− return (LApp tc (LV (Glob fn)) (map (LV . Glob) env ++ args'))
177+ return (LApp tc (LV fn) (map LV env ++ args'))
177lift env (LLazyApp n args) = do args' <- mapM (lift env) args
178lift env (LLazyApp n args) = do args' <- mapM (lift env) args
178 return (LLazyApp n args')
179 return (LLazyApp n args')
179lift env (LLazyExp (LConst c)) = return (LConst c)
180lift env (LLazyExp (LConst c)) = return (LConst c)
@@ -183,7 +184,7 @@ lift env (LLazyExp e) = do e' <- lift env e
183 let usedArgs = nub $ usedIn env e'
184 let usedArgs = nub $ usedIn env e'
184 fn <- getNextName
185 fn <- getNextName
185 addFn fn (LFun [NoInline] fn usedArgs e')
186 addFn fn (LFun [NoInline] fn usedArgs e')
186− return (LLazyApp fn (map (LV . Glob) usedArgs))
187+ return (LLazyApp fn (map LV usedArgs))
187lift env (LForce e) = do e' <- lift env e
188lift env (LForce e) = do e' <- lift env e
188 return (LForce e')
189 return (LForce e')
189lift env (LLet n v e) = do v' <- lift env v
190lift env (LLet n v e) = do v' <- lift env v
@@ -193,7 +194,7 @@ lift env (LLam args e) = do e' <- lift (env ++ args) e
193 let usedArgs = nub $ usedIn env e'
194 let usedArgs = nub $ usedIn env e'
194 fn <- getNextName
195 fn <- getNextName
195 addFn fn (LFun [Inline] fn (usedArgs ++ args) e')
196 addFn fn (LFun [Inline] fn (usedArgs ++ args) e')
196− return (LApp False (LV (Glob fn)) (map (LV . Glob) usedArgs))
197+ return (LApp False (LV fn) (map LV usedArgs))
197lift env (LProj t i) = do t' <- lift env t
198lift env (LProj t i) = do t' <- lift env t
198 return (LProj t' i)
199 return (LProj t' i)
199lift env (LCon loc i n args) = do args' <- mapM (lift env) args
200lift env (LCon loc i n args) = do args' <- mapM (lift env) args
@@ -228,11 +229,11 @@ allocUnique defs (n, LFun opts fn args e)
228 -- Keep track of 'updatable' names in the state, i.e. names whose heap
229 -- Keep track of 'updatable' names in the state, i.e. names whose heap
229 -- entry may be reused, along with the arity which was there
230 -- entry may be reused, along with the arity which was there
230 findUp :: LExp -> State [(Name, Int)] LExp
231 findUp :: LExp -> State [(Name, Int)] LExp
231− findUp (LApp t (LV (Glob n)) as)
232+ findUp (LApp t (LV n) as)
232 | Just (LConstructor _ i ar) <- lookupCtxtExact n defs,
233 | Just (LConstructor _ i ar) <- lookupCtxtExact n defs,
233 ar == length as
234 ar == length as
234 = findUp (LCon Nothing i n as)
235 = findUp (LCon Nothing i n as)
235− findUp (LV (Glob n))
236+ findUp (LV n)
236 | Just (LConstructor _ i 0) <- lookupCtxtExact n defs
237 | Just (LConstructor _ i 0) <- lookupCtxtExact n defs
237 = return $ LCon Nothing i n [] -- nullary cons are global, no need to update
238 = return $ LCon Nothing i n [] -- nullary cons are global, no need to update
238 findUp (LApp t f as) = LApp t <$> findUp f <*> mapM findUp as
239 findUp (LApp t f as) = LApp t <$> findUp f <*> mapM findUp as
@@ -252,7 +253,7 @@ allocUnique defs (n, LFun opts fn args e)
252 = LForeign t s <$> mapM (\ (t, e) -> do e' <- findUp e
253 = LForeign t s <$> mapM (\ (t, e) -> do e' <- findUp e
253 return (t, e')) es
254 return (t, e')) es
254 findUp (LOp o es) = LOp o <$> mapM findUp es
255 findUp (LOp o es) = LOp o <$> mapM findUp es
255− findUp (LCase Updatable e@(LV (Glob n)) as)
256+ findUp (LCase Updatable e@(LV n) as)
256 = LCase Updatable e <$> mapM (doUpAlt n) as
257 = LCase Updatable e <$> mapM (doUpAlt n) as
257 findUp (LCase t e as)
258 findUp (LCase t e as)
258 = LCase t <$> findUp e <*> mapM findUpAlt as
259 = LCase t <$> findUp e <*> mapM findUpAlt as
@@ -276,7 +277,7 @@ allocUnique defs (n, LFun opts fn args e)
276
277
277 findVar _ [] i = return Nothing
278 findVar _ [] i = return Nothing
278 findVar acc ((n, l) : ns) i | l == i = do put (reverse acc ++ ns)
279 findVar acc ((n, l) : ns) i | l == i = do put (reverse acc ++ ns)
279− return (Just (Glob n))
280+ return (Just n)
280 findVar acc (n : ns) i = findVar (n : acc) ns i
281 findVar acc (n : ns) i = findVar (n : acc) ns i
281
282
282
283
@@ -286,7 +287,7 @@ usedArg env n | n `elem` env = [n]
286 | otherwise = []
287 | otherwise = []
287
288
288usedIn :: [Name] -> LExp -> [Name]
289usedIn :: [Name] -> LExp -> [Name]
289−usedIn env (LV (Glob n)) = usedArg env n
290+usedIn env (LV n) = usedArg env n
290usedIn env (LApp _ e args) = usedIn env e ++ concatMap (usedIn env) args
291usedIn env (LApp _ e args) = usedIn env e ++ concatMap (usedIn env) args
291usedIn env (LLazyApp n args) = concatMap (usedIn env) args ++ usedArg env n
292usedIn env (LLazyApp n args) = concatMap (usedIn env) args ++ usedArg env n
292usedIn env (LLazyExp e) = usedIn env e
293usedIn env (LLazyExp e) = usedIn env e
@@ -296,7 +297,7 @@ usedIn env (LLam ns e) = usedIn (env \\ ns) e
296usedIn env (LCon v i n args) = let rest = concatMap (usedIn env) args in
297usedIn env (LCon v i n args) = let rest = concatMap (usedIn env) args in
297 case v of
298 case v of
298 Nothing -> rest
299 Nothing -> rest
299− Just (Glob n) -> usedArg env n ++ rest
300+ Just n -> usedArg env n ++ rest
300usedIn env (LProj t i) = usedIn env t
301usedIn env (LProj t i) = usedIn env t
301usedIn env (LCase up e alts) = usedIn env e ++ concatMap (usedInA env) alts
302usedIn env (LCase up e alts) = usedIn env e ++ concatMap (usedInA env) alts
302 where usedInA env (LConCase i n ns e) = usedIn env e
303 where usedInA env (LConCase i n ns e) = usedIn env e
@@ -307,7 +308,7 @@ usedIn env (LOp f args) = concatMap (usedIn env) args
307usedIn env _ = []
308usedIn env _ = []
308
309
309lsubst :: Name -> LExp -> LExp -> LExp
310lsubst :: Name -> LExp -> LExp -> LExp
310−lsubst n new (LV (Glob x)) | n == x = new
311+lsubst n new (LV x) | n == x = new
311lsubst n new (LApp t e args) = let e' = lsubst n new e
312lsubst n new (LApp t e args) = let e' = lsubst n new e
312 args' = map (lsubst n new) args in
313 args' = map (lsubst n new) args in
313 LApp t e' args'
314 LApp t e' args'
@@ -332,8 +333,7 @@ lsubst n new tm = tm
332
333
333instance Show LExp where
334instance Show LExp where
334 show e = show' [] "" e where
335 show e = show' [] "" e where
335− show' env ind (LV (Loc i)) = env!!i
336+ show' env ind (LV n) = show n
336− show' env ind (LV (Glob n)) = show n
337
337
338 show' env ind (LLazyApp e args)
338 show' env ind (LLazyApp e args)
339 = show e ++ "|(" ++ showSep ", " (map (show' env ind) args) ++")"
339 = show e ++ "|(" ++ showSep ", " (map (show' env ind) args) ++")"
src/IRTS/LangOpts.hs+9−9
@@ -35,14 +35,14 @@ nextN = do i <- get
35doInline :: LDefs -> LDecl -> LDecl
35doInline :: LDefs -> LDecl -> LDecl
36doInline defs d@(LConstructor _ _ _) = d
36doInline defs d@(LConstructor _ _ _) = d
37doInline defs (LFun opts topn args exp)
37doInline defs (LFun opts topn args exp)
38− = let res = evalState (inlineWith [topn] (map (\n -> (n, LV (Glob n))) args) exp) 0 in
38+ = let res = evalState (inlineWith [topn] (map (\n -> (n, LV n)) args) exp) 0 in
39 LFun opts topn args res
39 LFun opts topn args res
40 where
40 where
41 inlineWith :: [Name] -> [(Name, LExp)] -> LExp -> State Int LExp
41 inlineWith :: [Name] -> [(Name, LExp)] -> LExp -> State Int LExp
42− inlineWith done env var@(LV (Glob n))
42+ inlineWith done env var@(LV n)
43− = case lookup n env of
43+ = case lookup n env of
44− Just t -> return t
44+ Just t -> return t
45− Nothing -> return var
45+ Nothing -> return var
46 inlineWith done env (LLazyApp n es) = LLazyApp n <$> (mapM (inlineWith done env) es)
46 inlineWith done env (LLazyApp n es) = LLazyApp n <$> (mapM (inlineWith done env) es)
47 inlineWith done env (LForce e) = LForce <$> inlineWith done env e
47 inlineWith done env (LForce e) = LForce <$> inlineWith done env e
48 inlineWith done env (LLazyExp e) = LLazyExp <$> inlineWith done env e
48 inlineWith done env (LLazyExp e) = LLazyExp <$> inlineWith done env e
@@ -51,12 +51,12 @@ doInline defs (LFun opts topn args exp)
51 inlineWith done env (LLet n val sc)
51 inlineWith done env (LLet n val sc)
52 = do n' <- nextN
52 = do n' <- nextN
53 LLet n' <$> inlineWith done env val <*>
53 LLet n' <$> inlineWith done env val <*>
54− inlineWith done ((n, LV (Glob n')) : env) sc
54+ inlineWith done ((n, LV n') : env) sc
55 inlineWith done env (LLam args sc)
55 inlineWith done env (LLam args sc)
56 = do ns' <- mapM (\n -> do n' <- nextN
56 = do ns' <- mapM (\n -> do n' <- nextN
57 return (n, n')) args
57 return (n, n')) args
58 LLam (map snd ns') <$>
58 LLam (map snd ns') <$>
59− inlineWith done (map (\ (n,n') -> (n, LV (Glob n'))) ns' ++ env) sc
59+ inlineWith done (map (\ (n,n') -> (n, LV n')) ns' ++ env) sc
60 inlineWith done env (LProj exp i) = LProj <$> inlineWith done env exp <*> return i
60 inlineWith done env (LProj exp i) = LProj <$> inlineWith done env exp <*> return i
61 inlineWith done env (LCon loc i n es)
61 inlineWith done env (LCon loc i n es)
62 = LCon loc i n <$> mapM (inlineWith done env) es
62 = LCon loc i n <$> mapM (inlineWith done env) es
@@ -64,7 +64,7 @@ doInline defs (LFun opts topn args exp)
64 = LCase ty <$> inlineWith done env e <*> mapM (inlineWithAlt done env) alts
64 = LCase ty <$> inlineWith done env e <*> mapM (inlineWithAlt done env) alts
65 inlineWith done env (LOp f es) = LOp f <$> mapM (inlineWith done env) es
65 inlineWith done env (LOp f es) = LOp f <$> mapM (inlineWith done env) es
66 -- the interesting case!
66 -- the interesting case!
67− inlineWith done env (LApp t (LV (Glob n)) es)
67+ inlineWith done env (LApp t (LV n) es)
68 | n `notElem` done,
68 | n `notElem` done,
69 [LFun opts _ args body] <- lookupCtxt n defs,
69 [LFun opts _ args body] <- lookupCtxt n defs,
70 Inline `elem` opts,
70 Inline `elem` opts,
@@ -82,6 +82,6 @@ doInline defs (LFun opts topn args exp)
82 = do ns' <- mapM (\n -> do n' <- nextN
82 = do ns' <- mapM (\n -> do n' <- nextN
83 return (n, n')) es
83 return (n, n')) es
84 LConCase i n (map snd ns') <$>
84 LConCase i n (map snd ns') <$>
85− inlineWith done (map (\ (n,n') -> (n, LV (Glob n'))) ns' ++ env) rhs
85+ inlineWith done (map (\ (n,n') -> (n, LV n')) ns' ++ env) rhs
86 inlineWithAlt done env (LConstCase c e) = LConstCase c <$> inlineWith done env e
86 inlineWithAlt done env (LConstCase c e) = LConstCase c <$> inlineWith done env e
87 inlineWithAlt done env (LDefaultCase e) = LDefaultCase <$> inlineWith done env e
87 inlineWithAlt done env (LDefaultCase e) = LDefaultCase <$> inlineWith done env e
src/IRTS/Portable.hs+1−1
@@ -5,7 +5,7 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8−{-# LANGUAGE OverloadedStrings #-}
8+{-# LANGUAGE FlexibleInstances, OverloadedStrings, TypeSynonymInstances #-}
9module IRTS.Portable (writePortable) where
9module IRTS.Portable (writePortable) where
10
10
11import Idris.Core.CaseTree
11import Idris.Core.CaseTree
src/IRTS/Simplified.hs+4−5
@@ -5,6 +5,7 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8+{-# LANGUAGE FlexibleContexts #-}
8module IRTS.Simplified(simplifyDefs, SDecl(..), SExp(..), SAlt(..)) where
9module IRTS.Simplified(simplifyDefs, SDecl(..), SExp(..), SAlt(..)) where
9
10
10import Idris.Core.CaseTree
11import Idris.Core.CaseTree
@@ -52,8 +53,7 @@ ldefs = do (l, h) <- get
52-- The boolean parameter indicates whether the expression is at tail
53-- The boolean parameter indicates whether the expression is at tail
53-- call position.
54-- call position.
54simplify :: Bool -> DExp -> State (DDefs, Int) SExp
55simplify :: Bool -> DExp -> State (DDefs, Int) SExp
55−simplify tl (DV (Loc i)) = return (SV (Loc i))
56+simplify tl (DV x)
56−simplify tl (DV (Glob x))
57 = do ctxt <- ldefs
57 = do ctxt <- ldefs
58 case lookupCtxtExact x ctxt of
58 case lookupCtxtExact x ctxt of
59 Just (DConstructor _ t 0) -> return $ SCon Nothing t x []
59 Just (DConstructor _ t 0) -> return $ SCon Nothing t x []
@@ -67,7 +67,7 @@ simplify tl (DLet n v e) = do v' <- simplify False v
67 return (SLet (Glob n) v' e')
67 return (SLet (Glob n) v' e')
68simplify tl (DUpdate n e) = do e' <- simplify False e
68simplify tl (DUpdate n e) = do e' <- simplify False e
69 return (SUpdate (Glob n) e')
69 return (SUpdate (Glob n) e')
70−simplify tl (DC loc i n args) = bindExprs args (SCon loc i n)
70+simplify tl (DC loc i n args) = bindExprs args (SCon (Glob <$> loc) i n)
71simplify tl (DProj t i) = bindExpr t (\var -> SProj var i)
71simplify tl (DProj t i) = bindExpr t (\var -> SProj var i)
72simplify tl (DCase up e alts)
72simplify tl (DCase up e alts)
73 = do alts' <- mapM (sAlt tl) alts
73 = do alts' <- mapM (sAlt tl) alts
@@ -96,12 +96,11 @@ bindExpr :: DExp -> (LVar -> SExp) -> State (DDefs, Int) SExp
96bindExpr e f = bindExprM e (return . f)
96bindExpr e f = bindExprM e (return . f)
97
97
98bindExprM :: DExp -> (LVar -> State (DDefs, Int) SExp) -> State (DDefs, Int) SExp
98bindExprM :: DExp -> (LVar -> State (DDefs, Int) SExp) -> State (DDefs, Int) SExp
99−bindExprM (DV (Glob x)) f
99+bindExprM (DV x) f
100 = do ctxt <- ldefs
100 = do ctxt <- ldefs
101 case lookupCtxtExact x ctxt of
101 case lookupCtxtExact x ctxt of
102 Just (DConstructor _ t 0) -> bindExprM (DC Nothing t x []) f
102 Just (DConstructor _ t 0) -> bindExprM (DC Nothing t x []) f
103 _ -> f (Glob x)
103 _ -> f (Glob x)
104−bindExprM (DV var) f = f var
105bindExprM e f =
104bindExprM e f =
106 do e' <- simplify False e
105 do e' <- simplify False e
107 var <- freshVar
106 var <- freshVar
src/Idris/AbsSyntax.hs+9−1
@@ -6,7 +6,7 @@ License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8
8
9−{-# LANGUAGE DeriveFunctor, PatternGuards #-}
9+{-# LANGUAGE DeriveFunctor, FlexibleContexts, PatternGuards #-}
10
10
11module Idris.AbsSyntax(
11module Idris.AbsSyntax(
12 module Idris.AbsSyntax
12 module Idris.AbsSyntax
@@ -1108,6 +1108,14 @@ allImportDirs = do i <- getIState
1108 let optdirs = opt_importdirs (idris_options i)
1108 let optdirs = opt_importdirs (idris_options i)
1109 return ("." : reverse optdirs)
1109 return ("." : reverse optdirs)
1110
1110
1111+-- Like allImportDirs but the dirs that are a prefix of
1112+-- the files path first. This makes it look in the current
1113+-- package first.
1114+rankedImportDirs :: FilePath -> Idris [FilePath]
1115+rankedImportDirs fp = do ids <- allImportDirs
1116+ let (prefixes, rest) = partition (`isPrefixOf`fp) ids
1117+ return $ prefixes ++ rest
1118+
1111addSourceDir :: FilePath -> Idris ()
1119addSourceDir :: FilePath -> Idris ()
1112addSourceDir fp = do i <- getIState
1120addSourceDir fp = do i <- getIState
1113 let opts = idris_options i
1121 let opts = idris_options i
src/Idris/AbsSyntaxTree.hs+10−1
@@ -6,7 +6,9 @@ License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8
8
9−{-# LANGUAGE DeriveDataTypeable, DeriveFunctor, DeriveGeneric, PatternGuards #-}
9+{-# LANGUAGE DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric,
10+ DeriveTraversable, FlexibleContexts, FlexibleInstances,
11+ MultiParamTypeClasses, PatternGuards, TypeSynonymInstances #-}
10
12
11module Idris.AbsSyntaxTree where
13module Idris.AbsSyntaxTree where
12
14
@@ -1047,6 +1049,7 @@ mapPTermFC f g (PDoBlock dos) = PDoBlock (map mapPDoFC dos)
1047 DoBindP (f fc) (mapPTermFC f g t1) (mapPTermFC f g t2) (map (\(l,r)-> (mapPTermFC f g l, mapPTermFC f g r)) alts)
1049 DoBindP (f fc) (mapPTermFC f g t1) (mapPTermFC f g t2) (map (\(l,r)-> (mapPTermFC f g l, mapPTermFC f g r)) alts)
1048 mapPDoFC (DoLet fc n nfc t1 t2) = DoLet (f fc) n (g nfc) (mapPTermFC f g t1) (mapPTermFC f g t2)
1050 mapPDoFC (DoLet fc n nfc t1 t2) = DoLet (f fc) n (g nfc) (mapPTermFC f g t1) (mapPTermFC f g t2)
1049 mapPDoFC (DoLetP fc t1 t2) = DoLetP (f fc) (mapPTermFC f g t1) (mapPTermFC f g t2)
1051 mapPDoFC (DoLetP fc t1 t2) = DoLetP (f fc) (mapPTermFC f g t1) (mapPTermFC f g t2)
1052+ mapPDoFC (DoRewrite fc h) = DoRewrite (f fc) (mapPTermFC f g h)
1050mapPTermFC f g (PIdiom fc t) = PIdiom (f fc) (mapPTermFC f g t)
1053mapPTermFC f g (PIdiom fc t) = PIdiom (f fc) (mapPTermFC f g t)
1051mapPTermFC f g (PMetavar fc n) = PMetavar (g fc) n
1054mapPTermFC f g (PMetavar fc n) = PMetavar (g fc) n
1052mapPTermFC f g (PProof tacs) = PProof (map (fmap (mapPTermFC f g)) tacs)
1055mapPTermFC f g (PProof tacs) = PProof (map (fmap (mapPTermFC f g)) tacs)
@@ -1171,6 +1174,7 @@ data PDo' t = DoExp FC t
1171 | DoBindP FC t t [(t,t)]
1174 | DoBindP FC t t [(t,t)]
1172 | DoLet FC Name FC t t -- ^ second FC is precise name location
1175 | DoLet FC Name FC t t -- ^ second FC is precise name location
1173 | DoLetP FC t t
1176 | DoLetP FC t t
1177+ | DoRewrite FC t -- rewrite in do block
1174 deriving (Eq, Ord, Functor, Data, Generic, Typeable)
1178 deriving (Eq, Ord, Functor, Data, Generic, Typeable)
1175{-!
1179{-!
1176deriving instance Binary PDo'
1180deriving instance Binary PDo'
@@ -1182,6 +1186,7 @@ instance Sized a => Sized (PDo' a) where
1182 size (DoBindP fc l r alts) = 1 + size fc + size l + size r + size alts
1186 size (DoBindP fc l r alts) = 1 + size fc + size l + size r + size alts
1183 size (DoLet fc nm nfc l r) = 1 + size fc + size nm + size l + size r
1187 size (DoLet fc nm nfc l r) = 1 + size fc + size nm + size l + size r
1184 size (DoLetP fc l r) = 1 + size fc + size l + size r
1188 size (DoLetP fc l r) = 1 + size fc + size l + size r
1189+ size (DoRewrite fc h) = 1 + size fc + size h
1185
1190
1186type PDo = PDo' PTerm
1191type PDo = PDo' PTerm
1187
1192
@@ -1277,6 +1282,7 @@ highestFC (PDoBlock lines) =
1277 getDoFC (DoBindP fc l r alts) = fc
1282 getDoFC (DoBindP fc l r alts) = fc
1278 getDoFC (DoLet fc nm nfc l r) = fc
1283 getDoFC (DoLet fc nm nfc l r) = fc
1279 getDoFC (DoLetP fc l r) = fc
1284 getDoFC (DoLetP fc l r) = fc
1285+ getDoFC (DoRewrite fc h) = fc
1280
1286
1281highestFC (PIdiom fc _) = Just fc
1287highestFC (PIdiom fc _) = Just fc
1282highestFC (PMetavar fc _) = Just fc
1288highestFC (PMetavar fc _) = Just fc
@@ -1951,6 +1957,9 @@ pprintPTerm ppo bnd docArgs infixes = prettySe (ppopt_depth ppo) startPrec bnd
1951 ppdo bnd (DoLetP _ _ _ : dos) = -- ok because never made by delab
1957 ppdo bnd (DoLetP _ _ _ : dos) = -- ok because never made by delab
1952 text "no pretty printer for pattern-matching do binding" :
1958 text "no pretty printer for pattern-matching do binding" :
1953 ppdo bnd dos
1959 ppdo bnd dos
1960+ ppdo bnd (DoRewrite _ _ : dos) = -- ok because never made by delab
1961+ text "no pretty printer for pattern-matching do binding" :
1962+ ppdo bnd dos
1954 ppdo _ [] = []
1963 ppdo _ [] = []
1955 prettySe d p bnd (PCoerced t) = prettySe d p bnd t
1964 prettySe d p bnd (PCoerced t) = prettySe d p bnd t
1956 prettySe d p bnd (PElabError s) = pretty s
1965 prettySe d p bnd (PElabError s) = pretty s
src/Idris/Apropos.hs+1
@@ -5,6 +5,7 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8+{-# LANGUAGE FlexibleInstances #-}
8module Idris.Apropos (apropos, aproposModules) where
9module Idris.Apropos (apropos, aproposModules) where
9
10
10import Idris.AbsSyntax
11import Idris.AbsSyntax
src/Idris/CaseSplit.hs+1−1
@@ -17,7 +17,7 @@ Always take the "more specific" argument when there is a discrepancy, i.e.
17names over '_', patterns over names, etc.
17names over '_', patterns over names, etc.
18-}
18-}
19
19
20−{-# LANGUAGE PatternGuards #-}
20+{-# LANGUAGE FlexibleContexts, PatternGuards #-}
21
21
22module Idris.CaseSplit(
22module Idris.CaseSplit(
23 splitOnLine, replaceSplits
23 splitOnLine, replaceSplits
src/Idris/Chaser.hs+2
@@ -5,6 +5,8 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8+{-# LANGUAGE FlexibleContexts #-}
9+
8module Idris.Chaser(
10module Idris.Chaser(
9 buildTree, getImports
11 buildTree, getImports
10 , getModuleFiles
12 , getModuleFiles
src/Idris/CmdOptions.hs−2
@@ -25,9 +25,7 @@ import Control.Monad.Trans.Except (throwE)
25import Control.Monad.Trans.Reader (ask)
25import Control.Monad.Trans.Reader (ask)
26import Data.Char
26import Data.Char
27import Data.Maybe
27import Data.Maybe
28−#if MIN_VERSION_optparse_applicative(0,13,0)
29import Data.Monoid ((<>))
28import Data.Monoid ((<>))
30−#endif
31import Options.Applicative
29import Options.Applicative
32import Options.Applicative.Arrows
30import Options.Applicative.Arrows
33import Options.Applicative.Types (ReadM(..))
31import Options.Applicative.Types (ReadM(..))
src/Idris/Core/Binary.hs+6−2
@@ -5,6 +5,8 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8+{-# LANGUAGE FlexibleInstances #-}
9+
8{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
10{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
9module Idris.Core.Binary where
11module Idris.Core.Binary where
10
12
@@ -14,6 +16,8 @@ import Control.Applicative ((<$>), (<*>))
14import Control.DeepSeq (($!!))
16import Control.DeepSeq (($!!))
15import Control.Monad (liftM2)
17import Control.Monad (liftM2)
16import Data.Binary
18import Data.Binary
19+import Data.Binary.Get
20+import Data.Binary.Put
17import qualified Data.Text as T
21import qualified Data.Text as T
18import qualified Data.Text.Encoding as E
22import qualified Data.Text.Encoding as E
19import Data.Vector.Binary
23import Data.Vector.Binary
@@ -398,7 +402,7 @@ instance Binary Const where
398 BI x1 -> do putWord8 1
402 BI x1 -> do putWord8 1
399 put x1
403 put x1
400 Fl x1 -> do putWord8 2
404 Fl x1 -> do putWord8 2
401− put x1
405+ putDoublele x1
402 Ch x1 -> do putWord8 3
406 Ch x1 -> do putWord8 3
403 put x1
407 put x1
404 Str x1 -> do putWord8 4
408 Str x1 -> do putWord8 4
@@ -425,7 +429,7 @@ instance Binary Const where
425 return (I x1)
429 return (I x1)
426 1 -> do x1 <- get
430 1 -> do x1 <- get
427 return (BI x1)
431 return (BI x1)
428− 2 -> do x1 <- get
432+ 2 -> do x1 <- getDoublele
429 return (Fl x1)
433 return (Fl x1)
430 3 -> do x1 <- get
434 3 -> do x1 <- get
431 return (Ch x1)
435 return (Ch x1)
src/Idris/Core/CaseTree.hs+3−2
@@ -18,8 +18,9 @@ allows casing on arbitrary terms, here we choose to maintain the distinction
18in order to allow for better optimisation opportunities.
18in order to allow for better optimisation opportunities.
19
19
20-}
20-}
21+
21−{-# LANGUAGE DeriveFunctor, DeriveGeneric, PatternGuards,
22+{-# LANGUAGE DeriveFunctor, DeriveGeneric, FlexibleContexts, FlexibleInstances,
22− TypeSynonymInstances #-}
23+ PatternGuards, TypeSynonymInstances #-}
23
24
24module Idris.Core.CaseTree (
25module Idris.Core.CaseTree (
25 CaseDef(..), SC, SC'(..), CaseAlt, CaseAlt'(..), ErasureInfo
26 CaseDef(..), SC, SC'(..), CaseAlt, CaseAlt'(..), ErasureInfo
src/Idris/Core/DeepSeq.hs+4−1
@@ -5,7 +5,8 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8+{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, TypeSynonymInstances,
8−{-# LANGUAGE BangPatterns, ViewPatterns #-}
9+ ViewPatterns #-}
9{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
10{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
10
11
11module Idris.Core.DeepSeq where
12module Idris.Core.DeepSeq where
@@ -27,7 +28,9 @@ forceDefCtxt (force -> !ctxt) = ctxt
27
28
28instance NFData NameOutput
29instance NFData NameOutput
29instance NFData TextFormatting
30instance NFData TextFormatting
31+#if !(MIN_VERSION_base(4,10,0))
30instance NFData Ordering
32instance NFData Ordering
33+#endif
31instance NFData OutputAnnotation
34instance NFData OutputAnnotation
32instance NFData SpecialName
35instance NFData SpecialName
33instance NFData Universe
36instance NFData Universe
src/Idris/Core/ProofState.hs+2−1
@@ -10,7 +10,8 @@ proofs, and some high level commands for introducing new theorems,
10evaluation/checking inside the proof system, etc.
10evaluation/checking inside the proof system, etc.
11-}
11-}
12
12
13−{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, PatternGuards #-}
13+{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses,
14+ PatternGuards #-}
14module Idris.Core.ProofState(
15module Idris.Core.ProofState(
15 ProofState(..), newProof, envAtFocus, goalAtFocus
16 ProofState(..), newProof, envAtFocus, goalAtFocus
16 , Tactic(..), Goal(..), processTactic, nowElaboratingPS
17 , Tactic(..), Goal(..), processTactic, nowElaboratingPS
src/Idris/Core/TT.hs+4−2
@@ -22,8 +22,10 @@ TT is the core language of Idris. The language has:
22 * We have a simple collection of tactics which we use to elaborate source
22 * We have a simple collection of tactics which we use to elaborate source
23 programs with implicit syntax into fully explicit terms.
23 programs with implicit syntax into fully explicit terms.
24-}
24-}
25−{-# LANGUAGE DeriveDataTypeable, DeriveFunctor, DeriveGeneric, FlexibleContexts,
25+{-# LANGUAGE DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric,
26+ DeriveTraversable, FlexibleContexts, FlexibleInstances,
26− FunctionalDependencies, MultiParamTypeClasses, PatternGuards #-}
27+ FunctionalDependencies, MultiParamTypeClasses, PatternGuards,
28+ TypeSynonymInstances #-}
27{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
29{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
28module Idris.Core.TT(
30module Idris.Core.TT(
29 AppStatus(..), ArithTy(..), Binder(..), Const(..), Ctxt(..)
31 AppStatus(..), ArithTy(..), Binder(..), Const(..), Ctxt(..)
src/Idris/Core/Typecheck.hs+2−2
@@ -6,8 +6,8 @@ License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8
8
9−{-# LANGUAGE DeriveFunctor, FlexibleInstances, MultiParamTypeClasses,
9+{-# LANGUAGE DeriveFunctor, FlexibleContexts, FlexibleInstances,
10− PatternGuards #-}
10+ MultiParamTypeClasses, PatternGuards #-}
11
11
12module Idris.Core.Typecheck where
12module Idris.Core.Typecheck where
13
13
src/Idris/Core/Unify.hs+1−1
@@ -11,7 +11,7 @@ Returns a list of hole names paired with the term which solves them, and
11a list of things which need to be injective.
11a list of things which need to be injective.
12
12
13-}
13-}
14−{-# LANGUAGE PatternGuards #-}
14+{-# LANGUAGE FlexibleContexts, PatternGuards #-}
15
15
16module Idris.Core.Unify(
16module Idris.Core.Unify(
17 match_unify, unify
17 match_unify, unify
src/Idris/Core/WHNF.hs+1−1
@@ -6,7 +6,7 @@ License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8
8
9−{-# LANGUAGE PatternGuards #-}
9+{-# LANGUAGE FlexibleContexts, PatternGuards #-}
10{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
10{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
11module Idris.Core.WHNF(whnf, whnfArgs, WEnv) where
11module Idris.Core.WHNF(whnf, whnfArgs, WEnv) where
12
12
src/Idris/Coverage.hs+1−1
@@ -5,7 +5,7 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8−{-# LANGUAGE PatternGuards #-}
8+{-# LANGUAGE FlexibleContexts, PatternGuards #-}
9module Idris.Coverage(genClauses, validCoverageCase, recoverableCoverage,
9module Idris.Coverage(genClauses, validCoverageCase, recoverableCoverage,
10 mkPatTm) where
10 mkPatTm) where
11
11
src/Idris/DSL.hs+2
@@ -109,6 +109,8 @@ expandSugar dsl (PDoBlock ds)
109 = PLet fc n nfc ty tm (block b rest)
109 = PLet fc n nfc ty tm (block b rest)
110 block b (DoLetP fc p tm : rest)
110 block b (DoLetP fc p tm : rest)
111 = PCase fc tm [(p, block b rest)]
111 = PCase fc tm [(p, block b rest)]
112+ block b (DoRewrite fc h : rest)
113+ = PRewrite fc Nothing h (block b rest) Nothing
112 block b (DoExp fc tm : rest)
114 block b (DoExp fc tm : rest)
113 = PApp fc b
115 = PApp fc b
114 [pexp tm,
116 [pexp tm,
src/Idris/DataOpts.hs+1−1
@@ -5,7 +5,7 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8−{-# LANGUAGE PatternGuards #-}
8+{-# LANGUAGE FlexibleInstances, PatternGuards #-}
9
9
10module Idris.DataOpts(applyOpts) where
10module Idris.DataOpts(applyOpts) where
11
11
src/Idris/DeepSeq.hs−14
@@ -29,20 +29,6 @@ import Control.DeepSeq
29import Network.Socket (PortNumber)
29import Network.Socket (PortNumber)
30
30
31-- These types don't have Generic instances
31-- These types don't have Generic instances
32−instance NFData CT.Options where
33− rnf (CT.Options x1 x2 x3 x4) = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` rnf x4 `seq` ()
34−
35−instance NFData CT.ListType where
36− rnf (CT.Bullet c) = rnf c `seq` ()
37− rnf (CT.Numbered nw i) = rnf nw `seq` rnf i `seq` ()
38−
39−instance NFData CT.CodeAttr where
40− rnf (CT.CodeAttr a b) = rnf a `seq` rnf b `seq` ()
41−
42−instance NFData CT.NumWrapper where
43− rnf CT.PeriodFollowing = ()
44− rnf CT.ParenFollowing = ()
45−
46instance NFData DynamicLib where
32instance NFData DynamicLib where
47 rnf (Lib x _) = rnf x `seq` ()
33 rnf (Lib x _) = rnf x `seq` ()
48
34
src/Idris/Docstrings.hs+2−1
@@ -6,7 +6,8 @@ License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8
8
9−{-# LANGUAGE DeriveFunctor, DeriveGeneric, ScopedTypeVariables #-}
9+{-# LANGUAGE DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable,
10+ ScopedTypeVariables #-}
10{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
11{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
11module Idris.Docstrings (
12module Idris.Docstrings (
12 Docstring(..), Block(..), Inline(..), parseDocstring, renderDocstring
13 Docstring(..), Block(..), Inline(..), parseDocstring, renderDocstring
src/Idris/Elab/Quasiquote.hs+1
@@ -75,6 +75,7 @@ extractDoUnquotes d (DoLet fc n nfc v b)
75 (b', ex2) <- extractUnquotes d b
75 (b', ex2) <- extractUnquotes d b
76 return (DoLet fc n nfc v' b', ex1 ++ ex2)
76 return (DoLet fc n nfc v' b', ex1 ++ ex2)
77extractDoUnquotes d (DoLetP fc t t') = fail "Pattern-matching lets cannot be quasiquoted"
77extractDoUnquotes d (DoLetP fc t t') = fail "Pattern-matching lets cannot be quasiquoted"
78+extractDoUnquotes d (DoRewrite fc h) = fail "Rewrites in Do block cannot be quasiquoted"
78
79
79
80
80extractUnquotes :: Int -> PTerm -> Elab' aux (PTerm, [(Name, PTerm)])
81extractUnquotes :: Int -> PTerm -> Elab' aux (PTerm, [(Name, PTerm)])
src/Idris/Elab/Term.hs+4−2
@@ -2659,9 +2659,11 @@ withErrorReflection x = idrisCatch x (\ e -> handle e >>= ierror)
2659 concat (intersperse ", " (map show handlers))
2659 concat (intersperse ", " (map show handlers))
2660 let reports = map (\n -> RApp (Var n) (reflectErr err)) handlers
2660 let reports = map (\n -> RApp (Var n) (reflectErr err)) handlers
2661
2661
2662− -- Typecheck error handlers - if this fails, then something else was wrong earlier!
2662+ -- Typecheck error handlers - if this fails, most
2663+ -- likely something which is needed by it has not
2664+ -- been imported, so keep the original error.
2663 handlers <- case mapM (check (tt_ctxt ist) []) reports of
2665 handlers <- case mapM (check (tt_ctxt ist) []) reports of
2664− Error e -> ierror $ ReflectionFailed "Type error while constructing reflected error" e
2666+ Error _ -> return [] -- ierror $ ReflectionFailed "Type error while constructing reflected error" e
2665 OK hs -> return hs
2667 OK hs -> return hs
2666
2668
2667 -- Normalize error handler terms to produce the new messages
2669 -- Normalize error handler terms to produce the new messages
src/Idris/Elab/Utils.hs+7−6
@@ -5,7 +5,7 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8−{-# LANGUAGE PatternGuards #-}
8+{-# LANGUAGE FlexibleContexts, PatternGuards #-}
9module Idris.Elab.Utils where
9module Idris.Elab.Utils where
10
10
11import Idris.AbsSyntax
11import Idris.AbsSyntax
@@ -449,9 +449,12 @@ displayWarnings est
449 = mapM_ displayImpWarning (implicit_warnings est)
449 = mapM_ displayImpWarning (implicit_warnings est)
450 where
450 where
451 displayImpWarning :: (FC, Name) -> Idris ()
451 displayImpWarning :: (FC, Name) -> Idris ()
452− displayImpWarning (fc, n) =
452+ displayImpWarning (fc, n) = do
453+ ist <- getIState
454+ let msg = show (nsroot n)
453− iputStrLn $ show fc ++ ":WARNING: " ++ show (nsroot n) ++ " is bound as an implicit\n"
455+ ++ " is bound as an implicit\n"
454− ++ "\tDid you mean to refer to " ++ show n ++ "?"
456+ ++ "\tDid you mean to refer to " ++ show n ++ "?"
457+ iWarn fc (pprintErr ist (Msg msg))
455
458
456propagateParams :: IState -> [Name] -> Type -> [Name] -> PTerm -> PTerm
459propagateParams :: IState -> [Name] -> Type -> [Name] -> PTerm -> PTerm
457propagateParams i ps t bound tm@(PApp _ (PRef fc hls n) args)
460propagateParams i ps t bound tm@(PApp _ (PRef fc hls n) args)
@@ -767,5 +770,3 @@ isPlausible ist var env n ty
767 collectConstraints env tcs t
770 collectConstraints env tcs t
768 | (V i, _) <- unApply t = (Just (env !! i), tcs)
771 | (V i, _) <- unApply t = (Just (env !! i), tcs)
769 | otherwise = (Nothing, tcs)
772 | otherwise = (Nothing, tcs)
770−
771−
src/Idris/Erasure.hs+120−12
@@ -1,6 +1,6 @@
1{-|
1{-|
2Module : Idris.Erasure
2Module : Idris.Erasure
3−Description : Utilities to erase irrelevant stuff.
3+Description : Utilities to erase stuff not necessary for runtime.
4Copyright :
4Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
@@ -145,10 +145,54 @@ performUsageAnalysis startNames = do
145 fmt n rs = show n ++ " from " ++ intercalate ", " [show rn ++ " arg# " ++ show ri | (rn,ri) <- rs]
145 fmt n rs = show n ++ " from " ++ intercalate ", " [show rn ++ " arg# " ++ show ri | (rn,ri) <- rs]
146 warn = logErasure 0
146 warn = logErasure 0
147
147
148+type Constraint = (Cond, DepSet)
149+
148-- | Find the minimal consistent usage by forward chaining.
150-- | Find the minimal consistent usage by forward chaining.
151+--
152+-- We use a cleverer implementation that:
153+-- 1. First transforms Deps into a collection of numbered constraints
154+-- 2. For each node, we remember the numbers of constraints
155+-- that contain that node among their preconditions.
156+-- 3. When performing forward chaining, we perform unit propagation
157+-- only on the relevant constraints, not all constraints.
158+--
159+-- Typical numbers from the current version of Blodwen:
160+-- * 56 iterations until fixpoint
161+-- * out of 20k constraints total, 5-1000 are relevant per iteration
149minimalUsage :: Deps -> (Deps, (Set Name, UseMap))
162minimalUsage :: Deps -> (Deps, (Set Name, UseMap))
150−minimalUsage = second gather . forwardChain
163+minimalUsage deps
164+ = fromNumbered *** gather
165+ $ forwardChain (index numbered) seedDeps seedDeps numbered
151 where
166 where
167+ numbered = toNumbered deps
168+
169+ -- The initial solution. Consists of nodes that are
170+ -- reachable immediately, without any preconditions.
171+ seedDeps :: DepSet
172+ seedDeps = M.unionsWith S.union [ds | (cond, ds) <- IM.elems numbered, S.null cond]
173+
174+ toNumbered :: Deps -> IntMap Constraint
175+ toNumbered = IM.fromList . zip [0..] . M.toList
176+
177+ fromNumbered :: IntMap Constraint -> Deps
178+ fromNumbered = IM.foldr addConstraint M.empty
179+ where
180+ addConstraint (ns, vs) = M.insertWith (M.unionWith S.union) ns vs
181+
182+ -- Build an index that maps every node to the set of constraints
183+ -- where the node appears among the preconditions.
184+ index :: IntMap Constraint -> Map Node IntSet
185+ index = IM.foldrWithKey (
186+ -- for each clause (i. ns --> _ds)
187+ \i (ns, _ds) ix -> foldr (
188+ -- for each node `n` in `ns`
189+ \n ix' -> M.insertWith IS.union n (IS.singleton i) ix'
190+ ) ix (S.toList ns)
191+ ) M.empty
192+
193+ -- Convert a solution of constraints into:
194+ -- 1. the list of names used in the program
195+ -- 2. the list of arguments used, together with their reasons
152 gather :: DepSet -> (Set Name, UseMap)
196 gather :: DepSet -> (Set Name, UseMap)
153 gather = foldr ins (S.empty, M.empty) . M.toList
197 gather = foldr ins (S.empty, M.empty) . M.toList
154 where
198 where
@@ -156,17 +200,81 @@ minimalUsage = second gather . forwardChain
156 ins ((n, Result), rs) (ns, umap) = (S.insert n ns, umap)
200 ins ((n, Result), rs) (ns, umap) = (S.insert n ns, umap)
157 ins ((n, Arg i ), rs) (ns, umap) = (ns, M.insertWith (IM.unionWith S.union) n (IM.singleton i rs) umap)
201 ins ((n, Arg i ), rs) (ns, umap) = (ns, M.insertWith (IM.unionWith S.union) n (IM.singleton i rs) umap)
158
202
159−forwardChain :: Deps -> (Deps, DepSet)
203+-- | In each iteration, we find the set of nodes immediately reachable
160−forwardChain deps
204+-- from the current set of constraints, and then reduce the set of constraints
161− | Just trivials <- M.lookup S.empty deps
205+-- based on that knowledge.
206+--
207+-- In the implementation, this is phase-shifted. We first reduce the set
208+-- of constraints, given the newly reachable nodes from the previous iteration,
209+-- and then compute the set of currently reachable nodes.
210+-- Then we decide whether to iterate further.
211+forwardChain
212+ :: Map Node IntSet -- ^ node index
213+ -> DepSet -- ^ all reachable nodes found so far
214+ -> DepSet -- ^ nodes reached in the previous iteration
215+ -> IntMap Constraint -- ^ numbered constraints
216+ -> (IntMap Constraint, DepSet)
217+forwardChain index solution previouslyNew constrs
218+ -- no newly reachable nodes, fixed point has been reached
219+ | M.null currentlyNew
220+ = (constrs, solution)
221+
222+ -- some newly reachable nodes, iterate more
223+ | otherwise
224+ = forwardChain index
162− = (M.unionWith S.union trivials)
225+ (M.unionWith S.union solution currentlyNew)
163− `second` forwardChain (remove trivials . M.delete S.empty $ deps)
226+ currentlyNew
164− | otherwise = (deps, M.empty)
227+ constrs'
165 where
228 where
166− -- Remove the given nodes from the Deps entirely,
229+ -- which constraints could give new results,
167− -- possibly creating new empty Conds.
230+ -- given that `previouslyNew` has been derived in the last iteration
168− remove :: DepSet -> Deps -> Deps
231+ affectedIxs = IS.unions [
169− remove ds = M.mapKeysWith (M.unionWith S.union) (S.\\ M.keysSet ds)
232+ M.findWithDefault IS.empty n index
233+ | n <- M.keys previouslyNew
234+ ]
235+
236+ -- traverse all (potentially) affected constraints, building:
237+ -- 1. a set of newly reached nodes
238+ -- 2. updated set of constraints where the previously
239+ -- reached nodes have been removed
240+ (currentlyNew, constrs')
241+ = IS.foldr
242+ (reduceConstraint $ M.keysSet previouslyNew)
243+ (M.empty, constrs)
244+ affectedIxs
245+
246+ -- Update the pair (newly reached nodes, numbered constraint set)
247+ -- by reducing the constraint with the given number.
248+ reduceConstraint
249+ :: Set Node -- ^ nodes reached in the previous iteration
250+ -> Int -- ^ constraint number
251+ -> (DepSet, IntMap (Cond, DepSet))
252+ -> (DepSet, IntMap (Cond, DepSet))
253+ reduceConstraint previouslyNew i (news, constrs)
254+ | Just (cond, deps) <- IM.lookup i constrs
255+ = case cond S.\\ previouslyNew of
256+ cond'
257+ -- This constraint's set of preconditions has shrunk
258+ -- to the empty set. We can add its RHS to the set of newly
259+ -- reached nodes, and remove the constraint altogether.
260+ | S.null cond'
261+ -> (M.unionWith S.union news deps, IM.delete i constrs)
262+
263+ -- This constraint's set of preconditions has shrunk
264+ -- so we need to overwrite the numbered slot
265+ -- with the updated constraint.
266+ | S.size cond' < S.size cond
267+ -> (news, IM.insert i (cond', deps) constrs)
268+
269+ -- This constraint's set of preconditions hasn't changed
270+ -- so we do not do anything about it.
271+ | otherwise
272+ -> (news, constrs)
273+
274+ -- Constraint number present in index but not found
275+ -- among the constraints. This happens more and more frequently
276+ -- as we delete constraints from the set.
277+ | otherwise = (news, constrs)
170
278
171-- | Build the dependency graph, starting the depth-first search from
279-- | Build the dependency graph, starting the depth-first search from
172-- a list of Names.
280-- a list of Names.
src/Idris/Error.hs+1
@@ -138,6 +138,7 @@ warnDisamb ist (PDoBlock steps) = mapM_ wStep steps
138 mapM_ (\(x,y) -> warnDisamb ist x >> warnDisamb ist y) cs
138 mapM_ (\(x,y) -> warnDisamb ist x >> warnDisamb ist y) cs
139 wStep (DoLet _ _ _ x y) = warnDisamb ist x >> warnDisamb ist y
139 wStep (DoLet _ _ _ x y) = warnDisamb ist x >> warnDisamb ist y
140 wStep (DoLetP _ x y) = warnDisamb ist x >> warnDisamb ist y
140 wStep (DoLetP _ x y) = warnDisamb ist x >> warnDisamb ist y
141+ wStep (DoRewrite _ h) = warnDisamb ist h
141warnDisamb ist (PIdiom _ x) = warnDisamb ist x
142warnDisamb ist (PIdiom _ x) = warnDisamb ist x
142warnDisamb ist (PMetavar _ _) = return ()
143warnDisamb ist (PMetavar _ _) = return ()
143warnDisamb ist (PProof tacs) = mapM_ (Foldable.mapM_ (warnDisamb ist)) tacs
144warnDisamb ist (PProof tacs) = mapM_ (Foldable.mapM_ (warnDisamb ist)) tacs
src/Idris/IBC.hs+24−24
@@ -5,7 +5,7 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8−{-# LANGUAGE TypeSynonymInstances #-}
8+{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}
9{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
9{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
10
10
11module Idris.IBC (loadIBC, loadPkgIndex,
11module Idris.IBC (loadIBC, loadPkgIndex,
@@ -48,7 +48,7 @@ import System.Directory
48import System.FilePath
48import System.FilePath
49
49
50ibcVersion :: Word16
50ibcVersion :: Word16
51−ibcVersion = 160
51+ibcVersion = 162
52
52
53-- | When IBC is being loaded - we'll load different things (and omit
53-- | When IBC is being loaded - we'll load different things (and omit
54-- different structures/definitions) depending on which phase we're in.
54-- different structures/definitions) depending on which phase we're in.
@@ -146,7 +146,7 @@ loadIBC reexport phase fp
146 Right archive -> do
146 Right archive -> do
147 if fullLoad
147 if fullLoad
148 then process reexport phase archive fp
148 then process reexport phase archive fp
149− else unhide phase archive
149+ else unhide phase fp archive
150 addImported reexport fp
150 addImported reexport fp
151
151
152-- | Load an entire package from its index file
152-- | Load an entire package from its index file
@@ -359,9 +359,9 @@ getEntry alt f a = case findEntryByPath f a of
359 Nothing -> return alt
359 Nothing -> return alt
360 Just e -> return $! (force . decode . fromEntry) e
360 Just e -> return $! (force . decode . fromEntry) e
361
361
362−unhide :: IBCPhase -> Archive -> Idris ()
362+unhide :: IBCPhase -> FilePath -> Archive -> Idris ()
363−unhide phase ar = do
363+unhide phase fp ar = do
364− processImports True phase ar
364+ processImports True phase fp ar
365 processAccess True phase ar
365 processAccess True phase ar
366
366
367process :: Bool -- ^ Reexporting
367process :: Bool -- ^ Reexporting
@@ -393,7 +393,7 @@ process reexp phase archive fn = do
393 when srcok $ timestampOlder source fn
393 when srcok $ timestampOlder source fn
394 processImportDirs archive
394 processImportDirs archive
395 processSourceDirs archive
395 processSourceDirs archive
396− processImports reexp phase archive
396+ processImports reexp phase fn archive
397 processImplicits archive
397 processImplicits archive
398 processInfix archive
398 processInfix archive
399 processStatics archive
399 processStatics archive
@@ -405,7 +405,7 @@ process reexp phase archive fn = do
405 processOptimise archive
405 processOptimise archive
406 processSyntax archive
406 processSyntax archive
407 processKeywords archive
407 processKeywords archive
408− processObjectFiles archive
408+ processObjectFiles fn archive
409 processLibs archive
409 processLibs archive
410 processCodegenFlags archive
410 processCodegenFlags archive
411 processDynamicLibs archive
411 processDynamicLibs archive
@@ -509,28 +509,21 @@ processSourceDirs ar = do
509 fs <- getEntry [] "ibc_sourcedirs" ar
509 fs <- getEntry [] "ibc_sourcedirs" ar
510 mapM_ addSourceDir fs
510 mapM_ addSourceDir fs
511
511
512−processImports :: Bool -> IBCPhase -> Archive -> Idris ()
512+processImports :: Bool -> IBCPhase -> FilePath -> Archive -> Idris ()
513−processImports reexp phase ar = do
513+processImports reexp phase fname ar = do
514 fs <- getEntry [] "ibc_imports" ar
514 fs <- getEntry [] "ibc_imports" ar
515 mapM_ (\(re, f) -> do
515 mapM_ (\(re, f) -> do
516 i <- getIState
516 i <- getIState
517 ibcsd <- valIBCSubDir i
517 ibcsd <- valIBCSubDir i
518− ids <- allImportDirs
518+ ids <- rankedImportDirs fname
519− fp <- findImport ids ibcsd f
520−-- if (f `elem` imported i)
521−-- then logLvl 1 $ "Already read " ++ f
522 putIState (i { imported = f : imported i })
519 putIState (i { imported = f : imported i })
523 let phase' = case phase of
520 let phase' = case phase of
524 IBC_REPL _ -> IBC_REPL False
521 IBC_REPL _ -> IBC_REPL False
525 p -> p
522 p -> p
523+ fp <- findIBC ids ibcsd f
526 case fp of
524 case fp of
527− LIDR fn -> do
528− logIBC 2 $ "Failed at " ++ fn
525+ Nothing -> do logIBC 2 $ "Failed to load ibc " ++ f
529− ifail "Must be an ibc"
530− IDR fn -> do
531− logIBC 2 $ "Failed at " ++ fn
532− ifail "Must be an ibc"
533− IBC fn src -> loadIBC (reexp && re) phase' fn) fs
526+ Just fn -> do loadIBC (reexp && re) phase' fn) fs
534
527
535processImplicits :: Archive -> Idris ()
528processImplicits :: Archive -> Idris ()
536processImplicits ar = do
529processImplicits ar = do
@@ -605,11 +598,11 @@ processKeywords ar = do
605 k <- getEntry [] "ibc_keywords" ar
598 k <- getEntry [] "ibc_keywords" ar
606 updateIState (\i -> i { syntax_keywords = k ++ syntax_keywords i })
599 updateIState (\i -> i { syntax_keywords = k ++ syntax_keywords i })
607
600
608−processObjectFiles :: Archive -> Idris ()
601+processObjectFiles :: FilePath -> Archive -> Idris ()
609−processObjectFiles ar = do
602+processObjectFiles fn ar = do
610 os <- getEntry [] "ibc_objs" ar
603 os <- getEntry [] "ibc_objs" ar
611 mapM_ (\ (cg, obj) -> do
604 mapM_ (\ (cg, obj) -> do
612− dirs <- allImportDirs
605+ dirs <- rankedImportDirs fn
613 o <- runIO $ findInPath dirs obj
606 o <- runIO $ findInPath dirs obj
614 addObjectFile cg o) os
607 addObjectFile cg o) os
615
608
@@ -2293,6 +2286,9 @@ instance (Binary t) => Binary (PDo' t) where
2293 put x1
2286 put x1
2294 put x2
2287 put x2
2295 put x3
2288 put x3
2289+ DoRewrite x1 x2 -> do putWord8 5
2290+ put x1
2291+ put x2
2296 get
2292 get
2297 = do i <- getWord8
2293 = do i <- getWord8
2298 case i of
2294 case i of
@@ -2319,6 +2315,10 @@ instance (Binary t) => Binary (PDo' t) where
2319 x2 <- get
2315 x2 <- get
2320 x3 <- get
2316 x3 <- get
2321 return (DoLetP x1 x2 x3)
2317 return (DoLetP x1 x2 x3)
2318+ 5 -> do
2319+ x1 <- get
2320+ x2 <- get
2321+ return (DoRewrite x1 x2)
2322 _ -> error "Corrupted binary data for PDo'"
2322 _ -> error "Corrupted binary data for PDo'"
2323
2323
2324
2324
src/Idris/IdrisDoc.hs+1
@@ -344,6 +344,7 @@ extractPDo (DoBindP _ p1 p2 ps) = let (ps1, ps2) = unzip ps
344 in concatMap extract (p1 : p2 : ps')
344 in concatMap extract (p1 : p2 : ps')
345extractPDo (DoLet _ n _ p1 p2) = n : concatMap extract [p1, p2]
345extractPDo (DoLet _ n _ p1 p2) = n : concatMap extract [p1, p2]
346extractPDo (DoLetP _ p1 p2) = concatMap extract [p1, p2]
346extractPDo (DoLetP _ p1 p2) = concatMap extract [p1, p2]
347+extractPDo (DoRewrite _ p) = extract p
347
348
348-- | Helper function for extractPTermNames
349-- | Helper function for extractPTermNames
349extractPTactic :: PTactic -> [Name]
350extractPTactic :: PTactic -> [Name]
src/Idris/Imports.hs+13−1
@@ -6,13 +6,14 @@ License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8module Idris.Imports(
8module Idris.Imports(
9− IFileType(..), findImport, findInPath, findPkgIndex
9+ IFileType(..), findIBC, findImport, findInPath, findPkgIndex
10 , ibcPathNoFallback, installedPackages, pkgIndex
10 , ibcPathNoFallback, installedPackages, pkgIndex
11 ) where
11 ) where
12
12
13import Idris.AbsSyntax
13import Idris.AbsSyntax
14import Idris.Core.TT
14import Idris.Core.TT
15import Idris.Error
15import Idris.Error
16+import Idris.Output
16import IRTS.System (getIdrisLibDir)
17import IRTS.System (getIdrisLibDir)
17
18
18import Control.Applicative ((<$>))
19import Control.Applicative ((<$>))
@@ -77,6 +78,17 @@ findImport (d:ds) ibcsd fp = do let fp_full = d </> fp
77 then return isrc
78 then return isrc
78 else findImport ds ibcsd fp
79 else findImport ds ibcsd fp
79
80
81+-- Only look for IBCs and not source
82+findIBC :: [FilePath] -> FilePath -> FilePath -> Idris (Maybe FilePath)
83+findIBC [] _ fp = return Nothing
84+findIBC (d:ds) ibcsd fp = do let fp_full = d </> fp
85+ ibcp <- runIO $ ibcPathWithFallback ibcsd fp_full
86+ ibc <- runIO $ doesFileExist' ibcp
87+ if ibc
88+ then return $ Just ibcp
89+ else findIBC ds ibcsd fp
90+
91+
80-- find a specific filename somewhere in a path
92-- find a specific filename somewhere in a path
81
93
82findInPath :: [FilePath] -> FilePath -> IO FilePath
94findInPath :: [FilePath] -> FilePath -> IO FilePath
src/Idris/Output.hs+1
@@ -6,6 +6,7 @@ License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8
8
9+{-# LANGUAGE FlexibleInstances #-}
9{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
10{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
10
11
11module Idris.Output where
12module Idris.Output where
src/Idris/Package/Parser.hs+1−8
@@ -5,10 +5,7 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8−{-# LANGUAGE CPP, ConstraintKinds #-}
8+{-# LANGUAGE CPP, ConstraintKinds, FlexibleInstances, TypeSynonymInstances #-}
9−#if !(MIN_VERSION_base(4,8,0))
10−{-# LANGUAGE OverlappingInstances #-}
11−#endif
12module Idris.Package.Parser where
9module Idris.Package.Parser where
13
10
14import Idris.AbsSyntaxTree
11import Idris.AbsSyntaxTree
@@ -50,11 +47,7 @@ instance {-# OVERLAPPING #-} DeltaParsing PParser where
50 {-# INLINE restOfLine #-}
47 {-# INLINE restOfLine #-}
51#endif
48#endif
52
49
53−#if MIN_VERSION_base(4,8,0)
54instance {-# OVERLAPPING #-} TokenParsing PParser where
50instance {-# OVERLAPPING #-} TokenParsing PParser where
55−#else
56−instance TokenParsing PParser where
57−#endif
58 someSpace = many (simpleWhiteSpace <|> singleLineComment <|> multiLineComment) *> pure ()
51 someSpace = many (simpleWhiteSpace <|> singleLineComment <|> multiLineComment) *> pure ()
59
52
60
53
src/Idris/Parser.hs+9−4
@@ -5,7 +5,8 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8−{-# LANGUAGE ConstraintKinds, GeneralizedNewtypeDeriving, PatternGuards #-}
8+{-# LANGUAGE ConstraintKinds, FlexibleContexts, GeneralizedNewtypeDeriving,
9+ PatternGuards #-}
9{-# OPTIONS_GHC -O0 #-}
10{-# OPTIONS_GHC -O0 #-}
10module Idris.Parser(module Idris.Parser,
11module Idris.Parser(module Idris.Parser,
11 module Idris.Parser.Expr,
12 module Idris.Parser.Expr,
@@ -1569,7 +1570,8 @@ parseImports fname input
1569 [ImportInfo],
1570 [ImportInfo],
1570 Maybe Delta),
1571 Maybe Delta),
1571 [(FC, OutputAnnotation)], IState)
1572 [(FC, OutputAnnotation)], IState)
1573+ imports = do optional shebang
1572− imports = do whiteSpace
1574+ whiteSpace
1573 (mdoc, mname, annots) <- moduleHeader
1575 (mdoc, mname, annots) <- moduleHeader
1574 ps_exp <- many import_
1576 ps_exp <- many import_
1575 mrk <- mark
1577 mrk <- mark
@@ -1594,6 +1596,9 @@ parseImports fname input
1594 (fc, AnnNamespace ns (Just path)) : addPath annots path
1596 (fc, AnnNamespace ns (Just path)) : addPath annots path
1595 addPath (annot:annots) path = annot : addPath annots path
1597 addPath (annot:annots) path = annot : addPath annots path
1596
1598
1599+ shebang :: IdrisParser ()
1600+ shebang = string "#!" *> many (satisfy $ not . isEol) *> eol *> pure ()
1601+
1597-- | There should be a better way of doing this...
1602-- | There should be a better way of doing this...
1598findFC :: Doc -> (FC, String)
1603findFC :: Doc -> (FC, String)
1599findFC x = let s = show (plain x) in findFC' s
1604findFC x = let s = show (plain x) in findFC' s
@@ -1659,7 +1664,7 @@ loadModule' f phase
1659 = do i <- getIState
1664 = do i <- getIState
1660 let file = takeWhile (/= ' ') f
1665 let file = takeWhile (/= ' ') f
1661 ibcsd <- valIBCSubDir i
1666 ibcsd <- valIBCSubDir i
1662− ids <- allImportDirs
1667+ ids <- rankedImportDirs file
1663 fp <- findImport ids ibcsd file
1668 fp <- findImport ids ibcsd file
1664 if file `elem` imported i
1669 if file `elem` imported i
1665 then do logParser 1 $ "Already read " ++ file
1670 then do logParser 1 $ "Already read " ++ file
@@ -1712,7 +1717,7 @@ loadSource lidr f toline
1712 (mdocs, mname, imports_in, pos) <- parseImports f file
1717 (mdocs, mname, imports_in, pos) <- parseImports f file
1713 ai <- getAutoImports
1718 ai <- getAutoImports
1714 let imports = map (\n -> ImportInfo True n Nothing [] NoFC NoFC) ai ++ imports_in
1719 let imports = map (\n -> ImportInfo True n Nothing [] NoFC NoFC) ai ++ imports_in
1715− ids <- allImportDirs
1720+ ids <- rankedImportDirs f
1716 ibcsd <- valIBCSubDir i
1721 ibcsd <- valIBCSubDir i
1717 mapM_ (\(re, f, ns, nfc) ->
1722 mapM_ (\(re, f, ns, nfc) ->
1718 do fp <- findImport ids ibcsd f
1723 do fp <- findImport ids ibcsd f
src/Idris/Parser/Expr.hs+7
@@ -234,6 +234,7 @@ updateSynMatch = update
234 = DoBindP fc (update ns i) (update ns t)
234 = DoBindP fc (update ns i) (update ns t)
235 (map (\(l,r) -> (update ns l, update ns r)) ts)
235 (map (\(l,r) -> (update ns l, update ns r)) ts)
236 upd ns (DoLetP fc i t) = DoLetP fc (update ns i) (update ns t)
236 upd ns (DoLetP fc i t) = DoLetP fc (update ns i) (update ns t)
237+ upd ns (DoRewrite fc h) = DoRewrite fc (update ns h)
237 update ns (PIdiom fc t) = PIdiom fc $ update ns t
238 update ns (PIdiom fc t) = PIdiom fc $ update ns t
238 update ns (PMetavar fc n) = uncurry (flip PMetavar) $ updateB ns (n, fc)
239 update ns (PMetavar fc n) = uncurry (flip PMetavar) $ updateB ns (n, fc)
239 update ns (PProof tacs) = PProof $ map (updTactic ns) tacs
240 update ns (PProof tacs) = PProof $ map (updTactic ns) tacs
@@ -1343,6 +1344,7 @@ doBlock syn
1343Do ::=
1344Do ::=
1344 'let' Name TypeSig'? '=' Expr
1345 'let' Name TypeSig'? '=' Expr
1345 | 'let' Expr' '=' Expr
1346 | 'let' Expr' '=' Expr
1347+ | 'rewrite Expr
1346 | Name '<-' Expr
1348 | Name '<-' Expr
1347 | Expr' '<-' Expr
1349 | Expr' '<-' Expr
1348 | Expr
1350 | Expr
@@ -1367,6 +1369,11 @@ do_ syn
1367 sc <- expr syn
1369 sc <- expr syn
1368 highlightP kw AnnKeyword
1370 highlightP kw AnnKeyword
1369 return (DoLetP fc i sc))
1371 return (DoLetP fc i sc))
1372+ <|> try (do kw <- reservedFC "rewrite"
1373+ fc <- getFC
1374+ sc <- expr syn
1375+ highlightP kw AnnKeyword
1376+ return (DoRewrite fc sc))
1370 <|> try (do (i, ifc) <- name
1377 <|> try (do (i, ifc) <- name
1371 symbol "<-"
1378 symbol "<-"
1372 fc <- getFC
1379 fc <- getFC
src/Idris/Parser/Helpers.hs+3−9
@@ -5,11 +5,9 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8+{-# LANGUAGE CPP, ConstraintKinds, FlexibleInstances,
8−{-# LANGUAGE CPP, ConstraintKinds, GeneralizedNewtypeDeriving, PatternGuards,
9+ GeneralizedNewtypeDeriving, PatternGuards, StandaloneDeriving,
9− StandaloneDeriving #-}
10+ TypeSynonymInstances #-}
10−#if !(MIN_VERSION_base(4,8,0))
11−{-# LANGUAGE OverlappingInstances #-}
12−#endif
13module Idris.Parser.Helpers where
11module Idris.Parser.Helpers where
14
12
15import Idris.AbsSyntax
13import Idris.AbsSyntax
@@ -70,11 +68,7 @@ instance {-# OVERLAPPING #-} DeltaParsing IdrisParser where
70
68
71#endif
69#endif
72
70
73−#if MIN_VERSION_base(4,8,0)
74instance {-# OVERLAPPING #-} TokenParsing IdrisParser where
71instance {-# OVERLAPPING #-} TokenParsing IdrisParser where
75−#else
76−instance TokenParsing IdrisParser where
77−#endif
78 someSpace = many (simpleWhiteSpace <|> singleLineComment <|> multiLineComment) *> pure ()
72 someSpace = many (simpleWhiteSpace <|> singleLineComment <|> multiLineComment) *> pure ()
79 token p = do s <- get
73 token p = do s <- get
80 (FC fn (sl, sc) _) <- getFC --TODO: Update after fixing getFC
74 (FC fn (sl, sc) _) <- getFC --TODO: Update after fixing getFC
src/Idris/Parser/Ops.hs+2−1
@@ -5,7 +5,8 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8−{-# LANGUAGE ConstraintKinds, GeneralizedNewtypeDeriving, PatternGuards #-}
8+{-# LANGUAGE ConstraintKinds, FlexibleContexts, GeneralizedNewtypeDeriving,
9+ PatternGuards #-}
9module Idris.Parser.Ops where
10module Idris.Parser.Ops where
10
11
11import Idris.AbsSyntax
12import Idris.AbsSyntax
src/Idris/PartialEval.hs+1−1
@@ -5,7 +5,7 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8−{-# LANGUAGE PatternGuards #-}
8+{-# LANGUAGE FlexibleContexts, PatternGuards #-}
9
9
10module Idris.PartialEval(
10module Idris.PartialEval(
11 partial_eval, getSpecApps, specType
11 partial_eval, getSpecApps, specType
src/Idris/Prover.hs+1
@@ -350,6 +350,7 @@ elabloop info fn d prompt prf e prev h env
350 Success (Right cmd') ->
350 Success (Right cmd') ->
351 case cmd' of
351 case cmd' of
352 DoLetP {} -> ifail "Pattern-matching let not supported here"
352 DoLetP {} -> ifail "Pattern-matching let not supported here"
353+ DoRewrite {} -> ifail "Pattern-matching do-rewrite not supported here"
353 DoBindP {} -> ifail "Pattern-matching <- not supported here"
354 DoBindP {} -> ifail "Pattern-matching <- not supported here"
354 DoLet fc i ifc Placeholder expr ->
355 DoLet fc i ifc Placeholder expr ->
355 do (tm, ty) <- elabVal (recinfo proverfc) ERHS (inLets ist env expr)
356 do (tm, ty) <- elabVal (recinfo proverfc) ERHS (inLets ist env expr)
src/Idris/REPL.hs+1−1
@@ -5,7 +5,7 @@ License : BSD3
5Maintainer : The Idris Community.
5Maintainer : The Idris Community.
6-}
6-}
7
7
8−{-# LANGUAGE PatternGuards #-}
8+{-# LANGUAGE FlexibleContexts, PatternGuards #-}
9
9
10module Idris.REPL
10module Idris.REPL
11 ( idemodeStart
11 ( idemodeStart
src/Idris/Reflection.hs−5
@@ -21,11 +21,6 @@ import Idris.AbsSyntaxTree (ArgOpt(..), ElabD, Fixity(..), IState(idris_datatype
21 initEState, pairCon, pairTy)
21 initEState, pairCon, pairTy)
22import Idris.Delaborate (delab)
22import Idris.Delaborate (delab)
23
23
24−#if __GLASGOW_HASKELL__ < 710
25−import Control.Applicative (pure, (<$>), (<*>))
26−import Data.Traversable (mapM)
27−import Prelude hiding (mapM)
28−#endif
29import Control.Monad (liftM, liftM2, liftM4)
24import Control.Monad (liftM, liftM2, liftM4)
30import Control.Monad.State.Strict (lift)
25import Control.Monad.State.Strict (lift)
31import Data.List (findIndex, (\\))
26import Data.List (findIndex, (\\))
src/Util/Pretty.hs+3
@@ -5,6 +5,9 @@ Copyright :
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
7-}
7-}
8+
9+{-# LANGUAGE MultiParamTypeClasses #-}
10+
8module Util.Pretty (
11module Util.Pretty (
9 module Text.PrettyPrint.Annotated.Leijen
12 module Text.PrettyPrint.Annotated.Leijen
10 , Sized(..)
13 , Sized(..)
stack-shell.nix+1−1
@@ -2,7 +2,7 @@ with (import <nixpkgs> {});
2
2
3let
3let
4 # MUST match resolver in stack.yaml
4 # MUST match resolver in stack.yaml
5− resolver = haskell.packages.lts-8_18.ghc;
5+ resolver = haskell.packages.lts-9_0.ghc;
6
6
7 native_libs = [
7 native_libs = [
8 libffi
8 libffi
stack.yaml+4−2
@@ -1,4 +1,5 @@
1+#recheck extra-deps next on resolver or cabal file change
1−resolver: lts-8.18
2+resolver: lts-9.0
2
3
3packages:
4packages:
4 - location: .
5 - location: .
@@ -9,7 +10,8 @@ flags:
9 GMP: true
10 GMP: true
10
11
11extra-deps:
12extra-deps:
12− - libffi-0.1
13+ - binary-0.8.5.1
14+ - cheapskate-0.1.1
13
15
14nix:
16nix:
15 enable: false
17 enable: false
test/TestData.hs+2−1
@@ -259,7 +259,8 @@ testFamiliesData = [
259 ( 77, ANY )]),
259 ( 77, ANY )]),
260 ("regression", "Regression",
260 ("regression", "Regression",
261 [ ( 1 , ANY ),
261 [ ( 1 , ANY ),
262− ( 2 , ANY )]),
262+ ( 2 , ANY ),
263+ ( 3 , ANY )]),
263 ("sourceLocation", "Source location",
264 ("sourceLocation", "Source location",
264 [ ( 1 , ANY )]),
265 [ ( 1 , ANY )]),
265 ("sugar", "Syntactic sugar",
266 ("sugar", "Syntactic sugar",
test/TestRun.hs+2−3
@@ -7,9 +7,7 @@ import Control.Monad
7import Data.Char (isLetter)
7import Data.Char (isLetter)
8import qualified Data.IntMap as IMap
8import qualified Data.IntMap as IMap
9import Data.List
9import Data.List
10−#if MIN_VERSION_optparse_applicative(0,13,0)
11import Data.Monoid ((<>))
10import Data.Monoid ((<>))
12−#endif
13import Data.Proxy
11import Data.Proxy
14import Data.Typeable
12import Data.Typeable
15import Options.Applicative
13import Options.Applicative
@@ -67,7 +65,8 @@ test testName path = goldenVsFileDiff testName diff ref output
67 where
65 where
68 ref = path </> "expected"
66 ref = path </> "expected"
69 output = path </> "output"
67 output = path </> "output"
68+ diff ref new | os == "openbsd" = ["diff", "-u", new, ref]
70− diff ref new = ["diff", "--strip-trailing-cr", "-u", new, ref]
69+ | otherwise = ["diff", "--strip-trailing-cr", "-u", new, ref]
71
70
72-- Should always output a 3-charater string from a postive Int
71-- Should always output a 3-charater string from a postive Int
73indexToString :: Int -> String
72indexToString :: Int -> String
test/base001/exit1.c+4
@@ -1,6 +1,10 @@
1#include <stdio.h>
1#include <stdio.h>
2#include <stdlib.h>
2#include <stdlib.h>
3
3
4+#ifdef __OpenBSD__
5+#include <sys/wait.h>
6+#endif
7+
4void doSystem(const char cmd[]) {
8void doSystem(const char cmd[]) {
5 printf("exit1: Executing cmd '%s'\n", cmd);
9 printf("exit1: Executing cmd '%s'\n", cmd);
6 int exitStatus = system(cmd);
10 int exitStatus = system(cmd);
test/base001/sys.c+4
@@ -2,6 +2,10 @@
2
2
3#include <stdlib.h>
3#include <stdlib.h>
4
4
5+#ifdef __OpenBSD__
6+#include <sys/wait.h>
7+#endif
8+
5int WIFEXITED_(int status) {
9int WIFEXITED_(int status) {
6 return WIFEXITED(status);
10 return WIFEXITED(status);
7}
11}
test/basic009/expected+1−1
@@ -1,5 +1,5 @@
1MAIN-PASS
1MAIN-PASS
2−Faulty.idr:6:9-12:WARNING: num is bound as an implicit
2+Faulty.idr:6:9-12:num is bound as an implicit
3 Did you mean to refer to A.num?
3 Did you mean to refer to A.num?
4Faulty.idr:7:7:When checking right hand side of fault with expected type
4Faulty.idr:7:7:When checking right hand side of fault with expected type
5 num = 0
5 num = 0
test/basic018/expected+4−2
@@ -1,6 +1,8 @@
1+basic018.idr:7:12-17:
1−basic018.idr:7:12-17:WARNING: thing is bound as an implicit
2+thing is bound as an implicit
2 Did you mean to refer to Main.thing?
3 Did you mean to refer to Main.thing?
4+basic018.idr:12:8-13:
3−basic018.idr:12:8-13:WARNING: thing is bound as an implicit
5+thing is bound as an implicit
4 Did you mean to refer to Main.thing?
6 Did you mean to refer to Main.thing?
5basic018.idr:13:6:When checking right hand side of test with expected type
7basic018.idr:13:6:When checking right hand side of test with expected type
6 thing = S 41
8 thing = S 41
test/interactive017/TestMod.idrnew file+5
@@ -0,0 +1,5 @@
1+module TestMod
2+
3+export
4+test : IO ()
5+test = putStrLn "Hello from a module"
test/interactive017/expectednew file+7
@@ -0,0 +1,7 @@
1+hello from C
2+hello from C
3+hello from node
4+hello from node
5+Hello ["aaa"]
6+Hello ["bbb", "aaa"]
7+Hello from a module
test/interactive017/runnew file+9
@@ -0,0 +1,9 @@
1+#!/bin/sh
2+PATH="../../scripts:$PATH"
3+./shebang.idr
4+./shebang.idr
5+./shebang-node.idr
6+./shebang-node.idr
7+./shebang-args.idr aaa
8+./shebang-args.idr bbb aaa
9+./shebang-import.idr
test/interactive017/shebang-args.idrnew file+6
@@ -0,0 +1,6 @@
1+#!/usr/bin/env runidris
2+
3+main : IO ()
4+main = do
5+ args <- getArgs
6+ putStrLn $ "Hello " ++ (show $ drop 1 args)
test/interactive017/shebang-import.idrnew file+6
@@ -0,0 +1,6 @@
1+#!/usr/bin/env runidris
2+
3+import TestMod
4+
5+main : IO ()
6+main = TestMod.test
test/interactive017/shebang-node.idrnew file+4
@@ -0,0 +1,4 @@
1+#!/usr/bin/env runidris-node
2+
3+main : IO ()
4+main = putStrLn "hello from node"
test/interactive017/shebang.idrnew file+4
@@ -0,0 +1,4 @@
1+#!/usr/bin/env runidris
2+
3+main : IO ()
4+main = putStrLn "hello from C"
test/proof002/Reflect.idr+1−1
@@ -10,7 +10,7 @@ using (xs : List a, ys : List a, G : List (List a))
10
10
11 data Elem : a -> List a -> Type where
11 data Elem : a -> List a -> Type where
12 Stop : Elem x (x :: xs)
12 Stop : Elem x (x :: xs)
13− Pop : Elem x ys -> Elem x (y :: xs)
13+ Pop : Elem x ys -> Elem x (y :: ys)
14
14
15-- Expr is a reflection of a list, indexed over the concrete list,
15-- Expr is a reflection of a list, indexed over the concrete list,
16-- and over a set of list variables.
16-- and over a set of list variables.
test/regression002/expected+2−1
@@ -110,7 +110,8 @@ reg068.idr:1:6:Main.nat has a name which may be implicitly bound.
110This is likely to lead to problems!
110This is likely to lead to problems!
111reg068.idr:2:6:Main.ze has a name which may be implicitly bound.
111reg068.idr:2:6:Main.ze has a name which may be implicitly bound.
112This is likely to lead to problems!
112This is likely to lead to problems!
113+reg068.idr:2:8-11:
113−reg068.idr:2:8-11:WARNING: nat is bound as an implicit
114+nat is bound as an implicit
114 Did you mean to refer to Main.nat?
115 Did you mean to refer to Main.nat?
115reg068.idr:2:6:When checking constructor Main.ze:
116reg068.idr:2:6:When checking constructor Main.ze:
116Type level variable nat is not Main.nat
117Type level variable nat is not Main.nat
test/regression003/expectednew file+1
@@ -0,0 +1 @@
1+ola
test/regression003/regression003.idrnew file+56
@@ -0,0 +1,56 @@
1+module Main
2+
3+data Free : (f : Type -> Type) -> (a : Type) -> Type where
4+ Pure : a -> Free f a
5+ Bind : f (Free f a) -> Free f a
6+
7+Functor f => Functor (Free f) where
8+ map f m = assert_total $ case m of
9+ Pure x => Pure (f x)
10+ Bind x => Bind (map (map f) x)
11+
12+Functor f => Applicative (Free f) where
13+ pure = Pure
14+
15+ m <*> x = assert_total $ case m of
16+ Pure f => map f x
17+ Bind f => Bind (map (<*> x) f)
18+
19+Functor f => Monad (Free f) where
20+ m >>= f = assert_total $ case m of
21+ Pure x => f x
22+ Bind x => Bind (map (>>= f) x)
23+
24+liftFree : Functor f => f a -> Free f a
25+liftFree = assert_total $ Bind . map Pure
26+
27+foldFree : (Monad m, Functor f) => ({ a : Type } -> f a -> m a) -> Free f b -> m b
28+foldFree f m = assert_total $ case m of
29+ Pure x => pure x
30+ Bind x => f x >>= foldFree f
31+
32+data FileSystemF next
33+ = ReadFile (String -> next)
34+
35+FileSystem : Type -> Type
36+FileSystem = Free FileSystemF
37+
38+Functor FileSystemF where
39+ map f (ReadFile nextFn) = ReadFile (f . nextFn)
40+
41+readFileF : FileSystem String
42+readFileF = liftFree $ ReadFile id
43+
44+
45+
46+interpret2 : FileSystemF a -> IO a
47+interpret2 (ReadFile nextFn) = do
48+ contents <- pure "ola"
49+ pure (nextFn contents)
50+
51+main : IO ()
52+main =
53+ do
54+ c <- foldFree interpret2 readFileF
55+ putStrLn' c
56+
test/regression003/runnew file+4
@@ -0,0 +1,4 @@
1+#!/usr/bin/env bash
2+${IDRIS:-idris} $@ regression003.idr -o regression003
3+./regression003
4+rm -f regression003 *.ibc