on master help sign in
Merge remote-tracking branch 'upstream/master' into idrisdoc
commit940da80d2aed761b54f9ecec9468ea869f5c339b authorPhilip Rasmussen <pjor@itu.dk> dateWed 30 Apr 2014, 14:52 (13 years ago) parent4aec152fd1219b
24 files changed+272−273
CHANGELOG+1 CONTRIBUTORS+1 idris.cabal+3−5 libs/Makefile−3 libs/base/Data/Complex.idr+2−2 libs/base/Data/Erased.idr+29 libs/base/base.ipkg+1−1 libs/effects/Effect/Random.idr+15−1 libs/javascript/JavaScript.idr−104 libs/javascript/JavaScript/JSON.idr−44 libs/javascript/Makefile−14 libs/javascript/javascript.ipkg−5 src/IRTS/Compiler.hs+126−47 src/Idris/CaseSplit.hs+7−4 src/Idris/Core/Elaborate.hs+1 src/Idris/Core/ProofState.hs+3−2 src/Idris/ElabTerm.hs+2−2 src/Idris/ParseExpr.hs+45−33 src/Idris/ParseOps.hs+1−2 src/Idris/Prover.hs+1 src/Idris/REPL.hs+5−4 test/reg042/expected+1 test/reg042/reg042.idr+24 test/reg042/run+4
CHANGELOG+1
@@ -6,6 +6,7 @@ New in 0.9.13:
66* Command line option -e (or --eval) to evaluate expressions without loading the
77 REPL. This is useful for writing more portable tests.
88* Many more of the basic functions and datatypes are documented.
9+* Removed javascript lib in favor of idris-hackers/iQuery
910
1011Internal changes
1112
CONTRIBUTORS+1
@@ -8,6 +8,7 @@ Edwin Brady
88David Raymond Christiansen
99Jason Dagit
1010Simon Fowler
11+Google
1112Cezar Ionescu
1213Irene Knapp
1314Shea Levy
idris.cabal+3−5
@@ -103,11 +103,6 @@ Extra-source-files:
103103 libs/oldeffects/Effect/*.idr
104104 libs/oldeffects/*.idr
105105
106− libs/javascript/*.idr
107− libs/javascript/JavaScript/*.idr
108− libs/javascript/Makefile
109− libs/javascript/javascript.ipkg
110−
111106 llvm/*.c
112107 llvm/Makefile
113108
@@ -237,6 +232,9 @@ Extra-source-files:
237232 test/reg041/run
238233 test/reg041/*.idr
239234 test/reg041/expected
235+ test/reg042/run
236+ test/reg042/*.idr
237+ test/reg042/expected
240238
241239 test/basic001/run
242240 test/basic001/*.idr
libs/Makefile−3
@@ -2,19 +2,16 @@ build:
22 $(MAKE) -C prelude build
33 $(MAKE) -C base build
44 $(MAKE) -C effects build
5− $(MAKE) -C javascript build
65
76
87install:
98 $(MAKE) -C prelude install
109 $(MAKE) -C base install
1110 $(MAKE) -C effects install
12− $(MAKE) -C javascript install
1311
1412clean:
1513 $(MAKE) -C prelude clean
1614 $(MAKE) -C base clean
1715 $(MAKE) -C effects clean
18− $(MAKE) -C javascript clean
1916
2017.PHONY: build install clean
libs/base/Data/Complex.idr+2−2
@@ -62,8 +62,8 @@ conjugate (r:+i) = (r :+ (0-i))
6262-- We can't do "instance Num a => Num (Complex a)" because
6363-- we need "abs" which needs "magnitude" which needs "sqrt" which needs Float
6464instance Num (Complex Float) where
65− (+) (a:+b) (c:+d) = ((a+b):+(c+d))
66− (-) (a:+b) (c:+d) = ((a-b):+(c-d))
65+ (+) (a:+b) (c:+d) = ((a+c):+(b+d))
66+ (-) (a:+b) (c:+d) = ((a-c):+(b-d))
6767 (*) (a:+b) (c:+d) = ((a*c-b*d):+(b*c+a*d))
6868 fromInteger x = (fromInteger x:+0)
6969 abs (a:+b) = (magnitude (a:+b):+0)
libs/base/Data/Erased.idrnew file+29
@@ -0,0 +1,29 @@
1+module Data.Erased
2+
3+%access public
4+%default total
5+
6+||| The erasure monad.
7+|||
8+||| Used when explicit modelling of erasure in the type system is needed.
9+data Erased : Type -> Type where
10+
11+ ||| Construct an erased value from any value.
12+ Erase : .(x : a) -> Erased a
13+
14+instance Functor Erased where
15+ map f (Erase x) = Erase (f x)
16+
17+instance Applicative Erased where
18+ pure = Erase
19+ (<$>) (Erase f) (Erase x) = Erase (f x)
20+
21+instance Monad Erased where
22+ (>>=) (Erase x) f = f x
23+
24+||| Project the erased value out of the monad.
25+|||
26+||| This is usable only in types and other erased contexts,
27+||| where it won't cause erasure violations.
28+unerase : Erased a -> a
29+unerase (Erase x) = x
libs/base/base.ipkg+1−1
@@ -22,7 +22,7 @@ modules = System,
2222 Data.SortedMap, Data.SortedSet, Data.BoundedList,
2323 Data.Vect, Data.HVect, Data.Vect.Quantifiers,
2424 Data.Floats, Data.Complex, Data.Heap, Data.Fun,
25− Data.Rel, Data.Buffer,
25+ Data.Rel, Data.Buffer, Data.Erased,
2626
2727 Control.Isomorphism, Control.Isomorphism.Primitives,
2828 Control.Monad.Identity,
libs/effects/Effect/Random.idr+15−1
@@ -16,18 +16,32 @@ using (m : Type -> Type)
1616RND : EFFECT
1717RND = MkEff Integer Random
1818
19+||| Generates a random Integer in a given range
1920rndInt : Integer -> Integer -> { [RND] } Eff m Integer
2021rndInt lower upper = do v <- getRandom
2122 return (v `prim__sremBigInt` (upper - lower) + lower)
2223
24+||| Generate a random number in Fin (S `k`)
25+|||
26+||| Note that rndFin k takes values 0, 1, ..., k.
2327rndFin : (k : Nat) -> { [RND] } Eff m (Fin (S k))
24−rndFin k = do let v = !getRandom `prim__sremBigInt` (cast k)
28+rndFin k = do let v = !getRandom `prim__sremBigInt` (cast (S k))
2529 return (toFin v)
2630 where toFin : Integer -> Fin (S k)
2731 toFin x = case integerToFin x (S k) of
2832 Just v => v
2933 Nothing => toFin (assert_smaller x (x - cast (S k)))
3034
35+||| Select a random element from a vector
36+rndSelect' : Vect (S k) a -> { [RND] } Eff IO a
37+rndSelect' {k} xs = return (Vect.index !(rndFin k) xs)
38+
39+||| Select a random element from a list, or Nothing if the list is empty
40+rndSelect : List a -> { [RND] } Eff IO (Maybe a)
41+rndSelect [] = return Nothing
42+rndSelect (x::xs) = return (Just !(rndSelect' (x::(fromList xs))))
43+
44+||| Sets the random seed
3145srand : Integer -> { [RND] } Eff m ()
3246srand n = setSeed n
3347
libs/javascript/JavaScript.idrdeleted−104
@@ -1,104 +0,0 @@
1−module JavaScript
2−
3−%access public
4−
5−private
6−isUndefined : Ptr -> IO Bool
7−isUndefined p = do
8− res <- mkForeign (
9− FFun "%0 === undefined" [FPtr] FString) p
10− if res == "false"
11− then (return False)
12− else (return True)
13−
14−--------------------------------------------------------------------------------
15−-- Events
16−--------------------------------------------------------------------------------
17−abstract
18−data Event : Type where
19− MkEvent : Ptr -> Event
20−
21−--------------------------------------------------------------------------------
22−-- Elements
23−--------------------------------------------------------------------------------
24−abstract
25−data Element : Type where
26− MkElem : Ptr -> Element
27−
28−setText : Element -> String -> IO ()
29−setText (MkElem p) s =
30− mkForeign (FFun "%0.textContent=%1" [FPtr, FString] FUnit) p s
31−
32−
33−setOnClick : Element -> (Event -> IO Bool) -> IO ()
34−setOnClick (MkElem e) f =
35− mkForeign (
36− FFun "%0['onclick']=%1" [ FPtr
37− , FFunction (FAny Event) (FAny (IO Bool))
38− ] FUnit) e f
39−--------------------------------------------------------------------------------
40−-- Nodelists
41−--------------------------------------------------------------------------------
42−abstract
43−data NodeList : Type where
44− MkNodeList : Ptr -> NodeList
45−
46−elemAt : NodeList -> Nat -> IO (Maybe Element)
47−elemAt (MkNodeList p) i = do
48− e <- mkForeign (FFun "%0.item(%1)" [FPtr, FInt] FPtr) p (
49− prim__truncBigInt_Int (cast i)
50− )
51− d <- isUndefined e
52− if d
53− then return $ Just (MkElem e)
54− else return Nothing
55−
56−--------------------------------------------------------------------------------
57−-- Intervals
58−--------------------------------------------------------------------------------
59−abstract
60−data Interval : Type where
61− MkInterval : Ptr -> Interval
62−
63−setInterval : (() -> IO ()) -> Float -> IO Interval
64−setInterval f t = do
65− e <- mkForeign (
66− FFun "setInterval(%0,%1)" [FFunction FUnit (FAny (IO ())), FFloat] FPtr
67− ) f t
68− return (MkInterval e)
69−
70−clearInterval : Interval -> IO ()
71−clearInterval (MkInterval p) =
72− mkForeign (FFun "clearInterval(%0)" [FPtr] FUnit) p
73−
74−--------------------------------------------------------------------------------
75−-- Timeouts
76−--------------------------------------------------------------------------------
77−data Timeout : Type where
78− MkTimeout : Ptr -> Timeout
79−
80−setTimeout : (() -> IO ()) -> Float -> IO Timeout
81−setTimeout f t = do
82− e <- mkForeign (
83− FFun "setTimeout(%0,%1)" [FFunction FUnit (FAny (IO ())), FFloat] FPtr
84− ) f t
85− return (MkTimeout e)
86−
87−clearTimeout : Timeout -> IO ()
88−clearTimeout (MkTimeout p) =
89− mkForeign (FFun "clearTimeout(%0)" [FPtr] FUnit) p
90−
91−--------------------------------------------------------------------------------
92−-- Basic IO
93−--------------------------------------------------------------------------------
94−alert : String -> IO ()
95−alert msg =
96− mkForeign (FFun "alert(%0)" [FString] FUnit) msg
97−
98−--------------------------------------------------------------------------------
99−-- DOM
100−--------------------------------------------------------------------------------
101−query : String -> IO NodeList
102−query q = do
103− e <- mkForeign (FFun "document.querySelectorAll(%0)" [FString] FPtr) q
104− return (MkNodeList e)
libs/javascript/JavaScript/JSON.idrdeleted−44
@@ -1,44 +0,0 @@
1−module JSON
2−
3−import Data.SortedMap
4−
5−data JSONType : Type where
6− JSONArray : (n : Nat) -> Vect n JSONType -> JSONType
7− JSONString : JSONType
8− JSONNumber : JSONType
9− JSONBool : JSONType
10− JSONObject : SortedMap String JSONType -> JSONType
11− JSONNull : JSONType
12−
13−mutual
14− using (ts : Vect n JSONType, fs : SortedMap String JSONType)
15− namespace JArray
16− data JArray : (n : Nat) -> Vect n JSONType -> Type where
17− Nil : JArray 0 []
18− (::) : JSON t -> JArray n ts -> JArray (S n) (t :: ts)
19−
20− namespace JObject
21− data JObject : SortedMap String JSONType -> Type where
22− Nil : JObject empty
23− (::) : (f : (String, JSON t)) ->
24− JObject fs ->
25− JObject (insert (fst f) t fs)
26−
27− data JSON : JSONType -> Type where
28− JSString : String -> JSON JSONString
29− JSNumber : Float -> JSON JSONNumber
30− JSBool : Bool -> JSON JSONBool
31− JSNull : JSON JSONNull
32− JSArray : JArray n ts -> JSON (JSONArray n ts)
33− JSObject : JObject fs -> JSON (JSONObject fs)
34−
35−index : (i : Fin n) -> JSON (JSONArray n ts) -> JSON (index i ts)
36−index fZ (JSArray (x :: xs)) = x
37−index (fS i) (JSArray (x :: xs)) = index i (JSArray xs)
38−
39−(++) : JSON (JSONArray m ts1) ->
40− JSON (JSONArray n ts2) ->
41− JSON (JSONArray (m + n) (ts1 ++ ts2))
42−(++) (JSArray []) ys = ys
43−(++) (JSArray (x :: xs)) ys with ((JSArray xs) ++ ys)
44− | (JSArray as) = JSArray (x :: as)
libs/javascript/Makefiledeleted−14
@@ -1,14 +0,0 @@
1−IDRIS := idris
2−
3−build:
4− $(IDRIS) --build javascript.ipkg
5−
6−install:
7− $(IDRIS) --install javascript.ipkg
8−
9−clean:
10− $(IDRIS) --clean javascript.ipkg
11−
12−rebuild: clean build
13−
14−.PHONY: build install clean rebuild
libs/javascript/javascript.ipkgdeleted−5
@@ -1,5 +0,0 @@
1−package javascript
2−
3−opts = "--nobasepkgs -i ../prelude -i ../base"
4−modules = JavaScript, JavaScript.JSON
5−
src/IRTS/Compiler.hs+126−47
@@ -262,20 +262,67 @@ irTerm vs env tm@(App f a) = case unApply tm of
262262 ,LConCase 1 (sNS (sUN "True" ) ["Bool","Prelude"]) [] t'
263263 ])
264264
265+ -- data constructor
265266 (P (DCon t arity) n _, args) -> do
266267 detag <- fgetState (opt_detaggable . ist_optimisation n)
267268 used <- map fst <$> fgetState (cg_usedpos . ist_callgraph n)
268269
269− when (length args > arity) $
270− ifail ("oversaturated data ctor: " ++ show tm)
271−
272− let args' = [a | (i,a) <- zip [0..] args, i `elem` used]
273− if length args' == 1 && detag -- detaggable
274− then irTerm vs env (head args') -- newtype
275− else irCon vs env (length used) n args'
276−
270+ let isNewtype = length used == 1 && detag
271+ let argsPruned = [a | (i,a) <- zip [0..] args, i `elem` used]
272+
273+ -- The following code removes fields from data constructors
274+ -- and performs the newtype optimisation.
275+ --
276+ -- The general rule here is:
277+ -- Everything we get as input is not touched by erasure,
278+ -- so it conforms to the official arities and types
279+ -- and we can reason about it like it's plain TT.
280+ --
281+ -- It's only the data that leaves this point that's erased
282+ -- and possibly no longer typed as the original TT version.
283+ --
284+ -- Especially, underapplied constructors must yield functions
285+ -- even if all the remaining arguments are erased
286+ -- (the resulting function *will* be applied, to NULLs).
287+ --
288+ -- This will probably need rethinking when we get erasure from functions.
289+
290+ -- "padLams" will wrap our term in LLam-bdas and give us
291+ -- the "list of future unerased args" coming from these lambdas.
292+ --
293+ -- We can do whatever we like with the list of unerased args,
294+ -- hence it takes a lambda: \unerased_argname_list -> resulting_LExp.
295+ let padLams = padLambdas used (length args) arity
296+
297+ case compare arity (length args) of
298+
299+ -- overapplied
300+ GT -> ifail ("overapplied data constructor: " ++ show tm)
301+
302+ -- exactly saturated
303+ EQ | isNewtype
304+ -> irTerm vs env (head argsPruned)
305+
306+ | otherwise -- not newtype, plain data ctor
307+ -> buildApp (LV $ Glob n) argsPruned
308+
309+ -- not saturated, underapplied
310+ LT | isNewtype -- newtype
311+ , length argsPruned == 1 -- and we already have the value
312+ -> padLams . (\tm [] -> tm) -- the [] asserts there are no unerased args
313+ <$> irTerm vs env (head argsPruned)
314+
315+ | isNewtype -- newtype but the value is not among args yet
316+ -> return . padLams $ \[vn] -> LApp False (LV $ Glob n) [LV $ Glob vn]
317+
318+ -- not a newtype, just apply to a constructor
319+ | otherwise
320+ -> padLams . applyToNames <$> buildApp (LV $ Glob n) argsPruned
321+
322+ -- type constructor
277323 (P (TCon t a) n _, args) -> return LNothing
278324
325+ -- a name applied to arguments
279326 (P _ n _, args) -> do
280327 ist <- getIState
281328 case lookup n (idris_scprims ist) of
@@ -296,29 +343,44 @@ irTerm vs env tm@(App f a) = case unApply tm of
296343 <*> mapM (irTerm vs env) args
297344
298345 where
346+ buildApp :: LExp -> [Term] -> Idris LExp
347+ buildApp e [] = return e
348+ buildApp e xs = LApp False e <$> mapM (irTerm vs env) xs
349+
350+ applyToNames :: LExp -> [Name] -> LExp
351+ applyToNames tm [] = tm
352+ applyToNames tm ns = LApp False tm $ map (LV . Glob) ns
353+
354+ padLambdas :: [Int] -> Int -> Int -> ([Name] -> LExp) -> LExp
355+ padLambdas used startIdx endSIdx mkTerm
356+ = LLam allNames $ mkTerm nonerasedNames
357+ where
358+ allNames = [sMN i "sat" | i <- [startIdx .. endSIdx-1]]
359+ nonerasedNames = [sMN i "sat" | i <- [startIdx .. endSIdx-1], i `elem` used]
360+
299361 applyName :: Name -> IState -> [Term] -> Idris LExp
300362 applyName n ist args =
301363 LApp False (LV $ Glob n) <$> mapM (irTerm vs env . erase) (zip [0..] args)
302− where
303− erase (i, x)
304− | i >= arity || i `elem` used = x
305− | otherwise = Erased
306−
307− arity = case fst4 <$> lookupCtxtExact n (definitions . tt_ctxt $ ist) of
308− Just (CaseOp ci ty tys def tot cdefs) -> length tys
309− Just (TyDecl (DCon tag ar) _) -> ar
310− Just (TyDecl Ref ty) -> length $ getArgTys ty
311− Just (Operator ty ar op) -> ar
312− Just def -> error $ "unknown arity: " ++ show (n, def)
313− Nothing -> 0 -- no definition, probably local name => can't erase anything
314−
315− -- name for purposes of usage info lookup
316− uName
317− | Just n' <- viMethod =<< M.lookup n vs = n'
318− | otherwise = n
319−
320− used = maybe [] (map fst . usedpos) $ lookupCtxtExact uName (idris_callgraph ist)
321− fst4 (x,_,_,_) = x
364+ where
365+ erase (i, x)
366+ | i >= arity || i `elem` used = x
367+ | otherwise = Erased
368+
369+ arity = case fst4 <$> lookupCtxtExact n (definitions . tt_ctxt $ ist) of
370+ Just (CaseOp ci ty tys def tot cdefs) -> length tys
371+ Just (TyDecl (DCon tag ar) _) -> ar
372+ Just (TyDecl Ref ty) -> length $ getArgTys ty
373+ Just (Operator ty ar op) -> ar
374+ Just def -> error $ "unknown arity: " ++ show (n, def)
375+ Nothing -> 0 -- no definition, probably local name => can't erase anything
376+
377+ -- name for purposes of usage info lookup
378+ uName
379+ | Just n' <- viMethod =<< M.lookup n vs = n'
380+ | otherwise = n
381+
382+ used = maybe [] (map fst . usedpos) $ lookupCtxtExact uName (idris_callgraph ist)
383+ fst4 (x,_,_,_) = x
322384
323385irTerm vs env (P _ n _) = return $ LV (Glob n)
324386irTerm vs env (V i)
@@ -345,24 +407,6 @@ irTerm vs env (TType _) = return $ LNothing
345407irTerm vs env Erased = return $ LNothing
346408irTerm vs env Impossible = return $ LNothing
347409
348−irCon :: Vars -> [Name] -> Int -> Name -> [Term] -> Idris LExp
349−irCon vs env arity n args
350− | length args > arity
351− = error $ "oversaturated data constructor: " ++ show (n, args)
352−
353− -- saturated
354− | length args == arity
355− = buildApp (LV (Glob n)) args
356−
357− -- undersaturated, wrap in lambdas
358− | otherwise
359− = let extraNs = [sMN i "sat" | i <- [length args .. arity-1]]
360− extraTs = [P Bound n undefined | n <- extraNs]
361− in LLam extraNs <$> irCon vs env arity n (args ++ extraTs)
362− where
363− buildApp e [] = return e
364− buildApp e xs = LApp False e <$> mapM (irTerm vs env) xs
365−
366410doForeign :: Vars -> [Name] -> [TT Name] -> Idris LExp
367411doForeign vs env (_ : fgn : args)
368412 | (_, (Constant (Str fgnName) : fgnArgTys : ret : [])) <- unApply fgn
@@ -470,6 +514,7 @@ irSC vs (Case n [ConCase (UN delay) i [_, _, n'] sc])
470514--
471515-- Hence, we check whether the variables are used at all
472516-- and erase the casesplit if they are not.
517+--
473518irSC vs (Case n [alt]) = do
474519 replacement <- case alt of
475520 ConCase cn a ns sc -> do
@@ -498,7 +543,41 @@ irSC vs (Case n [alt]) = do
498543 subexpr (LConstCase _ e) = e
499544 subexpr (LDefaultCase e) = e
500545
501−irSC vs (Case n alts) = LCase (LV (Glob n)) <$> mapM (irAlt vs (LV (Glob n))) alts
546+-- FIXME: When we have a non-singleton case-tree of the form
547+--
548+-- case {e0} of
549+-- C(x) => ...
550+-- ... => ...
551+--
552+-- and C is detaggable (the only constructor of the family), we can be sure
553+-- that the first branch will be always taken -- so we add special handling
554+-- to remove the dead default branch.
555+--
556+-- If we don't do so and C is newtype-optimisable, we will miss this newtype
557+-- transformation and the resulting code will probably segfault.
558+--
559+-- This work-around is not entirely optimal; the best approach would be
560+-- to ensure that such case trees don't arise in the first place.
561+--
562+irSC vs (Case n alts@[ConCase cn a ns sc, DefaultCase sc']) = do
563+ detag <- fgetState (opt_detaggable . ist_optimisation cn)
564+ if detag
565+ then irSC vs (Case n [ConCase cn a ns sc])
566+ else LCase (LV (Glob n)) <$> mapM (irAlt vs (LV (Glob n))) alts
567+
568+irSC vs sc@(Case n alts) = do
569+ -- check that neither alternative needs the newtype optimisation,
570+ -- see comment above
571+ goneWrong <- or <$> mapM isDetaggable alts
572+ when goneWrong
573+ $ ifail ("irSC: non-trivial case-match on detaggable data: " ++ show sc)
574+
575+ -- everything okay
576+ LCase (LV (Glob n)) <$> mapM (irAlt vs (LV (Glob n))) alts
577+ where
578+ isDetaggable (ConCase cn _ _ _) = fgetState $ opt_detaggable . ist_optimisation cn
579+ isDetaggable _ = return False
580+
502581irSC vs ImpossibleCase = return LNothing
503582
504583irAlt :: Vars -> LExp -> CaseAlt -> Idris LAlt
src/Idris/CaseSplit.hs+7−4
@@ -361,16 +361,19 @@ getProofClause l fn fp
361361
362362mkWith :: String -> Name -> String
363363mkWith str n = let str' = replaceRHS str "with (_)"
364− newpat = " " ++
365− replaceRHS str "| with_pat = ?" ++ show n ++ "_rhs" in
366− str' ++ "\n" ++ newpat
364+ in str' ++ "\n" ++ newpat str
367365
368366 where replaceRHS [] str = str
369367 replaceRHS ('?':'=': rest) str = str
370− replaceRHS ('=': rest) str
368+ replaceRHS ('=': rest) str
371369 | not ('=' `elem` rest) = str
372370 replaceRHS (x : rest) str = x : replaceRHS rest str
373371
372+ newpat ('>':patstr) = '>':newpat patstr
373+ newpat patstr =
374+ " " ++
375+ replaceRHS patstr "| with_pat = ?" ++ show n ++ "_rhs"
376+
374377-- Replace _ with names in missing clauses
375378
376379nameMissing :: [PTerm] -> Idris [PTerm]
src/Idris/Core/Elaborate.hs+1
@@ -646,6 +646,7 @@ no_errors tac err
646646 Error _ -> lift $ Error e
647647 OK (a, s') -> do put s'
648648 return a
649+ unifyProblems
649650 ps' <- get_probs
650651 if (length ps' > length ps) then
651652 case reverse ps' of
src/Idris/Core/ProofState.hs+3−2
@@ -817,8 +817,9 @@ mergeNotunified :: Env -> [(Name, Term)] -> ([(Name, Term)], Fails)
817817mergeNotunified env ns = mnu ns [] [] where
818818 mnu [] ns_acc ps_acc = (reverse ns_acc, reverse ps_acc)
819819 mnu ((n, t):ns) ns_acc ps_acc
820− | Just t' <- lookup n ns = mnu ns ((n,t) : ns_acc)
821− ((t,t',env,Msg "", [],Match) : ps_acc)
820+ | Just t' <- lookup n ns, t /= t'
821+ = mnu ns ((n,t') : ns_acc)
822+ ((t,t',env,Msg "", [],Unify) : ps_acc)
822823 | otherwise = mnu ns ((n,t) : ns_acc) ps_acc
823824
824825updateNotunified [] nu = nu
src/Idris/ElabTerm.hs+2−2
@@ -1187,8 +1187,8 @@ reifyApp _ t [x]
11871187reifyApp ist t [l, r] | t == reflm "Seq" = liftM2 TSeq (reify ist l) (reify ist r)
11881188reifyApp ist t [Constant (Str n), x]
11891189 | t == reflm "GoalType" = liftM (GoalType n) (reify ist x)
1190−reifyApp _ t [Constant (Str n)]
1191− | t == reflm "Intro" = return $ Intro [sUN n]
1190+reifyApp _ t [n] | t == reflm "Intro" = liftM (Intro . (:[])) (reifyTTName n)
1191+reifyApp _ t [n] | t == reflm "Induction" = liftM Induction (reifyTTName n)
11921192reifyApp ist t [t']
11931193 | t == reflm "ApplyTactic" = liftM (ApplyTactic . delab ist) (reifyTT t')
11941194reifyApp ist t [t']
src/Idris/ParseExpr.hs+45−33
@@ -54,14 +54,22 @@ fullExpr syn = do x <- expr syn
5454 return $ debindApp syn (desugar syn i x)
5555
5656
57−{- |Parses an expression
57+{- | Parses an expression
5858@
59− Expr ::= Expr';
59+ Expr ::= Pi
6060@
61−-}
61+ -}
6262expr :: SyntaxInfo -> IdrisParser PTerm
63−expr syn = do i <- get
64− buildExpressionParser (table (idris_infixes i)) (expr' syn)
63+expr = pi
64+
65+{- | Parses an expression with possible operator applied
66+@
67+ OpExpr ::= {- Expression Parser with Operators based on Expr' -};
68+@
69+-}
70+opExpr :: SyntaxInfo -> IdrisParser PTerm
71+opExpr syn = do i <- get
72+ buildExpressionParser (table (idris_infixes i)) (expr' syn)
6573
6674{- | Parses either an internally defined expression or
6775 a user-defined one
@@ -70,16 +78,10 @@ Expr' ::= "External (User-defined) Syntax"
7078 | InternalExpr;
7179@
7280 -}
73−expr' syn = doexpr' syn
74−-- = do l <- restOfLine
75−-- f <- getFC
76−-- e <- trace (show (f, l)) $ doexpr' syn
77−-- return e
78−
79−doexpr' :: SyntaxInfo -> IdrisParser PTerm
80−doexpr' syn = try (externalExpr syn)
81− <|> internalExpr syn
82− <?> "expression"
81+expr' :: SyntaxInfo -> IdrisParser PTerm
82+expr' syn = try (externalExpr syn)
83+ <|> internalExpr syn
84+ <?> "expression"
8385
8486{- | Parses a user-defined expression -}
8587externalExpr :: SyntaxInfo -> IdrisParser PTerm
@@ -197,7 +199,6 @@ InternalExpr ::=
197199 | QuoteGoal
198200 | Let
199201 | RewriteTerm
200− | Pi
201202 | CaseExpr
202203 | DoBlock
203204 | App
@@ -214,7 +215,6 @@ internalExpr syn =
214215 <|> quoteGoal syn
215216 <|> let_ syn
216217 <|> rewriteTerm syn
217− <|> try (pi syn)
218218 <|> doBlock syn
219219 <|> caseExpr syn
220220 <|> app syn
@@ -363,7 +363,7 @@ bracketed' syn =
363363 return (PDPair fc TypeOrTerm (PRef fc ln) lty r))
364364 <|> try (do fc <- getFC; o <- operator; e <- expr syn; lchar ')'
365365 -- No prefix operators! (bit of a hack here...)
366− if (o == "-" || o == "!")
366+ if (o == "-" || o == "!")
367367 then fail "minus not allowed in section"
368368 else return $ PLam (sMN 1000 "ARG") Placeholder
369369 (PApp fc (PRef fc (sUN o)) [pexp (PRef fc (sMN 1000 "ARG")),
@@ -754,11 +754,16 @@ quoteGoal syn = do reserved "quoteGoal"; n <- name;
754754{- | Parses a dependent type signature
755755
756756@
757−Pi ::=
758− '|'? Static? '(' TypeDeclList ')' DocComment '->' Expr
759− | '|'? Static? '{' TypeDeclList '}' '->' Expr
760− | '{' 'auto' TypeDeclList '}' '->' Expr
761− | '{' 'default' TypeDeclList '}' '->' Expr
757+Pi ::= PiOpts Static? Pi'
758+@
759+
760+@
761+Pi' ::=
762+ OpExpr ('->' Pi)?
763+ | '(' TypeDeclList ')' '->' Pi
764+ | '{' TypeDeclList '}' '->' Pi
765+ | '{' 'auto' TypeDeclList '}' '->' Pi
766+ | '{' 'default' SimpleExpr TypeDeclList '}' '->' Pi
762767 ;
763768@
764769 -}
@@ -767,37 +772,44 @@ pi :: SyntaxInfo -> IdrisParser PTerm
767772pi syn =
768773 do opts <- piOpts syn
769774 st <- static
770− (do try (lchar '('); xt <- typeDeclList syn; lchar ')'
775+ (do xt <- try (lchar '(' *> typeDeclList syn <* lchar ')')
771776 symbol "->"
772777 sc <- expr syn
773778 return (bindList (PPi (Exp opts st False)) xt sc)) <|> (do
774− lchar '{'
775− (do reserved "auto"
779+ (do try (lchar '{' *> reserved "auto")
776780 when (st == Static) $ fail "auto type constraints can not be lazy or static"
777781 xt <- typeDeclList syn
778782 lchar '}'
779783 symbol "->"
780784 sc <- expr syn
781785 return (bindList (PPi
782− (TacImp [] Dynamic (PTactics [Trivial]))) xt sc))
783− <|> (do
784− reserved "default"
786+ (TacImp [] Dynamic (PTactics [Trivial]))) xt sc)) <|> (do
787+ try (lchar '{' *> reserved "default")
785788 when (st == Static) $ fail "default tactic constraints can not be lazy or static"
786789 script <- simpleExpr syn
787790 xt <- typeDeclList syn
788791 lchar '}'
789792 symbol "->"
790793 sc <- expr syn
791− return (bindList (PPi (TacImp [] Dynamic script)) xt sc))
794+ return (bindList (PPi (TacImp [] Dynamic script)) xt sc))
792795 <|> (if implicitAllowed syn then do
793− xt <- typeDeclList syn
794− lchar '}'
796+ xt <- try (lchar '{' *> typeDeclList syn <* lchar '}')
795797 symbol "->"
796798 sc <- expr syn
797799 return (bindList (PPi (Imp opts st False)) xt sc)
798800 else do fail "no implicit arguments allowed here"))
801+ <|> (do x <- opExpr syn
802+ (do symbol "->"
803+ sc <- expr syn
804+ return (PPi (Exp opts st False) (sUN "__pi_arg") x sc))
805+ <|> return x)
799806 <?> "dependent type signature"
800807
808+{- | Parses Possible Options for Pi Expressions
809+@
810+ PiOpts ::= '.'?
811+@
812+-}
801813piOpts :: SyntaxInfo -> IdrisParser [ArgOpt]
802814piOpts syn | implicitAllowed syn =
803815 lchar '.' *> return [InaccessibleArg]
@@ -1079,7 +1091,7 @@ Static ::=
10791091@
10801092-}
10811093static :: IdrisParser Static
1082−static = do lchar '['; reserved "static"; lchar ']'; return Static
1094+static = do reserved "[static]"; return Static
10831095 <|> return Dynamic
10841096 <?> "static modifier"
10851097
src/Idris/ParseOps.hs+1−2
@@ -38,8 +38,7 @@ table fixes
3838 ++ toTable (reverse fixes) ++
3939 [[backtick],
4040 [binary "$" (\fc x y -> flatten $ PApp fc x [pexp y]) AssocRight],
41− [binary "=" PEq AssocLeft],
42− [binary "->" (\fc x y -> PPi expl (sUN "__pi_arg") x y) AssocRight]]
41+ [binary "=" PEq AssocLeft]]
4342 where
4443 flatten :: PTerm -> PTerm -- flatten application
4544 flatten (PApp fc (PApp _ f as) bs) = flatten (PApp fc f (as ++ bs))
src/Idris/Prover.hs+1
@@ -85,6 +85,7 @@ prove opt ctxt lit n ty
8585 [([], P Ref n ty, ptm)]
8686 [([], P Ref n ty, ptm')] ty)
8787 solveDeferred n
88+
8889elabStep :: ElabState [PDecl] -> ElabD a -> Idris (a, ElabState [PDecl])
8990elabStep st e = case runStateT eCheck st of
9091 OK (a, st') -> return (a, st')
src/Idris/REPL.hs+5−4
@@ -900,14 +900,15 @@ process h fn (RmProof n')
900900
901901process h fn' (AddProof prf)
902902 = do fn <- do
903− ex <- runIO $ doesFileExist fn'
904− let fnExt = fn' <.> "idr"
903+ let fn'' = takeWhile (/= ' ') fn'
904+ ex <- runIO $ doesFileExist fn''
905+ let fnExt = fn'' <.> "idr"
905906 exExt <- runIO $ doesFileExist fnExt
906907 if ex
907− then return fn'
908+ then return fn''
908909 else if exExt
909910 then return fnExt
910− else ifail $ "Neither \""++fn'++"\" nor \""++fnExt++"\" exist"
911+ else ifail $ "Neither \""++fn''++"\" nor \""++fnExt++"\" exist"
911912 let fb = fn ++ "~"
912913 runIO $ copyFile fn fb -- make a backup in case something goes wrong!
913914 prog <- runIO $ readFile fb
test/reg042/expectednew file+1
@@ -0,0 +1 @@
1+7
test/reg042/reg042.idrnew file+24
@@ -0,0 +1,24 @@
1+-- This regtest tests for incorrect erasure from underapplied data constructors.
2+
3+data T : Type where
4+ C : Nat -> Nat -> Nat -> T
5+
6+data Q : Type where
7+ D : (Nat -> T) -> Q
8+
9+-- The bug was here: (C 3 4) would compile to plain data,
10+-- not to a function that would expect another (albeit erased) argument.
11+f : Q
12+f = D (C 3 4)
13+
14+proj : Nat -> Q -> Nat -> T
15+proj Z (D f) = f
16+proj (S n) q = proj n q
17+
18+g : T -> Nat
19+g (C x y z) = x + y
20+
21+-- Here, we'd apply the not-a-function to the erased argument 4,
22+-- which would make the program go wrong.
23+main : IO ()
24+main = print $ g (proj 3 f 4)
test/reg042/runnew file+4
@@ -0,0 +1,4 @@
1+#!/usr/bin/env bash
2+idris $@ reg042 -o reg042 --warnreach
3+./reg042
4+rm -f reg042 *.ibc