on master help sign in
Merge remote-tracking branch 'refs/remotes/upstream/master' into quasiquote

Conflicts: CHANGELOG

commite08a18daf4ad76fb2fbef64ad8c93903ade656f4 authorDavid Raymond Christiansen <david@davidchristiansen.dk> dateSat 28 Jun 2014, 23:56 (12 years ago) parentae5c48a86b1a78
22 files changed+291−186
CHANGELOG+1 Setup.hs+49−8 idris.cabal+9 jsrts/Runtime-common.js−1 jsrts/jsbn/jsbn.js+3−3 libs/base/System.idr+3 libs/prelude/Prelude/Nat.idr+39−45 src/IRTS/CodegenC.hs−1 src/IRTS/CodegenJavaScript.hs+82−48 src/IRTS/CodegenLLVM.hs−1 src/IRTS/Compiler.hs−2 src/IRTS/System.hs+7−2 src/Idris/AbsSyntax.hs−2 src/Idris/AbsSyntaxTree.hs−2 src/Idris/DSL.hs−1 src/Idris/ElabDecls.hs−1 src/Idris/IdrisDoc.hs+1−1 src/Idris/Imports.hs−1 src/Idris/REPL.hs+1−1 src/Idris/TypeSearch.hs+96−62 src/Pkg/PParser.hs−2 src/Pkg/Package.hs−2
CHANGELOG+1
@@ -9,6 +9,7 @@ New in 0.9.14:
99 functions and let. The keyword for this is "pi".
1010* Experimental 'neweffects' library, with simplified API
1111* All new JavaScript backend (avoids callstack overflows)
12+* Add support for %lib directive for NodeJS
1213* Quasiquotes and quasiquote patterns allow easier work with reflected terms.
1314 `(EXPR) quasiquotes EXPR, causing the elaborator to be used to produce a reflected
1415 version of it. Subterms prefixed with ~ are unquoted - on the RHS, they are reflected
Setup.hs+49−8
@@ -13,8 +13,9 @@ import Distribution.Simple.Utils (createDirectoryIfMissingVerbose, rewriteFile)
1313import Distribution.PackageDescription
1414import Distribution.Text
1515
16+import System.Environment
1617import System.Exit
17−import System.FilePath ((</>), splitDirectories)
18+import System.FilePath ((</>), splitDirectories,isAbsolute)
1819import System.Directory
1920import qualified System.FilePath.Posix as Px
2021import System.Process
@@ -70,6 +71,12 @@ isRelease flags =
7071 Just False -> False
7172 Nothing -> False
7273
74+isFreestanding :: S.ConfigFlags -> Bool
75+isFreestanding flags =
76+ case lookup (FlagName "freestanding") (S.configConfigurationsFlags flags) of
77+ Just True -> True
78+ Just False -> False
79+ Nothing -> False
7380-- -----------------------------------------------------------------------------
7481-- Clean
7582
@@ -98,12 +105,12 @@ gitHash = do h <- Control.Exception.catch (readProcess "git" ["rev-parse", "--sh
98105-- Put the Git hash into a module for use in the program
99106-- For release builds, just put the empty string in the module
100107generateVersionModule verbosity dir release = do
101− hash <- gitHash
102− let versionModulePath = dir </> "Version_idris" Px.<.> "hs"
103− putStrLn $ "Generating " ++ versionModulePath ++
108+ hash <- gitHash
109+ let versionModulePath = dir </> "Version_idris" Px.<.> "hs"
110+ putStrLn $ "Generating " ++ versionModulePath ++
104111 if release then " for release" else (" for prerelease " ++ hash)
105− createDirectoryIfMissingVerbose verbosity True dir
106− rewriteFile versionModulePath (versionModuleContents hash)
112+ createDirectoryIfMissingVerbose verbosity True dir
113+ rewriteFile versionModulePath (versionModuleContents hash)
107114
108115 where versionModuleContents h = "module Version_idris where\n\n" ++
109116 "gitHash :: String\n" ++
@@ -111,9 +118,38 @@ generateVersionModule verbosity dir release = do
111118 then "gitHash = \"\"\n"
112119 else "gitHash = \"-git:" ++ h ++ "\"\n"
113120
121+-- Generate a module that contains the lib path for a freestanding Idris
122+generateTargetModule verbosity dir targetDir = do
123+ absPath <- return $ isAbsolute targetDir
124+ let targetModulePath = dir </> "Target_idris" Px.<.> "hs"
125+ putStrLn $ "Generating " ++ targetModulePath
126+ createDirectoryIfMissingVerbose verbosity True dir
127+ rewriteFile targetModulePath (versionModuleContents absPath targetDir)
128+ where versionModuleContents absolute td = "module Target_idris where\n\n" ++
129+ "import System.FilePath\n" ++
130+ "import System.Environment\n" ++
131+ "getDataDir :: IO String\n" ++
132+ if absolute
133+ then "getDataDir = return \"" ++ td ++ "\"\n"
134+ else "getDataDir = do \n" ++
135+ " expath <- getExecutablePath\n" ++
136+ " execDir <- return $ dropFileName expath\n" ++
137+ " return $ execDir ++ \"" ++ td ++ "\"\n"
138+ ++ "getDataFileName :: FilePath -> IO FilePath\n"
139+ ++ "getDataFileName name = do\n"
140+ ++ " dir <- getDataDir\n"
141+ ++ " return (dir ++ \"/\" ++ name)"
142+
143+
114144idrisConfigure _ flags _ local = do
115145 configureRTS
116146 generateVersionModule verbosity (autogenModulesDir local) (isRelease (configFlags local))
147+ when (isFreestanding $ configFlags local) (do
148+ targetDir <- lookupEnv "IDRIS_INSTALL_DIR"
149+ case targetDir of
150+ Just d -> generateTargetModule verbosity (autogenModulesDir local) d
151+ Nothing -> error $ "Trying to build freestanding without a target directory."
152+ ++ " Set it by defining IDRIS_INSTALL_DIR.")
117153 where
118154 verbosity = S.fromFlag $ S.configVerbosity flags
119155 version = pkgVersion . package $ localPkgDescr local
@@ -128,12 +164,16 @@ idrisPreSDist args flags = do
128164 let dir = S.fromFlag (S.sDistDirectory flags)
129165 let verb = S.fromFlag (S.sDistVerbosity flags)
130166 generateVersionModule verb ("src") True
167+ generateTargetModule verb "src" "./libs"
131168 preSDist simpleUserHooks args flags
132169
133170idrisPostSDist args flags desc lbi = do
134171 Control.Exception.catch (do let file = "src" </> "Version_idris" Px.<.> "hs"
135− putStrLn $ "Removing generated module " ++ file
136− removeFile file)
172+ let targetFile = "src" </> "Target_idris" Px.<.> "hs"
173+ putStrLn $ "Removing generated modules:\n "
174+ ++ file ++ "\n" ++ targetFile
175+ removeFile file
176+ removeFile targetFile)
137177 (\e -> let e' = (e :: SomeException) in return ())
138178 postSDist simpleUserHooks args flags desc lbi
139179
@@ -168,6 +208,7 @@ idrisBuild _ flags _ local = do
168208 gmpflag True = ["GMP=-DIDRIS_GMP"]
169209
170210
211+
171212-- -----------------------------------------------------------------------------
172213-- Copy/Install
173214
idris.cabal+9
@@ -515,6 +515,11 @@ Flag release
515515 Default: False
516516 manual: True
517517
518+Flag freestanding
519+ Description: Build an Idris that doesn't use cabal
520+ Default: False
521+ manual: True
522+
518523Library
519524 hs-source-dirs: src
520525 Exposed-modules:
@@ -627,6 +632,7 @@ Library
627632 , directory
628633 , directory >= 1.2
629634 , filepath
635+ , fingertree >= 0.1
630636 , haskeline >= 0.7
631637 , language-java >= 0.2.6
632638 , lens >= 4.1.1
@@ -688,6 +694,9 @@ Library
688694 if flag(curses)
689695 build-depends: hscurses
690696 cpp-options: -DCURSES
697+ if flag(freestanding)
698+ other-modules: Target_idris
699+ cpp-options: -DFREESTANDING
691700
692701Executable idris
693702 Main-is: Main.hs
jsrts/Runtime-common.js−1
@@ -5,7 +5,6 @@ var i$VM = function() {
55 this.valstack_base = 0;
66
77 this.ret = null;
8− this.reg1 = null;
98
109 this.callstack = [];
1110}
jsrts/jsbn/jsbn.js+3−3
@@ -1,4 +1,4 @@
1−var __IDRRT__bigInt = (function() {
1+var i$bigInt = (function() {
22// Copyright (c) 2005 Tom Wu
33// All Rights Reserved.
44// See "LICENSE" for details.
@@ -1234,5 +1234,5 @@ return function(val) {
12341234}
12351235})();
12361236
1237−var __IDRRT__ZERO = __IDRRT__bigInt("0");
1238−var __IDRRT__ONE = __IDRRT__bigInt("1");
1237+var i$ZERO = i$bigInt("0");
1238+var i$ONE = i$bigInt("1");
libs/base/System.idr+3
@@ -80,3 +80,6 @@ time = mkForeign (FFun "idris_time" [] FInt)
8080usleep : Int -> IO ()
8181usleep i = mkForeign (FFun "usleep" [FInt] FUnit) i
8282
83+system : String -> IO Int
84+system cmd = mkForeign (FFun "system" [FString] FInt) cmd
85+
libs/prelude/Prelude/Nat.idr+39−45
@@ -146,19 +146,15 @@ gt left right = lt right left
146146
147147||| Find the least of two natural numbers
148148total minimum : Nat -> Nat -> Nat
149−minimum left right =
150− if lte left right then
151− left
152− else
153− right
149+minimum Z m = Z
150+minimum (S n) Z = Z
151+minimum (S n) (S m) = S (minimum n m)
154152
155153||| Find the greatest of two natural numbers
156154total maximum : Nat -> Nat -> Nat
157−maximum left right =
158− if lte left right then
159− right
160− else
161− left
155+maximum Z m = m
156+maximum (S n) Z = S n
157+maximum (S n) (S m) = S (maximum n m)
162158
163159--------------------------------------------------------------------------------
164160-- Type class instances
@@ -635,8 +631,40 @@ lteSuccZeroFalse Z = refl
635631lteSuccZeroFalse (S n) = refl
636632
637633-- Minimum and maximum
634+total maximumAssociative : (l,c,r : Nat) -> maximum l (maximum c r) = maximum (maximum l c) r
635+maximumAssociative Z c r = refl
636+maximumAssociative (S k) Z r = refl
637+maximumAssociative (S k) (S j) Z = refl
638+maximumAssociative (S k) (S j) (S i) = rewrite maximumAssociative k j i in refl
639+
640+total maximumCommutative : (l, r : Nat) -> maximum l r = maximum r l
641+maximumCommutative Z Z = refl
642+maximumCommutative Z (S k) = refl
643+maximumCommutative (S k) Z = refl
644+maximumCommutative (S k) (S j) = rewrite maximumCommutative k j in refl
645+
646+total maximumIdempotent : (n : Nat) -> maximum n n = n
647+maximumIdempotent Z = refl
648+maximumIdempotent (S k) = cong (maximumIdempotent k)
649+
650+total minimumAssociative : (l,c,r : Nat) -> minimum l (minimum c r) = minimum (minimum l c) r
651+minimumAssociative Z c r = refl
652+minimumAssociative (S k) Z r = refl
653+minimumAssociative (S k) (S j) Z = refl
654+minimumAssociative (S k) (S j) (S i) = rewrite minimumAssociative k j i in refl
655+
656+total minimumCommutative : (l, r : Nat) -> minimum l r = minimum r l
657+minimumCommutative Z Z = refl
658+minimumCommutative Z (S k) = refl
659+minimumCommutative (S k) Z = refl
660+minimumCommutative (S k) (S j) = rewrite minimumCommutative k j in refl
661+
662+total minimumIdempotent : (n : Nat) -> minimum n n = n
663+minimumIdempotent Z = refl
664+minimumIdempotent (S k) = cong (minimumIdempotent k)
665+
638666total minimumZeroZeroRight : (right : Nat) -> minimum 0 right = Z
639−minimumZeroZeroRight Z = refl
667+minimumZeroZeroRight Z = refl
640668minimumZeroZeroRight (S right) = minimumZeroZeroRight right
641669
642670total minimumZeroZeroLeft : (left : Nat) -> minimum left 0 = Z
@@ -652,15 +680,6 @@ minimumSuccSucc (S left) (S right) =
652680 let inductiveHypothesis = minimumSuccSucc left right in
653681 ?minimumSuccSuccStepCase
654682
655−total minimumCommutative : (left : Nat) -> (right : Nat) ->
656− minimum left right = minimum right left
657−minimumCommutative Z Z = refl
658−minimumCommutative Z (S right) = refl
659−minimumCommutative (S left) Z = refl
660−minimumCommutative (S left) (S right) =
661− let inductiveHypothesis = minimumCommutative left right in
662− ?minimumCommutativeStepCase
663−
664683total maximumZeroNRight : (right : Nat) -> maximum Z right = right
665684maximumZeroNRight Z = refl
666685maximumZeroNRight (S right) = refl
@@ -678,15 +697,6 @@ maximumSuccSucc (S left) (S right) =
678697 let inductiveHypothesis = maximumSuccSucc left right in
679698 ?maximumSuccSuccStepCase
680699
681−total maximumCommutative : (left : Nat) -> (right : Nat) ->
682− maximum left right = maximum right left
683−maximumCommutative Z Z = refl
684−maximumCommutative (S left) Z = refl
685−maximumCommutative Z (S right) = refl
686−maximumCommutative (S left) (S right) =
687− let inductiveHypothesis = maximumCommutative left right in
688− ?maximumCommutativeStepCase
689−
690700-- div and mod
691701total modZeroZero : (n : Nat) -> mod 0 n = Z
692702modZeroZero Z = refl
@@ -852,28 +862,12 @@ plusZeroRightNeutralStepCase = proof {
852862 trivial;
853863}
854864
855−maximumCommutativeStepCase = proof {
856− intros;
857− rewrite (boolElimSuccSucc (lte left right) right left);
858− rewrite (boolElimSuccSucc (lte right left) left right);
859− rewrite inductiveHypothesis;
860− trivial;
861−}
862−
863865maximumSuccSuccStepCase = proof {
864866 intros;
865867 rewrite sym (boolElimSuccSucc (lte left right) (S right) (S left));
866868 trivial;
867869}
868870
869−minimumCommutativeStepCase = proof {
870− intros;
871− rewrite (boolElimSuccSucc (lte left right) left right);
872− rewrite (boolElimSuccSucc (lte right left) right left);
873− rewrite inductiveHypothesis;
874− trivial;
875−}
876−
877871minimumSuccSuccStepCase = proof {
878872 intros;
879873 rewrite (boolElimSuccSucc (lte left right) (S left) (S right));
src/IRTS/CodegenC.hs−1
@@ -7,7 +7,6 @@ import IRTS.Simplified
77import IRTS.System
88import IRTS.CodegenCommon
99import Idris.Core.TT
10−import Paths_idris
1110import Util.System
1211
1312import Numeric
src/IRTS/CodegenJavaScript.hs+82−48
@@ -7,7 +7,7 @@ import IRTS.Lang
77import IRTS.Simplified
88import IRTS.CodegenCommon
99import Idris.Core.TT
10−import Paths_idris
10+import IRTS.System
1111import Util.System
1212
1313import Control.Arrow
@@ -24,21 +24,39 @@ import System.IO
2424import System.Directory
2525
2626
27−idrNamespace :: String
28−idrNamespace = "__IDR__"
29−idrRTNamespace = "__IDRRT__"
30−idrLTNamespace = "__IDRLT__"
31−idrCTRNamespace = "__IDRCTR__"
32−
33−data CompileInfo = CompileInfo { compileInfoApplyCases :: [Int]
34− , compileInfoEvalCases :: [Int]
27+data CompileInfo = CompileInfo { compileInfoApplyCases :: [Int]
28+ , compileInfoEvalCases :: [Int]
29+ , compileInfoNeedsBigInt :: Bool
3530 }
3631
3732
3833initCompileInfo :: [(Name, [BC])] -> CompileInfo
3934initCompileInfo bc =
40− CompileInfo (collectCases "APPLY" bc) (collectCases "EVAL" bc)
35+ CompileInfo (collectCases "APPLY" bc) (collectCases "EVAL" bc) (lookupBigInt bc)
4136 where
37+ lookupBigInt :: [(Name, [BC])] -> Bool
38+ lookupBigInt = any (needsBigInt . snd)
39+ where
40+ needsBigInt :: [BC] -> Bool
41+ needsBigInt bc = or $ map testBCForBigInt bc
42+ where
43+ testBCForBigInt :: BC -> Bool
44+ testBCForBigInt (ASSIGNCONST _ c) =
45+ testConstForBigInt c
46+
47+ testBCForBigInt (CONSTCASE _ c d) =
48+ maybe False needsBigInt d
49+ || (or $ map (needsBigInt . snd) c)
50+ || (or $ map (testConstForBigInt . fst) c)
51+
52+ testBCForBigInt _ = False
53+
54+ testConstForBigInt :: Const -> Bool
55+ testConstForBigInt (BI _) = True
56+ testConstForBigInt (B64 _) = True
57+ testConstForBigInt _ = False
58+
59+
4260 collectCases :: String -> [(Name, [BC])] -> [Int]
4361 collectCases fun bc = getCases $ findFunction fun bc
4462
@@ -147,7 +165,7 @@ ffi code args = let parsed = ffiParse code in
147165 | isDigit s =
148166 FFIArg (read $ s : takeWhile isDigit ss) : ffiParse (dropWhile isDigit ss)
149167 | otherwise =
150− [FFIError $ "FFI - Invalid positional argument"]
168+ [FFIError "FFI - Invalid positional argument"]
151169 ffiParse (s:ss) = FFICode s : ffiParse ss
152170
153171
@@ -159,8 +177,8 @@ ffi code args = let parsed = ffiParse code in
159177
160178 renderFFI :: [FFI] -> [String] -> String
161179 renderFFI [] _ = ""
162− renderFFI ((FFICode c) : fs) args = c : renderFFI fs args
163− renderFFI ((FFIArg i) : fs) args
180+ renderFFI (FFICode c : fs) args = c : renderFFI fs args
181+ renderFFI (FFIArg i : fs) args
164182 | i < length args && i >= 0 = args !! i ++ renderFFI fs args
165183 | otherwise = error "FFI - Argument index out of bounds"
166184
@@ -190,18 +208,18 @@ compileJS' indent (JSFunction args body) =
190208 ++ "\n}\n"
191209
192210compileJS' indent (JSType ty)
193− | JSIntTy <- ty = idrRTNamespace ++ "Int"
194− | JSStringTy <- ty = idrRTNamespace ++ "String"
195− | JSIntegerTy <- ty = idrRTNamespace ++ "Integer"
196− | JSFloatTy <- ty = idrRTNamespace ++ "Float"
197− | JSCharTy <- ty = idrRTNamespace ++ "Char"
198− | JSPtrTy <- ty = idrRTNamespace ++ "Ptr"
199− | JSForgotTy <- ty = idrRTNamespace ++ "Forgot"
211+ | JSIntTy <- ty = "i$Int"
212+ | JSStringTy <- ty = "i$String"
213+ | JSIntegerTy <- ty = "i$Integer"
214+ | JSFloatTy <- ty = "i$Float"
215+ | JSCharTy <- ty = "i$Char"
216+ | JSPtrTy <- ty = "i$Ptr"
217+ | JSForgotTy <- ty = "i$Forgot"
200218
201219compileJS' indent (JSSeq seq) =
202220 intercalate ";\n" (
203221 map (
204− ((replicate indent ' ') ++) . (compileJS' indent)
222+ (replicate indent ' ' ++) . (compileJS' indent)
205223 ) $ filter (/= JSNoop) seq
206224 ) ++ ";"
207225
@@ -260,10 +278,10 @@ compileJS' indent (JSString str) =
260278compileJS' indent (JSNum num)
261279 | JSInt i <- num = show i
262280 | JSFloat f <- num = show f
263− | JSInteger JSBigZero <- num = "__IDRRT__ZERO"
264− | JSInteger JSBigOne <- num = "__IDRRT__ONE"
281+ | JSInteger JSBigZero <- num = "i$ZERO"
282+ | JSInteger JSBigOne <- num = "i$ONE"
265283 | JSInteger (JSBigInt i) <- num = show i
266− | JSInteger (JSBigIntExpr e) <- num = "__IDRRT__bigInt(" ++ compileJS' indent e ++ ")"
284+ | JSInteger (JSBigIntExpr e) <- num = "i$bigInt(" ++ compileJS' indent e ++ ")"
267285
268286compileJS' indent (JSAssign lhs rhs) =
269287 compileJS' indent lhs ++ " = " ++ compileJS' indent rhs
@@ -294,14 +312,16 @@ compileJS' indent (JSCond branches) =
294312 ++ replicate (indent + 2) ' ' ++ compileJS' (indent + 2) e
295313 ++ ";\n" ++ replicate indent ' ' ++ "}"
296314
297−compileJS' indent (JSSwitch val [(_,seq)] Nothing) =
298− compileJS' indent seq
315+compileJS' indent (JSSwitch val [(_,JSSeq seq)] Nothing) =
316+ let (h,t) = splitAt 1 seq in
317+ (concatMap (compileJS' indent) h ++ ";\n")
318+ ++ (intercalate ";\n" $ map ((replicate indent ' ' ++) . compileJS' indent) t)
299319
300320compileJS' indent (JSSwitch val branches def) =
301321 "switch(" ++ compileJS' indent val ++ "){\n"
302322 ++ concatMap mkBranch branches
303323 ++ mkDefault def
304− ++ (replicate indent ' ') ++ "}"
324+ ++ replicate indent ' ' ++ "}"
305325 where
306326 mkBranch :: (JS, JS) -> String
307327 mkBranch (tag, code) =
@@ -335,24 +355,27 @@ compileJS' indent (JSWord word)
335355 | JSWord8 b <- word = "new Uint8Array([" ++ show b ++ "])"
336356 | JSWord16 b <- word = "new Uint16Array([" ++ show b ++ "])"
337357 | JSWord32 b <- word = "new Uint32Array([" ++ show b ++ "])"
338− | JSWord64 b <- word = idrRTNamespace ++ "bigInt(\"" ++ show b ++ "\")"
358+ | JSWord64 b <- word = "i$bigInt(\"" ++ show b ++ "\")"
339359
340360codegenJavaScript :: CodeGenerator
341−codegenJavaScript ci = codegenJS_all JavaScript (simpleDecls ci)
342− (includes ci) (outputFile ci) (outputType ci)
361+codegenJavaScript ci =
362+ codegenJS_all JavaScript (simpleDecls ci)
363+ (includes ci) [] (outputFile ci) (outputType ci)
343364
344365codegenNode :: CodeGenerator
345−codegenNode ci = codegenJS_all Node (simpleDecls ci)
346− (includes ci) (outputFile ci) (outputType ci)
366+codegenNode ci =
367+ codegenJS_all Node (simpleDecls ci)
368+ (includes ci) (compileLibs ci) (outputFile ci) (outputType ci)
347369
348370codegenJS_all
349371 :: JSTarget
350372 -> [(Name, SDecl)]
351373 -> [FilePath]
374+ -> [String]
352375 -> FilePath
353376 -> OutputType
354377 -> IO ()
355−codegenJS_all target definitions includes filename outputType = do
378+codegenJS_all target definitions includes libs filename outputType = do
356379 let bytecode = map toBC definitions
357380 let info = initCompileInfo bytecode
358381 let js = concatMap (translateDecl info) bytecode
@@ -365,14 +388,26 @@ codegenJS_all target definitions includes filename outputType = do
365388 path <- (++) <$> getDataDir <*> (pure "/jsrts/")
366389 idrRuntime <- readFile $ path ++ "Runtime-common.js"
367390 tgtRuntime <- readFile $ concat [path, "Runtime", rt, ".js"]
368− jsbn <- readFile $ path ++ "jsbn/jsbn.js"
369− let runtime = header ++ included ++ jsbn ++ idrRuntime ++ tgtRuntime
391+ jsbn <- if compileInfoNeedsBigInt info
392+ then readFile $ path ++ "jsbn/jsbn.js"
393+ else return ""
394+ let runtime = ( header
395+ ++ includeLibs libs
396+ ++ included
397+ ++ jsbn
398+ ++ idrRuntime
399+ ++ tgtRuntime
400+ )
370401 writeFile filename $ runtime ++ concat code ++ main ++ invokeMain
371402 setPermissions filename (emptyPermissions { readable = True
372− , executable = target == Node
373− , writable = True
374− })
403+ , executable = target == Node
404+ , writable = True
405+ })
375406 where
407+ includeLibs :: [String] -> String
408+ includeLibs =
409+ concatMap (\lib -> "var " ++ lib ++ " = require(\"" ++ lib ++"\");\n")
410+
376411 getIncludes :: [FilePath] -> IO [String]
377412 getIncludes = mapM readFile
378413
@@ -455,15 +490,15 @@ splitFunction (JSAlloc name (Just (JSFunction args body@(JSSeq _)))) = do
455490 where
456491 processBranches :: [(JS,JS)] -> RWS () [(Int,JS)] Int [(JS,JS)]
457492 processBranches =
458− traverse (runKleisli (arr id *** (Kleisli splitSequence)))
493+ traverse (runKleisli (arr id *** Kleisli splitSequence))
459494
460495 splitSequence :: JS -> RWS () [(Int, JS)] Int JS
461− splitSequence js@(JSSeq seq) = do
496+ splitSequence js@(JSSeq seq) =
462497 let (pre,post) = break isCall seq in
463498 case post of
464499 [] -> JSSeq <$> traverse splitCondition seq
465500 [js@(JSCond _)] -> splitCondition js
466− [js@(JSSwitch _ _ _)] -> splitCondition js
501+ [js@(JSSwitch {})] -> splitCondition js
467502 [_] -> return js
468503 (call:rest) -> do
469504 depth <- get
@@ -533,7 +568,7 @@ translateDecl info (name@(MN 0 fun), bc)
533568
534569 isCase :: BC -> Bool
535570 isCase bc
536− | CASE _ _ _ _ <- bc = True
571+ | CASE {} <- bc = True
537572 | otherwise = False
538573
539574 defaultCase :: [BC] -> [BC]
@@ -571,7 +606,7 @@ translateDecl info (name, bc) =
571606translateReg :: Reg -> JS
572607translateReg reg
573608 | RVal <- reg = jsRET
574− | Tmp <- reg = JSProj (JSIdent "vm") "reg1"
609+ | Tmp <- reg = JSRaw "//TMPREG"
575610 | L n <- reg = jsLOC n
576611 | T n <- reg = jsTOP n
577612
@@ -612,7 +647,7 @@ translateChar ch
612647 | '\\' <- ch = "\\\\"
613648 | '\"' <- ch = "\\\""
614649 | '\'' <- ch = "\\\'"
615− | ch `elem` asciiTab = "\\u00" ++ fill (showIntAtBase 16 intToDigit (ord ch) "")
650+ | ch `elem` asciiTab = "\\u00" ++ fill (showHex (ord ch) "")
616651 | otherwise = [ch]
617652 where
618653 fill :: String -> String
@@ -628,8 +663,8 @@ translateChar ch
628663
629664translateName :: Name -> String
630665translateName n = "_idris_" ++ concatMap cchar (showCG n)
631− where cchar x | isAlpha x || isDigit x = [x]
632− | otherwise = "_" ++ show (fromEnum x) ++ "_"
666+ where cchar x | isAlphaNum x = [x]
667+ | otherwise = "_" ++ show (fromEnum x) ++ "_"
633668
634669jsASSIGN :: CompileInfo -> Reg -> Reg -> JS
635670jsASSIGN _ r1 r2 = JSAssign (translateReg r1) (translateReg r2)
@@ -1499,6 +1534,5 @@ translateBC info bc
14991534 | PROJECT r l a <- bc = jsPROJECT info r l a
15001535 | OP r o a <- bc = jsOP info r o a
15011536 | ERROR e <- bc = jsERROR info e
1502− | otherwise = JSRaw $ show bc
1503− {- PROJECTINTO _ _ _ <- bc = undefined -}
1537+ | otherwise = JSRaw $ "//" ++ show bc
15041538
src/IRTS/CodegenLLVM.hs−1
@@ -9,7 +9,6 @@ import qualified Idris.Core.TT as TT
99import Idris.Core.TT (ArithTy(..), IntTy(..), NativeTy(..), nativeTyWidth)
1010
1111import Util.System
12−import Paths_idris
1312
1413import LLVM.General.Context
1514import LLVM.General.Diagnostic
src/IRTS/Compiler.hs−2
@@ -47,8 +47,6 @@ import System.Directory
4747import System.Environment
4848import System.FilePath ((</>), addTrailingPathSeparator)
4949
50−import Paths_idris
51−
5250compile :: Codegen -> FilePath -> Term -> Idris ()
5351compile codegen f tm
5452 = do checkMVs -- check for undefined metavariables
src/IRTS/System.hs+7−2
@@ -1,6 +1,6 @@
11{-# LANGUAGE CPP #-}
2−module IRTS.System(getTargetDir,getCC,getLibFlags,getIdrisLibDir,
3− getIncFlags,getMvn,getExecutablePom) where
2+module IRTS.System(getDataFileName, getDataDir, getTargetDir,getCC,getLibFlags,getIdrisLibDir,
3+ getIncFlags,getMvn,getExecutablePom, version) where
44
55import Util.System
66
@@ -9,7 +9,12 @@ import Data.Maybe (fromMaybe)
99import System.FilePath ((</>), addTrailingPathSeparator)
1010import System.Environment
1111
12+#ifdef FREESTANDING
13+import Target_idris
14+import Paths_idris (version)
15+#else
1216import Paths_idris
17+#endif
1318
1419getCC :: IO String
1520getCC = fromMaybe "gcc" <$> environment "IDRIS_CC"
src/Idris/AbsSyntax.hs−2
@@ -14,8 +14,6 @@ import Idris.IdeSlave hiding (Opt(..))
1414import IRTS.CodegenCommon
1515import Util.DynamicLinker
1616
17−import Paths_idris
18−
1917import System.Console.Haskeline
2018import System.IO
2119
src/Idris/AbsSyntaxTree.hs−2
@@ -15,8 +15,6 @@ import Util.DynamicLinker
1515
1616import Idris.Colours
1717
18−import Paths_idris
19−
2018import System.Console.Haskeline
2119import System.IO
2220
src/Idris/DSL.hs−1
@@ -3,7 +3,6 @@
33module Idris.DSL where
44
55import Idris.AbsSyntax
6−import Paths_idris
76
87import Idris.Core.TT
98import Idris.Core.Evaluate
src/Idris/ElabDecls.hs−1
@@ -19,7 +19,6 @@ import Idris.PartialEval
1919import Idris.DeepSeq
2020import Idris.Output (iputStrLn, pshow, iWarn)
2121import IRTS.Lang
22−import Paths_idris
2322
2423import Idris.Core.TT
2524import Idris.Core.Elaborate hiding (Tactic(..))
src/Idris/IdrisDoc.hs+1−1
@@ -14,7 +14,7 @@ import Idris.AbsSyntax
1414import Idris.Docs
1515import Idris.Docstrings (nullDocstring)
1616
17−import Paths_idris (getDataFileName)
17+import IRTS.System (getDataFileName)
1818
1919import Control.Monad (forM_)
2020import Control.Monad.Trans.Error
src/Idris/Imports.hs−1
@@ -4,7 +4,6 @@ import Idris.AbsSyntax
44import Idris.Error
55
66import Idris.Core.TT
7−import Paths_idris
87
98import System.FilePath
109import System.Directory
src/Idris/REPL.hs+1−1
@@ -34,7 +34,6 @@ import Idris.Interactive
3434import Idris.WhoCalls
3535import Idris.TypeSearch (searchByType)
3636
37−import Paths_idris
3837import Version_idris (gitHash)
3938import Util.System
4039import Util.DynamicLinker
@@ -48,6 +47,7 @@ import Idris.Core.Constraints
4847
4948import IRTS.Compiler
5049import IRTS.CodegenCommon
50+import IRTS.System
5151
5252import Data.List.Split (splitOn)
5353import qualified Data.Text as T
src/Idris/TypeSearch.hs+96−62
@@ -10,14 +10,15 @@ import Data.Function (on)
1010import Data.List (find, minimumBy, partition, sortBy, (\\))
1111import Data.Map (Map)
1212import qualified Data.Map as M
13−import Data.Maybe (catMaybes, fromMaybe, isJust)
13+import Data.Maybe (catMaybes, fromMaybe, isJust, maybeToList)
1414import Data.Monoid (Monoid (mempty, mappend))
15+import qualified Data.PriorityQueue.FingerTree as Q
1516import Data.Set (Set)
1617import qualified Data.Set as S
1718import qualified Data.Text as T (pack, isPrefixOf)
1819
1920import Idris.AbsSyntax (addUsingConstraints, addImpl, getContext, getIState, putIState, implicit)
20−import Idris.AbsSyntaxTree (class_instances, defaultSyntax, Idris,
21+import Idris.AbsSyntaxTree (class_instances, ClassInfo, defaultSyntax, Idris,
2122 IState (idris_classes, idris_docstrings, tt_ctxt),
2223 implicitAllowed, prettyDocumentedIst, prettyIst, PTerm, toplevel)
2324import Idris.Core.Evaluate (Context (definitions), Def (Function, TyDecl, CaseOp), normaliseC)
@@ -41,7 +42,7 @@ searchByType h pterm = do
4142 ty <- elabType' False toplevel syn (fst noDocs) (snd noDocs) emptyFC [] n pterm'
4243 putIState i -- don't actually make any changes
4344 let names = searchUsing searchPred i ty
44− let names' = take numLimit . takeWhile ((< scoreLimit) . getScore) $
45+ let names' = take numLimit $
4546 sortBy (compare `on` getScore) names
4647 let docs =
4748 [ let docInfo = (n, delabTy i n, fmap (overview . fst) (lookupCtxtExact n (idris_docstrings i))) in
@@ -51,7 +52,6 @@ searchByType h pterm = do
5152 where
5253 getScore = defaultScoreFunction . snd . snd
5354 numLimit = 50
54− scoreLimit = 100
5555 syn = defaultSyntax { implicitAllowed = True } -- syntax
5656 n = sMN 0 "searchType" -- name
5757
@@ -84,10 +84,9 @@ searchUsing pred istate ty =
8484
8585-- Our default search predicate.
8686searchPred :: IState -> Type -> Type -> Maybe Score
87−searchPred istate ty1 = \ty2 -> case matcher ty2 of
88− xs -> guard (not (null xs)) >> return (minimumBy (compare `on` defaultScoreFunction) xs)
89− where
90− matcher = unifyWithHoles istate ty1
87+searchPred istate ty1 = matcher where
88+ maxScore = 100
89+ matcher = unifyWithHoles istate maxScore ty1
9190
9291
9392typeFromDef :: (Def, b, c, d) -> Maybe Type
@@ -218,36 +217,53 @@ inArgTys :: (Type -> Type) -> ArgsDAG -> ArgsDAG
218217inArgTys = map . first . second
219218
220219
220+typeclassUnify :: Ctxt ClassInfo -> Context -> Type -> Type -> Maybe [(Name, Type)]
221+typeclassUnify classInfo ctxt ty tyTry = do
222+ res <- tcToMaybe $ match_unify ctxt [] ty retTy [] holes []
223+ guard $ null (holes \\ map fst res)
224+ let argTys' = map (second $ foldr (.) id [ subst n t | (n, t) <- res ]) tcArgs
225+ return argTys'
226+ where
227+ tyTry' = vToP tyTry
228+ holes = map fst nonTcArgs
229+ retTy = getRetTy tyTry'
230+ (tcArgs, nonTcArgs) = partition (isTypeClassArg classInfo . snd) $ getArgTys tyTry'
231+
232+isTypeClassArg :: Ctxt ClassInfo -> Type -> Bool
233+isTypeClassArg classInfo ty = not (null (getClassName clss >>= flip lookupCtxt classInfo)) where
234+ (clss, args) = unApply ty
235+ getClassName (P (TCon _ _) className _) = [className]
236+ getClassName _ = []
237+
238+
239+instance Ord Score where
240+ compare = compare `on` defaultScoreFunction
241+
221242--DONT run vToP first!
222243-- | Try to match two types together in a unification-like procedure.
223244-- Returns a list of possible scores representing ways in which the two
224245-- types can be matched.
225−unifyWithHoles :: IState -> Type -> Type -> [Score]
226−unifyWithHoles istate type1 = \type2 -> let
246+unifyWithHoles :: IState -> Int -> Type -> Type -> Maybe Score
247+unifyWithHoles istate maxScore type1 = \type2 -> let
227248 (dag2, typeClassArgs2, retTy2) = makeDag (uniqueBinders argNames1 type2)
228249 argNames2 = map (fst . fst) dag2
229250 startingHoles = argNames1 ++ argNames2
230251
231252 startingTypes = (retTy1, retTy2) : []
232− in case unifyQueue (State startingHoles dag1 dag2
253+ in do
254+ state <- unifyQueue (State startingHoles dag1 dag2
233255 typeClassArgs1 typeClassArgs2
234256 mempty startingHoles) startingTypes
235− of Nothing -> []
236− Just state -> possibleMatches state
257+ getResults (Q.singleton (score state) state)
237258 where
238259 ctxt = tt_ctxt istate
239260 classInfo = idris_classes istate
240261
241− isTypeClassArg :: Type -> Bool
242− isTypeClassArg ty = not (null (getClassName clss >>= flip lookupCtxt classInfo)) where
243− (clss, args) = unApply ty
244− getClassName (P (TCon _ _) className _) = [className]
245− getClassName _ = []
246−
247262 (dag1, typeClassArgs1, retTy1) = makeDag type1
248263 argNames1 = map (fst . fst) dag1
249264 makeDag :: Type -> (ArgsDAG, [(Name, Type)], Type)
250− makeDag = first3 (zipWith (\i (ty, deps) -> (ty, (i, deps))) [0..] . reverseDag) . computeDagP isTypeClassArg . vToP
265+ makeDag = first3 (zipWith (\i (ty, deps) -> (ty, (i, deps))) [0..] . reverseDag) .
266+ computeDagP (isTypeClassArg classInfo) . vToP
251267 first3 f (a,b,c) = (f a, b, c)
252268
253269 -- update our state with the unification resolutions
@@ -278,9 +294,13 @@ unifyWithHoles istate type1 = \type2 -> let
278294 (Nothing, Nothing) -> nextStep
279295 _ -> error ("Shouldn't happen. Watch the alpha conversion!\n" ++ show args1 ++ "\n\n" ++ show args2)
280296 where
297+ varsInTy = map fst $ M.toList (usedVars term) --[]
298+ toDelete = name : varsInTy
299+ deleteMany = foldr (.) id $ [ deleteLeft t . deleteRight t | t <- toDelete ]
300+
281301 inScore f state = state { score = f (score state) }
282− state' = modifyTypes (subst name term) . deleteLeft name . deleteRight name $
283− state { holes = holes \\ [name]}
302+ state' = modifyTypes (subst name term) . deleteMany $
303+ state { holes = holes \\ toDelete }
284304 nextStep = resolveUnis xs state'
285305
286306
@@ -288,12 +308,13 @@ unifyWithHoles istate type1 = \type2 -> let
288308 unifyQueue :: State -> [(Type, Type)] -> Maybe State
289309 unifyQueue state [] = return state
290310 unifyQueue state ((ty1, ty2) : queue) = do
311+ --trace ("go: \n" ++ show state) True `seq` return ()
291312 res <- tcToMaybe $ match_unify ctxt [] ty1 ty2 [] (holes state) []
292313 (state', queueAdditions) <- resolveUnis res state
293314 guard $ scoreCriterion (score state')
294315 unifyQueue state' (queue ++ queueAdditions)
295316
296− possClassInstances :: [Name] -> Type -> [([(Name, Type)], Type)]
317+ possClassInstances :: [Name] -> Type -> [Type]
297318 possClassInstances usedNames ty = do
298319 className <- getClassName clss
299320 classDef <- lookupCtxt className classInfo
@@ -301,57 +322,70 @@ unifyWithHoles istate type1 = \type2 -> let
301322 def <- lookupCtxt n (definitions ctxt)
302323 ty <- normaliseC ctxt [] <$> (case typeFromDef def of Just x -> [x]; Nothing -> [])
303324 let ty' = vToP (uniqueBinders usedNames ty)
304− return (getArgTys ty', getRetTy ty')
325+ return ty'
305326 where
306− (clss, args) = unApply ty
327+ (clss, _) = unApply ty
307328 getClassName (P (TCon _ _) className _) = [className]
308329 getClassName _ = []
309330
331+
332+ getResults :: Q.PQueue Score State -> Maybe Score
333+ getResults queue = do
334+ ((nextScore, next), rest) <- Q.minViewWithKey queue
335+ if isFinal next
336+ then return nextScore
337+ else do
338+ guard (defaultScoreFunction nextScore <= maxScore)
339+ let additions = if scoreCriterion nextScore
340+ then Q.fromList [ (score state, state) | state <- nextSteps next ]
341+ else Q.empty
342+ getResults (Q.union rest additions)
343+ where
344+ isFinal (State [] [] [] [] [] score _) = True
345+ isFinal _ = False
346+
310347 -- | Find all possible matches starting from a given state.
311− possibleMatches :: State -> [Score]
312− possibleMatches (State [] [] [] [] [] scoreAcc _) = [scoreAcc]
313− possibleMatches (State holes dag1 dag2 c1 c2 scoreAcc usedNames) =
314− concat [ possibleMatches state | state <- results, scoreCriterion (score state) ] where
348+ -- We go in stages rather than concatenating all three results in hopes of narrowing
349+ -- the search tree. Once we advance in a phase, there should be no going back.
350+ nextSteps :: State -> [State]
351+
352+ -- Stage 2 - match typeclasses
353+ nextSteps (State [] [] [] c1 c2 scoreAcc usedNames) =
354+ if null results2 then results3 else results2
355+ where
356+ -- try to match a typeclass argument from the left with a typeclass argument from the right
357+ results2 =
358+ catMaybes [ unifyQueue (State [] [] []
359+ (deleteFromArgList n1 c1) (map (second subst2for1) (deleteFromArgList n2 c2)) scoreAcc usedNames) [(ty1, ty2)]
360+ | (n1, ty1) <- c1, (n2, ty2) <- c2, let subst2for1 = psubst n2 (P Bound n1 ty1)]
361+
362+ -- try to hunt match a typeclass constraint by replacing it with an instance
363+ results3 = results3A ++ results3B
364+ typeClassArgs classes = [ ((n, ty), inst) | (n, ty) <- classes, inst <- possClassInstances usedNames ty ]
365+ results3A = [ State [] [] []
366+ (deleteFromArgList n c1 ++ newClassArgs) c2
367+ (scoreAcc `mappend` (mempty { leftTypeClass = 1 }))
368+ (usedNames ++ newHoles)
369+ | ((n, ty), inst) <- typeClassArgs c1
370+ , newClassArgs <- maybeToList $ typeclassUnify classInfo ctxt ty inst
371+ , let newHoles = map fst newClassArgs ]
372+ results3B = [ State [] [] []
373+ c1 (deleteFromArgList n c2 ++ newClassArgs)
374+ (scoreAcc `mappend` (mempty { rightTypeClass = 1 }))
375+ (usedNames ++ newHoles)
376+ | ((n, ty), inst) <- typeClassArgs c2
377+ , newClassArgs <- maybeToList $ typeclassUnify classInfo ctxt ty inst
378+ , let newHoles = map fst newClassArgs ]
379+
380+ -- Stage 1 - match arguments
381+ nextSteps (State holes dag1 dag2 c1 c2 scoreAcc usedNames) = results1 where
315382
316383 -- we only try to match arguments whose names don't appear in the types
317384 -- of any other arguments
318385 canBeFirst :: ArgsDAG -> [(Name, Type)]
319386 canBeFirst = map fst . filter (S.null . snd . snd)
320387
321− -- this is done rather than concatenating all three results in hopes of narrowing
322− -- the search tree
323− results = fromMaybe [] $ find (not . null) [results1, results2, results3]
324−
325388 -- try to match an argument from the left with an argument from the right
326389 results1 = catMaybes [ unifyQueue (State (holes \\ [n1, n2]) (deleteFromDag n1 dag1)
327390 ((inArgTys subst2for1) $ deleteFromDag n2 dag2) c1 (map (second subst2for1) c2) scoreAcc usedNames) [(ty1, ty2)]
328391 | (n1, ty1) <- canBeFirst dag1, (n2, ty2) <- canBeFirst dag2, let subst2for1 = psubst n2 (P Bound n1 ty1)]
329−
330− -- try to match a typeclass argument from the left with a typeclass argument from the right
331− results2 = catMaybes [ unifyQueue (State (holes \\ [n1, n2]) dag1 (inArgTys subst2for1 dag2)
332− (deleteFromArgList n1 c1) (map (second subst2for1) (deleteFromArgList n2 c2)) scoreAcc usedNames) [(ty1, ty2)]
333− | (n1, ty1) <- c1, (n2, ty2) <- c2, let subst2for1 = psubst n2 (P Bound n1 ty1)]
334−
335− -- try to hunt match a typeclass constraint by replacing it with an instance
336− results3 = if null dag1 || null dag2 then catMaybes (results3A ++ results3B) else []
337− typeClassArgs classes = [ ((n, ty), inst) | (n, ty) <- classes, inst <- possClassInstances usedNames ty ]
338− noDeps (n, ty) = ((n, ty), (0, S.empty))
339− results3A = [ unifyQueue
340− (State ((holes \\ [n]) ++ newHoles) (dag1 ++ map noDeps newNonClassArgs) dag2
341− (deleteFromArgList n c1 ++ newClassArgs) c2
342− (scoreAcc `mappend` (mempty { leftTypeClass = 1 }))
343− (usedNames ++ newHoles)
344− )
345− [(ty, inst)]
346− | ((n, ty), (newArgs, inst)) <- typeClassArgs c1, let newHoles = map fst newArgs
347− , let (newClassArgs, newNonClassArgs) = partition (isTypeClassArg . snd) newArgs ]
348− results3B = [ unifyQueue
349− (State ((holes \\ [n]) ++ newHoles) dag1 (dag2 ++ map noDeps newNonClassArgs)
350− c1 (deleteFromArgList n c2 ++ newClassArgs)
351− (scoreAcc `mappend` (mempty { rightTypeClass = 1 }))
352− (usedNames ++ newHoles)
353− )
354− [(ty, inst)]
355− | ((n, ty), (newArgs, inst)) <- typeClassArgs c2, let newHoles = map fst newArgs
356− , let (newClassArgs, newNonClassArgs) = partition (isTypeClassArg . snd) newArgs ]
357−
src/Pkg/PParser.hs−2
@@ -10,8 +10,6 @@ import Idris.AbsSyntaxTree
1010import Idris.ParseHelpers
1111import Idris.CmdOptions
1212
13−import Paths_idris
14−
1513import Control.Monad.State.Strict
1614import Control.Applicative
1715
src/Pkg/Package.hs−2
@@ -29,8 +29,6 @@ import IRTS.System
2929
3030import Pkg.PParser
3131
32−import Paths_idris (getDataDir)
33−
3432-- To build a package:
3533-- * read the package description
3634-- * check all the library dependencies exist