@@ -25,11 +25,13 @@ import Data.Maybe
25import Debug.Trace
25import Debug.Trace
27-- | Data type representing binding-time annotations for partial evaluation of arguments
27-- | Data type representing binding-time annotations for partial evaluation of arguments
28−data PEArgType = ImplicitS -- ^ Implicit static argument
28+data PEArgType = ImplicitS Name -- ^ Implicit static argument
29− | ImplicitD -- ^ Implicit dynamic argument
29+ | ImplicitD Name -- ^ Implicit dynamic argument
30+ | ConstraintS -- ^ Implementation constraint
31+ | ConstraintD -- ^ Implementation constraint
30− | ExplicitS -- ^ Explicit static argument
32+ | ExplicitS -- ^ Explicit static argument
31− | ExplicitD -- ^ Explicit dynamic argument
33+ | ExplicitD -- ^ Explicit dynamic argument
32− | UnifiedD -- ^ Erasable dynamic argument (found under unification)
34+ | UnifiedD -- ^ Erasable dynamic argument (found under unification)
33 deriving (Eq, Show)
35 deriving (Eq, Show)
35-- | A partially evaluated function. pe_app captures the lhs of the
37-- | A partially evaluated function. pe_app captures the lhs of the
@@ -97,7 +99,9 @@ specType args ty = let (t, args') = runState (unifyEq args ty) [] in
97 -- of expecting it as a function argument
99 -- of expecting it as a function argument
98 st ((ExplicitS, v) : xs) (Bind n (Pi _ t _) sc)
100 st ((ExplicitS, v) : xs) (Bind n (Pi _ t _) sc)
99 = Bind n (Let t v) (st xs sc)
101 = Bind n (Let t v) (st xs sc)
102+ st ((ImplicitS _, v) : xs) (Bind n (Pi _ t _) sc)
103+ = Bind n (Let t v) (st xs sc)
100− st ((ImplicitS, v) : xs) (Bind n (Pi _ t _) sc)
104+ st ((ConstraintS, v) : xs) (Bind n (Pi _ t _) sc)
101 = Bind n (Let t v) (st xs sc)
105 = Bind n (Let t v) (st xs sc)
102 -- Erase argument from function type
106 -- Erase argument from function type
103 st ((UnifiedD, _) : xs) (Bind n (Pi _ t _) sc)
107 st ((UnifiedD, _) : xs) (Bind n (Pi _ t _) sc)
@@ -109,7 +113,7 @@ specType args ty = let (t, args') = runState (unifyEq args ty) [] in
110 -- Erase implicit dynamic argument if existing argument shares it value,
114 -- Erase implicit dynamic argument if existing argument shares it value,
111 -- by substituting the value of previous argument
115 -- by substituting the value of previous argument
112− unifyEq (imp@(ImplicitD, v) : xs) (Bind n (Pi i t k) sc)
116+ unifyEq (imp@(ImplicitD _, v) : xs) (Bind n (Pi i t k) sc)
113 = do amap <- get
117 = do amap <- get
114 case lookup imp amap of
118 case lookup imp amap of
115 Just n' ->
119 Just n' ->
@@ -139,11 +143,12 @@ mkPE_TyDecl ist args ty = mkty args ty
140 mkty ((ExplicitD, v) : xs) (Bind n (Pi _ t k) sc)
144 mkty ((ExplicitD, v) : xs) (Bind n (Pi _ t k) sc)
141 = PPi expl n NoFC (delab ist (generaliseIn t)) (mkty xs sc)
145 = PPi expl n NoFC (delab ist (generaliseIn t)) (mkty xs sc)
142− mkty ((ImplicitD, v) : xs) (Bind n (Pi _ t k) sc)
146+ mkty ((ConstraintD, v) : xs) (Bind n (Pi _ t k) sc)
143 | concreteInterface ist t = mkty xs sc
147 | concreteInterface ist t = mkty xs sc
144 | interfaceConstraint ist t
148 | interfaceConstraint ist t
145 = PPi constraint n NoFC (delab ist (generaliseIn t)) (mkty xs sc)
149 = PPi constraint n NoFC (delab ist (generaliseIn t)) (mkty xs sc)
150+ mkty ((ImplicitD _, v) : xs) (Bind n (Pi _ t k) sc)
146− | otherwise = PPi impl n NoFC (delab ist (generaliseIn t)) (mkty xs sc)
151+ = PPi impl n NoFC (delab ist (generaliseIn t)) (mkty xs sc)
148 mkty (_ : xs) t
153 mkty (_ : xs) t
149 = mkty xs t
154 = mkty xs t
@@ -200,7 +205,8 @@ mkNewPats ist d ns newname sname lhs rhs | all dynVar (map fst d)
200 (_, args) -> dynArgs ns args
205 (_, args) -> dynArgs ns args
201 dynArgs _ [] = True -- can definitely reduce from here
206 dynArgs _ [] = True -- can definitely reduce from here
202 -- if Static, doesn't matter what the argument is
207 -- if Static, doesn't matter what the argument is
208+ dynArgs ((ImplicitS _, _) : ns) (a : as) = dynArgs ns as
203− dynArgs ((ImplicitS, _) : ns) (a : as) = dynArgs ns as
209+ dynArgs ((ConstraintS, _) : ns) (a : as) = dynArgs ns as
204 dynArgs ((ExplicitS, _) : ns) (a : as) = dynArgs ns as
210 dynArgs ((ExplicitS, _) : ns) (a : as) = dynArgs ns as
205 -- if Dynamic, it had better be a variable or we'll need to
211 -- if Dynamic, it had better be a variable or we'll need to
206 -- do some more work
212 -- do some more work
@@ -209,7 +215,7 @@ mkNewPats ist d ns newname sname lhs rhs | all dynVar (map fst d)
209 dynArgs _ _ = False -- and now we'll get stuck
215 dynArgs _ _ = False -- and now we'll get stuck
211mkNewPats ist d ns newname sname lhs rhs =
217mkNewPats ist d ns newname sname lhs rhs =
212− PEDecl lhs rhs (map mkClause d) False
218+ PEDecl lhs rhs (map mkClause d) False
214 mkClause :: (Term, Term) -> (PTerm, PTerm)
220 mkClause :: (Term, Term) -> (PTerm, PTerm)
215 mkClause (oldlhs, oldrhs)
221 mkClause (oldlhs, oldrhs)
@@ -221,25 +227,37 @@ mkNewPats ist d ns newname sname lhs rhs =
221 (lhs, rhs)
227 (lhs, rhs)
223 mkLHSargs _ [] _ = []
229 mkLHSargs _ [] _ = []
224− -- dynamics don't appear if they're implicit
230+ -- dynamics don't appear on the LHS if they're implicit
225 mkLHSargs sub ((ExplicitD, t) : ns) (a : as)
231 mkLHSargs sub ((ExplicitD, t) : ns) (a : as)
226 = pexp (delab ist (substNames sub a)) : mkLHSargs sub ns as
232 = pexp (delab ist (substNames sub a)) : mkLHSargs sub ns as
227− mkLHSargs sub ((ImplicitD, _) : ns) (a : as)
233+ mkLHSargs sub ((ImplicitD n, t) : ns) (a : as)
234+ = pimp n (delab ist (substNames sub a)) True : mkLHSargs sub ns as
235+ mkLHSargs sub ((ConstraintD, t) : ns) (a : as)
228− = mkLHSargs sub ns as
236+ = pconst (delab ist (substNames sub a)) : mkLHSargs sub ns as
229 mkLHSargs sub ((UnifiedD, _) : ns) (a : as)
237 mkLHSargs sub ((UnifiedD, _) : ns) (a : as)
230 = mkLHSargs sub ns as
238 = mkLHSargs sub ns as
231 -- statics get dropped in any case
239 -- statics get dropped in any case
232− mkLHSargs sub ((ImplicitS, t) : ns) (a : as)
240+ mkLHSargs sub ((ImplicitS _, t) : ns) (a : as)
233 = mkLHSargs (extend a t sub) ns as
241 = mkLHSargs (extend a t sub) ns as
234 mkLHSargs sub ((ExplicitS, t) : ns) (a : as)
242 mkLHSargs sub ((ExplicitS, t) : ns) (a : as)
235 = mkLHSargs (extend a t sub) ns as
243 = mkLHSargs (extend a t sub) ns as
244+ mkLHSargs sub ((ConstraintS, t) : ns) (a : as)
245+ = mkLHSargs (extend a t sub) ns as
236 mkLHSargs sub _ [] = [] -- no more LHS
246 mkLHSargs sub _ [] = [] -- no more LHS
238 extend (P _ n _) t sub = (n, t) : sub
248 extend (P _ n _) t sub = (n, t) : sub
239 extend _ _ sub = sub
249 extend _ _ sub = sub
251+ --- 'as' are the LHS arguments
241 mkRHSargs ((ExplicitS, t) : ns) as = pexp (delab ist t) : mkRHSargs ns as
252 mkRHSargs ((ExplicitS, t) : ns) as = pexp (delab ist t) : mkRHSargs ns as
242 mkRHSargs ((ExplicitD, t) : ns) (a : as) = a : mkRHSargs ns as
253 mkRHSargs ((ExplicitD, t) : ns) (a : as) = a : mkRHSargs ns as
254+ -- Keep the implicits on the RHS, in case they got matched on
255+ mkRHSargs ((ImplicitD n, t) : ns) (a : as) = a : mkRHSargs ns as
256+ mkRHSargs ((ImplicitS n, t) : ns) as -- Dropped from LHS
257+ = pimp n (delab ist t) True : mkRHSargs ns as
258+ mkRHSargs ((ConstraintD, t) : ns) (a : as) = a : mkRHSargs ns as
259+ mkRHSargs ((ConstraintS, t) : ns) as -- Dropped from LHS
260+ = pconst (delab ist t) : mkRHSargs ns as
243 mkRHSargs (_ : ns) as = mkRHSargs ns as
261 mkRHSargs (_ : ns) as = mkRHSargs ns as
244 mkRHSargs _ _ = []
262 mkRHSargs _ _ = []
@@ -254,12 +272,26 @@ mkNewPats ist d ns newname sname lhs rhs =
254mkPE_TermDecl :: IState
272mkPE_TermDecl :: IState
275+ -> PTerm -- ^ Type of specialised function
257 -> [(PEArgType, Term)]
276 -> [(PEArgType, Term)]
258 -> PEDecl
277 -> PEDecl
259−mkPE_TermDecl ist newname sname ns
278+mkPE_TermDecl ist newname sname specty ns
279+ {- We need to erase the *dynamic* arguments
280+ where their *name* appears in the *type* of a later argument
282+ i.e. if a later dynamic argument depends on an earlier dynamic
283+ argument, we should infer the earlier one.
284+ Then we need to erase names from the LHS which no longer appear
287+ = let deps = getDepNames (eraseRet specty)
288+ lhs = eraseDeps deps $
260− = let lhs = PApp emptyFC (PRef emptyFC [] newname) (map pexp (mkp ns))
289+ PApp emptyFC (PRef emptyFC [] newname) (mkp ns)
290+ rhs = eraseDeps deps $
261− rhs = eraseImps $ delab ist (mkApp (P Ref sname Erased) (map snd ns))
291+ delab ist (mkApp (P Ref sname Erased) (map snd ns))
292+ patdef = -- trace (showTmImpls specty ++ "\n" ++ showTmImpls lhs ++ "\n"
293+ -- ++ showTmImpls rhs) $
262− patdef = lookupCtxtExact sname (idris_patdefs ist)
294+ lookupCtxtExact sname (idris_patdefs ist)
263 newpats = case patdef of
295 newpats = case patdef of
264 Nothing -> PEDecl lhs rhs [(lhs, rhs)] True
296 Nothing -> PEDecl lhs rhs [(lhs, rhs)] True
265 Just d -> mkNewPats ist (getPats d) ns
297 Just d -> mkNewPats ist (getPats d) ns
@@ -268,17 +300,28 @@ mkPE_TermDecl ist newname sname ns
269 getPats (ps, _) = map (\(_, lhs, rhs) -> (lhs, rhs)) ps
301 getPats (ps, _) = map (\(_, lhs, rhs) -> (lhs, rhs)) ps
303+ eraseRet (PPi p n fc ty sc) = PPi p n fc ty (eraseRet sc)
304+ eraseRet _ = Placeholder
306+ -- Get names used in later arguments; assume we've called eraseRet so there's
307+ -- no names going to appear in return type
308+ getDepNames (PPi _ n _ _ sc)
309+ | n `elem` allNamesIn sc = n : getDepNames sc
310+ | otherwise = getDepNames sc
271 mkp [] = []
313 mkp [] = []
272− mkp ((ExplicitD, tm) : tms) = delab ist tm : mkp tms
314+ mkp ((ExplicitD, tm) : tms) = pexp (delab ist tm) : mkp tms
315+ mkp ((ImplicitD n, tm) : tms) = pimp n (delab ist tm) True : mkp tms
273 mkp (_ : tms) = mkp tms
316 mkp (_ : tms) = mkp tms
275− eraseImps tm = mapPT deImp tm
318+ eraseDeps ns tm = mapPT (deImp ns) tm
277− deImp (PApp fc t as) = PApp fc t (map deImpArg as)
320+ deImp ns (PApp fc t as) = PApp fc t (map (deImpArg ns) as)
278− deImp t = t
321+ deImp ns t = t
280− deImpArg a@(PImp _ _ _ _ _) = a { getTm = Placeholder }
323+ deImpArg ns a | pname a `elem` ns = a { getTm = Placeholder }
281− deImpArg a = a
324+ | otherwise = a
283-- | Get specialised applications for a given function
326-- | Get specialised applications for a given function
284getSpecApps :: IState
327getSpecApps :: IState
@@ -290,14 +333,22 @@ getSpecApps ist env tm = ga env (explicitNames tm) where
290-- staticArg env True _ tm@(P _ n _) _ | n `elem` env = Just (True, tm)
333-- staticArg env True _ tm@(P _ n _) _ | n `elem` env = Just (True, tm)
291-- staticArg env True _ tm@(App f a) _ | (P _ n _, args) <- unApply tm,
334-- staticArg env True _ tm@(App f a) _ | (P _ n _, args) <- unApply tm,
292-- n `elem` env = Just (True, tm)
335-- n `elem` env = Just (True, tm)
293− staticArg env x imp tm n
336+ staticArg env True imp tm n
294− | x && imparg imp = (ImplicitS, tm)
337+ | Just n <- imparg imp = (ImplicitS n, tm)
338+ | constrarg imp = (ConstraintS, tm)
295− | x = (ExplicitS, tm)
339+ | otherwise = (ExplicitS, tm)
341+ staticArg env False imp tm n
296− | imparg imp = (ImplicitD, tm)
342+ | Just nm <- imparg imp = (ImplicitD nm, (P Ref (sUN (show n ++ "arg")) Erased))
343+ | constrarg imp = (ConstraintD, tm)
297 | otherwise = (ExplicitD, (P Ref (sUN (show n ++ "arg")) Erased))
344 | otherwise = (ExplicitD, (P Ref (sUN (show n ++ "arg")) Erased))
299− imparg (PExp _ _ _ _) = False
346+ imparg (PExp _ _ _ _) = Nothing
300− imparg _ = True
347+ imparg (PConstraint _ _ _ _) = Nothing
348+ imparg arg = Just (pname arg)
350+ constrarg (PConstraint _ _ _ _) = True
351+ constrarg arg = False
302 buildApp env [] [] _ _ = []
353 buildApp env [] [] _ _ = []
303 buildApp env (s:ss) (i:is) (a:as) (n:ns)
354 buildApp env (s:ss) (i:is) (a:as) (n:ns)