on master help sign in
New size change graph builder

Looks at patterns, rather than case tree, and therefore finds it easier to spot structurally smaller arguments which are more complex.

commitd9435c672a0fd7df7950709df1f5a1c310cefbbf authorEdwin Brady <ecb10@st-andrews.ac.uk> dateFri 31 May 2013, 18:15 (13 years ago) parentcc7426f
6 files changed+100−14
lib/Prelude/List.idr+1 src/Core/CaseTree.hs+12−6 src/Core/Evaluate.hs+6−4 src/IRTS/Compiler.hs+2 src/Idris/Coverage.hs+75−4 src/Idris/ElabDecls.hs+4
lib/Prelude/List.idr+1
@@ -399,6 +399,7 @@ span p (x::xs) =
399399break : (a -> Bool) -> List a -> (List a, List a)
400400break p = span (not . p)
401401
402+%assert_total
402403split : (a -> Bool) -> List a -> List (List a)
403404split p [] = []
404405split p xs =
src/Core/CaseTree.hs+12−6
@@ -351,10 +351,13 @@ argsToAlt rs@((r, m) : rest)
351351 return (newArgs, addRs rs)
352352 where
353353 getNewVars [] = return []
354− getNewVars ((PV n) : ns) = do v <- getVar
354+ getNewVars ((PV n) : ns) = do v <- getVar "e"
355355 nsv <- getNewVars ns
356356 return (v : nsv)
357− getNewVars (_ : ns) = do v <- getVar
357+ getNewVars (PAny : ns) = do v <- getVar "i"
358+ nsv <- getNewVars ns
359+ return (v : nsv)
360+ getNewVars (_ : ns) = do v <- getVar "e"
358361 nsv <- getNewVars ns
359362 return (v : nsv)
360363 addRs [] = []
@@ -363,8 +366,8 @@ argsToAlt rs@((r, m) : rest)
363366 uniq i (UN n) = MN i n
364367 uniq i n = n
365368
366−getVar :: State CS Name
367−getVar = do (t, v) <- get; put (t, v+1); return (MN v "e")
369+getVar :: String -> State CS Name
370+getVar b = do (t, v) <- get; put (t, v+1); return (MN v b)
368371
369372groupCons :: [Clause] -> State CS [Group]
370373groupCons cs = gc [] cs
@@ -393,10 +396,12 @@ varRule (v : vs) alts err =
393396 do let alts' = map (repVar v) alts
394397 match vs alts' err
395398 where
396− repVar v (PV p : ps , (lhs, res)) = (ps, (lhs, subst p (P Bound v Erased) res))
399+ repVar v (PV p : ps , (lhs, res))
400+ = (ps, (lhs, subst p (P Bound v Erased) res))
397401 repVar v (PAny : ps , res) = (ps, res)
398402
399403-- fix: case e of S k -> f (S k) ==> case e of S k -> f e
404+
400405depatt :: [Name] -> SC -> SC
401406depatt ns tm = dp [] tm
402407 where
@@ -419,8 +424,9 @@ depatt ns tm = dp [] tm
419424 | and ((length args == length args') :
420425 (n == cn) : zipWith same args args') = P Ref x Erased
421426 | otherwise = applyMap ms nt cn pty args'
422− same n (P _ n' _) = n == n'
427+ same n (P _ n' _) = n == n'
423428 same _ _ = False
429+
424430 applyMaps ms (App f a) = App (applyMaps ms f) (applyMaps ms a)
425431 applyMaps ms t = t
426432
src/Core/Evaluate.hs+6−4
@@ -91,8 +91,9 @@ specialise ctxt env limits t
9191simplify :: Context -> Bool -> Env -> TT Name -> TT Name
9292simplify ctxt runtime env t
9393 = evalState (do val <- eval False ctxt [(UN "lazy", 0),
94− (UN "par", 0),
95− (UN "fork", 0)]
94+ (UN "assert_smaller", 0),
95+ (UN "par", 0),
96+ (UN "fork", 0)]
9697 (map finalEntry env) (finalise t)
9798 [Simplify runtime]
9899 quote 0 val) initEval
@@ -751,11 +752,12 @@ simplifyCasedef n uctxt
751752 [(CaseOp inl inr ty [] ps args sc args' sc', acc, tot)] ->
752753 ctxt -- nothing to simplify (or already done...)
753754 [(CaseOp inl inr ty ps_in ps args sc args' sc', acc, tot)] ->
754− let pdef = map debind $ map simpl ps_in in
755+ let ps_in' = map simpl ps_in
756+ pdef = map debind ps_in' in
755757 case simpleCase False True CompileTime (FC "" 0) pdef of
756758 OK (CaseDef args sc _) ->
757759 addDef n (CaseOp inl inr
758− ty ps_in ps args sc args' sc',
760+ ty ps_in' ps args sc args' sc',
759761 acc, tot) ctxt
760762 _ -> ctxt in
761763 uctxt { definitions = ctxt' }
src/IRTS/Compiler.hs+2
@@ -169,6 +169,8 @@ instance ToIR (TT Name) where
169169 | (P _ (UN "lazy") _, [_, arg]) <- unApply tm
170170 = do arg' <- ir' env arg
171171 return $ LLazyExp arg'
172+ | (P _ (UN "assert_smaller") _, [_, _, _, arg]) <- unApply tm
173+ = ir' env arg
172174 | (P _ (UN "par") _, [_, arg]) <- unApply tm
173175 = do arg' <- ir' env arg
174176 return $ LOp LPar [LLazyExp arg']
src/Idris/Coverage.hs+75−4
@@ -311,15 +311,85 @@ buildSCG (_, n) = do
311311 ist <- getIState
312312 case lookupCtxt n (idris_callgraph ist) of
313313 [cg] -> case lookupDef n (tt_ctxt ist) of
314− [CaseOp _ _ _ _ _ args sc _ _] ->
315− do logLvl 3 $ "Building SCG for " ++ show n ++ " from\n"
316− ++ show sc
317− let newscg = buildSCG' ist sc args
314+ [CaseOp _ _ _ pats _ args sc _ _] ->
315+ do logLvl 2 $ "Building SCG for " ++ show n ++ " from\n"
316+ ++ show pats ++ "\n" ++ show sc
317+ let newscg = buildSCG' ist (rights pats) args
318318 logLvl 5 $ show newscg
319319 addToCG n ( cg { scg = newscg } )
320320 [] -> logLvl 5 $ "Could not build SCG for " ++ show n ++ "\n"
321321 x -> error $ "buildSCG: " ++ show (n, x)
322322
323+buildSCG' :: IState -> [(Term, Term)] -> [Name] -> [SCGEntry]
324+buildSCG' ist pats args = nub $ concatMap scgPat pats where
325+ scgPat (lhs, rhs) = let (f, pargs) = unApply (dePat lhs) in
326+ findCalls (dePat rhs) (patvars lhs) pargs
327+
328+ findCalls ap@(App f a) pvs pargs
329+ | (P _ (UN "lazy") _, [_, arg]) <- unApply ap
330+ = findCalls arg pvs pargs
331+ | (P _ n _, args) <- unApply ap
332+ = mkChange n args pargs ++
333+ concatMap (\x -> findCalls x pvs pargs) args
334+ findCalls (App f a) pvs pargs
335+ = findCalls f pvs pargs ++ findCalls a pvs pargs
336+ findCalls (Bind n (Let t v) e) pvs pargs
337+ = findCalls v pvs pargs ++ findCalls e (n : pvs) pargs
338+ findCalls (Bind n _ e) pvs pargs
339+ = findCalls e (n : pvs) pargs
340+ findCalls (P _ f _ ) pvs pargs
341+ | not (f `elem` pvs) = [(f, [])]
342+ findCalls _ _ _ = []
343+
344+ mkChange n args pargs = [(n, sizes args)]
345+ where
346+ sizes [] = []
347+ sizes (a : as) = checkSize a pargs 0 : sizes as
348+
349+ -- find which argument in pargs <a> is smaller than, if any
350+ checkSize a (p : ps) i
351+ | a == p = Just (i, Same)
352+ | smaller Nothing a (p, Nothing) = Just (i, Smaller)
353+ | otherwise = checkSize a ps (i + 1)
354+ checkSize a [] i = Nothing
355+
356+ -- the smaller thing we find must be the same type as <a>, and
357+ -- not be coinductive - so carry the type of the constructor we've
358+ -- gone under.
359+
360+ smaller (Just tyn) a (t, Just tyt)
361+ | a == t = isInductive (fst (unApply (getRetTy tyn)))
362+ (fst (unApply (getRetTy tyt)))
363+ smaller ty a (ap@(App f s), _)
364+ | (P (DCon _ _) n _, args) <- unApply ap
365+ = let tyn = getType n in
366+ any (smaller (ty `mplus` Just tyn) a)
367+ (zip args (map toJust (getArgTys tyn)))
368+ -- check higher order recursive arguments
369+ smaller ty (App f s) a = smaller ty f a
370+ smaller _ _ _ = False
371+
372+ toJust (n, t) = Just t
373+
374+ getType n = case lookupTy n (tt_ctxt ist) of
375+ [ty] -> ty -- must exist
376+
377+ isInductive (P _ nty _) (P _ nty' _) =
378+ let co = case lookupCtxt nty (idris_datatypes ist) of
379+ [TI _ x _] -> x
380+ _ -> False in
381+ nty == nty' && not co
382+ isInductive _ _ = False
383+
384+-- getTypeFam t | (P _ n _, _) <- unApply t
385+
386+ dePat (Bind x (PVar ty) sc) = dePat (instantiate (P Bound x ty) sc)
387+ dePat t = t
388+
389+ patvars (Bind x (PVar _) sc) = x : patvars sc
390+ patvars _ = []
391+
392+{-
323393buildSCG' :: IState -> SC -> [Name] -> [SCGEntry]
324394buildSCG' ist sc args = -- trace ("Building SCG for " ++ show sc) $
325395 nub $ scg sc (zip args args)
@@ -406,6 +476,7 @@ buildSCG' ist sc args = -- trace ("Building SCG for " ++ show sc) $
406476 getArgPos i n [] = Nothing
407477 getArgPos i n (x : xs) | n == x = Just i
408478 | otherwise = getArgPos (i + 1) n xs
479+-}
409480
410481checkSizeChange :: Name -> Idris Totality
411482checkSizeChange n = do
src/Idris/ElabDecls.hs+4
@@ -458,6 +458,7 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
458458 else stripCollapsed pats
459459
460460 logLvl 5 $ "Patterns:\n" ++ show pats
461+ logLvl 3 $ "SIMPLIFIED: \n" ++ show pdef
461462
462463 let optpdef = map debind $ map (simpl True (tt_ctxt ist)) optpats
463464 tree@(CaseDef scargs sc _) <- tclift $
@@ -938,6 +939,9 @@ elabClass info syn doc fc constraints tn ps ds
938939 -- build instance constructor type
939940 -- decorate names of functions to ensure they can't be referred
940941 -- to elsewhere in the class declaration
942+ -- TODO: Remove mdec to make it a dependent record, which would
943+ -- allow dependent type classes, but building instances will
944+ -- then need some attention.
941945 let cty = impbind ps $ conbind constraints
942946 $ pibind (map (\ (n, ty) -> (mdec n, ty)) methods)
943947 constraint