@@ -14,11 +14,13 @@ import Idris.Providers
1414import Idris.Primitives
1515import Idris.Inliner
1616import Idris.PartialEval
17+import Idris.Transforms
1718import Idris.DeepSeq
1819import Idris.Output (iputStrLn, pshow, iWarn)
1920import IRTS.Lang
2021
2122import Idris.Elab.Type
23+import Idris.Elab.Transform
2224import Idris.Elab.Utils
2325
2426import Idris.Core.TT
@@ -48,6 +50,7 @@ import Data.Char(isLetter, toLower)
4850import Data.List.Split (splitOn)
4951
5052import Util.Pretty(pretty, text)
53+import Numeric
5154
5255-- | Elaborate a collection of left-hand and right-hand pairs - that is, a
5356-- top-level definition.
@@ -81,13 +84,25 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
8184 addIBC (IBCOpt n)
8285
8386 ist <- getIState
84− let pats = map (simple_lhs (tt_ctxt ist)) $ doTransforms ist pats_in
87+ let tpats = transformPats ist pats_in
88+ let pats = map (simple_lhs (tt_ctxt ist)) $
89+ doPartialEval ist tpats
8590
8691 -- logLvl 3 (showSep "\n" (map (\ (l,r) ->
8792 -- show l ++ " = " ++
8893 -- show r) pats))
8994 let tcase = opt_typecase (idris_options ist)
9095
96+ -- Look for 'static' names and generate new specialised
97+ -- definitions for them, as well as generating rewrite rules
98+ -- for partially evaluated definitions
99+ mapM_ (\ e -> case e of
100+ Left _ -> return ()
101+ Right (l, r) -> elabPE info fc n r) pats
102+
103+ -- Redo transforms with the newly generated transformations
104+ let pats_transformed = transformPats ist pats
105+
91106 -- Summary of what's about to happen: Definitions go:
92107 --
93108 -- pats_in -> pats -> pdef -> pdef'
@@ -97,18 +112,11 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
97112 -- pdef is the compile-time pattern definition.
98113 -- This will get further optimised for run-time, and, separately,
99114 -- further inlined to help with totality checking.
100− let pdef = map debind pats
115+ let pdef = map debind pats_transformed
101116
102117 logLvl 5 $ "Initial typechecked patterns:\n" ++ show pats
103118 logLvl 5 $ "Initial typechecked pattern def:\n" ++ show pdef
104119
105− -- Look for 'static' names and generate new specialised
106− -- definitions for them
107−
108− mapM_ (\ e -> case e of
109− Left _ -> return ()
110− Right (l, r) -> elabPE info fc n r) pats
111−
112120 -- NOTE: Need to store original definition so that proofs which
113121 -- rely on its structure aren't affected by any changes to the
114122 -- inliner. Just use the inlined version to generate pdef' and to
@@ -120,7 +128,7 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
120128 numArgs <- tclift $ sameLength pdef
121129
122130 case specNames opts of
123− Just _ -> logLvl 5 $ "Partially evaluated:\n" ++ show pats
131+ Just _ -> logLvl 1 $ "Partially evaluated:\n" ++ show pats
124132 _ -> return ()
125133
126134 erInfo <- getErasureInfo <$> getIState
@@ -163,7 +171,6 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
163171 -- then case tot of
164172 -- Total _ -> return ()
165173 -- t -> tclift $ tfail (At fc (Msg (show n ++ " is " ++ show t)))
166− -- else return ()
167174 -- _ -> return ()
168175 case tree of
169176 CaseDef _ _ [] -> return ()
@@ -271,9 +278,8 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
271278 else tfail (At fc (Msg "Clauses have differing numbers of arguments "))
272279 sameLength [] = return 0
273280
274− -- apply all transformations (just specialisation for now, add
275− -- user defined transformation rules later)
276− doTransforms ist pats =
281+ -- Partially evaluate, if the definition is marked as specialisable
282+ doPartialEval ist pats =
277283 case specNames opts of
278284 Nothing -> pats
279285 Just ns -> partial_eval (tt_ctxt ist) ns pats
@@ -285,38 +291,45 @@ elabPE info fc caller r =
285291 let sa = getSpecApps ist [] r
286292 mapM_ (mkSpecialised ist) sa
287293 where
288− -- TODO: Add a PTerm level transformation rule, which is basically the
294+ -- Make a specialised version of the application, and
295+ -- add a PTerm level transformation rule, which is basically the
289296 -- new definition in reverse (before specialising it).
290297 -- RHS => LHS where implicit arguments are left blank in the
291298 -- transformation.
292299
293− -- Apply that transformation after every PClauses elaboration
300+ -- Transformation rules are applied after every PClause elaboration
294301
295302 mkSpecialised ist specapp_in = do
296303 let (specTy, specapp) = getSpecTy ist specapp_in
297− let (n, newnm, pats) = getSpecClause ist specapp
304+ let (n, newnm, (lhs, rhs)) = getSpecClause ist specapp
298305 let undef = case lookupDef newnm (tt_ctxt ist) of
299306 [] -> True
300307 _ -> False
301− logLvl 5 $ show (newnm, map (concreteArg ist) (snd specapp))
308+ logLvl 3 $ show (newnm, map (concreteArg ist) (snd specapp))
302309 idrisCatch
303310 (when (undef && all (concreteArg ist) (snd specapp)) $ do
304311 cgns <- getAllNames n
305312 let opts = [Specialise (map (\x -> (x, Nothing)) cgns ++
306313 mapMaybe specName (snd specapp))]
307314 logLvl 3 $ "Specialising application: " ++ show specapp
308− logLvl 2 $ "New name: " ++ show newnm
309− iLOG $ "PE definition type : " ++ (show specTy)
315+ ++ " with " ++ show cgns
316+ logLvl 3 $ "New name: " ++ show newnm
317+ logLvl 3 $ "PE definition type : " ++ (show specTy)
310318 ++ "\n" ++ show opts
311− logLvl 2 $ "PE definition " ++ show newnm ++ ":\n" ++
312− showSep "\n"
313− (map (\ (lhs, rhs) ->
319+ logLvl 3 $ "PE definition " ++ show newnm ++ ":\n" ++
320+-- showSep "\n"
321+-- (map (\ (lhs, rhs) ->
314322 (showTmImpls lhs ++ " = " ++
315− showTmImpls rhs)) pats)
323+ showTmImpls rhs) -- pats)
324+
325+ logLvl 2 $ show n ++ " transformation rule: " ++
326+ show rhs ++ " ==> " ++ show lhs
327+
316328 elabType info defaultSyntax emptyDocstring [] fc opts newnm specTy
317− let def = map (\ (lhs, rhs) -> PClause fc newnm lhs [] rhs []) pats
318− elabClauses info fc opts newnm def
319− logLvl 2 $ "Specialised " ++ show newnm)
329+ elabTransform info fc False rhs lhs
330+ let def = -- map (\ (lhs, rhs) ->
331+ [PClause fc newnm lhs [] rhs []] --) pats
332+ elabClauses info fc opts newnm def)
320333 -- if it doesn't work, just don't specialise. Could happen for lots
321334 -- of valid reasons (e.g. local variables in scope which can't be
322335 -- lifted out).
@@ -351,14 +364,20 @@ elabPE info fc caller r =
351364
352365 -- get the clause of a specialised application
353366 getSpecClause ist (n, args)
354− = let newnm = sUN ("__"++show (nsroot n) ++ "_" ++
355− showSep "_" (map showArg args)) in
367+ = let newnm = sUN ("PE_"++show (nsroot n) ++ "_" ++
368+ qhash 0 (showSep "_" (map showArg args))) in
356369 -- UN (show n ++ show (map snd args)) in
357370 (n, newnm, mkPE_TermDecl ist newnm n args)
358371 where showArg (ExplicitS, n) = show n
359372 showArg (ImplicitS, n) = show n
360373 showArg _ = ""
361374
375+ -- TMP for readability! This is obviously a really bad hashing
376+ -- function.
377+ qhash :: Int -> String -> String
378+ qhash acc [] = showHex acc ""
379+ qhash acc (x:xs) = qhash (fromEnum x + acc) xs
380+
362381-- checks if the clause is a possible left hand side. Returns the term if
363382-- possible, otherwise Nothing.
364383