on master help sign in
Partial evaluation fixes

- Dealing with constraint arguments better - Dealing with implicits better (only erase to placeholder if other arguments depend on them) - Remove "Can't happen" and replace with proper error

commit97319d9f7edb1ab075b8cc2940678115cf15ff57 authorEdwin Brady <ecb10@st-andrews.ac.uk> dateSun 2 Oct 2016, 13:24 (10 years ago) parent92c5375
5 files changed+110−55
src/Idris/Elab/Clause.hs+19−15 src/Idris/Elab/Implementation.hs+2−1 src/Idris/PartialEval.hs+82−31 test/dsl001/expected+7−7 test/dsl001/test001.idr−1
src/Idris/Elab/Clause.hs+19−15
@@ -371,8 +371,8 @@ elabPE info fc caller r =
371371 mkSpecialised specapp_in = do
372372 ist <- getIState
373373 ctxt <- getContext
374− let (specTy, specapp) = getSpecTy ist specapp_in
375− let (n, newnm, specdecl) = getSpecClause ist specapp
374+ (specTy, specapp) <- getSpecTy ist specapp_in
375+ let (n, newnm, specdecl) = getSpecClause ist specapp specTy
376376 let lhs = pe_app specdecl
377377 let rhs = pe_def specdecl
378378 let undef = case lookupDefExact newnm ctxt of
@@ -382,11 +382,12 @@ elabPE info fc caller r =
382382 idrisCatch
383383 (if (undef && all (concreteArg ist) (snd specapp)) then do
384384 cgns <- getAllNames n
385+ cgns_caller <- getAllNames caller
385386 -- on the RHS of the new definition, we should reduce
386387 -- everything that's not itself static (because we'll
387388 -- want to be a PE version of those next)
388389 let cgns' = filter (\x -> x /= n &&
389− notStatic ist x) cgns
390+ notStatic ist x) (cgns ++ cgns_caller)
390391 -- set small reduction limit on partial/productive things
391392 let maxred = case lookupTotal n ctxt of
392393 [Total _] -> 65536
@@ -402,18 +403,19 @@ elabPE info fc caller r =
402403 (n, Just maxred) : specnames ++
403404 concat descs)]
404405 logElab 3 $ "Specialising application: " ++ show specapp
405− ++ " in " ++ show caller ++
406− " with " ++ show opts
406+ ++ "\n in \n" ++ show caller ++
407+ "\n with \n" ++ show opts
408+ ++ "\nCalling: " ++ show cgns
407409 logElab 3 $ "New name: " ++ show newnm
408410 logElab 3 $ "PE definition type : " ++ (show specTy)
409411 ++ "\n" ++ show opts
410− logElab 5 $ "PE definition " ++ show newnm ++ ":\n" ++
412+ logElab 2 $ "PE definition " ++ show newnm ++ ":\n" ++
411413 showSep "\n"
412414 (map (\ (lhs, rhs) ->
413415 (showTmImpls lhs ++ " = " ++
414416 showTmImpls rhs)) (pe_clauses specdecl))
415417
416− logElab 2 $ show n ++ " transformation rule: " ++
418+ logElab 5 $ show n ++ " transformation rule: " ++
417419 showTmImpls rhs ++ " ==> " ++ showTmImpls lhs
418420
419421 elabType info defaultSyntax emptyDocstring [] fc opts newnm NoFC specTy
@@ -429,16 +431,18 @@ elabPE info fc caller r =
429431 -- if it doesn't work, just don't specialise. Could happen for lots
430432 -- of valid reasons (e.g. local variables in scope which can't be
431433 -- lifted out).
432− (\e -> do logElab 3 $ "Couldn't specialise: " ++ (pshow ist e)
434+ (\e -> do logElab 5 $ "Couldn't specialise: " ++ (pshow ist e)
433435 return [])
434436
435437 hiddenToPH (PHidden _) = Placeholder
436438 hiddenToPH x = x
437439
438− specName simpl (ImplicitS, tm)
440+ specName simpl (ImplicitS _, tm)
439441 | (P Ref n _, _) <- unApply tm = Just (n, Just (if simpl then 1 else 0))
440442 specName simpl (ExplicitS, tm)
441443 | (P Ref n _, _) <- unApply tm = Just (n, Just (if simpl then 1 else 0))
444+ specName simpl (ConstraintS, tm)
445+ | (P Ref n _, _) <- unApply tm = Just (n, Just (if simpl then 1 else 0))
442446 specName simpl _ = Nothing
443447
444448 -- get the descendants of the name 'n' which are marked %static
@@ -459,7 +463,7 @@ elabPE info fc caller r =
459463 Just s -> not (or s)
460464 _ -> True
461465
462− concreteArg ist (ImplicitS, tm) = concreteTm ist tm
466+ concreteArg ist (ImplicitS _, tm) = concreteTm ist tm
463467 concreteArg ist (ExplicitS, tm) = concreteTm ist tm
464468 concreteArg ist _ = True
465469
@@ -479,18 +483,18 @@ elabPE info fc caller r =
479483 [ty] -> let (specty_in, args') = specType args (explicitNames ty)
480484 specty = normalise (tt_ctxt ist) [] (finalise specty_in)
481485 t = mkPE_TyDecl ist args' (explicitNames specty) in
482− (t, (n, args'))
486+ return (t, (n, args'))
483487-- (normalise (tt_ctxt ist) [] (specType args ty))
484− _ -> error "Can't happen (getSpecTy)"
488+ _ -> ifail $ "Ambiguous name " ++ show n ++ " (getSpecTy)"
485489
486490 -- get the clause of a specialised application
487− getSpecClause ist (n, args)
491+ getSpecClause ist (n, args) specTy
488492 = let newnm = sUN ("PE_" ++ show (nsroot n) ++ "_" ++
489493 qhash 5381 (showSep "_" (map showArg args))) in
490494 -- UN (show n ++ show (map snd args)) in
491− (n, newnm, mkPE_TermDecl ist newnm n args)
495+ (n, newnm, mkPE_TermDecl ist newnm n specTy args)
492496 where showArg (ExplicitS, n) = qshow n
493− showArg (ImplicitS, n) = qshow n
497+ showArg (ImplicitS _, n) = qshow n
494498 showArg _ = ""
495499
496500 qshow (Bind _ _ _) = "fn"
src/Idris/Elab/Implementation.hs+2−1
@@ -192,6 +192,7 @@ elabImplementation info syn doc argDocs what fc cs parents acc opts n nfc ps pex
192192
193193 let wbVals' = map (addParams prop_params) wbVals
194194
195+ logElab 5 ("Elaborating method bodies: " ++ show wbVals')
195196 mapM_ (rec_elabDecl info EAll info) wbVals'
196197
197198 mapM_ (checkInjectiveDef fc (interface_methods ci)) (zip ds' wbVals')
@@ -472,7 +473,7 @@ checkInjectiveDef fc ns (PClauses _ _ n cs, PClauses _ _ elabn _)
472473 clookup n [] = Nothing
473474 clookup n ((n', d) : ds) | nsroot n == nsroot n' = Just d
474475 | otherwise = Nothing
475−checkInjectiveDef fc ns _ = return()
476+checkInjectiveDef fc ns _ = return ()
476477
477478checkInjectiveArgs :: FC -> Name -> [Int] -> Maybe Type -> Idris ()
478479checkInjectiveArgs fc n ds Nothing = return ()
src/Idris/PartialEval.hs+82−31
@@ -25,11 +25,13 @@ import Data.Maybe
2525import Debug.Trace
2626
2727-- | Data type representing binding-time annotations for partial evaluation of arguments
28−data PEArgType = ImplicitS -- ^ Implicit static argument
29− | ImplicitD -- ^ Implicit dynamic argument
30− | ExplicitS -- ^ Explicit static argument
31− | ExplicitD -- ^ Explicit dynamic argument
32− | UnifiedD -- ^ Erasable dynamic argument (found under unification)
28+data PEArgType = ImplicitS Name -- ^ Implicit static argument
29+ | ImplicitD Name -- ^ Implicit dynamic argument
30+ | ConstraintS -- ^ Implementation constraint
31+ | ConstraintD -- ^ Implementation constraint
32+ | ExplicitS -- ^ Explicit static argument
33+ | ExplicitD -- ^ Explicit dynamic argument
34+ | UnifiedD -- ^ Erasable dynamic argument (found under unification)
3335 deriving (Eq, Show)
3436
3537-- | 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
9799 -- of expecting it as a function argument
98100 st ((ExplicitS, v) : xs) (Bind n (Pi _ t _) sc)
99101 = Bind n (Let t v) (st xs sc)
100− st ((ImplicitS, v) : xs) (Bind n (Pi _ t _) sc)
102+ st ((ImplicitS _, v) : xs) (Bind n (Pi _ t _) sc)
103+ = Bind n (Let t v) (st xs sc)
104+ st ((ConstraintS, v) : xs) (Bind n (Pi _ t _) sc)
101105 = Bind n (Let t v) (st xs sc)
102106 -- Erase argument from function type
103107 st ((UnifiedD, _) : xs) (Bind n (Pi _ t _) sc)
@@ -109,7 +113,7 @@ specType args ty = let (t, args') = runState (unifyEq args ty) [] in
109113
110114 -- Erase implicit dynamic argument if existing argument shares it value,
111115 -- 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)
113117 = do amap <- get
114118 case lookup imp amap of
115119 Just n' ->
@@ -139,11 +143,12 @@ mkPE_TyDecl ist args ty = mkty args ty
139143 where
140144 mkty ((ExplicitD, v) : xs) (Bind n (Pi _ t k) sc)
141145 = 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)
143147 | concreteInterface ist t = mkty xs sc
144148 | interfaceConstraint ist t
145149 = PPi constraint n NoFC (delab ist (generaliseIn t)) (mkty xs sc)
146− | otherwise = PPi impl n NoFC (delab ist (generaliseIn t)) (mkty xs sc)
150+ mkty ((ImplicitD _, v) : xs) (Bind n (Pi _ t k) sc)
151+ = PPi impl n NoFC (delab ist (generaliseIn t)) (mkty xs sc)
147152
148153 mkty (_ : xs) t
149154 = mkty xs t
@@ -200,7 +205,8 @@ mkNewPats ist d ns newname sname lhs rhs | all dynVar (map fst d)
200205 (_, args) -> dynArgs ns args
201206 dynArgs _ [] = True -- can definitely reduce from here
202207 -- if Static, doesn't matter what the argument is
203− dynArgs ((ImplicitS, _) : ns) (a : as) = dynArgs ns as
208+ dynArgs ((ImplicitS _, _) : ns) (a : as) = dynArgs ns as
209+ dynArgs ((ConstraintS, _) : ns) (a : as) = dynArgs ns as
204210 dynArgs ((ExplicitS, _) : ns) (a : as) = dynArgs ns as
205211 -- if Dynamic, it had better be a variable or we'll need to
206212 -- do some more work
@@ -209,7 +215,7 @@ mkNewPats ist d ns newname sname lhs rhs | all dynVar (map fst d)
209215 dynArgs _ _ = False -- and now we'll get stuck
210216
211217mkNewPats ist d ns newname sname lhs rhs =
212− PEDecl lhs rhs (map mkClause d) False
218+ PEDecl lhs rhs (map mkClause d) False
213219 where
214220 mkClause :: (Term, Term) -> (PTerm, PTerm)
215221 mkClause (oldlhs, oldrhs)
@@ -221,25 +227,37 @@ mkNewPats ist d ns newname sname lhs rhs =
221227 (lhs, rhs)
222228
223229 mkLHSargs _ [] _ = []
224− -- dynamics don't appear if they're implicit
230+ -- dynamics don't appear on the LHS if they're implicit
225231 mkLHSargs sub ((ExplicitD, t) : ns) (a : as)
226232 = pexp (delab ist (substNames sub a)) : mkLHSargs sub ns as
227− mkLHSargs sub ((ImplicitD, _) : ns) (a : as)
228− = mkLHSargs sub ns 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)
236+ = pconst (delab ist (substNames sub a)) : mkLHSargs sub ns as
229237 mkLHSargs sub ((UnifiedD, _) : ns) (a : as)
230238 = mkLHSargs sub ns as
231239 -- statics get dropped in any case
232− mkLHSargs sub ((ImplicitS, t) : ns) (a : as)
240+ mkLHSargs sub ((ImplicitS _, t) : ns) (a : as)
233241 = mkLHSargs (extend a t sub) ns as
234242 mkLHSargs sub ((ExplicitS, t) : ns) (a : as)
235243 = mkLHSargs (extend a t sub) ns as
244+ mkLHSargs sub ((ConstraintS, t) : ns) (a : as)
245+ = mkLHSargs (extend a t sub) ns as
236246 mkLHSargs sub _ [] = [] -- no more LHS
237247
238248 extend (P _ n _) t sub = (n, t) : sub
239249 extend _ _ sub = sub
240250
251+ --- 'as' are the LHS arguments
241252 mkRHSargs ((ExplicitS, t) : ns) as = pexp (delab ist t) : mkRHSargs ns as
242253 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
243261 mkRHSargs (_ : ns) as = mkRHSargs ns as
244262 mkRHSargs _ _ = []
245263
@@ -254,12 +272,26 @@ mkNewPats ist d ns newname sname lhs rhs =
254272mkPE_TermDecl :: IState
255273 -> Name
256274 -> Name
275+ -> PTerm -- ^ Type of specialised function
257276 -> [(PEArgType, Term)]
258277 -> PEDecl
259−mkPE_TermDecl ist newname sname ns
260− = let lhs = PApp emptyFC (PRef emptyFC [] newname) (map pexp (mkp ns))
261− rhs = eraseImps $ delab ist (mkApp (P Ref sname Erased) (map snd ns))
262− patdef = lookupCtxtExact sname (idris_patdefs ist)
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
281+ in specty.
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
285+ on the RHS.
286+ -}
287+ = let deps = getDepNames (eraseRet specty)
288+ lhs = eraseDeps deps $
289+ PApp emptyFC (PRef emptyFC [] newname) (mkp ns)
290+ rhs = eraseDeps deps $
291+ delab ist (mkApp (P Ref sname Erased) (map snd ns))
292+ patdef = -- trace (showTmImpls specty ++ "\n" ++ showTmImpls lhs ++ "\n"
293+ -- ++ showTmImpls rhs) $
294+ lookupCtxtExact sname (idris_patdefs ist)
263295 newpats = case patdef of
264296 Nothing -> PEDecl lhs rhs [(lhs, rhs)] True
265297 Just d -> mkNewPats ist (getPats d) ns
@@ -268,17 +300,28 @@ mkPE_TermDecl ist newname sname ns
268300
269301 getPats (ps, _) = map (\(_, lhs, rhs) -> (lhs, rhs)) ps
270302
303+ eraseRet (PPi p n fc ty sc) = PPi p n fc ty (eraseRet sc)
304+ eraseRet _ = Placeholder
305+
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
311+ getDepNames tm = []
312+
271313 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
273316 mkp (_ : tms) = mkp tms
274317
275− eraseImps tm = mapPT deImp tm
318+ eraseDeps ns tm = mapPT (deImp ns) tm
276319
277− deImp (PApp fc t as) = PApp fc t (map deImpArg as)
278− deImp t = t
320+ deImp ns (PApp fc t as) = PApp fc t (map (deImpArg ns) as)
321+ deImp ns t = t
279322
280− deImpArg a@(PImp _ _ _ _ _) = a { getTm = Placeholder }
281− deImpArg a = a
323+ deImpArg ns a | pname a `elem` ns = a { getTm = Placeholder }
324+ | otherwise = a
282325
283326-- | Get specialised applications for a given function
284327getSpecApps :: IState
@@ -290,14 +333,22 @@ getSpecApps ist env tm = ga env (explicitNames tm) where
290333-- staticArg env True _ tm@(P _ n _) _ | n `elem` env = Just (True, tm)
291334-- staticArg env True _ tm@(App f a) _ | (P _ n _, args) <- unApply tm,
292335-- n `elem` env = Just (True, tm)
293− staticArg env x imp tm n
294− | x && imparg imp = (ImplicitS, tm)
295− | x = (ExplicitS, tm)
296− | imparg imp = (ImplicitD, tm)
336+ staticArg env True imp tm n
337+ | Just n <- imparg imp = (ImplicitS n, tm)
338+ | constrarg imp = (ConstraintS, tm)
339+ | otherwise = (ExplicitS, tm)
340+
341+ staticArg env False imp tm n
342+ | Just nm <- imparg imp = (ImplicitD nm, (P Ref (sUN (show n ++ "arg")) Erased))
343+ | constrarg imp = (ConstraintD, tm)
297344 | otherwise = (ExplicitD, (P Ref (sUN (show n ++ "arg")) Erased))
298345
299− imparg (PExp _ _ _ _) = False
300− imparg _ = True
346+ imparg (PExp _ _ _ _) = Nothing
347+ imparg (PConstraint _ _ _ _) = Nothing
348+ imparg arg = Just (pname arg)
349+
350+ constrarg (PConstraint _ _ _ _) = True
351+ constrarg arg = False
301352
302353 buildApp env [] [] _ _ = []
303354 buildApp env (s:ss) (i:is) (a:as) (n:ns)
test/dsl001/expected+7−7
@@ -1,14 +1,14 @@
1124
2212
33testFac : Int
4−testFac = PE_interp_f79b3e31 [] (PE_fromInteger_a0377313 4)
4+testFac = PE_interp_f79b3e31 [] (PE_fromInteger_d6648df 4)
55PE_interp_f79b3e31 : Env G -> Int -> Int
66PE_interp_f79b3e31 (3arg) = \x =>
7− ifThenElse (PE_==_a03270d8 x
8− (PE_fromInteger_a0377313 0))
9− (Delay (PE_fromInteger_a0377313 1))
10− (Delay (PE_*_a725d5d6 (PE_interp_f79b3e31 (x ::
7+ ifThenElse (PE_==_ba2f651f x
8+ (PE_fromInteger_d6648df 0))
9+ (Delay (PE_fromInteger_d6648df 1))
10+ (Delay (PE_*_ba2f651f (PE_interp_f79b3e31 (x ::
1111 (3arg))
12− (PE_-_a71cf640 x
13− (PE_fromInteger_a0377313 1)))
12+ (PE_-_ba2f651f x
13+ (PE_fromInteger_d6648df 1)))
1414 x))
test/dsl001/test001.idr−1
@@ -101,4 +101,3 @@ main = do { printLn testFac
101101 printLn test }
102102
103103
104−