@@ -90,22 +90,23 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
9090 Nothing -> transformPats ist pats_in
9191 _ -> pats_in
9292
93− let pats = map (simple_lhs (tt_ctxt ist)) $
94− doPartialEval ist tpats
93+ -- If the definition is specialisable, this reduces the
94+ -- RHS
95+ pe_tm <- doPartialEval ist tpats
96+ let pats = map (simple_lhs (tt_ctxt ist)) pe_tm
9597
96− -- logLvl 3 (showSep "\n" (map (\ (l,r) ->
97− -- show l ++ " = " ++
98− -- show r) pats))
9998 let tcase = opt_typecase (idris_options ist)
10099
101100 -- Look for 'static' names and generate new specialised
102101 -- definitions for them, as well as generating rewrite rules
103102 -- for partially evaluated definitions
104− mapM_ (\ e -> case e of
105− Left _ -> return ()
106− Right (l, r) -> elabPE info fc n r) pats
103+ newrules <- mapM (\ e -> case e of
104+ Left _ -> return []
105+ Right (l, r) -> elabPE info fc n r) pats
107106
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
109110 ist <- getIState
110111 let pats_transformed = transformPats ist pats
111112
@@ -134,7 +135,9 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
134135 numArgs <- tclift $ sameLength pdef
135136
136137 case specNames opts of
137− Just _ -> logLvl 1 $ "Partially evaluated:\n" ++ show pats
138+ Just _ ->
139+ do logLvl 2 $ "Partially evaluated:\n" ++ show pats
140+ logLvl 2 $ "Transformed:\n" ++ show pats_transformed
138141 _ -> return ()
139142
140143 erInfo <- getErasureInfo <$> getIState
@@ -257,22 +260,12 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
257260
258261 getLHS (_, l, _) = l
259262
260− simple_lhs ctxt (Right (x, y)) = Right (normalise ctxt [] x,
261− force (normalisePats ctxt [] y))
263+ simple_lhs ctxt (Right (x, y)) = Right (normalise ctxt [] x, y)
262264 simple_lhs ctxt t = t
263265
264266 simple_rt ctxt (p, x, y) = (p, x, force (uniqueBinders p
265267 (rt_simplify ctxt [] y)))
266268
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
275−
276269 specNames [] = Nothing
277270 specNames (Specialise ns : _) = Just ns
278271 specNames (_ : xs) = specNames xs
@@ -287,15 +280,19 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
287280 -- Partially evaluate, if the definition is marked as specialisable
288281 doPartialEval ist pats =
289282 case specNames opts of
290− Nothing -> pats
291− Just ns -> partial_eval (tt_ctxt ist) ns pats
292−
293−-- | Find 'static' applications in a term and partially evaluate them
294−elabPE :: ElabInfo -> FC -> Name -> Term -> Idris ()
283+ Nothing -> return pats
284+ Just ns -> case partial_eval (tt_ctxt ist) ns pats of
285+ Just t -> return t
286+ Nothing -> ierror (At fc (Msg "No specialisation achieved"))
287+
288+-- | Find 'static' applications in a term and partially evaluate them.
289+-- Return any new transformation rules
290+elabPE :: ElabInfo -> FC -> Name -> Term -> Idris [(Term, Term)]
295291elabPE info fc caller r =
296292 do ist <- getIState
297293 let sa = getSpecApps ist [] r
298− mapM_ (mkSpecialised ist) sa
294+ rules <- mapM mkSpecialised sa
295+ return $ concat rules
299296 where
300297 -- Make a specialised version of the application, and
301298 -- add a PTerm level transformation rule, which is basically the
@@ -305,41 +302,48 @@ elabPE info fc caller r =
305302
306303 -- Transformation rules are applied after every PClause elaboration
307304
308− mkSpecialised ist specapp_in = do
305+ mkSpecialised :: (Name, [(PEArgType, Term)]) -> Idris [(Term, Term)]
306+ mkSpecialised specapp_in = do
307+ ist <- getIState
309308 let (specTy, specapp) = getSpecTy ist specapp_in
310309 let (n, newnm, (lhs, rhs)) = getSpecClause ist specapp
311− let undef = case lookupDef newnm (tt_ctxt ist) of
312− [] -> True
310+ let undef = case lookupDefExact newnm (tt_ctxt ist) of
311+ Nothing -> True
313312 _ -> False
314− logLvl 3 $ show (newnm, map (concreteArg ist) (snd specapp))
313+ logLvl 5 $ show (newnm, undef, map (concreteArg ist) (snd specapp))
315314 idrisCatch
316− (when (undef && all (concreteArg ist) (snd specapp)) $ do
317− cgns <- getAllNames n
318− let opts = [Specialise (map (\x -> (x, Nothing)) cgns ++
319− mapMaybe specName (snd specapp))]
320− logLvl 3 $ "Specialising application: " ++ show specapp
321− ++ " with " ++ show opts
322− logLvl 3 $ "New name: " ++ show newnm
323− logLvl 3 $ "PE definition type : " ++ (show specTy)
324− ++ "\n" ++ show opts
325− logLvl 3 $ "PE definition " ++ show newnm ++ ":\n" ++
326−-- showSep "\n"
327−-- (map (\ (lhs, rhs) ->
328− (showTmImpls lhs ++ " = " ++
329− showTmImpls rhs) -- pats)
330−
331− logLvl 2 $ show n ++ " transformation rule: " ++
332− show rhs ++ " ==> " ++ show lhs
333−
334− elabType info defaultSyntax emptyDocstring [] fc opts newnm specTy
335− let def = -- map (\ (lhs, rhs) ->
336− [PClause fc newnm lhs [] rhs []] --) pats
337− elabTransform info fc False rhs lhs
338− elabClauses info fc opts newnm def)
315+ (if (undef && all (concreteArg ist) (snd specapp)) then do
316+ cgns <- getAllNames n
317+ let cgns' = filter (/= n) cgns
318+ let opts = [Specialise (map (\x -> (x, Nothing)) cgns' ++
319+ (n, Just 65536) :
320+ mapMaybe specName (snd specapp))]
321+ logLvl 3 $ "Specialising application: " ++ show specapp
322+ ++ " with " ++ show opts
323+ logLvl 3 $ "New name: " ++ show newnm
324+ logLvl 3 $ "PE definition type : " ++ (show specTy)
325+ ++ "\n" ++ show opts
326+ logLvl 3 $ "PE definition " ++ show newnm ++ ":\n" ++
327+ -- showSep "\n"
328+ -- (map (\ (lhs, rhs) ->
329+ (showTmImpls lhs ++ " = " ++
330+ showTmImpls rhs) -- pats)
331+
332+ logLvl 2 $ show n ++ " transformation rule: " ++
333+ show rhs ++ " ==> " ++ show lhs
334+
335+ elabType info defaultSyntax emptyDocstring [] fc opts newnm specTy
336+ let def = -- map (\ (lhs, rhs) ->
337+ [PClause fc newnm lhs [] rhs []] --) pats
338+ trans <- elabTransform info fc False rhs lhs
339+ elabClauses info fc opts newnm def
340+ return [trans]
341+ else return [])
339342 -- if it doesn't work, just don't specialise. Could happen for lots
340343 -- of valid reasons (e.g. local variables in scope which can't be
341344 -- lifted out).
342− (\e -> logLvl 4 $ "Couldn't specialise: " ++ (pshow ist e))
345+ (\e -> do logLvl 4 $ "Couldn't specialise: " ++ (pshow ist e)
346+ return [])
343347
344348 specName (ImplicitS, tm)
345349 | (P Ref n _, _) <- unApply tm = Just (n, Just 1)
@@ -370,7 +374,7 @@ elabPE info fc caller r =
370374
371375 -- get the clause of a specialised application
372376 getSpecClause ist (n, args)
373− = let newnm = sUN ("PE_"++ show (nsroot n) ++ "_" ++
377+ = let newnm = sUN ("PE_" ++ show (nsroot n) ++ "_" ++
374378 qhash 0 (showSep "_" (map showArg args))) in
375379 -- UN (show n ++ show (map snd args)) in
376380 (n, newnm, mkPE_TermDecl ist newnm n args)