@@ -90,22 +90,23 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
90 Nothing -> transformPats ist pats_in
90 Nothing -> transformPats ist pats_in
91 _ -> pats_in
91 _ -> pats_in
93+ -- If the definition is specialisable, this reduces the
95+ pe_tm <- doPartialEval ist tpats
93− let pats = map (simple_lhs (tt_ctxt ist)) $
96+ let pats = map (simple_lhs (tt_ctxt ist)) pe_tm
94− doPartialEval ist tpats
96− -- logLvl 3 (showSep "\n" (map (\ (l,r) ->
97− -- show l ++ " = " ++
99 let tcase = opt_typecase (idris_options ist)
98 let tcase = opt_typecase (idris_options ist)
101 -- Look for 'static' names and generate new specialised
100 -- Look for 'static' names and generate new specialised
102 -- definitions for them, as well as generating rewrite rules
101 -- definitions for them, as well as generating rewrite rules
103 -- for partially evaluated definitions
102 -- for partially evaluated definitions
104− mapM_ (\ e -> case e of
103+ newrules <- mapM (\ e -> case e of
105− Left _ -> return ()
104+ Left _ -> return []
106− Right (l, r) -> elabPE info fc n r) pats
105+ Right (l, r) -> elabPE info fc n r) pats
108− -- Redo transforms with the newly generated transformations
107+ -- Redo transforms with the newly generated transformations, so
108+ -- that the specialised application we've just made gets
109+ -- used in place of the general one
109 ist <- getIState
110 ist <- getIState
110 let pats_transformed = transformPats ist pats
111 let pats_transformed = transformPats ist pats
@@ -134,7 +135,9 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
134 numArgs <- tclift $ sameLength pdef
135 numArgs <- tclift $ sameLength pdef
136 case specNames opts of
137 case specNames opts of
137− Just _ -> logLvl 1 $ "Partially evaluated:\n" ++ show pats
139+ do logLvl 2 $ "Partially evaluated:\n" ++ show pats
140+ logLvl 2 $ "Transformed:\n" ++ show pats_transformed
138 _ -> return ()
141 _ -> return ()
140 erInfo <- getErasureInfo <$> getIState
143 erInfo <- getErasureInfo <$> getIState
@@ -257,22 +260,12 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
258 getLHS (_, l, _) = l
261 getLHS (_, l, _) = l
260− simple_lhs ctxt (Right (x, y)) = Right (normalise ctxt [] x,
263+ simple_lhs ctxt (Right (x, y)) = Right (normalise ctxt [] x, y)
261− force (normalisePats ctxt [] y))
262 simple_lhs ctxt t = t
264 simple_lhs ctxt t = t
264 simple_rt ctxt (p, x, y) = (p, x, force (uniqueBinders p
266 simple_rt ctxt (p, x, y) = (p, x, force (uniqueBinders p
265 (rt_simplify ctxt [] y)))
267 (rt_simplify ctxt [] y)))
267− -- this is so pattern types are in the right form for erasure
268− normalisePats ctxt env (Bind n (PVar t) sc)
269− = let t' = normalise ctxt env t in
270− Bind n (PVar t') (normalisePats ctxt ((n, PVar t') : env) sc)
271− normalisePats ctxt env (Bind n (PVTy t) sc)
272− = let t' = normalise ctxt env t in
273− Bind n (PVTy t') (normalisePats ctxt ((n, PVar t') : env) sc)
274− normalisePats ctxt env t = t
276 specNames [] = Nothing
269 specNames [] = Nothing
277 specNames (Specialise ns : _) = Just ns
270 specNames (Specialise ns : _) = Just ns
278 specNames (_ : xs) = specNames xs
271 specNames (_ : xs) = specNames xs
@@ -287,15 +280,19 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
287 -- Partially evaluate, if the definition is marked as specialisable
280 -- Partially evaluate, if the definition is marked as specialisable
288 doPartialEval ist pats =
281 doPartialEval ist pats =
289 case specNames opts of
282 case specNames opts of
290− Nothing -> pats
283+ Nothing -> return pats
291− Just ns -> partial_eval (tt_ctxt ist) ns pats
284+ Just ns -> case partial_eval (tt_ctxt ist) ns pats of
292−
285+ Just t -> return t
286+ Nothing -> ierror (At fc (Msg "No specialisation achieved"))
293−-- | Find 'static' applications in a term and partially evaluate them
288+-- | Find 'static' applications in a term and partially evaluate them.
289+-- Return any new transformation rules
294−elabPE :: ElabInfo -> FC -> Name -> Term -> Idris ()
290+elabPE :: ElabInfo -> FC -> Name -> Term -> Idris [(Term, Term)]
295elabPE info fc caller r =
291elabPE info fc caller r =
296 do ist <- getIState
292 do ist <- getIState
297 let sa = getSpecApps ist [] r
293 let sa = getSpecApps ist [] r
298− mapM_ (mkSpecialised ist) sa
294+ rules <- mapM mkSpecialised sa
295+ return $ concat rules
300 -- Make a specialised version of the application, and
297 -- Make a specialised version of the application, and
301 -- add a PTerm level transformation rule, which is basically the
298 -- add a PTerm level transformation rule, which is basically the
@@ -305,41 +302,48 @@ elabPE info fc caller r =
306 -- Transformation rules are applied after every PClause elaboration
303 -- Transformation rules are applied after every PClause elaboration
305+ mkSpecialised :: (Name, [(PEArgType, Term)]) -> Idris [(Term, Term)]
308− mkSpecialised ist specapp_in = do
306+ mkSpecialised specapp_in = do
309 let (specTy, specapp) = getSpecTy ist specapp_in
308 let (specTy, specapp) = getSpecTy ist specapp_in
310 let (n, newnm, (lhs, rhs)) = getSpecClause ist specapp
309 let (n, newnm, (lhs, rhs)) = getSpecClause ist specapp
311− let undef = case lookupDef newnm (tt_ctxt ist) of
310+ let undef = case lookupDefExact newnm (tt_ctxt ist) of
312− [] -> True
311+ Nothing -> True
313 _ -> False
312 _ -> False
314− logLvl 3 $ show (newnm, map (concreteArg ist) (snd specapp))
313+ logLvl 5 $ show (newnm, undef, map (concreteArg ist) (snd specapp))
315 idrisCatch
314 idrisCatch
316− (when (undef && all (concreteArg ist) (snd specapp)) $ do
315+ (if (undef && all (concreteArg ist) (snd specapp)) then do
317− cgns <- getAllNames n
316+ cgns <- getAllNames n
317+ let cgns' = filter (/= n) cgns
318− let opts = [Specialise (map (\x -> (x, Nothing)) cgns ++
318+ let opts = [Specialise (map (\x -> (x, Nothing)) cgns' ++
319− mapMaybe specName (snd specapp))]
320+ mapMaybe specName (snd specapp))]
320− logLvl 3 $ "Specialising application: " ++ show specapp
321+ logLvl 3 $ "Specialising application: " ++ show specapp
321− ++ " with " ++ show opts
322+ ++ " with " ++ show opts
322− logLvl 3 $ "New name: " ++ show newnm
323+ logLvl 3 $ "New name: " ++ show newnm
323− logLvl 3 $ "PE definition type : " ++ (show specTy)
324+ logLvl 3 $ "PE definition type : " ++ (show specTy)
324− ++ "\n" ++ show opts
325+ ++ "\n" ++ show opts
325− logLvl 3 $ "PE definition " ++ show newnm ++ ":\n" ++
326+ logLvl 3 $ "PE definition " ++ show newnm ++ ":\n" ++
326−-- showSep "\n"
327+ -- showSep "\n"
327−-- (map (\ (lhs, rhs) ->
328+ -- (map (\ (lhs, rhs) ->
328− (showTmImpls lhs ++ " = " ++
329+ (showTmImpls lhs ++ " = " ++
329− showTmImpls rhs) -- pats)
330+ showTmImpls rhs) -- pats)
331− logLvl 2 $ show n ++ " transformation rule: " ++
332+ logLvl 2 $ show n ++ " transformation rule: " ++
332− show rhs ++ " ==> " ++ show lhs
333+ show rhs ++ " ==> " ++ show lhs
334− elabType info defaultSyntax emptyDocstring [] fc opts newnm specTy
335+ elabType info defaultSyntax emptyDocstring [] fc opts newnm specTy
335− let def = -- map (\ (lhs, rhs) ->
336+ let def = -- map (\ (lhs, rhs) ->
336− [PClause fc newnm lhs [] rhs []] --) pats
337+ [PClause fc newnm lhs [] rhs []] --) pats
337− elabTransform info fc False rhs lhs
338+ trans <- elabTransform info fc False rhs lhs
338− elabClauses info fc opts newnm def)
339+ elabClauses info fc opts newnm def
339 -- if it doesn't work, just don't specialise. Could happen for lots
342 -- if it doesn't work, just don't specialise. Could happen for lots
340 -- of valid reasons (e.g. local variables in scope which can't be
343 -- of valid reasons (e.g. local variables in scope which can't be
341 -- lifted out).
344 -- lifted out).
342− (\e -> logLvl 4 $ "Couldn't specialise: " ++ (pshow ist e))
345+ (\e -> do logLvl 4 $ "Couldn't specialise: " ++ (pshow ist e)
344 specName (ImplicitS, tm)
348 specName (ImplicitS, tm)
345 | (P Ref n _, _) <- unApply tm = Just (n, Just 1)
349 | (P Ref n _, _) <- unApply tm = Just (n, Just 1)
@@ -370,7 +374,7 @@ elabPE info fc caller r =
371 -- get the clause of a specialised application
375 -- get the clause of a specialised application
372 getSpecClause ist (n, args)
376 getSpecClause ist (n, args)
373− = let newnm = sUN ("PE_"++ show (nsroot n) ++ "_" ++
377+ = let newnm = sUN ("PE_" ++ show (nsroot n) ++ "_" ++
374 qhash 0 (showSep "_" (map showArg args))) in
378 qhash 0 (showSep "_" (map showArg args))) in
375 -- UN (show n ++ show (map snd args)) in
379 -- UN (show n ++ show (map snd args)) in
376 (n, newnm, mkPE_TermDecl ist newnm n args)
380 (n, newnm, mkPE_TermDecl ist newnm n args)